summaryrefslogtreecommitdiff
path: root/nonprism/pidgin-nonprism
diff options
context:
space:
mode:
authorMárcio Alexandre Silva Delgado <coadde@lavabit.com>2013-08-28 00:23:33 -0300
committerMárcio Alexandre Silva Delgado <coadde@lavabit.com>2013-08-28 00:23:33 -0300
commit63783b026b1d255b8fe78f7a186a2efc418e94c1 (patch)
treef80ae894fba401c7729cc1e0c29a87c2ee71b1b0 /nonprism/pidgin-nonprism
parentdbf13bac1929ba47a83aa868b4687f8dcc65d443 (diff)
adding pidgin-nonprism to nonprism repo
Diffstat (limited to 'nonprism/pidgin-nonprism')
-rw-r--r--nonprism/pidgin-nonprism/PKGBUILD131
-rw-r--r--nonprism/pidgin-nonprism/nonprism.patch171507
-rw-r--r--nonprism/pidgin-nonprism/pidgin-2.10.7-link-libirc-to-libsasl2.patch12
-rw-r--r--nonprism/pidgin-nonprism/pidgin.install11
4 files changed, 171661 insertions, 0 deletions
diff --git a/nonprism/pidgin-nonprism/PKGBUILD b/nonprism/pidgin-nonprism/PKGBUILD
new file mode 100644
index 000000000..ccf2a9af6
--- /dev/null
+++ b/nonprism/pidgin-nonprism/PKGBUILD
@@ -0,0 +1,131 @@
+# $Id: PKGBUILD 185869 2013-05-19 16:42:53Z foutrelis $
+# Maintainer: Evangelos Foutras <evangelos@foutrelis.com>
+# Contributor: Ionut Biru <ibiru@archlinux.org>
+# Contributor: Andrea Scarpino <andrea@archlinux.org>
+# Contributor: Alexander Fehr <pizzapunk gmail com>
+# Contributor: Lucien Immink <l.immink@student.fnt.hvu.nl>
+
+_pkgname=pidgin
+pkgname=('pidgin-nonprism' 'libpurple-nonprism' 'finch-nonprism')
+pkgver=2.10.7
+pkgrel=4
+arch=('i686' 'x86_64' 'mips64el')
+url="http://pidgin.im/"
+license=('GPL')
+makedepends=('startup-notification' 'gtkspell' 'libxss' 'nss' 'libsasl' 'libsm'
+ 'libidn' 'python2' 'hicolor-icon-theme' 'farstream-0.1' 'avahi'
+ 'tk' 'ca-certificates' 'intltool' 'networkmanager')
+options=('!libtool')
+source=(http://downloads.sourceforge.net/$_pkgname/$_pkgname-$pkgver.tar.bz2
+ pidgin-2.10.7-link-libirc-to-libsasl2.patch nonprism.patch)
+sha256sums=('eba32994eca20d1cf24a4261b059b2de71a1ec2dd0926e904074b0db49f7f192'
+ '063723d5dc5726c43137b4b383c9d07c2c008391f6a626faaf6cedd31a2f1e8f'
+ '54c185493f7139768e316b989a5d23aa9d46662bf69026a92efbf69ad7d00973')
+
+prepare() {
+ cd "$srcdir/$_pkgname-$pkgver"
+ msg 'remove nonfree services'
+ patch -Np1 -i $srcdir/nonprism.patch
+ #rm -vrf libpurple/protocols/{gg,jabber/google,msn,mxit,myspace,novell,oscar,yahoo}
+ #rm -v pidgin/pixmaps/protocols/16/{aim,facebook,gadu-gadu,google-talk,icq,msn,mxit,myspace,novell,yahoo}.png
+ #rm -v pidgin/pixmaps/protocols/16/scalable/{aim,gadu-gadu,icq,msn,novell,yahoo}.svg
+ #rm -v pidgin/pixmaps/protocols/22/{aim,facebook,gadu-gadu,google-talk,icq,msn,mxit,myspace,novell,yahoo}.png
+ #rm -v pidgin/pixmaps/protocols/22/scalable/{aim,gadu-gadu,icq,msn,novell,yahoo}.svg
+ #rm -v pidgin/pixmaps/protocols/48/{aim,facebook,gadu-gadu,icq,msn,mxit,myspace,novell,yahoo}.png
+ #rm -v pidgin/pixmaps/protocols/scalable/{aim,gadu-gadu,google-talk,icq,msn,mxit,novell,yahoo}.svg
+ msg 'remove wrong OS term'
+ sed -i 's|on Linux|on GNU/Linux|' libpurple/valgrind.h
+ sed -i 's|On Linux|On GNU/Linux|' libpurple/connection.h
+}
+
+build() {
+ cd "$srcdir/$_pkgname-$pkgver"
+
+ # https://developer.pidgin.im/ticket/15517
+ patch -Np1 -i "$srcdir/pidgin-2.10.7-link-libirc-to-libsasl2.patch"
+ autoreconf -vi
+
+ # Use Python 2
+ sed -i 's/env python$/&2/' */plugins/*.py \
+ libpurple/purple-{remote,notifications-example,url-handler}
+
+ ./configure \
+ --prefix=/usr \
+ --sysconfdir=/etc \
+ --disable-schemas-install \
+ --disable-meanwhile \
+ --disable-gnutls \
+ --enable-cyrus-sasl \
+ --disable-doxygen \
+ --enable-nm \
+ --with-python=/usr/bin/python2 \
+ --with-system-ssl-certs=/etc/ssl/certs
+ make
+}
+
+package_pidgin-nonprism(){
+ pkgdesc="Multi-protocol instant messaging client"
+ depends=('libpurple' 'startup-notification' 'gtkspell' 'libxss' 'libsm'
+ 'hicolor-icon-theme')
+ optdepends=('aspell: for spelling correction')
+ provides=("$_pkgname=$pkgver")
+ conflicts=$_pkgname
+ replaces=$_pkgname
+ install=pidgin.install
+
+ cd "$srcdir/pidgin-$pkgver"
+
+ # For linking
+ make -C libpurple DESTDIR="$pkgdir" install-libLTLIBRARIES
+
+ make -C pidgin DESTDIR="$pkgdir" install
+ make -C doc DESTDIR="$pkgdir" install
+
+ # Remove files that are packaged in libpurle
+ make -C libpurple DESTDIR="$pkgdir" uninstall-libLTLIBRARIES
+
+ install -Dm644 pidgin.desktop "$pkgdir"/usr/share/applications/pidgin.desktop
+
+ rm "$pkgdir/usr/share/man/man1/finch.1"
+}
+
+package_libpurple-nonprism(){
+ pkgdesc="IM library extracted from Pidgin"
+ depends=('farstream-0.1' 'libsasl' 'libidn' 'dbus-glib' 'nss')
+ optdepends=('avahi: Bonjour protocol support'
+ 'ca-certificates: SSL CA certificates'
+ 'python2-dbus: for purple-remote and purple-url-handler'
+ 'tk: Tcl/Tk scripting support')
+ provides=("${pkgname%-nonprism}=$pkgver")
+ conflicts=${pkgname%-nonprism}
+ replaces=${pkgname%-nonprism}
+
+ cd "$srcdir/pidgin-$pkgver"
+
+ for _dir in libpurple share/sounds share/ca-certs m4macros po; do
+ make -C "$_dir" DESTDIR="$pkgdir" install
+ done
+}
+
+package_finch-nonprism(){
+ pkgdesc="A ncurses-based messaging client"
+ depends=("libpurple=$pkgver-$pkgrel" 'libx11' 'python2')
+ provides=("${pkgname%-nonprism}=$pkgver")
+ conflicts=${pkgname%-nonprism}
+ replaces=${pkgname%-nonprism}
+
+ cd "$srcdir/pidgin-$pkgver"
+
+ # For linking
+ make -C libpurple DESTDIR="$pkgdir" install-libLTLIBRARIES
+
+ make -C finch DESTDIR="$pkgdir" install
+ make -C doc DESTDIR="$pkgdir" install
+
+ # Remove files that are packaged in libpurle
+ make -C libpurple DESTDIR="$pkgdir" uninstall-libLTLIBRARIES
+
+ rm "$pkgdir"/usr/share/man/man1/pidgin.1
+}
+
+# vim:set ts=2 sw=2 et:
diff --git a/nonprism/pidgin-nonprism/nonprism.patch b/nonprism/pidgin-nonprism/nonprism.patch
new file mode 100644
index 000000000..448558a5f
--- /dev/null
+++ b/nonprism/pidgin-nonprism/nonprism.patch
@@ -0,0 +1,171507 @@
+diff -Nur pidgin-2.10.7/config.h.in pidgin-2.10.7-nonprism/config.h.in
+--- pidgin-2.10.7/config.h.in 2013-02-11 07:17:16.000000000 -0200
++++ pidgin-2.10.7-nonprism/config.h.in 2013-08-16 22:16:16.833531712 -0300
+@@ -151,9 +151,6 @@
+ /* Define to 1 if you have the `db' library (-ldb). */
+ #undef HAVE_LIBDB
+
+-/* Define to 1 if you have libgadu. */
+-#undef HAVE_LIBGADU
+-
+ /* Define to 1 if you have the `nsl' library (-lnsl). */
+ #undef HAVE_LIBNSL
+
+diff -Nur pidgin-2.10.7/configure pidgin-2.10.7-nonprism/configure
+--- pidgin-2.10.7/configure 2013-02-11 07:17:26.000000000 -0200
++++ pidgin-2.10.7-nonprism/configure 2013-08-27 16:47:16.890662082 -0300
+@@ -716,45 +716,23 @@
+ STATIC_LINK_LIBS
+ STATIC_ZEPHYR_FALSE
+ STATIC_ZEPHYR_TRUE
+-STATIC_YAHOO_FALSE
+-STATIC_YAHOO_TRUE
+ STATIC_SIMPLE_FALSE
+ STATIC_SIMPLE_TRUE
+ STATIC_SILC_FALSE
+ STATIC_SILC_TRUE
+-STATIC_SAMETIME_FALSE
+-STATIC_SAMETIME_TRUE
+-STATIC_OSCAR_FALSE
+-STATIC_OSCAR_TRUE
+-STATIC_NOVELL_FALSE
+-STATIC_NOVELL_TRUE
+-STATIC_MXIT_FALSE
+-STATIC_MXIT_TRUE
+-STATIC_MYSPACE_FALSE
+-STATIC_MYSPACE_TRUE
+-STATIC_MSN_FALSE
+-STATIC_MSN_TRUE
+ STATIC_JABBER_FALSE
+ STATIC_JABBER_TRUE
+ STATIC_IRC_FALSE
+ STATIC_IRC_TRUE
+-STATIC_GG_FALSE
+-STATIC_GG_TRUE
+ STATIC_BONJOUR_FALSE
+ STATIC_BONJOUR_TRUE
+ STATIC_PRPLS
+ DISTRIB_FALSE
+ DISTRIB_TRUE
+-USE_INTERNAL_LIBGADU_FALSE
+-USE_INTERNAL_LIBGADU_TRUE
+-GADU_LIBS
+-GADU_CFLAGS
+ SILC_LIBS
+ SILC_CFLAGS
+ AVAHI_LIBS
+ AVAHI_CFLAGS
+-MEANWHILE_LIBS
+-MEANWHILE_CFLAGS
+ IDN_LIBS
+ IDN_CFLAGS
+ USE_VV_FALSE
+@@ -1021,14 +999,11 @@
+ enable_farstream
+ enable_vv
+ enable_idn
+-enable_meanwhile
+ enable_avahi
+ with_avahi_client_includes
+ with_avahi_client_libs
+ with_silc_includes
+ with_silc_libs
+-with_gadu_includes
+-with_gadu_libs
+ enable_distrib
+ with_static_prpls
+ with_dynamic_prpls
+@@ -1100,14 +1075,10 @@
+ FARSTREAM_LIBS
+ IDN_CFLAGS
+ IDN_LIBS
+-MEANWHILE_CFLAGS
+-MEANWHILE_LIBS
+ AVAHI_CFLAGS
+ AVAHI_LIBS
+ SILC_CFLAGS
+ SILC_LIBS
+-GADU_CFLAGS
+-GADU_LIBS
+ DBUS_CFLAGS
+ DBUS_LIBS
+ NETWORKMANAGER_CFLAGS
+@@ -1773,8 +1744,6 @@
+ --disable-farstream compile without farstream support
+ --disable-vv compile without voice and video support
+ --disable-idn compile without IDN support
+- --disable-meanwhile compile without meanwhile (required for Sametime
+- support)
+ --disable-avahi compile without avahi (required for Bonjour support)
+
+ --disable-plugins compile without plugin support
+@@ -1826,9 +1795,6 @@
+ --with-silc-includes=DIR
+ compile the SILC plugin against includes in DIR
+ --with-silc-libs=DIR compile the SILC plugin against the SILC libs in DIR
+- --with-gadu-includes=DIR
+- compile the Gadu-Gadu plugin against includes in DIR
+- --with-gadu-libs=DIR compile the Gadu-Gadu plugin against the libs in DIR
+ --with-static-prpls Link to certain protocols statically
+ --with-dynamic-prpls specify which protocols to build dynamically
+ --with-krb4=PREFIX compile Zephyr plugin with Kerberos 4 support
+@@ -1905,17 +1871,11 @@
+ linker flags for FARSTREAM, overriding pkg-config
+ IDN_CFLAGS C compiler flags for IDN, overriding pkg-config
+ IDN_LIBS linker flags for IDN, overriding pkg-config
+- MEANWHILE_CFLAGS
+- C compiler flags for MEANWHILE, overriding pkg-config
+- MEANWHILE_LIBS
+- linker flags for MEANWHILE, overriding pkg-config
+ AVAHI_CFLAGS
+ C compiler flags for AVAHI, overriding pkg-config
+ AVAHI_LIBS linker flags for AVAHI, overriding pkg-config
+ SILC_CFLAGS C compiler flags for SILC, overriding pkg-config
+ SILC_LIBS linker flags for SILC, overriding pkg-config
+- GADU_CFLAGS C compiler flags for GADU, overriding pkg-config
+- GADU_LIBS linker flags for GADU, overriding pkg-config
+ DBUS_CFLAGS C compiler flags for DBUS, overriding pkg-config
+ DBUS_LIBS linker flags for DBUS, overriding pkg-config
+ NETWORKMANAGER_CFLAGS
+@@ -18487,105 +18447,6 @@
+ fi
+ fi
+
+-# Check whether --enable-meanwhile was given.
+-if test "${enable_meanwhile+set}" = set; then :
+- enableval=$enable_meanwhile; enable_meanwhile="$enableval"
+-else
+- enable_meanwhile="yes"
+-fi
+-
+-if test "x$enable_meanwhile" = "xyes"; then
+-
+-pkg_failed=no
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for MEANWHILE" >&5
+-$as_echo_n "checking for MEANWHILE... " >&6; }
+-
+-if test -n "$MEANWHILE_CFLAGS"; then
+- pkg_cv_MEANWHILE_CFLAGS="$MEANWHILE_CFLAGS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"meanwhile >= 1.0.0 meanwhile < 2.0.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "meanwhile >= 1.0.0 meanwhile < 2.0.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_MEANWHILE_CFLAGS=`$PKG_CONFIG --cflags "meanwhile >= 1.0.0 meanwhile < 2.0.0" 2>/dev/null`
+- test "x$?" != "x0" && pkg_failed=yes
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-if test -n "$MEANWHILE_LIBS"; then
+- pkg_cv_MEANWHILE_LIBS="$MEANWHILE_LIBS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"meanwhile >= 1.0.0 meanwhile < 2.0.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "meanwhile >= 1.0.0 meanwhile < 2.0.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_MEANWHILE_LIBS=`$PKG_CONFIG --libs "meanwhile >= 1.0.0 meanwhile < 2.0.0" 2>/dev/null`
+- test "x$?" != "x0" && pkg_failed=yes
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-
+-
+-
+-if test $pkg_failed = yes; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+- _pkg_short_errors_supported=yes
+-else
+- _pkg_short_errors_supported=no
+-fi
+- if test $_pkg_short_errors_supported = yes; then
+- MEANWHILE_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "meanwhile >= 1.0.0 meanwhile < 2.0.0" 2>&1`
+- else
+- MEANWHILE_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "meanwhile >= 1.0.0 meanwhile < 2.0.0" 2>&1`
+- fi
+- # Put the nasty error message in config.log where it belongs
+- echo "$MEANWHILE_PKG_ERRORS" >&5
+-
+-
+- have_meanwhile="no"
+- if test "x$force_deps" = "xyes" ; then
+- as_fn_error $? "
+-Meanwhile development headers not found.
+-Use --disable-meanwhile if you do not need meanwhile (Sametime) support.
+-" "$LINENO" 5
+- fi
+-elif test $pkg_failed = untried; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+- have_meanwhile="no"
+- if test "x$force_deps" = "xyes" ; then
+- as_fn_error $? "
+-Meanwhile development headers not found.
+-Use --disable-meanwhile if you do not need meanwhile (Sametime) support.
+-" "$LINENO" 5
+- fi
+-else
+- MEANWHILE_CFLAGS=$pkg_cv_MEANWHILE_CFLAGS
+- MEANWHILE_LIBS=$pkg_cv_MEANWHILE_LIBS
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+-
+- have_meanwhile="yes"
+-
+-fi
+-fi
+-
+-
+-
+ # Check whether --enable-avahi was given.
+ if test "${enable_avahi+set}" = set; then :
+ enableval=$enable_avahi; enable_avahi="$enableval"
+@@ -19207,267 +19068,6 @@
+ fi
+
+
+-# Check whether --with-gadu-includes was given.
+-if test "${with_gadu_includes+set}" = set; then :
+- withval=$with_gadu_includes; ac_gadu_includes="$withval"
+-else
+- ac_gadu_includes="no"
+-fi
+-
+-
+-# Check whether --with-gadu-libs was given.
+-if test "${with_gadu_libs+set}" = set; then :
+- withval=$with_gadu_libs; ac_gadu_libs="$withval"
+-else
+- ac_gadu_libs="no"
+-fi
+-
+-GADU_CFLAGS=""
+-GADU_LIBS=""
+-if test -n "$with_gadu_includes" || test -n "$with_gadu_libs"; then
+- gadu_manual_check="yes"
+-else
+- gadu_manual_check="no"
+-fi
+-if test "x$gadu_manual_check" = "xno"; then
+-
+-pkg_failed=no
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for GADU" >&5
+-$as_echo_n "checking for GADU... " >&6; }
+-
+-if test -n "$GADU_CFLAGS"; then
+- pkg_cv_GADU_CFLAGS="$GADU_CFLAGS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgadu >= 1.11.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libgadu >= 1.11.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_GADU_CFLAGS=`$PKG_CONFIG --cflags "libgadu >= 1.11.0" 2>/dev/null`
+- test "x$?" != "x0" && pkg_failed=yes
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-if test -n "$GADU_LIBS"; then
+- pkg_cv_GADU_LIBS="$GADU_LIBS"
+- elif test -n "$PKG_CONFIG"; then
+- if test -n "$PKG_CONFIG" && \
+- { { $as_echo "$as_me:${as_lineno-$LINENO}: \$PKG_CONFIG --exists --print-errors \"libgadu >= 1.11.0\""; } >&5
+- ($PKG_CONFIG --exists --print-errors "libgadu >= 1.11.0") 2>&5
+- ac_status=$?
+- $as_echo "$as_me:${as_lineno-$LINENO}: \$? = $ac_status" >&5
+- test $ac_status = 0; }; then
+- pkg_cv_GADU_LIBS=`$PKG_CONFIG --libs "libgadu >= 1.11.0" 2>/dev/null`
+- test "x$?" != "x0" && pkg_failed=yes
+-else
+- pkg_failed=yes
+-fi
+- else
+- pkg_failed=untried
+-fi
+-
+-
+-
+-if test $pkg_failed = yes; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+-if $PKG_CONFIG --atleast-pkgconfig-version 0.20; then
+- _pkg_short_errors_supported=yes
+-else
+- _pkg_short_errors_supported=no
+-fi
+- if test $_pkg_short_errors_supported = yes; then
+- GADU_PKG_ERRORS=`$PKG_CONFIG --short-errors --print-errors --cflags --libs "libgadu >= 1.11.0" 2>&1`
+- else
+- GADU_PKG_ERRORS=`$PKG_CONFIG --print-errors --cflags --libs "libgadu >= 1.11.0" 2>&1`
+- fi
+- # Put the nasty error message in config.log where it belongs
+- echo "$GADU_PKG_ERRORS" >&5
+-
+-
+- gadu_includes="no"
+-
+-elif test $pkg_failed = untried; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+-
+- gadu_includes="no"
+-
+-else
+- GADU_CFLAGS=$pkg_cv_GADU_CFLAGS
+- GADU_LIBS=$pkg_cv_GADU_LIBS
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+-
+- gadu_includes="yes"
+- gadu_libs="yes"
+-
+-fi
+-else
+- if test "$ac_gadu_includes" != "no"; then
+- GADU_CFLAGS="-I$ac_gadu_includes"
+- fi
+- CPPFLAGS_save="$CPPFLAGS"
+- CPPFLAGS="$CPPFLAGS $GADU_CFLAGS"
+- ac_fn_c_check_header_mongrel "$LINENO" "libgadu.h" "ac_cv_header_libgadu_h" "$ac_includes_default"
+-if test "x$ac_cv_header_libgadu_h" = xyes; then :
+- gadu_includes=yes
+-fi
+-
+-
+- CPPFLAGS="$CPPFLAGS_save"
+-
+- if test "$ac_gadu_libs" != "no"; then
+- GADU_LIBS="-L$ac_gadu_libs"
+- fi
+- GADU_LIBS="$GADU_LIBS -lgadu"
+- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for gg_libgadu_version in -lgadu" >&5
+-$as_echo_n "checking for gg_libgadu_version in -lgadu... " >&6; }
+-if ${ac_cv_lib_gadu_gg_libgadu_version+:} false; then :
+- $as_echo_n "(cached) " >&6
+-else
+- ac_check_lib_save_LIBS=$LIBS
+-LIBS="-lgadu $GADU_LIBS $LIBS"
+-cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-
+-/* Override any GCC internal prototype to avoid an error.
+- Use char because int might match the return type of a GCC
+- builtin and then its argument prototype would still apply. */
+-#ifdef __cplusplus
+-extern "C"
+-#endif
+-char gg_libgadu_version ();
+-int
+-main ()
+-{
+-return gg_libgadu_version ();
+- ;
+- return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_link "$LINENO"; then :
+- ac_cv_lib_gadu_gg_libgadu_version=yes
+-else
+- ac_cv_lib_gadu_gg_libgadu_version=no
+-fi
+-rm -f core conftest.err conftest.$ac_objext \
+- conftest$ac_exeext conftest.$ac_ext
+-LIBS=$ac_check_lib_save_LIBS
+-fi
+-{ $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_gadu_gg_libgadu_version" >&5
+-$as_echo "$ac_cv_lib_gadu_gg_libgadu_version" >&6; }
+-if test "x$ac_cv_lib_gadu_gg_libgadu_version" = xyes; then :
+- gadu_libs=yes
+-fi
+-
+-fi
+-GADU_CFLAGS=`echo $GADU_CFLAGS |$sedpath 's/-Wall//'`
+-
+-if test "x$gadu_libs" = "xyes"; then
+- { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libgadu GPL compatibility" >&5
+-$as_echo_n "checking for libgadu GPL compatibility... " >&6; }
+- CPPFLAGS_save="$CPPFLAGS"
+- CPPFLAGS="$CPPFLAGS $GADU_CFLAGS"
+- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-#include <libgadu.h>
+-int
+-main ()
+-{
+-
+-#if defined(__GG_LIBGADU_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_OPENSSL)
+-#error "libgadu is not compatible with the GPL when compiled with OpenSSL support."
+-#endif
+-
+- ;
+- return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"; then :
+-
+- cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+-/* end confdefs.h. */
+-#include <libgadu.h>
+-int
+-main ()
+-{
+-
+-#if GG_DEFAULT_PROTOCOL_VERSION < 0x2e
+-#error "Your libgadu version is too old. libpurple requires 1.11.0 or higher."
+-#endif
+-
+- ;
+- return 0;
+-}
+-_ACEOF
+-if ac_fn_c_try_compile "$LINENO"; then :
+-
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
+-$as_echo "yes" >&6; }
+-
+-$as_echo "#define HAVE_LIBGADU 1" >>confdefs.h
+-
+-
+-else
+-
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+- echo
+- echo
+- echo "Your supplied copy of libgadu is too old."
+- echo "Install version 1.11.0 or newer."
+- echo "Then rerun this ./configure"
+- echo
+- echo "Falling back to using our own copy of libgadu"
+- echo
+- GADU_LIBS=""
+- GADU_CFLAGS=""
+- gadu_libs=no
+-
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+-
+-else
+-
+- { $as_echo "$as_me:${as_lineno-$LINENO}: result: no" >&5
+-$as_echo "no" >&6; }
+- echo
+- echo
+- echo "libgadu is not compatible with the GPL when compiled with OpenSSL support."
+- echo "To compile against system libgadu, please recompile libgadu using:"
+- echo "./autogen.sh --disable-libgadu-openssl --disable-static --enable-shared"
+- echo "Then rerun this ./configure"
+- echo
+- echo "Falling back to using our own copy of libgadu"
+- echo
+- GADU_LIBS=""
+- GADU_CFLAGS=""
+- gadu_libs=no
+-
+-fi
+-rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
+- CPPFLAGS="$CPPFLAGS_save"
+-fi
+-
+- if test "x$gadu_libs" != "xyes"; then
+- USE_INTERNAL_LIBGADU_TRUE=
+- USE_INTERNAL_LIBGADU_FALSE='#'
+-else
+- USE_INTERNAL_LIBGADU_TRUE='#'
+- USE_INTERNAL_LIBGADU_FALSE=
+-fi
+-
+-
+-if test "x$gadu_libs" = "x"; then
+- gadu_libs=no
+-fi
+-
+
+
+
+@@ -19500,10 +19100,7 @@
+ fi
+
+ if test "x$STATIC_PRPLS" = "xall" ; then
+- STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+-fi
+-if test "x$have_meanwhile" != "xyes" ; then
+- STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'`
++ STATIC_PRPLS="bonjour irc jabber silc simple zephyr"
+ fi
+ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then
+ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'`
+@@ -19519,46 +19116,22 @@
+ extern_init=
+ load_proto=
+ for i in $STATIC_PRPLS ; do
+- 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.la"
+- 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();"
+- elif test "x$i" = "xyahoo"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/yahoo/libymsg.la"
+- extern_init="$extern_init extern gboolean purple_init_yahoo_plugin();"
+- extern_init="$extern_init extern gboolean purple_init_yahoojp_plugin();"
+- load_proto="$load_proto purple_init_yahoo_plugin();"
+- load_proto="$load_proto purple_init_yahoojp_plugin();"
++ if test "x$i" = "xsilc"; then
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
++ elif test "x$i" = "xsilc10"; then
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la"
+ else
+- if test "x$i" = "xsilc"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
+- elif test "x$i" = "xsilc10"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la"
+- else
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
+- fi
+- extern_init="$extern_init extern gboolean purple_init_${i}_plugin();"
+- load_proto="$load_proto purple_init_${i}_plugin();"
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
+ 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 ;;
+ irc) static_irc=yes ;;
+ jabber) static_jabber=yes ;;
+- msn) static_msn=yes ;;
+- myspace) static_myspace=yes ;;
+- mxit) static_mxit=yes ;;
+- novell) static_novell=yes ;;
+- oscar) static_oscar=yes ;;
+- aim) static_oscar=yes ;;
+- icq) static_oscar=yes ;;
+- sametime) static_sametime=yes ;;
+ silc) static_silc=yes ;;
+ silc10) static_silc=yes ;;
+ simple) static_simple=yes ;;
+- yahoo) static_yahoo=yes ;;
+ zephyr) static_zephyr=yes ;;
+ *) echo "Invalid static protocol $i!!" ; exit 1 ;;
+ esac
+@@ -19571,14 +19144,6 @@
+ STATIC_BONJOUR_FALSE=
+ fi
+
+- if test "x$static_gg" = "xyes"; then
+- STATIC_GG_TRUE=
+- STATIC_GG_FALSE='#'
+-else
+- STATIC_GG_TRUE='#'
+- STATIC_GG_FALSE=
+-fi
+-
+ if test "x$static_irc" = "xyes"; then
+ STATIC_IRC_TRUE=
+ STATIC_IRC_FALSE='#'
+@@ -19595,54 +19160,6 @@
+ STATIC_JABBER_FALSE=
+ fi
+
+- if test "x$static_msn" = "xyes"; then
+- STATIC_MSN_TRUE=
+- STATIC_MSN_FALSE='#'
+-else
+- STATIC_MSN_TRUE='#'
+- STATIC_MSN_FALSE=
+-fi
+-
+- if test "x$static_myspace" = "xyes"; then
+- STATIC_MYSPACE_TRUE=
+- STATIC_MYSPACE_FALSE='#'
+-else
+- STATIC_MYSPACE_TRUE='#'
+- STATIC_MYSPACE_FALSE=
+-fi
+-
+- if test "x$static_mxit" = "xyes"; then
+- STATIC_MXIT_TRUE=
+- STATIC_MXIT_FALSE='#'
+-else
+- STATIC_MXIT_TRUE='#'
+- STATIC_MXIT_FALSE=
+-fi
+-
+- if test "x$static_novell" = "xyes"; then
+- STATIC_NOVELL_TRUE=
+- STATIC_NOVELL_FALSE='#'
+-else
+- STATIC_NOVELL_TRUE='#'
+- STATIC_NOVELL_FALSE=
+-fi
+-
+- if test "x$static_oscar" = "xyes"; then
+- STATIC_OSCAR_TRUE=
+- STATIC_OSCAR_FALSE='#'
+-else
+- STATIC_OSCAR_TRUE='#'
+- STATIC_OSCAR_FALSE=
+-fi
+-
+- if test "x$static_sametime" = "xyes" -a "x$have_meanwhile" = "xyes"; then
+- STATIC_SAMETIME_TRUE=
+- STATIC_SAMETIME_FALSE='#'
+-else
+- STATIC_SAMETIME_TRUE='#'
+- STATIC_SAMETIME_FALSE=
+-fi
+-
+ if test "x$static_silc" = "xyes" -a "x$have_silc" = "xyes"; then
+ STATIC_SILC_TRUE=
+ STATIC_SILC_FALSE='#'
+@@ -19659,14 +19176,6 @@
+ STATIC_SIMPLE_FALSE=
+ fi
+
+- if test "x$static_yahoo" = "xyes"; then
+- STATIC_YAHOO_TRUE=
+- STATIC_YAHOO_FALSE='#'
+-else
+- STATIC_YAHOO_TRUE='#'
+- STATIC_YAHOO_FALSE=
+-fi
+-
+ if test "x$static_zephyr" = "xyes"; then
+ STATIC_ZEPHYR_TRUE=
+ STATIC_ZEPHYR_FALSE='#'
+@@ -19689,10 +19198,7 @@
+ fi
+
+ if test "x$DYNAMIC_PRPLS" = "xall" ; then
+- DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+-fi
+-if test "x$have_meanwhile" != "xyes"; then
+- DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'`
++ DYNAMIC_PRPLS="bonjour irc jabber silc simple zephyr"
+ fi
+ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then
+ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'`
+@@ -19707,22 +19213,12 @@
+ for i in $DYNAMIC_PRPLS ; do
+ case $i in
+ bonjour) dynamic_bonjour=yes ;;
+- gg) dynamic_gg=yes ;;
+ irc) dynamic_irc=yes ;;
+ jabber) dynamic_jabber=yes ;;
+- msn) dynamic_msn=yes ;;
+- myspace) dynamic_myspace=yes ;;
+- mxit) dynamic_mxit=yes ;;
+- novell) dynamic_novell=yes ;;
+ null) dynamic_null=yes ;;
+- oscar) dynamic_oscar=yes ;;
+- aim) dynamic_oscar=yes ;;
+- icq) dynamic_oscar=yes ;;
+- sametime) dynamic_sametime=yes ;;
+ silc) dynamic_silc=yes ;;
+ silc10) dynamic_silc=yes ;;
+ simple) dynamic_simple=yes ;;
+- yahoo) dynamic_yahoo=yes ;;
+ zephyr) dynamic_zephyr=yes ;;
+ *) echo "Invalid dynamic protocol $i!!" ; exit 1 ;;
+ esac
+@@ -21001,7 +20497,7 @@
+ fi
+
+
+-msg_ssl="None. MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
++msg_ssl="None."
+ looked_for_gnutls="no"
+ if test "x$enable_gnutls" != "xno"; then
+ enable_gnutls="no"
+@@ -21871,19 +21367,17 @@
+ as_fn_error $? "
+ Neither GnuTLS or NSS SSL development headers found.
+ Use --disable-nss --disable-gnutls if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!
++
+ " "$LINENO" 5
+ elif test "x$looked_for_gnutls" = "xyes" -a "x$force_deps" = "xyes" ; then
+ as_fn_error $? "
+ GnuTLS SSL development headers not found.
+ Use --disable-gnutls if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+ " "$LINENO" 5
+ elif test "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then
+ as_fn_error $? "
+ NSS SSL development headers not found.
+ Use --disable-nss if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+ " "$LINENO" 5
+ fi
+
+@@ -23176,7 +22670,7 @@
+ fi
+
+
+-ac_config_files="$ac_config_files Makefile Doxyfile doc/Makefile doc/pidgin.1 doc/finch.1 m4macros/Makefile pidgin.apspec pidgin/Makefile pidgin/pidgin.pc pidgin/pidgin-uninstalled.pc pidgin/pidgin-2.pc pidgin/pidgin-2-uninstalled.pc pidgin/pixmaps/Makefile pidgin/pixmaps/emotes/default/24/Makefile pidgin/pixmaps/emotes/none/Makefile pidgin/pixmaps/emotes/small/16/Makefile pidgin/plugins/Makefile pidgin/plugins/cap/Makefile pidgin/plugins/disco/Makefile pidgin/plugins/gestures/Makefile pidgin/plugins/gevolution/Makefile pidgin/plugins/musicmessaging/Makefile pidgin/plugins/perl/Makefile pidgin/plugins/perl/common/Makefile.PL pidgin/plugins/ticker/Makefile libpurple/ciphers/Makefile libpurple/example/Makefile libpurple/gconf/Makefile libpurple/purple.pc libpurple/purple-uninstalled.pc libpurple/purple-2.pc libpurple/purple-2-uninstalled.pc libpurple/plugins/Makefile libpurple/plugins/mono/Makefile libpurple/plugins/mono/api/Makefile libpurple/plugins/mono/loader/Makefile libpurple/plugins/perl/Makefile libpurple/plugins/perl/common/Makefile.PL libpurple/plugins/ssl/Makefile libpurple/plugins/tcl/Makefile libpurple/Makefile libpurple/protocols/Makefile libpurple/protocols/bonjour/Makefile libpurple/protocols/gg/Makefile libpurple/protocols/irc/Makefile libpurple/protocols/jabber/Makefile libpurple/protocols/msn/Makefile libpurple/protocols/myspace/Makefile libpurple/protocols/mxit/Makefile libpurple/protocols/novell/Makefile libpurple/protocols/null/Makefile libpurple/protocols/oscar/Makefile libpurple/protocols/sametime/Makefile libpurple/protocols/silc/Makefile libpurple/protocols/silc10/Makefile libpurple/protocols/simple/Makefile libpurple/protocols/yahoo/Makefile libpurple/protocols/zephyr/Makefile libpurple/tests/Makefile libpurple/purple.h libpurple/version.h share/sounds/Makefile share/ca-certs/Makefile finch/finch.pc finch/Makefile finch/libgnt/Makefile finch/libgnt/gnt.pc finch/libgnt/wms/Makefile finch/plugins/Makefile po/Makefile.in pidgin.spec"
++ac_config_files="$ac_config_files Makefile Doxyfile doc/Makefile doc/pidgin.1 doc/finch.1 m4macros/Makefile pidgin.apspec pidgin/Makefile pidgin/pidgin.pc pidgin/pidgin-uninstalled.pc pidgin/pidgin-2.pc pidgin/pidgin-2-uninstalled.pc pidgin/pixmaps/Makefile pidgin/pixmaps/emotes/default/24/Makefile pidgin/pixmaps/emotes/none/Makefile pidgin/pixmaps/emotes/small/16/Makefile pidgin/plugins/Makefile pidgin/plugins/cap/Makefile pidgin/plugins/disco/Makefile pidgin/plugins/gestures/Makefile pidgin/plugins/gevolution/Makefile pidgin/plugins/musicmessaging/Makefile pidgin/plugins/perl/Makefile pidgin/plugins/perl/common/Makefile.PL pidgin/plugins/ticker/Makefile libpurple/ciphers/Makefile libpurple/example/Makefile libpurple/gconf/Makefile libpurple/purple.pc libpurple/purple-uninstalled.pc libpurple/purple-2.pc libpurple/purple-2-uninstalled.pc libpurple/plugins/Makefile libpurple/plugins/mono/Makefile libpurple/plugins/mono/api/Makefile libpurple/plugins/mono/loader/Makefile libpurple/plugins/perl/Makefile libpurple/plugins/perl/common/Makefile.PL libpurple/plugins/ssl/Makefile libpurple/plugins/tcl/Makefile libpurple/Makefile libpurple/protocols/Makefile libpurple/protocols/bonjour/Makefile libpurple/protocols/irc/Makefile libpurple/protocols/jabber/Makefile libpurple/protocols/null/Makefile libpurple/protocols/silc/Makefile libpurple/protocols/silc10/Makefile libpurple/protocols/simple/Makefile libpurple/protocols/zephyr/Makefile libpurple/tests/Makefile libpurple/purple.h libpurple/version.h share/sounds/Makefile share/ca-certs/Makefile finch/finch.pc finch/Makefile finch/libgnt/Makefile finch/libgnt/gnt.pc finch/libgnt/wms/Makefile finch/plugins/Makefile po/Makefile.in pidgin.spec"
+
+ cat >confcache <<\_ACEOF
+ # This file is a shell script that caches the results of configure
+@@ -23344,10 +22838,6 @@
+ as_fn_error $? "conditional \"USE_VV\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
+-if test -z "${USE_INTERNAL_LIBGADU_TRUE}" && test -z "${USE_INTERNAL_LIBGADU_FALSE}"; then
+- as_fn_error $? "conditional \"USE_INTERNAL_LIBGADU\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+ if test -z "${DISTRIB_TRUE}" && test -z "${DISTRIB_FALSE}"; then
+ as_fn_error $? "conditional \"DISTRIB\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+@@ -23356,10 +22846,6 @@
+ as_fn_error $? "conditional \"STATIC_BONJOUR\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
+-if test -z "${STATIC_GG_TRUE}" && test -z "${STATIC_GG_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_GG\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+ if test -z "${STATIC_IRC_TRUE}" && test -z "${STATIC_IRC_FALSE}"; then
+ as_fn_error $? "conditional \"STATIC_IRC\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+@@ -23368,30 +22854,6 @@
+ as_fn_error $? "conditional \"STATIC_JABBER\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
+-if test -z "${STATIC_MSN_TRUE}" && test -z "${STATIC_MSN_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_MSN\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+-if test -z "${STATIC_MYSPACE_TRUE}" && test -z "${STATIC_MYSPACE_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_MYSPACE\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+-if test -z "${STATIC_MXIT_TRUE}" && test -z "${STATIC_MXIT_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_MXIT\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+-if test -z "${STATIC_NOVELL_TRUE}" && test -z "${STATIC_NOVELL_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_NOVELL\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+-if test -z "${STATIC_OSCAR_TRUE}" && test -z "${STATIC_OSCAR_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_OSCAR\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+-if test -z "${STATIC_SAMETIME_TRUE}" && test -z "${STATIC_SAMETIME_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_SAMETIME\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+ if test -z "${STATIC_SILC_TRUE}" && test -z "${STATIC_SILC_FALSE}"; then
+ as_fn_error $? "conditional \"STATIC_SILC\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+@@ -23400,10 +22862,6 @@
+ as_fn_error $? "conditional \"STATIC_SIMPLE\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+ fi
+-if test -z "${STATIC_YAHOO_TRUE}" && test -z "${STATIC_YAHOO_FALSE}"; then
+- as_fn_error $? "conditional \"STATIC_YAHOO\" was never defined.
+-Usually this means the macro was only invoked conditionally." "$LINENO" 5
+-fi
+ if test -z "${STATIC_ZEPHYR_TRUE}" && test -z "${STATIC_ZEPHYR_FALSE}"; then
+ as_fn_error $? "conditional \"STATIC_ZEPHYR\" was never defined.
+ Usually this means the macro was only invoked conditionally." "$LINENO" 5
+@@ -24425,20 +23883,12 @@
+ "libpurple/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/Makefile" ;;
+ "libpurple/protocols/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/Makefile" ;;
+ "libpurple/protocols/bonjour/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/bonjour/Makefile" ;;
+- "libpurple/protocols/gg/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/gg/Makefile" ;;
+ "libpurple/protocols/irc/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/irc/Makefile" ;;
+ "libpurple/protocols/jabber/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/jabber/Makefile" ;;
+- "libpurple/protocols/msn/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/msn/Makefile" ;;
+- "libpurple/protocols/myspace/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/myspace/Makefile" ;;
+- "libpurple/protocols/mxit/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/mxit/Makefile" ;;
+- "libpurple/protocols/novell/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/novell/Makefile" ;;
+ "libpurple/protocols/null/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/null/Makefile" ;;
+- "libpurple/protocols/oscar/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/oscar/Makefile" ;;
+- "libpurple/protocols/sametime/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/sametime/Makefile" ;;
+ "libpurple/protocols/silc/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/silc/Makefile" ;;
+ "libpurple/protocols/silc10/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/silc10/Makefile" ;;
+ "libpurple/protocols/simple/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/simple/Makefile" ;;
+- "libpurple/protocols/yahoo/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/yahoo/Makefile" ;;
+ "libpurple/protocols/zephyr/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/protocols/zephyr/Makefile" ;;
+ "libpurple/tests/Makefile") CONFIG_FILES="$CONFIG_FILES libpurple/tests/Makefile" ;;
+ "libpurple/purple.h") CONFIG_FILES="$CONFIG_FILES libpurple/purple.h" ;;
+@@ -25863,7 +25313,6 @@
+ echo Build with Cyrus SASL support. : $enable_cyrus_sasl
+ echo Use kerberos 4 with zephyr.... : $kerberos
+ echo Use external libzephyr........ : $zephyr
+-echo Use external libgadu.......... : $gadu_libs
+ echo Install pixmaps............... : $enable_pixmaps
+ echo Old tray icon compatibility... : $enable_traycompat
+ echo Install translations.......... : $enable_i18n
+diff -Nur pidgin-2.10.7/configure.ac pidgin-2.10.7-nonprism/configure.ac
+--- pidgin-2.10.7/configure.ac 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/configure.ac 2013-08-16 23:44:41.800496326 -0300
+@@ -854,28 +854,6 @@
+ fi
+
+ dnl #######################################################################
+-dnl # Check for Meanwhile headers (for Sametime)
+-dnl #######################################################################
+-AC_ARG_ENABLE(meanwhile,
+- [AC_HELP_STRING([--disable-meanwhile],
+- [compile without meanwhile (required for Sametime support)])],
+- enable_meanwhile="$enableval", enable_meanwhile="yes")
+-if test "x$enable_meanwhile" = "xyes"; then
+- PKG_CHECK_MODULES(MEANWHILE, [meanwhile >= 1.0.0 meanwhile < 2.0.0], [
+- have_meanwhile="yes"
+- ], [
+- have_meanwhile="no"
+- if test "x$force_deps" = "xyes" ; then
+- AC_MSG_ERROR([
+-Meanwhile development headers not found.
+-Use --disable-meanwhile if you do not need meanwhile (Sametime) support.
+-])
+- fi])
+-fi
+-AC_SUBST(MEANWHILE_CFLAGS)
+-AC_SUBST(MEANWHILE_LIBS)
+-
+-dnl #######################################################################
+ dnl # Check for Native Avahi headers (for Bonjour)
+ dnl #######################################################################
+ AC_ARG_ENABLE(avahi,
+@@ -1020,100 +998,6 @@
+ CPPFLAGS="$CPPFLAGS_save"
+ fi
+
+-dnl #######################################################################
+-dnl # Check for Gadu-Gadu client includes and libraries
+-dnl #######################################################################
+-AC_ARG_WITH(gadu-includes, [AC_HELP_STRING([--with-gadu-includes=DIR], [compile the Gadu-Gadu plugin against includes in DIR])], [ac_gadu_includes="$withval"], [ac_gadu_includes="no"])
+-AC_ARG_WITH(gadu-libs, [AC_HELP_STRING([--with-gadu-libs=DIR], [compile the Gadu-Gadu plugin against the libs in DIR])], [ac_gadu_libs="$withval"], [ac_gadu_libs="no"])
+-GADU_CFLAGS=""
+-GADU_LIBS=""
+-if test -n "$with_gadu_includes" || test -n "$with_gadu_libs"; then
+- gadu_manual_check="yes"
+-else
+- gadu_manual_check="no"
+-fi
+-if test "x$gadu_manual_check" = "xno"; then
+- PKG_CHECK_MODULES(GADU, [libgadu >= 1.11.0], [
+- gadu_includes="yes"
+- gadu_libs="yes"
+- ], [
+- gadu_includes="no"
+- ])
+-else
+- if test "$ac_gadu_includes" != "no"; then
+- GADU_CFLAGS="-I$ac_gadu_includes"
+- fi
+- CPPFLAGS_save="$CPPFLAGS"
+- CPPFLAGS="$CPPFLAGS $GADU_CFLAGS"
+- AC_CHECK_HEADER(libgadu.h, [gadu_includes=yes])
+- CPPFLAGS="$CPPFLAGS_save"
+-
+- if test "$ac_gadu_libs" != "no"; then
+- GADU_LIBS="-L$ac_gadu_libs"
+- fi
+- GADU_LIBS="$GADU_LIBS -lgadu"
+- AC_CHECK_LIB(gadu, gg_libgadu_version, [gadu_libs=yes], , $GADU_LIBS)
+-fi
+-GADU_CFLAGS=`echo $GADU_CFLAGS |$sedpath 's/-Wall//'`
+-
+-if test "x$gadu_libs" = "xyes"; then
+- AC_MSG_CHECKING(for libgadu GPL compatibility)
+- CPPFLAGS_save="$CPPFLAGS"
+- CPPFLAGS="$CPPFLAGS $GADU_CFLAGS"
+- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[
+-#if defined(__GG_LIBGADU_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_OPENSSL)
+-#error "libgadu is not compatible with the GPL when compiled with OpenSSL support."
+-#endif
+- ]])], [
+- AC_COMPILE_IFELSE([AC_LANG_PROGRAM([[#include <libgadu.h>]], [[
+-#if GG_DEFAULT_PROTOCOL_VERSION < 0x2e
+-#error "Your libgadu version is too old. libpurple requires 1.11.0 or higher."
+-#endif
+- ]])], [
+- AC_MSG_RESULT(yes)
+- AC_DEFINE([HAVE_LIBGADU], [1],
+- [Define to 1 if you have libgadu.])
+- ], [
+- AC_MSG_RESULT(no)
+- echo
+- echo
+- echo "Your supplied copy of libgadu is too old."
+- echo "Install version 1.11.0 or newer."
+- echo "Then rerun this ./configure"
+- echo
+- echo "Falling back to using our own copy of libgadu"
+- echo
+- GADU_LIBS=""
+- GADU_CFLAGS=""
+- gadu_libs=no
+- ])
+- ], [
+- AC_MSG_RESULT(no)
+- echo
+- echo
+- echo "libgadu is not compatible with the GPL when compiled with OpenSSL support."
+- echo "To compile against system libgadu, please recompile libgadu using:"
+- echo "./autogen.sh --disable-libgadu-openssl --disable-static --enable-shared"
+- echo "Then rerun this ./configure"
+- echo
+- echo "Falling back to using our own copy of libgadu"
+- echo
+- GADU_LIBS=""
+- GADU_CFLAGS=""
+- gadu_libs=no
+- ])
+- CPPFLAGS="$CPPFLAGS_save"
+-fi
+-
+-AM_CONDITIONAL(USE_INTERNAL_LIBGADU, test "x$gadu_libs" != "xyes")
+-
+-if test "x$gadu_libs" = "x"; then
+- gadu_libs=no
+-fi
+-
+-AC_SUBST(GADU_LIBS)
+-AC_SUBST(GADU_CFLAGS)
+-
+ AC_ARG_ENABLE(distrib,,,enable_distrib=no)
+ AM_CONDITIONAL(DISTRIB, test "x$enable_distrib" = "xyes")
+ DYNAMIC_PRPLS=all
+@@ -1123,10 +1007,7 @@
+ fi
+
+ if test "x$STATIC_PRPLS" = "xall" ; then
+- STATIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+-fi
+-if test "x$have_meanwhile" != "xyes" ; then
+- STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/sametime//'`
++ STATIC_PRPLS="bonjour irc jabber silc simple zephyr"
+ fi
+ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then
+ STATIC_PRPLS=`echo $STATIC_PRPLS | $sedpath 's/bonjour//'`
+@@ -1143,64 +1024,31 @@
+ load_proto=
+ for i in $STATIC_PRPLS ; do
+ dnl Ugly special case for "libsilcpurple.la":
+- dnl ... and Ugly special case for multi-protocol oscar and yahoo
+- 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.la"
+- 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();"
+- elif test "x$i" = "xyahoo"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/yahoo/libymsg.la"
+- extern_init="$extern_init extern gboolean purple_init_yahoo_plugin();"
+- extern_init="$extern_init extern gboolean purple_init_yahoojp_plugin();"
+- load_proto="$load_proto purple_init_yahoo_plugin();"
+- load_proto="$load_proto purple_init_yahoojp_plugin();"
++ if test "x$i" = "xsilc"; then
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
++ elif test "x$i" = "xsilc10"; then
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la"
+ else
+- if test "x$i" = "xsilc"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib${i}purple.la"
+- elif test "x$i" = "xsilc10"; then
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/libsilcpurple.la"
+- else
+- STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
+- fi
+- extern_init="$extern_init extern gboolean purple_init_${i}_plugin();"
+- load_proto="$load_proto purple_init_${i}_plugin();"
++ STATIC_LINK_LIBS="$STATIC_LINK_LIBS \$(top_builddir)/libpurple/protocols/$i/lib$i.la"
+ 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 ;;
+ irc) static_irc=yes ;;
+ jabber) static_jabber=yes ;;
+- msn) static_msn=yes ;;
+- myspace) static_myspace=yes ;;
+- mxit) static_mxit=yes ;;
+- novell) static_novell=yes ;;
+- oscar) static_oscar=yes ;;
+- aim) static_oscar=yes ;;
+- icq) static_oscar=yes ;;
+- sametime) static_sametime=yes ;;
+ silc) static_silc=yes ;;
+ silc10) static_silc=yes ;;
+ simple) static_simple=yes ;;
+- yahoo) static_yahoo=yes ;;
+ zephyr) static_zephyr=yes ;;
+ *) echo "Invalid static protocol $i!!" ; exit 1 ;;
+ esac
+ done
+ AM_CONDITIONAL(STATIC_BONJOUR, test "x$static_bonjour" = "xyes")
+-AM_CONDITIONAL(STATIC_GG, test "x$static_gg" = "xyes")
+ AM_CONDITIONAL(STATIC_IRC, test "x$static_irc" = "xyes")
+ AM_CONDITIONAL(STATIC_JABBER, test "x$static_jabber" = "xyes")
+-AM_CONDITIONAL(STATIC_MSN, test "x$static_msn" = "xyes")
+-AM_CONDITIONAL(STATIC_MYSPACE, test "x$static_myspace" = "xyes")
+-AM_CONDITIONAL(STATIC_MXIT, test "x$static_mxit" = "xyes")
+-AM_CONDITIONAL(STATIC_NOVELL, test "x$static_novell" = "xyes")
+-AM_CONDITIONAL(STATIC_OSCAR, test "x$static_oscar" = "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$have_silc" = "xyes")
+ AM_CONDITIONAL(STATIC_SIMPLE, test "x$static_simple" = "xyes")
+-AM_CONDITIONAL(STATIC_YAHOO, test "x$static_yahoo" = "xyes")
+ AM_CONDITIONAL(STATIC_ZEPHYR, test "x$static_zephyr" = "xyes")
+ AC_SUBST(STATIC_LINK_LIBS)
+ AC_DEFINE_UNQUOTED(STATIC_PROTO_INIT, $extern_init static void static_proto_init(void) { $load_proto },
+@@ -1208,10 +1056,7 @@
+
+ AC_ARG_WITH(dynamic_prpls, [AC_HELP_STRING([--with-dynamic-prpls], [specify which protocols to build dynamically])], [DYNAMIC_PRPLS=`echo $withval | $sedpath 's/,/ /g'`])
+ if test "x$DYNAMIC_PRPLS" = "xall" ; then
+- DYNAMIC_PRPLS="bonjour gg irc jabber msn myspace mxit novell oscar sametime silc simple yahoo zephyr"
+-fi
+-if test "x$have_meanwhile" != "xyes"; then
+- DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/sametime//'`
++ DYNAMIC_PRPLS="bonjour irc jabber silc simple zephyr"
+ fi
+ if test "x$avahiincludes" != "xyes" -o "x$avahilibs" != "xyes"; then
+ DYNAMIC_PRPLS=`echo $DYNAMIC_PRPLS | $sedpath 's/bonjour//'`
+@@ -1226,22 +1071,12 @@
+ for i in $DYNAMIC_PRPLS ; do
+ case $i in
+ bonjour) dynamic_bonjour=yes ;;
+- gg) dynamic_gg=yes ;;
+ irc) dynamic_irc=yes ;;
+ jabber) dynamic_jabber=yes ;;
+- msn) dynamic_msn=yes ;;
+- myspace) dynamic_myspace=yes ;;
+- mxit) dynamic_mxit=yes ;;
+- novell) dynamic_novell=yes ;;
+ null) dynamic_null=yes ;;
+- oscar) dynamic_oscar=yes ;;
+- aim) dynamic_oscar=yes ;;
+- icq) dynamic_oscar=yes ;;
+- sametime) dynamic_sametime=yes ;;
+ silc) dynamic_silc=yes ;;
+ silc10) dynamic_silc=yes ;;
+ simple) dynamic_simple=yes ;;
+- yahoo) dynamic_yahoo=yes ;;
+ zephyr) dynamic_zephyr=yes ;;
+ *) echo "Invalid dynamic protocol $i!!" ; exit 1 ;;
+ esac
+@@ -1713,7 +1548,7 @@
+ [enable_nss="$enableval"],
+ [enable_nss="yes"])
+
+-msg_ssl="None. MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!"
++msg_ssl="None."
+ looked_for_gnutls="no"
+ dnl #
+ dnl # Check for GnuTLS if it's specified.
+@@ -2124,19 +1959,16 @@
+ AC_MSG_ERROR([
+ Neither GnuTLS or NSS SSL development headers found.
+ Use --disable-nss --disable-gnutls if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without GnuTLS or NSS. OpenSSL is NOT usable!
+ ])
+ elif test "x$looked_for_gnutls" = "xyes" -a "x$force_deps" = "xyes" ; then
+ AC_MSG_ERROR([
+ GnuTLS SSL development headers not found.
+ Use --disable-gnutls if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+ ])
+ elif test "x$looked_for_nss" = "xyes" -a "x$force_deps" = "xyes" ; then
+ AC_MSG_ERROR([
+ NSS SSL development headers not found.
+ Use --disable-nss if you do not need SSL support.
+-MSN, Yahoo!, Novell Groupwise and Google Talk will not work without SSL support.
+ ])
+ fi
+
+@@ -2577,20 +2409,12 @@
+ libpurple/Makefile
+ libpurple/protocols/Makefile
+ libpurple/protocols/bonjour/Makefile
+- libpurple/protocols/gg/Makefile
+ libpurple/protocols/irc/Makefile
+ libpurple/protocols/jabber/Makefile
+- libpurple/protocols/msn/Makefile
+- libpurple/protocols/myspace/Makefile
+- libpurple/protocols/mxit/Makefile
+- libpurple/protocols/novell/Makefile
+ libpurple/protocols/null/Makefile
+- libpurple/protocols/oscar/Makefile
+- libpurple/protocols/sametime/Makefile
+ libpurple/protocols/silc/Makefile
+ libpurple/protocols/silc10/Makefile
+ libpurple/protocols/simple/Makefile
+- libpurple/protocols/yahoo/Makefile
+ libpurple/protocols/zephyr/Makefile
+ libpurple/tests/Makefile
+ libpurple/purple.h
+@@ -2635,7 +2459,6 @@
+ echo Build with Cyrus SASL support. : $enable_cyrus_sasl
+ echo Use kerberos 4 with zephyr.... : $kerberos
+ echo Use external libzephyr........ : $zephyr
+-echo Use external libgadu.......... : $gadu_libs
+ echo Install pixmaps............... : $enable_pixmaps
+ echo Old tray icon compatibility... : $enable_traycompat
+ echo Install translations.......... : $enable_i18n
+diff -Nur pidgin-2.10.7/doc/finch.1.in pidgin-2.10.7-nonprism/doc/finch.1.in
+--- pidgin-2.10.7/doc/finch.1.in 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/doc/finch.1.in 2013-08-16 21:01:16.682280145 -0300
+@@ -30,11 +30,8 @@
+ .SH DESCRIPTION
+ .PP
+ \fBfinch\fR is a console-based modular messaging client based on libpurple
+-which is capable of connecting to AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC,
+-Novell GroupWise, Lotus Sametime, Zephyr, Gadu-Gadu, and QQ all at once. It has
++which is capable of connecting to XMPP, IRC, SILC and Zephyr all at once. It has
+ many common features found in other clients, as well as many unique features.
+-Finch is not endorsed by or affiliated with America Online, ICQ, Microsoft, or
+-Yahoo.
+
+ .SH OPTIONS
+ The following options are provided by \fBfinch\fR using the standard GNU
+diff -Nur pidgin-2.10.7/doc/funniest_home_convos.txt pidgin-2.10.7-nonprism/doc/funniest_home_convos.txt
+--- pidgin-2.10.7/doc/funniest_home_convos.txt 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/doc/funniest_home_convos.txt 2013-08-16 23:08:16.148841464 -0300
+@@ -301,8 +301,6 @@
+ ---
+
+ 18:33:26 <NoName> hello there
+-18:34:03 <NoName> I just wanted to share some bevavior that I think its kinda of
+- unsafe when using GAIM with yahoo messenges accounts
+ 18:34:43 <NoName> Whenever you transfer files between users, no receiving
+ confirmation is requested, the file gets transfered
+ automatically
+diff -Nur pidgin-2.10.7/doc/Makefile.in pidgin-2.10.7-nonprism/doc/Makefile.in
+--- pidgin-2.10.7/doc/Makefile.in 2013-02-11 07:17:17.000000000 -0200
++++ pidgin-2.10.7-nonprism/doc/Makefile.in 2013-08-17 00:02:41.026999785 -0300
+@@ -155,8 +155,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -218,8 +216,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/doc/pidgin.1.in pidgin-2.10.7-nonprism/doc/pidgin.1.in
+--- pidgin-2.10.7/doc/pidgin.1.in 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/doc/pidgin.1.in 2013-08-16 21:00:30.964181946 -0300
+@@ -29,11 +29,8 @@
+ .SH DESCRIPTION
+ .PP
+ \fBpidgin\fR is a graphical modular messaging client based on libpurple
+-which is capable of connecting to AIM, MSN, Yahoo!, XMPP, ICQ, IRC, SILC,
+-Novell GroupWise, Lotus Sametime, Zephyr, Gadu-Gadu, and QQ all at once. It has
++which is capable of connecting to XMPP, IRC, SILC and Zephyr all at once. It has
+ many common features found in other clients, as well as many unique features.
+-Pidgin is not endorsed by or affiliated with America Online, ICQ, Microsoft, or
+-Yahoo.
+ .PP
+ Pidgin can be extended by plugins written in multiple programming languages and
+ controlled through DBus or \fBpurple-remote\fR.
+diff -Nur pidgin-2.10.7/finch/libgnt/Makefile.in pidgin-2.10.7-nonprism/finch/libgnt/Makefile.in
+--- pidgin-2.10.7/finch/libgnt/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/finch/libgnt/Makefile.in 2013-08-16 23:49:33.762819097 -0300
+@@ -233,8 +233,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -296,8 +294,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/finch/libgnt/wms/Makefile.in pidgin-2.10.7-nonprism/finch/libgnt/wms/Makefile.in
+--- pidgin-2.10.7/finch/libgnt/wms/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/finch/libgnt/wms/Makefile.in 2013-08-16 23:49:49.779979208 -0300
+@@ -191,8 +191,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -254,8 +252,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/finch/Makefile.in pidgin-2.10.7-nonprism/finch/Makefile.in
+--- pidgin-2.10.7/finch/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/finch/Makefile.in 2013-08-16 23:49:15.322251029 -0300
+@@ -233,8 +233,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -296,8 +294,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/finch/plugins/Makefile.in pidgin-2.10.7-nonprism/finch/plugins/Makefile.in
+--- pidgin-2.10.7/finch/plugins/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/finch/plugins/Makefile.in 2013-08-16 23:50:13.010694932 -0300
+@@ -237,8 +237,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -300,8 +298,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/account.c pidgin-2.10.7-nonprism/libpurple/account.c
+--- pidgin-2.10.7/libpurple/account.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/account.c 2013-08-16 23:31:48.026518940 -0300
+@@ -482,55 +482,6 @@
+ /*********************************************************************
+ * Reading from disk *
+ *********************************************************************/
+-static void
+-migrate_yahoo_japan(PurpleAccount *account)
+-{
+- /* detect a Yahoo! JAPAN account that existed prior to 2.6.0 and convert it
+- * to use the new prpl-yahoojp. Also remove the account-specific settings
+- * we no longer need */
+-
+- if(purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoo")) {
+- if(purple_account_get_bool(account, "yahoojp", FALSE)) {
+- const char *serverjp = purple_account_get_string(account, "serverjp", NULL);
+- const char *xferjp_host = purple_account_get_string(account, "xferjp_host", NULL);
+-
+- g_return_if_fail(serverjp != NULL);
+- g_return_if_fail(xferjp_host != NULL);
+-
+- purple_account_set_string(account, "server", serverjp);
+- purple_account_set_string(account, "xfer_host", xferjp_host);
+-
+- purple_account_set_protocol_id(account, "prpl-yahoojp");
+- }
+-
+- /* these should always be nuked */
+- purple_account_remove_setting(account, "yahoojp");
+- purple_account_remove_setting(account, "serverjp");
+- purple_account_remove_setting(account, "xferjp_host");
+-
+- }
+-}
+-
+-static void
+-migrate_icq_server(PurpleAccount *account)
+-{
+- /* Migrate the login server setting for ICQ accounts. See
+- * 'mtn log --last 1 --no-graph --from b6d7712e90b68610df3bd2d8cbaf46d94c8b3794'
+- * for details on the change. */
+-
+- if(purple_strequal(purple_account_get_protocol_id(account), "prpl-icq")) {
+- const char *tmp = purple_account_get_string(account, "server", NULL);
+-
+- /* Non-secure server */
+- if(purple_strequal(tmp, "login.messaging.aol.com") ||
+- purple_strequal(tmp, "login.oscar.aol.com"))
+- purple_account_set_string(account, "server", "login.icq.com");
+-
+- /* Secure server */
+- if(purple_strequal(tmp, "slogin.oscar.aol.com"))
+- purple_account_set_string(account, "server", "slogin.icq.com");
+- }
+-}
+
+ static void
+ migrate_xmpp_encryption(PurpleAccount *account)
+@@ -615,12 +566,6 @@
+ g_free(data);
+ }
+
+- /* we do this here because we need access to account settings to determine
+- * if we can/should migrate an old Yahoo! JAPAN account */
+- migrate_yahoo_japan(account);
+- /* we do this here because we need access to account settings to determine
+- * if we can/should migrate an ICQ account's server setting */
+- migrate_icq_server(account);
+ /* we do this here because we need to do it before the user views the
+ * Edit Account dialog. */
+ migrate_xmpp_encryption(account);
+@@ -874,7 +819,6 @@
+ return NULL;
+ }
+
+- ret = purple_account_new(name, _purple_oscar_convert(name, protocol_id)); /* XXX: */
+ g_free(name);
+ g_free(protocol_id);
+
+diff -Nur pidgin-2.10.7/libpurple/blist.c pidgin-2.10.7-nonprism/libpurple/blist.c
+--- pidgin-2.10.7/libpurple/blist.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/blist.c 2013-08-16 22:53:19.640535242 -0300
+@@ -466,9 +466,7 @@
+
+ acct_name = xmlnode_get_attrib(bnode, "account");
+ protocol = xmlnode_get_attrib(bnode, "protocol");
+- protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */
+ proto = xmlnode_get_attrib(bnode, "proto");
+- proto = _purple_oscar_convert(acct_name, proto); /* XXX: Remove */
+
+ if (!acct_name || (!proto && !protocol))
+ return;
+@@ -967,10 +965,6 @@
+ purple_blist_update_node_icon((PurpleBlistNode *)buddy);
+ }
+
+-/*
+- * TODO: Maybe remove the call to this from server.c and call it
+- * from oscar.c and toc.c instead?
+- */
+ void purple_blist_rename_buddy(PurpleBuddy *buddy, const char *name)
+ {
+ PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
+diff -Nur pidgin-2.10.7/libpurple/buddyicon.c pidgin-2.10.7-nonprism/libpurple/buddyicon.c
+--- pidgin-2.10.7/libpurple/buddyicon.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/buddyicon.c 2013-08-16 23:28:49.244233493 -0300
+@@ -1099,18 +1099,6 @@
+ {
+ PurpleAccount *account = purple_buddy_get_account((PurpleBuddy *)node);
+ const char *prpl_id = purple_account_get_protocol_id(account);
+-
+- if (g_str_equal(prpl_id, "prpl-yahoo") || g_str_equal(prpl_id, "prpl-yahoojp"))
+- {
+- int checksum = purple_blist_node_get_int(node, "icon_checksum");
+- if (checksum != 0)
+- {
+- char *checksum_str = g_strdup_printf("%i", checksum);
+- purple_blist_node_remove_setting(node, "icon_checksum");
+- purple_blist_node_set_string(node, "icon_checksum", checksum_str);
+- g_free(checksum_str);
+- }
+- }
+ }
+ }
+ }
+diff -Nur pidgin-2.10.7/libpurple/certificate.c pidgin-2.10.7-nonprism/libpurple/certificate.c
+--- pidgin-2.10.7/libpurple/certificate.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/certificate.c 2013-08-17 00:24:11.603381489 -0300
+@@ -108,7 +108,7 @@
+ "and time are accurate.");
+ break;
+ case PURPLE_CERTIFICATE_NAME_MISMATCH:
+- /* Translators: "domain" refers to a DNS domain (e.g. talk.google.com) */
++ /* Translators: "domain" refers to a DNS domain */
+ return _("The certificate presented is not issued to this domain.");
+ break;
+ case PURPLE_CERTIFICATE_NO_CA_POOL:
+diff -Nur pidgin-2.10.7/libpurple/ciphers/Makefile.in pidgin-2.10.7-nonprism/libpurple/ciphers/Makefile.in
+--- pidgin-2.10.7/libpurple/ciphers/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/ciphers/Makefile.in 2013-08-16 23:52:56.489066605 -0300
+@@ -152,8 +152,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -215,8 +213,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/example/Makefile.in pidgin-2.10.7-nonprism/libpurple/example/Makefile.in
+--- pidgin-2.10.7/libpurple/example/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/example/Makefile.in 2013-08-16 23:52:31.591632423 -0300
+@@ -155,8 +155,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -218,8 +216,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/ft.h pidgin-2.10.7-nonprism/libpurple/ft.h
+--- pidgin-2.10.7/libpurple/ft.h 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/ft.h 2013-08-16 22:51:20.590085226 -0300
+@@ -470,8 +470,6 @@
+ * can be used to jump backward in the file if the protocol detects
+ * that some bit of data needs to be resent or has been sent twice.
+ *
+- * It's used for pausing and resuming an oscar file transfer.
+- *
+ * @param xfer The file transfer.
+ * @param bytes_sent The new current position in the file. If we're
+ * sending a file then this is the byte that we will
+diff -Nur pidgin-2.10.7/libpurple/gaim-compat.h pidgin-2.10.7-nonprism/libpurple/gaim-compat.h
+--- pidgin-2.10.7/libpurple/gaim-compat.h 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/gaim-compat.h 2013-08-16 23:33:16.372629159 -0300
+@@ -2302,16 +2302,8 @@
+ #define gaim_init_ssl_plugin purple_init_ssl_plugin
+ #define gaim_init_ssl_openssl_plugin purple_init_ssl_openssl_plugin
+ #define gaim_init_ssl_gnutls_plugin purple_init_ssl_gnutls_plugin
+-#define gaim_init_gg_plugin purple_init_gg_plugin
+ #define gaim_init_jabber_plugin purple_init_jabber_plugin
+-#define gaim_init_sametime_plugin purple_init_sametime_plugin
+-#define gaim_init_msn_plugin purple_init_msn_plugin
+-#define gaim_init_novell_plugin purple_init_novell_plugin
+-#define gaim_init_qq_plugin purple_init_qq_plugin
+ #define gaim_init_simple_plugin purple_init_simple_plugin
+-#define gaim_init_yahoo_plugin purple_init_yahoo_plugin
+ #define gaim_init_zephyr_plugin purple_init_zephyr_plugin
+-#define gaim_init_aim_plugin purple_init_aim_plugin
+-#define gaim_init_icq_plugin purple_init_icq_plugin
+
+ #endif /* _GAIM_COMPAT_H_ */
+diff -Nur pidgin-2.10.7/libpurple/gconf/Makefile.in pidgin-2.10.7-nonprism/libpurple/gconf/Makefile.in
+--- pidgin-2.10.7/libpurple/gconf/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/gconf/Makefile.in 2013-08-16 23:53:07.209397103 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/internal.h pidgin-2.10.7-nonprism/libpurple/internal.h
+--- pidgin-2.10.7/libpurple/internal.h 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/internal.h 2013-08-17 00:24:37.244172407 -0300
+@@ -43,7 +43,7 @@
+ *
+ * The Singular/Plural/Number ngettext dummy definition below was
+ * taken from an email to the texinfo mailing list by Manuel Guerrero.
+- * Thank you Manuel, and thank you Alex's good friend Google.
++ * Thank you Manuel.
+ */
+ #ifdef ENABLE_NLS
+ # include <locale.h>
+diff -Nur pidgin-2.10.7/libpurple/Makefile.in pidgin-2.10.7-nonprism/libpurple/Makefile.in
+--- pidgin-2.10.7/libpurple/Makefile.in 2013-02-11 07:17:18.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/Makefile.in 2013-08-16 23:52:14.487771867 -0300
+@@ -302,8 +302,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -365,8 +363,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/Makefile.mingw
+--- pidgin-2.10.7/libpurple/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,169 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libpurple
+-#
+-
+-PIDGIN_TREE_TOP := ..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libpurple
+-NEEDED_DLLS = $(LIBXML2_TOP)/bin/libxml2-2.dll
+-
+-ifeq ($(CYRUS_SASL), 1)
+-NEEDED_DLLS += $(CYRUS_SASL_TOP)/bin/libsasl.dll
+-
+-CYRUS_SASL_PLUGINS = \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslANONYMOUS.dll \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslCRAMMD5.dll \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslDIGESTMD5.dll \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslGSSAPI.dll \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslLOGIN.dll \
+- $(CYRUS_SASL_TOP)/bin/sasl2/saslPLAIN.dll
+-
+-endif
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(LIBXML2_TOP)/include/libxml2
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(LIBXML2_TOP)/lib
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = \
+- account.c \
+- accountopt.c \
+- blist.c \
+- buddyicon.c \
+- certificate.c \
+- cipher.c \
+- ciphers/des.c \
+- ciphers/gchecksum.c \
+- ciphers/hmac.c \
+- ciphers/md4.c \
+- ciphers/md5.c \
+- ciphers/rc4.c \
+- ciphers/sha1.c \
+- ciphers/sha256.c \
+- circbuffer.c \
+- cmds.c \
+- connection.c \
+- conversation.c \
+- core.c \
+- debug.c \
+- dnsquery.c \
+- dnssrv.c \
+- eventloop.c \
+- ft.c \
+- idle.c \
+- imgstore.c \
+- log.c \
+- mediamanager.c \
+- media.c \
+- mime.c \
+- nat-pmp.c \
+- network.c \
+- notify.c \
+- ntlm.c \
+- plugin.c \
+- pluginpref.c \
+- pounce.c \
+- prefs.c \
+- privacy.c \
+- proxy.c \
+- prpl.c \
+- request.c \
+- roomlist.c \
+- savedstatuses.c \
+- server.c \
+- signals.c \
+- smiley.c \
+- sound-theme-loader.c \
+- sound-theme.c \
+- sound.c \
+- sslconn.c \
+- status.c \
+- stringref.c \
+- stun.c \
+- theme-loader.c \
+- theme-manager.c \
+- theme.c \
+- upnp.c \
+- util.c \
+- value.c \
+- version.c \
+- whiteboard.c \
+- xmlnode.c \
+- win32/giowin32.c \
+- win32/libc_interface.c \
+- win32/win32dep.c
+-
+-RC_SRC = win32/libpurplerc.rc
+-
+-OBJECTS = $(C_SRC:%.c=%.o) $(RC_SRC:%.rc=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lgthread-2.0 \
+- -lgobject-2.0 \
+- -lgmodule-2.0 \
+- -lintl \
+- -lws2_32 \
+- -lxml2
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install install_shallow clean
+-
+-all: $(TARGET).dll
+- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE)
+-
+-install_shallow: $(PURPLE_INSTALL_DIR) $(TARGET).dll
+- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
+- cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
+-ifeq ($(CYRUS_SASL), 1)
+- mkdir -p $(PURPLE_INSTALL_DIR)/sasl2
+- cp $(CYRUS_SASL_PLUGINS) $(PURPLE_INSTALL_DIR)/sasl2
+-endif
+-
+-install: install_shallow all
+- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) install
+-
+-./win32/libpurplerc.rc: ./win32/libpurplerc.rc.in $(PIDGIN_TREE_TOP)/VERSION
+- sed -e 's/@PURPLE_VERSION@/$(PURPLE_VERSION)/g' \
+- $@.in > $@
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H)
+-
+-$(TARGET).dll $(TARGET).dll.a: $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS) $(RC_SRC) $(PURPLE_VERSION_H) $(PURPLE_PURPLE_H)
+- rm -f $(TARGET).dll $(TARGET).dll.a $(TARGET).def
+- $(MAKE) -C $(PURPLE_PROTOS_TOP) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(PURPLE_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/media/backend-fs2.c pidgin-2.10.7-nonprism/libpurple/media/backend-fs2.c
+--- pidgin-2.10.7/libpurple/media/backend-fs2.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/media/backend-fs2.c 2013-08-17 00:23:19.488440821 -0300
+@@ -1661,18 +1661,6 @@
+ g_object_set(G_OBJECT(session->session),
+ "no-rtcp-timeout", 0, NULL);
+
+- /*
+- * Hack to make x264 work with Gmail video.
+- */
+- if (is_nice && !strcmp(sess_id, "google-video")) {
+- FsElementAddedNotifier *notifier =
+- fs_element_added_notifier_new();
+- g_signal_connect(G_OBJECT(notifier), "element-added",
+- G_CALLBACK(gst_element_added_cb), NULL);
+- fs_element_added_notifier_add(notifier,
+- GST_BIN(priv->conference));
+- }
+-
+ session->id = g_strdup(sess_id);
+ session->backend = self;
+ session->type = type;
+diff -Nur pidgin-2.10.7/libpurple/plugins/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.in 2013-08-16 23:53:13.792933405 -0300
+@@ -406,8 +406,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -469,8 +467,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.mingw
+--- pidgin-2.10.7/libpurple/plugins/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,82 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libpurple Plugins
+-#
+-
+-PIDGIN_TREE_TOP := ../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-PERL_PLUGIN := ./perl
+-TCL_PLUGIN := ./tcl
+-SSL_PLUGIN := ./ssl
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .dll
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lgobject-2.0 \
+- -lgmodule-2.0 \
+- -lintl \
+- -lws2_32 \
+- -lpurple
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all clean plugins install
+-
+-all: $(PURPLE_DLL).a plugins
+- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE)
+-
+-install: all $(PURPLE_INSTALL_PLUGINS_DIR)
+- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) install
+- cp *.dll $(PURPLE_INSTALL_PLUGINS_DIR)
+-
+-%.dll: %.c $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H)
+- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@.o -c $<
+- $(CC) -shared $@.o $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
+-
+-plugins: \
+- autoaccept.dll \
+- buddynote.dll \
+- idle.dll \
+- joinpart.dll \
+- log_reader.dll \
+- newline.dll \
+- offlinemsg.dll \
+- psychic.dll \
+- statenotify.dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f *.o *.dll
+- $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(TCL_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) clean
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/plugins/mono/api/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/api/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/mono/api/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/api/Makefile.in 2013-08-17 00:05:58.593066418 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/loader/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/loader/Makefile.in 2013-08-17 00:06:17.736987877 -0300
+@@ -184,8 +184,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -247,8 +245,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/mono/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/mono/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/mono/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/mono/Makefile.in 2013-08-16 23:53:49.027353090 -0300
+@@ -191,8 +191,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -254,8 +252,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/perl/common/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/perl/common/Makefile.mingw
+--- pidgin-2.10.7/libpurple/plugins/perl/common/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/common/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,124 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for Purple perl module.
+-#
+-
+-PIDGIN_TREE_TOP := ../../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-TARGET = Purple
+-AUTOSPLIT = lib/auto/Purple/autosplit.ix
+-PERL_PLUGIN_TOP := ..
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(PERL_LIB_TOP)/CORE
+-
+-LIB_PATHS += -L$(PERL_LIB_TOP) \
+- -L$(PERL_PLUGIN_TOP) \
+- -L$(PURPLE_TOP) \
+- -L$(GTK_TOP)/lib
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-XS_FILES = Account.xs \
+- AccountOpts.xs \
+- BuddyIcon.xs \
+- BuddyList.xs \
+- Cipher.xs \
+- Cmds.xs \
+- Certificate.xs \
+- Connection.xs \
+- Conversation.xs \
+- Core.xs \
+- Debug.xs \
+- FT.xs \
+- Idle.xs \
+- Purple.xs \
+- ImgStore.xs \
+- Log.xs \
+- Network.xs \
+- Notify.xs \
+- Plugin.xs \
+- PluginPref.xs \
+- Pounce.xs \
+- Prefs.xs \
+- Privacy.xs \
+- Proxy.xs \
+- Prpl.xs \
+- Request.xs \
+- Roomlist.xs \
+- SSLConn.xs \
+- SavedStatuses.xs \
+- Server.xs \
+- Signal.xs \
+- Smiley.xs \
+- Sound.xs \
+- Status.xs \
+- Stringref.xs \
+- Util.xs \
+- Whiteboard.xs \
+- XMLNode.xs
+-
+-#FALLBACKS = const-c.inc const-xs.inc
+-C_FILES = $(XS_FILES:%.xs=%.c)
+-OBJECTS = $(C_FILES:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lperl510 \
+- -lperl \
+- -lpurple \
+- -lglib-2.0
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-%.inc:
+- cp fallback/$@ ./
+-
+-##
+-## TARGETS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll $(AUTOSPLIT)
+-
+-install: all
+- rm -rf $(PURPLE_INSTALL_PERL_DIR)
+- mkdir -p $(PURPLE_INSTALL_PERL_DIR)
+- cp -R lib/* $(PURPLE_INSTALL_PERL_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_PERL_DIR)/auto/Purple
+-
+-$(C_FILES): $(PURPLE_CONFIG_H)
+-
+-$(AUTOSPLIT):
+- mkdir -p ./lib/auto
+- cp Purple.pm ./lib
+- $(PERL) -MAutoSplit -e 'autosplit("lib/Purple.pm")'
+-
+-$(TARGET).dll: $(PURPLE_DLL).a $(PURPLE_PERL_DLL).a $(FALLBACKS) $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN
+-##
+-clean:
+- rm -rf $(TARGET).dll $(FALLBACKS) lib
+- rm -f *.o $(C_FILES)
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/plugins/perl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/perl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.in 2013-08-16 23:53:53.240816341 -0300
+@@ -182,8 +182,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -245,8 +243,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/perl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.mingw
+--- pidgin-2.10.7/libpurple/plugins/perl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/perl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,84 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for perl plugin loader plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-TARGET = perl
+-
+-# Perl headers with /* /* */ type comments.. Turn off warnings.
+-GCCWARNINGS += -Wno-comment
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(PERL_LIB_TOP)/CORE
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PERL_LIB_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = perl.c \
+- perl-common.c \
+- perl-handlers.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lgmodule-2.0 \
+- -lgobject-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple \
+- -lperl510
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
+-
+-install: all $(PURPLE_INSTALL_PLUGINS_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-##
+-## BUILD DLL
+-##
+-$(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--export-all-symbols -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll $(TARGET).dll.a
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/plugins/psychic.c pidgin-2.10.7-nonprism/libpurple/plugins/psychic.c
+--- pidgin-2.10.7/libpurple/plugins/psychic.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/psychic.c 2013-08-27 21:18:22.251908751 -0300
+@@ -20,8 +20,7 @@
+ #define PLUGIN_NAME N_("Psychic Mode")
+ #define PLUGIN_SUMMARY N_("Psychic mode for incoming conversation")
+ #define PLUGIN_DESC N_("Causes conversation windows to appear as other" \
+- " users begin to message you. This works for" \
+- " AIM, ICQ, XMPP, Sametime, and Yahoo!")
++ " users begin to message you. This works for XMPP")
+ #define PLUGIN_AUTHOR "Christopher O'Brien <siege@preoccupied.net>"
+
+
+diff -Nur pidgin-2.10.7/libpurple/plugins/ssl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/ssl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.in 2013-08-16 23:53:57.577616732 -0300
+@@ -225,8 +225,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -288,8 +286,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/ssl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.mingw
+--- pidgin-2.10.7/libpurple/plugins/ssl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/ssl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,96 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for ssl plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-##
+-## VARIABLE DEFINITIONS
+-##
+-TARGET = ssl
+-TARGET_NSS = ssl-nss
+-
+-NEEDED_DLLS = \
+- $(NSS_TOP)/lib/freebl3.dll \
+- $(NSS_TOP)/lib/libnspr4.dll \
+- $(NSS_TOP)/lib/libplc4.dll \
+- $(NSS_TOP)/lib/libplds4.dll \
+- $(NSS_TOP)/lib/nss3.dll \
+- $(NSS_TOP)/lib/nssutil3.dll \
+- $(NSS_TOP)/lib/smime3.dll \
+- $(NSS_TOP)/lib/softokn3.dll \
+- $(NSS_TOP)/lib/sqlite3.dll \
+- $(NSS_TOP)/lib/ssl3.dll
+-
+-##
+-## 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$(NSS_TOP)/include
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(NSS_TOP)/lib
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = ssl.c
+-C_SRC_NSS = ssl-nss.c
+-OBJECTS = $(C_SRC:%.c=%.o)
+-OBJECTS_NSS = $(C_SRC_NSS:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple \
+- -lnss3 \
+- -lnspr4 \
+- -lssl3 \
+- -lsmime3
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll $(TARGET_NSS).dll
+-
+-install: all $(PURPLE_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR)
+- cp $(TARGET_NSS).dll $(PURPLE_INSTALL_PLUGINS_DIR)
+- cp $(NEEDED_DLLS) $(PURPLE_INSTALL_DIR)
+-
+-$(OBJECTS) $(OBJECTS_NSS): $(PURPLE_CONFIG_H)
+-
+-##
+-## BUILD DLL
+-##
+-$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-$(TARGET_NSS).dll: $(PURPLE_DLL) $(OBJECTS_NSS)
+- $(CC) -shared $(OBJECTS_NSS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET_NSS).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS) $(OBJECTS_NSS) $(TARGET).dll $(TARGET_NSS).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/plugins/tcl/Makefile.in pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.in
+--- pidgin-2.10.7/libpurple/plugins/tcl/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.in 2013-08-16 23:54:01.251063337 -0300
+@@ -185,8 +185,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -248,8 +246,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/plugins/tcl/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.mingw
+--- pidgin-2.10.7/libpurple/plugins/tcl/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/plugins/tcl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,77 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for tcl plugin loader plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = tcl
+-TCL_INC_DIR := $(TCL_LIB_TOP)/include
+-DEFINES += -DHAVE_TK -DUSE_TCL_STUBS -DUSE_TK_STUBS
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(TCL_INC_DIR)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(TCL_LIB_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = tcl.c \
+- tcl_cmd.c \
+- tcl_cmds.c \
+- tcl_glib.c \
+- tcl_ref.c \
+- tcl_signals.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple \
+- -ltclstub84 \
+- -ltkstub84
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(PURPLE_INSTALL_PLUGINS_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_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 -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/pounce.c pidgin-2.10.7-nonprism/libpurple/pounce.c
+--- pidgin-2.10.7/libpurple/pounce.c 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/pounce.c 2013-08-16 23:02:20.671021669 -0300
+@@ -409,7 +409,6 @@
+ g_free(data->account_name);
+ data->account_name = g_strdup(buffer);
+ tmp = data->protocol_id;
+- data->protocol_id = g_strdup(_purple_oscar_convert(buffer, tmp));
+ g_free(tmp);
+ }
+ else if (purple_strequal(element_name, "pouncee")) {
+diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.in 2013-08-16 23:51:12.255853844 -0300
+@@ -199,8 +199,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -262,8 +260,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/bonjour/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,98 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libbonjour
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libbonjour
+-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
+-
+-CFLAGS += -DUSE_BONJOUR_APPLE
+-
+-##
+-## 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$(BONJOUR_TOP)/Include \
+- -I$(LIBXML2_TOP)/include/libxml2 \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(LIBXML2_TOP)/lib \
+- -L$(PURPLE_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = bonjour.c \
+- bonjour_ft.c \
+- buddy.c \
+- dns_sd_proxy.c \
+- jabber.c \
+- mdns_common.c \
+- mdns_win32.c \
+- parser.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lnetapi32 \
+- -lxml2 \
+- -lpurple
+-
+-ifeq ($(LINK_DNS_SD_DIRECTLY), 1)
+- CFLAGS += -DLINK_DNS_SD_DIRECTLY
+- LIB_PATHS += -L$(BONJOUR_TOP)/lib/win32 -L$(BONJOUR_TOP)/lib
+- LIBS += -ldnssd
+-endif
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/buddylist.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.c
+--- pidgin-2.10.7/libpurple/protocols/gg/buddylist.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,188 +0,0 @@
+-/**
+- * @file buddylist.c
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#include <libgadu.h>
+-
+-#include "gg.h"
+-#include "gg-utils.h"
+-#include "buddylist.h"
+-
+-#define F_FIRSTNAME 0
+-#define F_LASTNAME 1
+-/* #define F_ 2 */
+-#define F_NICKNAME 3
+-#define F_PHONE 4
+-#define F_GROUP 5
+-#define F_UIN 6
+-
+-/* void ggp_buddylist_send(PurpleConnection *gc) {{{ */
+-void ggp_buddylist_send(PurpleConnection *gc)
+-{
+- GGPInfo *info = gc->proto_data;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- GSList *buddies;
+- uin_t *userlist;
+- gchar *types;
+- int i = 0, ret = 0;
+- int size;
+-
+- buddies = purple_find_buddies(account, NULL);
+-
+- size = g_slist_length(buddies);
+- userlist = g_new(uin_t, size);
+- types = g_new(gchar, size);
+-
+- for (buddies = purple_find_buddies(account, NULL); buddies;
+- buddies = g_slist_delete_link(buddies, buddies), ++i)
+- {
+- PurpleBuddy *buddy = buddies->data;
+- const gchar *name = purple_buddy_get_name(buddy);
+-
+- userlist[i] = ggp_str_to_uin(name);
+- types[i] = GG_USER_NORMAL;
+- purple_debug_info("gg", "ggp_buddylist_send: adding %d\n",
+- userlist[i]);
+- }
+-
+- ret = gg_notify_ex(info->session, userlist, types, size);
+- purple_debug_info("gg", "send: ret=%d; size=%d\n", ret, size);
+-
+- if (userlist) {
+- g_free(userlist);
+- g_free(types);
+- }
+-}
+-/* }}} */
+-
+-/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
+-void ggp_buddylist_load(PurpleConnection *gc, char *buddylist)
+-{
+- PurpleBuddy *buddy;
+- PurpleGroup *group;
+- gchar **users_tbl;
+- int i;
+- char *utf8buddylist = charset_convert(buddylist, "CP1250", "UTF-8");
+-
+- /* Don't limit the number of records in a buddylist. */
+- users_tbl = g_strsplit(utf8buddylist, "\r\n", -1);
+-
+- for (i = 0; users_tbl[i] != NULL; i++) {
+- gchar **data_tbl;
+- gchar *name, *show, *g;
+-
+- if (strlen(users_tbl[i]) == 0)
+- continue;
+-
+- data_tbl = g_strsplit(users_tbl[i], ";", 8);
+- if (ggp_array_size(data_tbl) < 8) {
+- purple_debug_warning("gg",
+- "Something is wrong on line %d of the buddylist. Skipping.\n",
+- i + 1);
+- continue;
+- }
+-
+- show = data_tbl[F_NICKNAME];
+- name = data_tbl[F_UIN];
+- if ('\0' == *name || !atol(name)) {
+- purple_debug_warning("gg",
+- "Identifier on line %d of the buddylist is not a number. Skipping.\n",
+- i + 1);
+- continue;
+- }
+-
+- if ('\0' == *show) {
+- show = name;
+- }
+-
+- purple_debug_info("gg", "got buddy: name=%s; show=%s\n", name, show);
+-
+- if (purple_find_buddy(purple_connection_get_account(gc), name)) {
+- g_strfreev(data_tbl);
+- continue;
+- }
+-
+- g = g_strdup("Gadu-Gadu");
+-
+- if ('\0' != data_tbl[F_GROUP]) {
+- /* XXX: Probably buddy should be added to all the groups. */
+- /* Hard limit to at most 50 groups */
+- gchar **group_tbl = g_strsplit(data_tbl[F_GROUP], ",", 50);
+- if (ggp_array_size(group_tbl) > 0) {
+- g_free(g);
+- g = g_strdup(group_tbl[0]);
+- }
+- g_strfreev(group_tbl);
+- }
+-
+- buddy = purple_buddy_new(purple_connection_get_account(gc), name,
+- strlen(show) ? show : NULL);
+-
+- if (!(group = purple_find_group(g))) {
+- group = purple_group_new(g);
+- purple_blist_add_group(group, NULL);
+- }
+-
+- purple_blist_add_buddy(buddy, NULL, group, NULL);
+- g_free(g);
+-
+- g_strfreev(data_tbl);
+- }
+- g_strfreev(users_tbl);
+- g_free(utf8buddylist);
+-
+- ggp_buddylist_send(gc);
+-}
+-/* }}} */
+-
+-/* char *ggp_buddylist_dump(PurpleAccount *account) {{{ */
+-char *ggp_buddylist_dump(PurpleAccount *account)
+-{
+- GSList *buddies;
+- GString *buddylist = g_string_sized_new(1024);
+- char *ptr;
+-
+- for (buddies = purple_find_buddies(account, NULL); buddies;
+- buddies = g_slist_delete_link(buddies, buddies)) {
+- PurpleBuddy *buddy = buddies->data;
+- PurpleGroup *group = purple_buddy_get_group(buddy);
+- const char *bname = purple_buddy_get_name(buddy);
+- const char *gname = purple_group_get_name(group);
+- const char *alias = purple_buddy_get_alias(buddy);
+-
+- if (alias == NULL)
+- alias = bname;
+-
+- g_string_append_printf(buddylist,
+- "%s;%s;%s;%s;%s;%s;%s;%s%s\r\n",
+- alias, alias, alias, alias,
+- "", gname, bname, "", "");
+- }
+-
+- ptr = charset_convert(buddylist->str, "UTF-8", "CP1250");
+- g_string_free(buddylist, TRUE);
+- return ptr;
+-}
+-/* }}} */
+-
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/buddylist.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.h
+--- pidgin-2.10.7/libpurple/protocols/gg/buddylist.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/buddylist.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,57 +0,0 @@
+-/**
+- * @file buddylist.h
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#ifndef _PURPLE_GG_BUDDYLIST_H
+-#define _PURPLE_GG_BUDDYLIST_H
+-
+-#include "connection.h"
+-#include "account.h"
+-
+-void
+-ggp_buddylist_send(PurpleConnection *gc);
+-
+-/**
+- * Load buddylist from server into the roster.
+- *
+- * @param gc PurpleConnection
+- * @param buddylist Pointer to the buddylist that will be loaded.
+- */
+-/* void ggp_buddylist_load(PurpleConnection *gc, char *buddylist) {{{ */
+-void
+-ggp_buddylist_load(PurpleConnection *gc, char *buddylist);
+-
+-/**
+- * Get all the buddies in the current account.
+- *
+- * @param account Current account.
+- *
+- * @return List of buddies.
+- */
+-char *
+-ggp_buddylist_dump(PurpleAccount *account);
+-
+-
+-#endif /* _PURPLE_GG_BUDDYLIST_H */
+-
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/confer.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.c
+--- pidgin-2.10.7/libpurple/protocols/gg/confer.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,170 +0,0 @@
+-/**
+- * @file confer.c
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#include <libgadu.h>
+-#include "gg.h"
+-#include "gg-utils.h"
+-#include "confer.h"
+-
+-/* PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name) {{{ */
+-PurpleConversation *ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name)
+-{
+- g_return_val_if_fail(gc != NULL, NULL);
+- g_return_val_if_fail(name != NULL, NULL);
+-
+- return purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name,
+- purple_connection_get_account(gc));
+-}
+-/* }}} */
+-
+-/* void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name, const uin_t uin) {{{ */
+-void ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name,
+- const uin_t uin)
+-{
+- PurpleConversation *conv;
+- GGPInfo *info = gc->proto_data;
+- GGPChat *chat;
+- GList *l;
+- gchar *str_uin;
+-
+- for (l = info->chats; l != NULL; l = l->next) {
+- chat = l->data;
+-
+- if (g_utf8_collate(chat->name, chat_name) != 0)
+- continue;
+-
+- if (g_list_find(chat->participants, GINT_TO_POINTER(uin)) == NULL) {
+- chat->participants = g_list_append(
+- chat->participants, GINT_TO_POINTER(uin));
+-
+- str_uin = g_strdup_printf("%lu", (unsigned long int)uin);
+- conv = ggp_confer_find_by_name(gc, chat_name);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv), str_uin, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+-
+- g_free(str_uin);
+- }
+- break;
+- }
+-}
+-/* }}} */
+-
+-/* void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name, const uin_t *recipients, int count) {{{ */
+-void ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name,
+- const uin_t *recipients, int count)
+-{
+- GGPInfo *info = gc->proto_data;
+- GList *l;
+- gchar *str_uin;
+-
+- for (l = info->chats; l != NULL; l = l->next) {
+- GGPChat *chat = l->data;
+- int i;
+-
+- if (g_utf8_collate(chat->name, chat_name) != 0)
+- continue;
+-
+- for (i = 0; i < count; i++) {
+- PurpleConversation *conv;
+-
+- if (g_list_find(chat->participants,
+- GINT_TO_POINTER(recipients[i])) != NULL) {
+- continue;
+- }
+-
+- chat->participants = g_list_append(chat->participants,
+- GINT_TO_POINTER(recipients[i]));
+-
+- str_uin = g_strdup_printf("%lu", (unsigned long int)recipients[i]);
+- conv = ggp_confer_find_by_name(gc, chat_name);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv),
+- str_uin, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+- g_free(str_uin);
+- }
+- break;
+- }
+-}
+-/* }}} */
+-
+-/* const char *ggp_confer_find_by_participants(PurpleConnection *gc, const uin_t *recipients, int count) {{{ */
+-const char *ggp_confer_find_by_participants(PurpleConnection *gc,
+- const uin_t *recipients, int count)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPChat *chat = NULL;
+- GList *l;
+- int matches;
+-
+- g_return_val_if_fail(info->chats != NULL, NULL);
+-
+- for (l = info->chats; l != NULL; l = l->next) {
+- GList *m;
+-
+- chat = l->data;
+- matches = 0;
+-
+- for (m = chat->participants; m != NULL; m = m->next) {
+- uin_t uin = GPOINTER_TO_INT(m->data);
+- int i;
+-
+- for (i = 0; i < count; i++)
+- if (uin == recipients[i])
+- matches++;
+- }
+-
+- if (matches == count)
+- break;
+-
+- chat = NULL;
+- }
+-
+- if (chat == NULL)
+- return NULL;
+- else
+- return chat->name;
+-}
+-/* }}} */
+-
+-/* const char *ggp_confer_add_new(PurpleConnection *gc, const char *name) {{{ */
+-const char *ggp_confer_add_new(PurpleConnection *gc, const char *name)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPChat *chat;
+-
+- chat = g_new0(GGPChat, 1);
+-
+- if (name == NULL)
+- chat->name = g_strdup_printf("conf#%d", info->chats_count++);
+- else
+- chat->name = g_strdup(name);
+-
+- chat->participants = NULL;
+-
+- info->chats = g_list_append(info->chats, chat);
+-
+- return chat->name;
+-}
+-/* }}} */
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/confer.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.h
+--- pidgin-2.10.7/libpurple/protocols/gg/confer.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/confer.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-/**
+- * @file confer.h
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#ifndef _PURPLE_GG_CONFER_H
+-#define _PURPLE_GG_CONFER_H
+-
+-#include "gg.h"
+-
+-/**
+- * Finds a CHAT conversation for the current account with the specified name.
+- *
+- * @param gc PurpleConnection instance.
+- * @param name Name of the conversation.
+- *
+- * @return PurpleConversation or NULL if not found.
+- */
+-PurpleConversation *
+-ggp_confer_find_by_name(PurpleConnection *gc, const gchar *name);
+-
+-/**
+- * Adds the specified UIN to the specified conversation.
+- *
+- * @param gc PurpleConnection.
+- * @param chat_name Name of the conversation.
+- */
+-void
+-ggp_confer_participants_add_uin(PurpleConnection *gc, const gchar *chat_name,
+- const uin_t uin);
+-
+-/**
+- * Add the specified UINs to the specified conversation.
+- *
+- * @param gc PurpleConnection.
+- * @param chat_name Name of the conversation.
+- * @param recipients List of the UINs.
+- * @param count Number of the UINs.
+- */
+-void
+-ggp_confer_participants_add(PurpleConnection *gc, const gchar *chat_name,
+- const uin_t *recipients, int count);
+-
+-/**
+- * Finds a conversation in which all the specified recipients participate.
+- *
+- * TODO: This function should be rewritten to better handle situations when
+- * somebody adds more people to the converation.
+- *
+- * @param gc PurpleConnection.
+- * @param recipients List of the people in the conversation.
+- * @param count Number of people.
+- *
+- * @return Name of the conversation.
+- */
+-const char*
+-ggp_confer_find_by_participants(PurpleConnection *gc, const uin_t *recipients,
+- int count);
+-
+-/**
+- * Adds a new conversation to the internal list of conversations.
+- * If name is NULL then it will be automagically generated.
+- *
+- * @param gc PurpleConnection.
+- * @param name Name of the conversation.
+- *
+- * @return Name of the conversation.
+- */
+-const char*
+-ggp_confer_add_new(PurpleConnection *gc, const char *name);
+-
+-
+-#endif /* _PURPLE_GG_CONFER_H */
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.c
+--- pidgin-2.10.7/libpurple/protocols/gg/gg.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2837 +0,0 @@
+-/**
+- * @file gg.c Gadu-Gadu protocol plugin
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * Some parts of the code are adapted or taken from the previous implementation
+- * of this plugin written by Arkadiusz Miskiewicz <misiek@pld.org.pl>
+- * Some parts Copyright (C) 2009 Krzysztof Klinikowski <grommasher@gmail.com>
+- *
+- * Thanks to Google's Summer of Code Program.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-
+-#include "plugin.h"
+-#include "version.h"
+-#include "notify.h"
+-#include "status.h"
+-#include "blist.h"
+-#include "accountopt.h"
+-#include "debug.h"
+-#include "util.h"
+-#include "request.h"
+-#include "xmlnode.h"
+-
+-#include <libgadu.h>
+-
+-#include "gg.h"
+-#include "confer.h"
+-#include "search.h"
+-#include "buddylist.h"
+-#include "gg-utils.h"
+-
+-#define DISABLE_AVATARS 1
+-
+-static PurplePlugin *my_protocol = NULL;
+-
+-/* Prototypes */
+-static void ggp_set_status(PurpleAccount *account, PurpleStatus *status);
+-static int ggp_to_gg_status(PurpleStatus *status, char **msg);
+-
+-/* ---------------------------------------------------------------------- */
+-/* ----- EXTERNAL CALLBACKS --------------------------------------------- */
+-/* ---------------------------------------------------------------------- */
+-
+-
+-/* ----- HELPERS -------------------------------------------------------- */
+-
+-/**
+- * Set up libgadu's proxy.
+- *
+- * @param account Account for which to set up the proxy.
+- *
+- * @return Zero if proxy setup is valid, otherwise -1.
+- */
+-static int ggp_setup_proxy(PurpleAccount *account)
+-{
+- PurpleProxyInfo *gpi;
+-
+- gpi = purple_proxy_get_setup(account);
+-
+- if ((purple_proxy_info_get_type(gpi) != PURPLE_PROXY_NONE) &&
+- (purple_proxy_info_get_host(gpi) == NULL ||
+- purple_proxy_info_get_port(gpi) <= 0)) {
+-
+- gg_proxy_enabled = 0;
+- purple_notify_error(NULL, NULL, _("Invalid proxy settings"),
+- _("Either the host name or port number specified for your given proxy type is invalid."));
+- return -1;
+- } else if (purple_proxy_info_get_type(gpi) != PURPLE_PROXY_NONE) {
+- gg_proxy_enabled = 1;
+- gg_proxy_host = g_strdup(purple_proxy_info_get_host(gpi));
+- gg_proxy_port = purple_proxy_info_get_port(gpi);
+- gg_proxy_username = g_strdup(purple_proxy_info_get_username(gpi));
+- gg_proxy_password = g_strdup(purple_proxy_info_get_password(gpi));
+- } else {
+- gg_proxy_enabled = 0;
+- }
+-
+- return 0;
+-}
+-
+-static void ggp_async_token_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = _gc;
+- GGPInfo *info = gc->proto_data;
+- GGPToken *token = info->token;
+- GGPTokenCallback cb;
+-
+- struct gg_token *t = NULL;
+-
+- purple_debug_info("gg", "token_handler: token->req: check = %d; state = %d;\n",
+- token->req->check, token->req->state);
+-
+- if (gg_token_watch_fd(token->req) == -1 || token->req->state == GG_STATE_ERROR) {
+- purple_debug_error("gg", "token error (1): %d\n", token->req->error);
+- purple_input_remove(token->inpa);
+- gg_token_free(token->req);
+- token->req = NULL;
+-
+- purple_notify_error(purple_connection_get_account(gc),
+- _("Token Error"),
+- _("Unable to fetch the token.\n"), NULL);
+- return;
+- }
+-
+- if (token->req->state != GG_STATE_DONE) {
+- purple_input_remove(token->inpa);
+- token->inpa = purple_input_add(token->req->fd,
+- (token->req->check == 1)
+- ? PURPLE_INPUT_WRITE
+- : PURPLE_INPUT_READ,
+- ggp_async_token_handler, gc);
+- return;
+- }
+-
+- if (!(t = token->req->data) || !token->req->body) {
+- purple_debug_error("gg", "token error (2): %d\n", token->req->error);
+- purple_input_remove(token->inpa);
+- gg_token_free(token->req);
+- token->req = NULL;
+-
+- purple_notify_error(purple_connection_get_account(gc),
+- _("Token Error"),
+- _("Unable to fetch the token.\n"), NULL);
+- return;
+- }
+-
+- purple_input_remove(token->inpa);
+-
+- token->id = g_strdup(t->tokenid);
+- token->size = token->req->body_size;
+- token->data = g_new0(char, token->size);
+- memcpy(token->data, token->req->body, token->size);
+-
+- purple_debug_info("gg", "TOKEN! tokenid = %s; size = %d\n",
+- token->id, token->size);
+-
+- gg_token_free(token->req);
+- token->req = NULL;
+- token->inpa = 0;
+-
+- cb = token->cb;
+- token->cb = NULL;
+- cb(gc);
+-}
+-
+-static void ggp_token_request(PurpleConnection *gc, GGPTokenCallback cb)
+-{
+- PurpleAccount *account;
+- struct gg_http *req;
+- GGPInfo *info;
+-
+- account = purple_connection_get_account(gc);
+-
+- if (ggp_setup_proxy(account) == -1)
+- return;
+-
+- info = gc->proto_data;
+-
+- if ((req = gg_token(1)) == NULL) {
+- purple_notify_error(account,
+- _("Token Error"),
+- _("Unable to fetch the token.\n"), NULL);
+- return;
+- }
+-
+- info->token = g_new(GGPToken, 1);
+- info->token->cb = cb;
+-
+- info->token->req = req;
+- info->token->inpa = purple_input_add(req->fd, PURPLE_INPUT_READ,
+- ggp_async_token_handler, gc);
+-}
+-/* }}} */
+-
+-/* ---------------------------------------------------------------------- */
+-
+-/**
+- * Request buddylist from the server.
+- * Buddylist is received in the ggp_callback_recv().
+- *
+- * @param Current action handler.
+- */
+-static void ggp_action_buddylist_get(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+- GGPInfo *info = gc->proto_data;
+-
+- purple_debug_info("gg", "Downloading...\n");
+-
+- gg_userlist_request(info->session, GG_USERLIST_GET, NULL);
+-}
+-
+-/**
+- * Upload the buddylist to the server.
+- *
+- * @param action Current action handler.
+- */
+-static void ggp_action_buddylist_put(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+- GGPInfo *info = gc->proto_data;
+-
+- char *buddylist = ggp_buddylist_dump(purple_connection_get_account(gc));
+-
+- purple_debug_info("gg", "Uploading...\n");
+-
+- if (buddylist == NULL)
+- return;
+-
+- gg_userlist_request(info->session, GG_USERLIST_PUT, buddylist);
+- g_free(buddylist);
+-}
+-
+-/**
+- * Delete buddylist from the server.
+- *
+- * @param action Current action handler.
+- */
+-static void ggp_action_buddylist_delete(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+- GGPInfo *info = gc->proto_data;
+-
+- purple_debug_info("gg", "Deleting...\n");
+-
+- gg_userlist_request(info->session, GG_USERLIST_PUT, NULL);
+-}
+-
+-static void ggp_callback_buddylist_save_ok(PurpleConnection *gc, const char *filename)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+-
+- char *buddylist = ggp_buddylist_dump(account);
+-
+- purple_debug_info("gg", "Saving...\n");
+- purple_debug_info("gg", "file = %s\n", filename);
+-
+- if (buddylist == NULL) {
+- purple_notify_info(account, _("Save Buddylist..."),
+- _("Your buddylist is empty, nothing was written to the file."),
+- NULL);
+- return;
+- }
+-
+- if(purple_util_write_data_to_file_absolute(filename, buddylist, -1)) {
+- purple_notify_info(account, _("Save Buddylist..."),
+- _("Buddylist saved successfully!"), NULL);
+- } else {
+- gchar *primary = g_strdup_printf(
+- _("Couldn't write buddy list for %s to %s"),
+- purple_account_get_username(account), filename);
+- purple_notify_error(account, _("Save Buddylist..."),
+- primary, NULL);
+- g_free(primary);
+- }
+-
+- g_free(buddylist);
+-}
+-
+-static void ggp_callback_buddylist_load_ok(PurpleConnection *gc, gchar *file)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- GError *error = NULL;
+- char *buddylist = NULL;
+- gsize length;
+-
+- purple_debug_info("gg", "file_name = %s\n", file);
+-
+- if (!g_file_get_contents(file, &buddylist, &length, &error)) {
+- purple_notify_error(account,
+- _("Couldn't load buddylist"),
+- _("Couldn't load buddylist"),
+- error->message);
+-
+- purple_debug_error("gg",
+- "Couldn't load buddylist. file = %s; error = %s\n",
+- file, error->message);
+-
+- g_error_free(error);
+-
+- return;
+- }
+-
+- ggp_buddylist_load(gc, buddylist);
+- g_free(buddylist);
+-
+- purple_notify_info(account,
+- _("Load Buddylist..."),
+- _("Buddylist loaded successfully!"), NULL);
+-}
+-/* }}} */
+-
+-/*
+- */
+-/* static void ggp_action_buddylist_save(PurplePluginAction *action) {{{ */
+-static void ggp_action_buddylist_save(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+-
+- purple_request_file(action, _("Save buddylist..."), NULL, TRUE,
+- G_CALLBACK(ggp_callback_buddylist_save_ok), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void ggp_action_buddylist_load(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+-
+- purple_request_file(action, _("Load buddylist from file..."), NULL,
+- FALSE,
+- G_CALLBACK(ggp_callback_buddylist_load_ok), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void ggp_callback_register_account_ok(PurpleConnection *gc,
+- PurpleRequestFields *fields)
+-{
+- PurpleAccount *account;
+- GGPInfo *info = gc->proto_data;
+- struct gg_http *h = NULL;
+- struct gg_pubdir *s;
+- uin_t uin;
+- gchar *email, *p1, *p2, *t;
+- GGPToken *token = info->token;
+-
+- email = charset_convert(purple_request_fields_get_string(fields, "email"),
+- "UTF-8", "CP1250");
+- p1 = charset_convert(purple_request_fields_get_string(fields, "password1"),
+- "UTF-8", "CP1250");
+- p2 = charset_convert(purple_request_fields_get_string(fields, "password2"),
+- "UTF-8", "CP1250");
+- t = charset_convert(purple_request_fields_get_string(fields, "token"),
+- "UTF-8", "CP1250");
+-
+- account = purple_connection_get_account(gc);
+-
+- if (email == NULL || p1 == NULL || p2 == NULL || t == NULL ||
+- *email == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+- _("You must fill in all registration fields"));
+- goto exit_err;
+- }
+-
+- if (g_utf8_collate(p1, p2) != 0) {
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+- _("Passwords do not match"));
+- goto exit_err;
+- }
+-
+- purple_debug_info("gg", "register_account_ok: token_id = %s; t = %s\n",
+- token->id, t);
+- h = gg_register3(email, p1, token->id, t, 0);
+- if (h == NULL || !(s = h->data) || !s->success) {
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+- _("Unable to register new account. An unknown error occurred."));
+- goto exit_err;
+- }
+-
+- uin = s->uin;
+- purple_debug_info("gg", "registered uin: %d\n", uin);
+-
+- g_free(t);
+- t = g_strdup_printf("%u", uin);
+- purple_account_set_username(account, t);
+- /* Save the password if remembering passwords for the account */
+- purple_account_set_password(account, p1);
+-
+- purple_notify_info(NULL, _("New Gadu-Gadu Account Registered"),
+- _("Registration completed successfully!"), NULL);
+-
+- if(account->registration_cb)
+- (account->registration_cb)(account, TRUE, account->registration_cb_user_data);
+- /* TODO: the currently open Accounts Window will not be updated withthe
+- * new username and etc, we need to somehow have it refresh at this
+- * point
+- */
+-
+- /* Need to disconnect or actually log in. For now, we disconnect. */
+- purple_account_disconnect(account);
+-
+-exit_err:
+- if(account->registration_cb)
+- (account->registration_cb)(account, FALSE, account->registration_cb_user_data);
+-
+- gg_register_free(h);
+- g_free(email);
+- g_free(p1);
+- g_free(p2);
+- g_free(t);
+- g_free(token->id);
+- g_free(token);
+-}
+-
+-static void ggp_callback_register_account_cancel(PurpleConnection *gc,
+- PurpleRequestFields *fields)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPToken *token = info->token;
+-
+- purple_account_disconnect(gc->account);
+-
+- g_free(token->id);
+- g_free(token->data);
+- g_free(token);
+-
+-}
+-
+-static void ggp_register_user_dialog(PurpleConnection *gc)
+-{
+- PurpleAccount *account;
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+-
+- GGPInfo *info = gc->proto_data;
+- GGPToken *token = info->token;
+-
+-
+- account = purple_connection_get_account(gc);
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_string_new("email",
+- _("Email"), "", FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("password1",
+- _("Password"), "", FALSE);
+- purple_request_field_string_set_masked(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("password2",
+- _("Password (again)"), "", FALSE);
+- purple_request_field_string_set_masked(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("token",
+- _("Enter captcha text"), "", FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- /* original size: 60x24 */
+- field = purple_request_field_image_new("token_img",
+- _("Captcha"), token->data, token->size);
+- purple_request_field_group_add_field(group, field);
+-
+- purple_request_fields(account,
+- _("Register New Gadu-Gadu Account"),
+- _("Register New Gadu-Gadu Account"),
+- _("Please, fill in the following fields"),
+- fields,
+- _("OK"), G_CALLBACK(ggp_callback_register_account_ok),
+- _("Cancel"), G_CALLBACK(ggp_callback_register_account_cancel),
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-/* ----- PUBLIC DIRECTORY SEARCH ---------------------------------------- */
+-
+-static void ggp_callback_show_next(PurpleConnection *gc, GList *row, gpointer user_data)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPSearchForm *form = user_data;
+- guint32 seq;
+-
+- form->page_number++;
+-
+- ggp_search_remove(info->searches, form->seq);
+- purple_debug_info("gg", "ggp_callback_show_next(): Removed seq %u\n",
+- form->seq);
+-
+- seq = ggp_search_start(gc, form);
+- ggp_search_add(info->searches, seq, form);
+- purple_debug_info("gg", "ggp_callback_show_next(): Added seq %u\n",
+- seq);
+-}
+-
+-static void ggp_callback_add_buddy(PurpleConnection *gc, GList *row, gpointer user_data)
+-{
+- purple_blist_request_add_buddy(purple_connection_get_account(gc),
+- g_list_nth_data(row, 0), NULL, NULL);
+-}
+-
+-static void ggp_callback_im(PurpleConnection *gc, GList *row, gpointer user_data)
+-{
+- PurpleAccount *account;
+- PurpleConversation *conv;
+- char *name;
+-
+- account = purple_connection_get_account(gc);
+-
+- name = g_list_nth_data(row, 0);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
+- purple_conversation_present(conv);
+-}
+-
+-static void ggp_callback_find_buddies(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPSearchForm *form;
+- guint32 seq;
+-
+- form = ggp_search_form_new(GGP_SEARCH_TYPE_FULL);
+-
+- form->user_data = info;
+- form->lastname = g_strdup(
+- purple_request_fields_get_string(fields, "lastname"));
+- form->firstname = g_strdup(
+- purple_request_fields_get_string(fields, "firstname"));
+- form->nickname = g_strdup(
+- purple_request_fields_get_string(fields, "nickname"));
+- form->city = g_strdup(
+- purple_request_fields_get_string(fields, "city"));
+- form->birthyear = g_strdup(
+- purple_request_fields_get_string(fields, "year"));
+-
+- switch (purple_request_fields_get_choice(fields, "gender")) {
+- case 1:
+- form->gender = g_strdup(GG_PUBDIR50_GENDER_MALE);
+- break;
+- case 2:
+- form->gender = g_strdup(GG_PUBDIR50_GENDER_FEMALE);
+- break;
+- default:
+- form->gender = NULL;
+- break;
+- }
+-
+- form->active = purple_request_fields_get_bool(fields, "active")
+- ? g_strdup(GG_PUBDIR50_ACTIVE_TRUE) : NULL;
+-
+- seq = ggp_search_start(gc, form);
+- ggp_search_add(info->searches, seq, form);
+- purple_debug_info("gg", "ggp_callback_find_buddies(): Added seq %u\n",
+- seq);
+-}
+-
+-static void ggp_find_buddies(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_string_new("lastname",
+- _("Last name"), NULL, FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("firstname",
+- _("First name"), NULL, FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("nickname",
+- _("Nickname"), NULL, FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("city",
+- _("City"), NULL, FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("year",
+- _("Year of birth"), NULL, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_choice_new("gender", _("Gender"), 0);
+- purple_request_field_choice_add(field, _("Male or female"));
+- purple_request_field_choice_add(field, _("Male"));
+- purple_request_field_choice_add(field, _("Female"));
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_bool_new("active",
+- _("Only online"), FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- purple_request_fields(gc,
+- _("Find buddies"),
+- _("Find buddies"),
+- _("Please, enter your search criteria below"),
+- fields,
+- _("OK"), G_CALLBACK(ggp_callback_find_buddies),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-/* ----- CHANGE PASSWORD ------------------------------------------------ */
+-
+-static void ggp_callback_change_passwd_ok(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- PurpleAccount *account;
+- GGPInfo *info = gc->proto_data;
+- struct gg_http *h;
+- gchar *cur, *p1, *p2, *t;
+-
+- cur = charset_convert(
+- purple_request_fields_get_string(fields, "password_cur"),
+- "UTF-8", "CP1250");
+- p1 = charset_convert(
+- purple_request_fields_get_string(fields, "password1"),
+- "UTF-8", "CP1250");
+- p2 = charset_convert(
+- purple_request_fields_get_string(fields, "password2"),
+- "UTF-8", "CP1250");
+- t = charset_convert(
+- purple_request_fields_get_string(fields, "token"),
+- "UTF-8", "CP1250");
+-
+- account = purple_connection_get_account(gc);
+-
+- if (cur == NULL || p1 == NULL || p2 == NULL || t == NULL ||
+- *cur == '\0' || *p1 == '\0' || *p2 == '\0' || *t == '\0') {
+- purple_notify_error(account, NULL, _("Fill in the fields."), NULL);
+- goto exit_err;
+- }
+-
+- if (g_utf8_collate(p1, p2) != 0) {
+- purple_notify_error(account, NULL,
+- _("New passwords do not match."), NULL);
+- goto exit_err;
+- }
+-
+- if (g_utf8_collate(cur, purple_account_get_password(account)) != 0) {
+- purple_notify_error(account, NULL,
+- _("Your current password is different from the one that you specified."),
+- NULL);
+- goto exit_err;
+- }
+-
+- purple_debug_info("gg", "Changing password\n");
+-
+- /* XXX: this email should be a pref... */
+- h = gg_change_passwd4(ggp_get_uin(account),
+- "user@example.net", purple_account_get_password(account),
+- p1, info->token->id, t, 0);
+-
+- if (h == NULL) {
+- purple_notify_error(account, NULL,
+- _("Unable to change password. Error occurred.\n"),
+- NULL);
+- goto exit_err;
+- }
+-
+- purple_account_set_password(account, p1);
+-
+- gg_change_passwd_free(h);
+-
+- purple_notify_info(account, _("Change password for the Gadu-Gadu account"),
+- _("Password was changed successfully!"), NULL);
+-
+-exit_err:
+- g_free(cur);
+- g_free(p1);
+- g_free(p2);
+- g_free(t);
+- g_free(info->token->id);
+- g_free(info->token->data);
+- g_free(info->token);
+-}
+-
+-static void ggp_change_passwd_dialog(PurpleConnection *gc)
+-{
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+-
+- GGPInfo *info = gc->proto_data;
+- GGPToken *token = info->token;
+-
+- char *msg;
+-
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_string_new("password_cur",
+- _("Current password"), "", FALSE);
+- purple_request_field_string_set_masked(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("password1",
+- _("Password"), "", FALSE);
+- purple_request_field_string_set_masked(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("password2",
+- _("Password (retype)"), "", FALSE);
+- purple_request_field_string_set_masked(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("token",
+- _("Enter current token"), "", FALSE);
+- purple_request_field_string_set_masked(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- /* original size: 60x24 */
+- field = purple_request_field_image_new("token_img",
+- _("Current token"), token->data, token->size);
+- purple_request_field_group_add_field(group, field);
+-
+- msg = g_strdup_printf("%s %d",
+- _("Please, enter your current password and your new password for UIN: "),
+- ggp_get_uin(purple_connection_get_account(gc)));
+-
+- purple_request_fields(gc,
+- _("Change Gadu-Gadu Password"),
+- _("Change Gadu-Gadu Password"),
+- msg,
+- fields, _("OK"), G_CALLBACK(ggp_callback_change_passwd_ok),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-
+- g_free(msg);
+-}
+-
+-static void ggp_change_passwd(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+-
+- ggp_token_request(gc, ggp_change_passwd_dialog);
+-}
+-
+-/* ----- CHANGE STATUS BROADCASTING ------------------------------------------------ */
+-
+-static void ggp_action_change_status_broadcasting_ok(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- GGPInfo *info = gc->proto_data;
+- int selected_field;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleStatus *status;
+-
+- selected_field = purple_request_fields_get_choice(fields, "status_broadcasting");
+-
+- if (selected_field == 0)
+- info->status_broadcasting = TRUE;
+- else
+- info->status_broadcasting = FALSE;
+-
+- status = purple_account_get_active_status(account);
+-
+- ggp_set_status(account, status);
+-}
+-
+-static void ggp_action_change_status_broadcasting(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *)action->context;
+- GGPInfo *info = gc->proto_data;
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_choice_new("status_broadcasting", _("Show status to:"), 0);
+- purple_request_field_choice_add(field, _("All people"));
+- purple_request_field_choice_add(field, _("Only buddies"));
+- purple_request_field_group_add_field(group, field);
+-
+- if (info->status_broadcasting)
+- purple_request_field_choice_set_default_value(field, 0);
+- else
+- purple_request_field_choice_set_default_value(field, 1);
+-
+- purple_request_fields(gc,
+- _("Change status broadcasting"),
+- _("Change status broadcasting"),
+- _("Please, select who can see your status"),
+- fields,
+- _("OK"), G_CALLBACK(ggp_action_change_status_broadcasting_ok),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-/* ----- CONFERENCES ---------------------------------------------------- */
+-
+-static void ggp_callback_add_to_chat_ok(PurpleBuddy *buddy, PurpleRequestFields *fields)
+-{
+- PurpleConnection *conn;
+- PurpleRequestField *field;
+- GList *sel;
+-
+- conn = purple_account_get_connection(purple_buddy_get_account(buddy));
+-
+- g_return_if_fail(conn != NULL);
+-
+- field = purple_request_fields_get_field(fields, "name");
+- sel = purple_request_field_list_get_selected(field);
+-
+- if (sel == NULL) {
+- purple_debug_error("gg", "No chat selected\n");
+- return;
+- }
+-
+- ggp_confer_participants_add_uin(conn, sel->data,
+- ggp_str_to_uin(purple_buddy_get_name(buddy)));
+-}
+-
+-static void ggp_bmenu_add_to_chat(PurpleBlistNode *node, gpointer ignored)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- GGPInfo *info;
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+-
+- GList *l;
+- gchar *msg;
+-
+- buddy = (PurpleBuddy *)node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- info = gc->proto_data;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_list_new("name", "Chat name");
+- for (l = info->chats; l != NULL; l = l->next) {
+- GGPChat *chat = l->data;
+- purple_request_field_list_add(field, chat->name, chat->name);
+- }
+- purple_request_field_group_add_field(group, field);
+-
+- msg = g_strdup_printf(_("Select a chat for buddy: %s"),
+- purple_buddy_get_alias(buddy));
+- purple_request_fields(gc,
+- _("Add to chat..."),
+- _("Add to chat..."),
+- msg,
+- fields,
+- _("Add"), G_CALLBACK(ggp_callback_add_to_chat_ok),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- buddy);
+- g_free(msg);
+-}
+-
+-/* ----- BLOCK BUDDIES -------------------------------------------------- */
+-
+-static void ggp_add_deny(PurpleConnection *gc, const char *who)
+-{
+- GGPInfo *info = gc->proto_data;
+- uin_t uin = ggp_str_to_uin(who);
+-
+- purple_debug_info("gg", "ggp_add_deny: %u\n", uin);
+-
+- gg_remove_notify_ex(info->session, uin, GG_USER_NORMAL);
+- gg_add_notify_ex(info->session, uin, GG_USER_BLOCKED);
+-}
+-
+-static void ggp_rem_deny(PurpleConnection *gc, const char *who)
+-{
+- GGPInfo *info = gc->proto_data;
+- uin_t uin = ggp_str_to_uin(who);
+-
+- purple_debug_info("gg", "ggp_rem_deny: %u\n", uin);
+-
+- gg_remove_notify_ex(info->session, uin, GG_USER_BLOCKED);
+- gg_add_notify_ex(info->session, uin, GG_USER_NORMAL);
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-/* ----- INTERNAL CALLBACKS --------------------------------------------- */
+-/* ---------------------------------------------------------------------- */
+-
+-#if !DISABLE_AVATARS
+-
+-struct gg_fetch_avatar_data
+-{
+- PurpleConnection *gc;
+- gchar *uin;
+- gchar *avatar_url;
+-};
+-
+-
+-static void gg_fetch_avatar_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *data, size_t len, const gchar *error_message) {
+- struct gg_fetch_avatar_data *d = user_data;
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- gpointer buddy_icon_data;
+-
+- purple_debug_info("gg", "gg_fetch_avatar_cb: got avatar image for %s\n",
+- d->uin);
+-
+- /* FIXME: This shouldn't be necessary */
+- if (!PURPLE_CONNECTION_IS_VALID(d->gc)) {
+- g_free(d->uin);
+- g_free(d->avatar_url);
+- g_free(d);
+- g_return_if_reached();
+- }
+-
+- account = purple_connection_get_account(d->gc);
+- buddy = purple_find_buddy(account, d->uin);
+-
+- if (buddy == NULL)
+- goto out;
+-
+- buddy_icon_data = g_memdup(data, len);
+-
+- purple_buddy_icons_set_for_user(account, purple_buddy_get_name(buddy),
+- buddy_icon_data, len, d->avatar_url);
+- purple_debug_info("gg", "gg_fetch_avatar_cb: UIN %s should have avatar "
+- "now\n", d->uin);
+-
+-out:
+- g_free(d->uin);
+- g_free(d->avatar_url);
+- g_free(d);
+-}
+-
+-static void gg_get_avatar_url_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *url_text, size_t len, const gchar *error_message) {
+- struct gg_fetch_avatar_data *data;
+- PurpleConnection *gc = user_data;
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- const char *uin;
+- const char *is_blank;
+- const char *checksum;
+-
+- gchar *bigavatar = NULL;
+- xmlnode *xml = NULL;
+- xmlnode *xmlnode_users;
+- xmlnode *xmlnode_user;
+- xmlnode *xmlnode_avatars;
+- xmlnode *xmlnode_avatar;
+- xmlnode *xmlnode_bigavatar;
+-
+- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
+- account = purple_connection_get_account(gc);
+-
+- if (error_message != NULL)
+- purple_debug_error("gg", "gg_get_avatars_cb error: %s\n", error_message);
+- else if (len > 0 && url_text && *url_text) {
+- xml = xmlnode_from_str(url_text, -1);
+- if (xml == NULL)
+- goto out;
+-
+- xmlnode_users = xmlnode_get_child(xml, "users");
+- if (xmlnode_users == NULL)
+- goto out;
+-
+- xmlnode_user = xmlnode_get_child(xmlnode_users, "user");
+- if (xmlnode_user == NULL)
+- goto out;
+-
+- uin = xmlnode_get_attrib(xmlnode_user, "uin");
+-
+- xmlnode_avatars = xmlnode_get_child(xmlnode_user, "avatars");
+- if (xmlnode_avatars == NULL)
+- goto out;
+-
+- xmlnode_avatar = xmlnode_get_child(xmlnode_avatars, "avatar");
+- if (xmlnode_avatar == NULL)
+- goto out;
+-
+- xmlnode_bigavatar = xmlnode_get_child(xmlnode_avatar, "originBigAvatar");
+- if (xmlnode_bigavatar == NULL)
+- goto out;
+-
+- is_blank = xmlnode_get_attrib(xmlnode_avatar, "blank");
+- bigavatar = xmlnode_get_data(xmlnode_bigavatar);
+-
+- purple_debug_info("gg", "gg_get_avatar_url_cb: UIN %s, IS_BLANK %s, "
+- "URL %s\n",
+- uin ? uin : "(null)", is_blank ? is_blank : "(null)",
+- bigavatar ? bigavatar : "(null)");
+-
+- if (uin != NULL && bigavatar != NULL) {
+- buddy = purple_find_buddy(account, uin);
+- if (buddy == NULL)
+- goto out;
+-
+- checksum = purple_buddy_icons_get_checksum_for_user(buddy);
+-
+- if (purple_strequal(is_blank, "1")) {
+- purple_buddy_icons_set_for_user(account,
+- purple_buddy_get_name(buddy), NULL, 0, NULL);
+- } else if (!purple_strequal(checksum, bigavatar)) {
+- data = g_new0(struct gg_fetch_avatar_data, 1);
+- data->gc = gc;
+- data->uin = g_strdup(uin);
+- data->avatar_url = g_strdup(bigavatar);
+-
+- purple_debug_info("gg", "gg_get_avatar_url_cb: "
+- "requesting avatar for %s\n", uin);
+- url_data = purple_util_fetch_url_request_len_with_account(account,
+- bigavatar, TRUE, "Mozilla/4.0 (compatible; MSIE 5.0)",
+- FALSE, NULL, FALSE, -1, gg_fetch_avatar_cb, data);
+- }
+- }
+- }
+-
+-out:
+- if (xml)
+- xmlnode_free(xml);
+- g_free(bigavatar);
+-}
+-
+-#endif
+-
+-/**
+- * Try to update avatar of the buddy.
+- *
+- * @param gc PurpleConnection
+- * @param uin UIN of the buddy.
+- */
+-static void ggp_update_buddy_avatar(PurpleConnection *gc, uin_t uin)
+-{
+-#if DISABLE_AVATARS
+- purple_debug_warning("gg", "ggp_update_buddy_avatar: disabled, please "
+- "update to 3.0.0, when available\n");
+-#else
+- gchar *avatarurl;
+- PurpleUtilFetchUrlData *url_data;
+-
+- purple_debug_info("gg", "ggp_update_buddy_avatar(gc, %u)\n", uin);
+-
+- avatarurl = g_strdup_printf("http://api.gadu-gadu.pl/avatars/%u/0.xml", uin);
+-
+- url_data = purple_util_fetch_url_request_len_with_account(
+- purple_connection_get_account(gc), avatarurl, TRUE,
+- "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE, NULL, FALSE, -1,
+- gg_get_avatar_url_cb, gc);
+-
+- g_free(avatarurl);
+-#endif
+-}
+-
+-/**
+- * Handle change of the status of the buddy.
+- *
+- * @param gc PurpleConnection
+- * @param uin UIN of the buddy.
+- * @param status ID of the status.
+- * @param descr Description.
+- */
+-static void ggp_generic_status_handler(PurpleConnection *gc, uin_t uin,
+- int status, const char *descr)
+-{
+- gchar *from;
+- const char *st;
+- char *status_msg = NULL;
+-
+- ggp_update_buddy_avatar(gc, uin);
+-
+- from = g_strdup_printf("%u", uin);
+-
+- switch (status) {
+- case GG_STATUS_NOT_AVAIL:
+- case GG_STATUS_NOT_AVAIL_DESCR:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_OFFLINE);
+- break;
+- case GG_STATUS_FFC:
+- case GG_STATUS_FFC_DESCR:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
+- break;
+- case GG_STATUS_AVAIL:
+- case GG_STATUS_AVAIL_DESCR:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
+- break;
+- case GG_STATUS_BUSY:
+- case GG_STATUS_BUSY_DESCR:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AWAY);
+- break;
+- case GG_STATUS_DND:
+- case GG_STATUS_DND_DESCR:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_UNAVAILABLE);
+- break;
+- case GG_STATUS_BLOCKED:
+- /* user is blocking us.... */
+- st = "blocked";
+- break;
+- default:
+- st = purple_primitive_get_id_from_type(PURPLE_STATUS_AVAILABLE);
+- purple_debug_info("gg",
+- "GG_EVENT_NOTIFY: Unknown status: %d\n", status);
+- break;
+- }
+-
+- if (descr != NULL) {
+- status_msg = g_strdup(descr);
+- g_strstrip(status_msg);
+- if (status_msg[0] == '\0') {
+- g_free(status_msg);
+- status_msg = NULL;
+- }
+- }
+-
+- purple_debug_info("gg", "status of %u is %s [%s]\n", uin, st,
+- status_msg ? status_msg : "");
+- if (status_msg == NULL) {
+- purple_prpl_got_user_status(purple_connection_get_account(gc),
+- from, st, NULL);
+- } else {
+- purple_prpl_got_user_status(purple_connection_get_account(gc),
+- from, st, "message", status_msg, NULL);
+- g_free(status_msg);
+- }
+- g_free(from);
+-}
+-
+-static void ggp_sr_close_cb(gpointer user_data)
+-{
+- GGPSearchForm *form = user_data;
+- GGPInfo *info = form->user_data;
+-
+- ggp_search_remove(info->searches, form->seq);
+- purple_debug_info("gg", "ggp_sr_close_cb(): Removed seq %u\n",
+- form->seq);
+- ggp_search_form_destroy(form);
+-}
+-
+-/**
+- * Translate a status' ID to a more user-friendly name.
+- *
+- * @param id The ID of the status.
+- *
+- * @return The user-friendly name of the status.
+- */
+-static const char *ggp_status_by_id(unsigned int id)
+-{
+- const char *st;
+-
+- purple_debug_info("gg", "ggp_status_by_id: %d\n", id);
+- switch (id) {
+- case GG_STATUS_NOT_AVAIL:
+- case GG_STATUS_NOT_AVAIL_DESCR:
+- st = _("Offline");
+- break;
+- case GG_STATUS_AVAIL:
+- case GG_STATUS_AVAIL_DESCR:
+- st = _("Available");
+- break;
+- case GG_STATUS_FFC:
+- case GG_STATUS_FFC_DESCR:
+- return _("Chatty");
+- case GG_STATUS_DND:
+- case GG_STATUS_DND_DESCR:
+- return _("Do Not Disturb");
+- case GG_STATUS_BUSY:
+- case GG_STATUS_BUSY_DESCR:
+- st = _("Away");
+- break;
+- default:
+- st = _("Unknown");
+- break;
+- }
+-
+- return st;
+-}
+-
+-static void ggp_pubdir_handle_info(PurpleConnection *gc, gg_pubdir50_t req,
+- GGPSearchForm *form)
+-{
+- PurpleNotifyUserInfo *user_info;
+- PurpleBuddy *buddy;
+- char *val, *who;
+-
+- user_info = purple_notify_user_info_new();
+-
+- val = ggp_search_get_result(req, 0, GG_PUBDIR50_STATUS);
+- /* XXX: Use of ggp_str_to_uin() is an ugly hack! */
+- purple_notify_user_info_add_pair(user_info, _("Status"), ggp_status_by_id(ggp_str_to_uin(val)));
+- g_free(val);
+-
+- who = ggp_search_get_result(req, 0, GG_PUBDIR50_UIN);
+- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+-
+- val = ggp_search_get_result(req, 0, GG_PUBDIR50_FIRSTNAME);
+- purple_notify_user_info_add_pair(user_info, _("First Name"), val);
+- g_free(val);
+-
+- val = ggp_search_get_result(req, 0, GG_PUBDIR50_NICKNAME);
+- purple_notify_user_info_add_pair(user_info, _("Nickname"), val);
+- g_free(val);
+-
+- val = ggp_search_get_result(req, 0, GG_PUBDIR50_CITY);
+- purple_notify_user_info_add_pair(user_info, _("City"), val);
+- g_free(val);
+-
+- val = ggp_search_get_result(req, 0, GG_PUBDIR50_BIRTHYEAR);
+- if (strncmp(val, "0", 1)) {
+- purple_notify_user_info_add_pair(user_info, _("Birth Year"), val);
+- }
+- g_free(val);
+-
+- /*
+- * Include a status message, if exists and buddy is in the blist.
+- */
+- buddy = purple_find_buddy(purple_connection_get_account(gc), who);
+- if (NULL != buddy) {
+- PurpleStatus *status;
+- const char *msg;
+- char *text;
+-
+- status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));
+- msg = purple_status_get_attr_string(status, "message");
+-
+- if (msg != NULL) {
+- text = g_markup_escape_text(msg, -1);
+- purple_notify_user_info_add_pair(user_info, _("Message"), text);
+- g_free(text);
+- }
+- }
+-
+- purple_notify_userinfo(gc, who, user_info, ggp_sr_close_cb, form);
+- g_free(who);
+- purple_notify_user_info_destroy(user_info);
+-}
+-
+-static void ggp_pubdir_handle_full(PurpleConnection *gc, gg_pubdir50_t req,
+- GGPSearchForm *form)
+-{
+- PurpleNotifySearchResults *results;
+- PurpleNotifySearchColumn *column;
+- int res_count;
+- int start;
+- int i;
+-
+- g_return_if_fail(form != NULL);
+-
+- res_count = gg_pubdir50_count(req);
+- res_count = (res_count > PUBDIR_RESULTS_MAX) ? PUBDIR_RESULTS_MAX : res_count;
+- if (form->page_size == 0)
+- form->page_size = res_count;
+-
+- results = purple_notify_searchresults_new();
+-
+- if (results == NULL) {
+- purple_debug_error("gg", "ggp_pubdir_reply_handler: "
+- "Unable to display the search results.\n");
+- purple_notify_error(gc, NULL,
+- _("Unable to display the search results."),
+- NULL);
+- if (form->window == NULL)
+- ggp_sr_close_cb(form);
+- return;
+- }
+-
+- column = purple_notify_searchresults_column_new(_("UIN"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- column = purple_notify_searchresults_column_new(_("First Name"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- column = purple_notify_searchresults_column_new(_("Nickname"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- column = purple_notify_searchresults_column_new(_("City"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- column = purple_notify_searchresults_column_new(_("Birth Year"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- purple_debug_info("gg", "Going with %d entries\n", res_count);
+-
+- start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START));
+- purple_debug_info("gg", "start = %d\n", start);
+-
+- for (i = 0; i < res_count; i++) {
+- GList *row = NULL;
+- char *birth = ggp_search_get_result(req, i, GG_PUBDIR50_BIRTHYEAR);
+-
+- /* TODO: Status will be displayed as an icon. */
+- /* row = g_list_append(row, ggp_search_get_result(req, i, GG_PUBDIR50_STATUS)); */
+- row = g_list_append(row, ggp_search_get_result(req, i,
+- GG_PUBDIR50_UIN));
+- row = g_list_append(row, ggp_search_get_result(req, i,
+- GG_PUBDIR50_FIRSTNAME));
+- row = g_list_append(row, ggp_search_get_result(req, i,
+- GG_PUBDIR50_NICKNAME));
+- row = g_list_append(row, ggp_search_get_result(req, i,
+- GG_PUBDIR50_CITY));
+- row = g_list_append(row,
+- (birth && strncmp(birth, "0", 1)) ? birth : g_strdup("-"));
+-
+- purple_notify_searchresults_row_add(results, row);
+- }
+-
+- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_CONTINUE,
+- ggp_callback_show_next);
+- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD,
+- ggp_callback_add_buddy);
+- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_IM,
+- ggp_callback_im);
+-
+- if (form->window == NULL) {
+- void *h = purple_notify_searchresults(gc,
+- _("Gadu-Gadu Public Directory"),
+- _("Search results"), NULL, results,
+- (PurpleNotifyCloseCallback)ggp_sr_close_cb,
+- form);
+-
+- if (h == NULL) {
+- purple_debug_error("gg", "ggp_pubdir_reply_handler: "
+- "Unable to display the search results.\n");
+- purple_notify_error(gc, NULL,
+- _("Unable to display the search results."),
+- NULL);
+- return;
+- }
+-
+- form->window = h;
+- } else {
+- purple_notify_searchresults_new_rows(gc, results, form->window);
+- }
+-}
+-
+-static void ggp_pubdir_reply_handler(PurpleConnection *gc, gg_pubdir50_t req)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPSearchForm *form;
+- int res_count;
+- guint32 seq;
+-
+- seq = gg_pubdir50_seq(req);
+- form = ggp_search_get(info->searches, seq);
+- purple_debug_info("gg",
+- "ggp_pubdir_reply_handler(): seq %u --> form %p\n", seq, form);
+- /*
+- * this can happen when user will request more results
+- * and close the results window before they arrive.
+- */
+- g_return_if_fail(form != NULL);
+-
+- res_count = gg_pubdir50_count(req);
+- if (res_count < 1) {
+- purple_debug_info("gg", "GG_EVENT_PUBDIR50_SEARCH_REPLY: Nothing found\n");
+- purple_notify_error(gc, NULL,
+- _("No matching users found"),
+- _("There are no users matching your search criteria."));
+- if (form->window == NULL)
+- ggp_sr_close_cb(form);
+- return;
+- }
+-
+- switch (form->search_type) {
+- case GGP_SEARCH_TYPE_INFO:
+- ggp_pubdir_handle_info(gc, req, form);
+- break;
+- case GGP_SEARCH_TYPE_FULL:
+- ggp_pubdir_handle_full(gc, req, form);
+- break;
+- default:
+- purple_debug_warning("gg", "Unknown search_type!\n");
+- break;
+- }
+-}
+-
+-static void ggp_recv_image_handler(PurpleConnection *gc, const struct gg_event *ev)
+-{
+- gint imgid = 0;
+- GGPInfo *info = gc->proto_data;
+- GList *entry = g_list_first(info->pending_richtext_messages);
+- gchar *handlerid = g_strdup_printf("IMGID_HANDLER-%i", ev->event.image_reply.crc32);
+-
+- imgid = purple_imgstore_add_with_id(
+- g_memdup(ev->event.image_reply.image, ev->event.image_reply.size),
+- ev->event.image_reply.size,
+- ev->event.image_reply.filename);
+-
+- purple_debug_info("gg", "ggp_recv_image_handler: got image with crc32: %u\n", ev->event.image_reply.crc32);
+-
+- while(entry) {
+- if (strstr((gchar *)entry->data, handlerid) != NULL) {
+- gchar **split = g_strsplit((gchar *)entry->data, handlerid, 3);
+- gchar *text = g_strdup_printf("%s%i%s", split[0], imgid, split[1]);
+- purple_debug_info("gg", "ggp_recv_image_handler: found message matching crc32: %s\n", (gchar *)entry->data);
+- g_strfreev(split);
+- info->pending_richtext_messages = g_list_remove(info->pending_richtext_messages, entry->data);
+- /* We don't have any more images to download */
+- if (strstr(text, "<IMG ID=\"IMGID_HANDLER") == NULL) {
+- gchar *buf = g_strdup_printf("%lu", (unsigned long int)ev->event.image_reply.sender);
+- serv_got_im(gc, buf, text, PURPLE_MESSAGE_IMAGES, time(NULL));
+- g_free(buf);
+- purple_debug_info("gg", "ggp_recv_image_handler: richtext message: %s\n", text);
+- g_free(text);
+- break;
+- }
+- info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, text);
+- break;
+- }
+- entry = g_list_next(entry);
+- }
+- g_free(handlerid);
+-
+- return;
+-}
+-
+-
+-/**
+- * Dispatch a message received from a buddy.
+- *
+- * @param gc PurpleConnection.
+- * @param ev Gadu-Gadu event structure.
+- *
+- * Image receiving, some code borrowed from Kadu http://www.kadu.net
+- */
+-static void ggp_recv_message_handler(PurpleConnection *gc, const struct gg_event *ev)
+-{
+- GGPInfo *info = gc->proto_data;
+- PurpleConversation *conv;
+- gchar *from;
+- gchar *msg;
+- gchar *tmp;
+-
+- if (ev->event.msg.message == NULL)
+- {
+- purple_debug_warning("gg", "ggp_recv_message_handler: NULL as message pointer\n");
+- return;
+- }
+-
+- from = g_strdup_printf("%lu", (unsigned long int)ev->event.msg.sender);
+-
+- /*
+- tmp = charset_convert((const char *)ev->event.msg.message,
+- "CP1250", "UTF-8");
+- */
+- tmp = g_strdup_printf("%s", ev->event.msg.message);
+- purple_str_strip_char(tmp, '\r');
+- msg = g_markup_escape_text(tmp, -1);
+- g_free(tmp);
+-
+- /* We got richtext message */
+- if (ev->event.msg.formats_length)
+- {
+- gboolean got_image = FALSE, bold = FALSE, italic = FALSE, under = FALSE;
+- char *cformats = (char *)ev->event.msg.formats;
+- char *cformats_end = cformats + ev->event.msg.formats_length;
+- gint increased_len = 0;
+- struct gg_msg_richtext_format *actformat;
+- struct gg_msg_richtext_image *actimage;
+- GString *message = g_string_new(msg);
+- gchar *handlerid;
+-
+- purple_debug_info("gg", "ggp_recv_message_handler: richtext msg from (%s): %s %i formats\n", from, msg, ev->event.msg.formats_length);
+-
+- while (cformats < cformats_end)
+- {
+- gint byteoffset;
+- actformat = (struct gg_msg_richtext_format *)cformats;
+- cformats += sizeof(struct gg_msg_richtext_format);
+- byteoffset = g_utf8_offset_to_pointer(message->str, actformat->position + increased_len) - message->str;
+-
+- if(actformat->position == 0 && actformat->font == 0) {
+- purple_debug_warning("gg", "ggp_recv_message_handler: bogus formatting (inc: %i)\n", increased_len);
+- continue;
+- }
+- purple_debug_info("gg", "ggp_recv_message_handler: format at pos: %i, image:%i, bold:%i, italic: %i, under:%i (inc: %i)\n",
+- actformat->position,
+- (actformat->font & GG_FONT_IMAGE) != 0,
+- (actformat->font & GG_FONT_BOLD) != 0,
+- (actformat->font & GG_FONT_ITALIC) != 0,
+- (actformat->font & GG_FONT_UNDERLINE) != 0,
+- increased_len);
+-
+- if (actformat->font & GG_FONT_IMAGE) {
+- got_image = TRUE;
+- actimage = (struct gg_msg_richtext_image*)(cformats);
+- cformats += sizeof(struct gg_msg_richtext_image);
+- purple_debug_info("gg", "ggp_recv_message_handler: image received, size: %d, crc32: %i\n", actimage->size, actimage->crc32);
+-
+- /* Checking for errors, image size shouldn't be
+- * larger than 255.000 bytes */
+- if (actimage->size > 255000) {
+- purple_debug_warning("gg", "ggp_recv_message_handler: received image large than 255 kb\n");
+- continue;
+- }
+-
+- gg_image_request(info->session, ev->event.msg.sender,
+- actimage->size, actimage->crc32);
+-
+- handlerid = g_strdup_printf("<IMG ID=\"IMGID_HANDLER-%i\">", actimage->crc32);
+- g_string_insert(message, byteoffset, handlerid);
+- increased_len += strlen(handlerid);
+- g_free(handlerid);
+- continue;
+- }
+-
+- if (actformat->font & GG_FONT_BOLD) {
+- if (bold == FALSE) {
+- g_string_insert(message, byteoffset, "<b>");
+- increased_len += 3;
+- bold = TRUE;
+- }
+- } else if (bold) {
+- g_string_insert(message, byteoffset, "</b>");
+- increased_len += 4;
+- bold = FALSE;
+- }
+-
+- if (actformat->font & GG_FONT_ITALIC) {
+- if (italic == FALSE) {
+- g_string_insert(message, byteoffset, "<i>");
+- increased_len += 3;
+- italic = TRUE;
+- }
+- } else if (italic) {
+- g_string_insert(message, byteoffset, "</i>");
+- increased_len += 4;
+- italic = FALSE;
+- }
+-
+- if (actformat->font & GG_FONT_UNDERLINE) {
+- if (under == FALSE) {
+- g_string_insert(message, byteoffset, "<u>");
+- increased_len += 3;
+- under = TRUE;
+- }
+- } else if (under) {
+- g_string_insert(message, byteoffset, "</u>");
+- increased_len += 4;
+- under = FALSE;
+- }
+-
+- if (actformat->font & GG_FONT_COLOR) {
+- cformats += sizeof(struct gg_msg_richtext_color);
+- }
+- }
+-
+- msg = message->str;
+- g_string_free(message, FALSE);
+-
+- if (got_image) {
+- info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, msg);
+- return;
+- }
+- }
+-
+- purple_debug_info("gg", "ggp_recv_message_handler: msg from (%s): %s (class = %d; rcpt_count = %d)\n",
+- from, msg, ev->event.msg.msgclass,
+- ev->event.msg.recipients_count);
+-
+- if (ev->event.msg.recipients_count == 0) {
+- serv_got_im(gc, from, msg, 0, ev->event.msg.time);
+- } else {
+- const char *chat_name;
+- int chat_id;
+- char *buddy_name;
+-
+- chat_name = ggp_confer_find_by_participants(gc,
+- ev->event.msg.recipients,
+- ev->event.msg.recipients_count);
+-
+- if (chat_name == NULL) {
+- chat_name = ggp_confer_add_new(gc, NULL);
+- serv_got_joined_chat(gc, info->chats_count, chat_name);
+-
+- ggp_confer_participants_add_uin(gc, chat_name,
+- ev->event.msg.sender);
+-
+- ggp_confer_participants_add(gc, chat_name,
+- ev->event.msg.recipients,
+- ev->event.msg.recipients_count);
+- }
+- conv = ggp_confer_find_by_name(gc, chat_name);
+- chat_id = purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv));
+-
+- buddy_name = ggp_buddy_get_name(gc, ev->event.msg.sender);
+- serv_got_chat_in(gc, chat_id, buddy_name,
+- PURPLE_MESSAGE_RECV, msg, ev->event.msg.time);
+- g_free(buddy_name);
+- }
+- g_free(msg);
+- g_free(from);
+-}
+-
+-static void ggp_send_image_handler(PurpleConnection *gc, const struct gg_event *ev)
+-{
+- GGPInfo *info = gc->proto_data;
+- PurpleStoredImage *image;
+- gint imgid = GPOINTER_TO_INT(g_hash_table_lookup(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32)));
+-
+- purple_debug_info("gg", "ggp_send_image_handler: image request received, crc32: %u, imgid: %d\n", ev->event.image_request.crc32, imgid);
+-
+- if(imgid)
+- {
+- if((image = purple_imgstore_find_by_id(imgid))) {
+- gint image_size = purple_imgstore_get_size(image);
+- gconstpointer image_bin = purple_imgstore_get_data(image);
+- const char *image_filename = purple_imgstore_get_filename(image);
+-
+- purple_debug_info("gg", "ggp_send_image_handler: sending image imgid: %i, crc: %u\n", imgid, ev->event.image_request.crc32);
+- gg_image_reply(info->session, (unsigned long int)ev->event.image_request.sender, image_filename, image_bin, image_size);
+- purple_imgstore_unref(image);
+- } else {
+- purple_debug_error("gg", "ggp_send_image_handler: image imgid: %i, crc: %u in hash but not found in imgstore!\n", imgid, ev->event.image_request.crc32);
+- }
+- g_hash_table_remove(info->pending_images, GINT_TO_POINTER(ev->event.image_request.crc32));
+- }
+-}
+-
+-static void ggp_typing_notification_handler(PurpleConnection *gc, uin_t uin, int length) {
+- gchar *from;
+-
+- from = g_strdup_printf("%u", uin);
+- if (length)
+- serv_got_typing(gc, from, 0, PURPLE_TYPING);
+- else
+- serv_got_typing_stopped(gc, from);
+- g_free(from);
+-}
+-
+-/**
+- * Handling of XML events.
+- *
+- * @param gc PurpleConnection.
+- * @param data Raw XML contents.
+- *
+- * @see http://toxygen.net/libgadu/protocol/#ch1.13
+- */
+-static void ggp_xml_event_handler(PurpleConnection *gc, char *data)
+-{
+- xmlnode *xml = NULL;
+- xmlnode *xmlnode_next_event;
+-
+- xml = xmlnode_from_str(data, -1);
+- if (xml == NULL)
+- goto out;
+-
+- xmlnode_next_event = xmlnode_get_child(xml, "event");
+- while (xmlnode_next_event != NULL)
+- {
+- xmlnode *xmlnode_current_event = xmlnode_next_event;
+-
+- xmlnode *xmlnode_type;
+- char *event_type_raw;
+- int event_type = 0;
+-
+- xmlnode *xmlnode_sender;
+- char *event_sender_raw;
+- uin_t event_sender = 0;
+-
+- xmlnode_next_event = xmlnode_get_next_twin(xmlnode_next_event);
+-
+- xmlnode_type = xmlnode_get_child(xmlnode_current_event, "type");
+- if (xmlnode_type == NULL)
+- continue;
+- event_type_raw = xmlnode_get_data(xmlnode_type);
+- if (event_type_raw != NULL)
+- event_type = atoi(event_type_raw);
+- g_free(event_type_raw);
+-
+- xmlnode_sender = xmlnode_get_child(xmlnode_current_event, "sender");
+- if (xmlnode_sender != NULL)
+- {
+- event_sender_raw = xmlnode_get_data(xmlnode_sender);
+- if (event_sender_raw != NULL)
+- event_sender = ggp_str_to_uin(event_sender_raw);
+- g_free(event_sender_raw);
+- }
+-
+- switch (event_type)
+- {
+- case 28: /* avatar update */
+- purple_debug_info("gg",
+- "ggp_xml_event_handler: avatar updated (uid: %u)\n",
+- event_sender);
+- ggp_update_buddy_avatar(gc, event_sender);
+- break;
+- default:
+- purple_debug_error("gg",
+- "ggp_xml_event_handler: unsupported event type=%d from=%u\n",
+- event_type, event_sender);
+- }
+- }
+-
+- out:
+- if (xml)
+- xmlnode_free(xml);
+-}
+-
+-static void ggp_callback_recv(gpointer _gc, gint fd, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = _gc;
+- GGPInfo *info = gc->proto_data;
+- struct gg_event *ev;
+- int i;
+-
+- if (!(ev = gg_watch_fd(info->session))) {
+- purple_debug_error("gg",
+- "ggp_callback_recv: gg_watch_fd failed -- CRITICAL!\n");
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to read from socket"));
+- return;
+- }
+-
+- switch (ev->type) {
+- case GG_EVENT_NONE:
+- /* Nothing happened. */
+- break;
+- case GG_EVENT_MSG:
+- ggp_recv_message_handler(gc, ev);
+- break;
+- case GG_EVENT_ACK:
+- /* Changing %u to %i fixes compiler warning */
+- purple_debug_info("gg",
+- "ggp_callback_recv: message sent to: %i, delivery status=%d, seq=%d\n",
+- ev->event.ack.recipient, ev->event.ack.status,
+- ev->event.ack.seq);
+- break;
+- case GG_EVENT_IMAGE_REPLY:
+- ggp_recv_image_handler(gc, ev);
+- break;
+- case GG_EVENT_IMAGE_REQUEST:
+- ggp_send_image_handler(gc, ev);
+- break;
+- case GG_EVENT_NOTIFY:
+- case GG_EVENT_NOTIFY_DESCR:
+- {
+- struct gg_notify_reply *n;
+- char *descr;
+-
+- purple_debug_info("gg", "notify_pre: (%d) status: %d\n",
+- ev->event.notify->uin,
+- GG_S(ev->event.notify->status));
+-
+- n = (ev->type == GG_EVENT_NOTIFY) ? ev->event.notify
+- : ev->event.notify_descr.notify;
+-
+- for (; n->uin; n++) {
+- descr = (ev->type == GG_EVENT_NOTIFY) ? NULL
+- : ev->event.notify_descr.descr;
+-
+- purple_debug_info("gg",
+- "notify: (%d) status: %d; descr: %s\n",
+- n->uin, GG_S(n->status), descr ? descr : "(null)");
+-
+- ggp_generic_status_handler(gc,
+- n->uin, GG_S(n->status), descr);
+- }
+- }
+- break;
+- case GG_EVENT_NOTIFY60:
+- for (i = 0; ev->event.notify60[i].uin; i++) {
+- purple_debug_info("gg",
+- "notify60: (%d) status=%d; version=%d; descr=%s\n",
+- ev->event.notify60[i].uin,
+- GG_S(ev->event.notify60[i].status),
+- ev->event.notify60[i].version,
+- ev->event.notify60[i].descr ? ev->event.notify60[i].descr : "(null)");
+-
+- ggp_generic_status_handler(gc, ev->event.notify60[i].uin,
+- GG_S(ev->event.notify60[i].status),
+- ev->event.notify60[i].descr);
+- }
+- break;
+- case GG_EVENT_STATUS:
+- purple_debug_info("gg", "status: (%d) status=%d; descr=%s\n",
+- ev->event.status.uin, GG_S(ev->event.status.status),
+- ev->event.status.descr ? ev->event.status.descr : "(null)");
+-
+- ggp_generic_status_handler(gc, ev->event.status.uin,
+- GG_S(ev->event.status.status), ev->event.status.descr);
+- break;
+- case GG_EVENT_STATUS60:
+- purple_debug_info("gg",
+- "status60: (%d) status=%d; version=%d; descr=%s\n",
+- ev->event.status60.uin, GG_S(ev->event.status60.status),
+- ev->event.status60.version,
+- ev->event.status60.descr ? ev->event.status60.descr : "(null)");
+-
+- ggp_generic_status_handler(gc, ev->event.status60.uin,
+- GG_S(ev->event.status60.status), ev->event.status60.descr);
+- break;
+- case GG_EVENT_USERLIST:
+- if (ev->event.userlist.type == GG_USERLIST_GET_REPLY) {
+- purple_debug_info("gg", "GG_USERLIST_GET_REPLY\n");
+- purple_notify_info(gc, NULL,
+- _("Buddy list downloaded"),
+- _("Your buddy list was downloaded from the server."));
+- if (ev->event.userlist.reply != NULL) {
+- ggp_buddylist_load(gc, ev->event.userlist.reply);
+- }
+- } else {
+- purple_debug_info("gg", "GG_USERLIST_PUT_REPLY\n");
+- purple_notify_info(gc, NULL,
+- _("Buddy list uploaded"),
+- _("Your buddy list was stored on the server."));
+- }
+- break;
+- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
+- ggp_pubdir_reply_handler(gc, ev->event.pubdir50);
+- break;
+- case GG_EVENT_TYPING_NOTIFICATION:
+- ggp_typing_notification_handler(gc, ev->event.typing_notification.uin,
+- ev->event.typing_notification.length);
+- break;
+- case GG_EVENT_XML_EVENT:
+- purple_debug_info("gg", "GG_EVENT_XML_EVENT\n");
+- ggp_xml_event_handler(gc, ev->event.xml_event.data);
+- break;
+- default:
+- purple_debug_error("gg",
+- "unsupported event type=%d\n", ev->type);
+- break;
+- }
+-
+- gg_free_event(ev);
+-}
+-
+-static void ggp_async_login_handler(gpointer _gc, gint fd, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = _gc;
+- GGPInfo *info;
+- struct gg_event *ev;
+-
+- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
+-
+- info = gc->proto_data;
+-
+- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
+- info->session->check, info->session->state);
+-
+- switch (info->session->state) {
+- case GG_STATE_RESOLVING:
+- purple_debug_info("gg", "GG_STATE_RESOLVING\n");
+- break;
+- case GG_STATE_RESOLVING_GG:
+- purple_debug_info("gg", "GG_STATE_RESOLVING_GG\n");
+- break;
+- case GG_STATE_CONNECTING_HUB:
+- purple_debug_info("gg", "GG_STATE_CONNECTING_HUB\n");
+- break;
+- case GG_STATE_READING_DATA:
+- purple_debug_info("gg", "GG_STATE_READING_DATA\n");
+- break;
+- case GG_STATE_CONNECTING_GG:
+- purple_debug_info("gg", "GG_STATE_CONNECTING_GG\n");
+- break;
+- case GG_STATE_READING_KEY:
+- purple_debug_info("gg", "GG_STATE_READING_KEY\n");
+- break;
+- case GG_STATE_READING_REPLY:
+- purple_debug_info("gg", "GG_STATE_READING_REPLY\n");
+- break;
+- case GG_STATE_TLS_NEGOTIATION:
+- purple_debug_info("gg", "GG_STATE_TLS_NEGOTIATION\n");
+- break;
+- default:
+- purple_debug_error("gg", "unknown state = %d\n",
+- info->session->state);
+- break;
+- }
+-
+- if (!(ev = gg_watch_fd(info->session))) {
+- purple_debug_error("gg", "login_handler: gg_watch_fd failed!\n");
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to read from socket"));
+- return;
+- }
+- purple_debug_info("gg", "login_handler: session->fd = %d\n", info->session->fd);
+- purple_debug_info("gg", "login_handler: session: check = %d; state = %d;\n",
+- info->session->check, info->session->state);
+-
+- purple_input_remove(gc->inpa);
+-
+- /** XXX I think that this shouldn't be done if ev->type is GG_EVENT_CONN_FAILED or GG_EVENT_CONN_SUCCESS -datallah */
+- if (info->session->fd >= 0)
+- gc->inpa = purple_input_add(info->session->fd,
+- (info->session->check == 1) ? PURPLE_INPUT_WRITE :
+- PURPLE_INPUT_READ,
+- ggp_async_login_handler, gc);
+-
+- switch (ev->type) {
+- case GG_EVENT_NONE:
+- /* Nothing happened. */
+- purple_debug_info("gg", "GG_EVENT_NONE\n");
+- break;
+- case GG_EVENT_CONN_SUCCESS:
+- {
+- purple_debug_info("gg", "GG_EVENT_CONN_SUCCESS\n");
+- purple_input_remove(gc->inpa);
+- gc->inpa = purple_input_add(info->session->fd,
+- PURPLE_INPUT_READ,
+- ggp_callback_recv, gc);
+-
+- ggp_buddylist_send(gc);
+- purple_connection_update_progress(gc, _("Connected"), 1, 2);
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+- }
+- break;
+- case GG_EVENT_CONN_FAILED:
+- purple_input_remove(gc->inpa);
+- gc->inpa = 0;
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Connection failed"));
+- break;
+- case GG_EVENT_MSG:
+- if (ev->event.msg.sender == 0)
+- /* system messages are mostly ads */
+- purple_debug_info("gg", "System message:\n%s\n",
+- ev->event.msg.message);
+- else
+- purple_debug_warning("gg", "GG_EVENT_MSG: message from user %u "
+- "unexpected while connecting:\n%s\n",
+- ev->event.msg.sender,
+- ev->event.msg.message);
+- break;
+- default:
+- purple_debug_error("gg", "strange event: %d\n", ev->type);
+- break;
+- }
+-
+- gg_free_event(ev);
+-}
+-
+-/* ---------------------------------------------------------------------- */
+-/* ----- PurplePluginProtocolInfo ----------------------------------------- */
+-/* ---------------------------------------------------------------------- */
+-
+-static const char *ggp_list_icon(PurpleAccount *account, PurpleBuddy *buddy)
+-{
+- return "gadu-gadu";
+-}
+-
+-static char *ggp_status_text(PurpleBuddy *b)
+-{
+- PurpleStatus *status;
+- const char *msg;
+- char *text;
+- char *tmp;
+-
+- status = purple_presence_get_active_status(
+- purple_buddy_get_presence(b));
+- msg = purple_status_get_attr_string(status, "message");
+-
+- if (msg == NULL)
+- return NULL;
+-
+- tmp = purple_markup_strip_html(msg);
+- text = g_markup_escape_text(tmp, -1);
+- g_free(tmp);
+-
+- return text;
+-}
+-
+-static void ggp_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
+-{
+- PurpleStatus *status;
+- char *text, *tmp;
+- const char *msg, *name, *alias;
+-
+- g_return_if_fail(b != NULL);
+-
+- status = purple_presence_get_active_status(purple_buddy_get_presence(b));
+- msg = purple_status_get_attr_string(status, "message");
+- name = purple_status_get_name(status);
+- alias = purple_buddy_get_alias(b);
+-
+- purple_notify_user_info_add_pair (user_info, _("Alias"), alias);
+-
+- if (msg != NULL) {
+- text = g_markup_escape_text(msg, -1);
+- if (PURPLE_BUDDY_IS_ONLINE(b)) {
+- tmp = g_strdup_printf("%s: %s", name, text);
+- purple_notify_user_info_add_pair(user_info, _("Status"), tmp);
+- g_free(tmp);
+- } else {
+- purple_notify_user_info_add_pair(user_info, _("Message"), text);
+- }
+- g_free(text);
+- /* We don't want to duplicate 'Status: Offline'. */
+- } else if (PURPLE_BUDDY_IS_ONLINE(b)) {
+- purple_notify_user_info_add_pair(user_info, _("Status"), name);
+- }
+-}
+-
+-static GList *ggp_status_types(PurpleAccount *account)
+-{
+- PurpleStatusType *type;
+- GList *types = NULL;
+-
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- /*
+- * Without this selecting Invisible as own status doesn't
+- * work. It's not used and not needed to show status of buddies.
+- */
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_INVISIBLE, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- /*
+- * New statuses for GG 8.0 like PoGGadaj ze mna (not yet because
+- * libpurple can't support Chatty status) and Nie przeszkadzac
+- */
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_UNAVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- /*
+- * This status is necessary to display guys who are blocking *us*.
+- */
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_INVISIBLE, "blocked", _("Blocked"), TRUE, FALSE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING), NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- return types;
+-}
+-
+-static GList *ggp_blist_node_menu(PurpleBlistNode *node)
+-{
+- PurpleMenuAction *act;
+- GList *m = NULL;
+- PurpleAccount *account;
+- GGPInfo *info;
+-
+- if (!PURPLE_BLIST_NODE_IS_BUDDY(node))
+- return NULL;
+-
+- account = purple_buddy_get_account((PurpleBuddy *) node);
+- info = purple_account_get_connection(account)->proto_data;
+- if (info->chats) {
+- act = purple_menu_action_new(_("Add to chat"),
+- PURPLE_CALLBACK(ggp_bmenu_add_to_chat),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+-
+- return m;
+-}
+-
+-static GList *ggp_chat_info(PurpleConnection *gc)
+-{
+- GList *m = NULL;
+- struct proto_chat_entry *pce;
+-
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _("Chat _name:");
+- pce->identifier = "name";
+- pce->required = TRUE;
+- m = g_list_append(m, pce);
+-
+- return m;
+-}
+-
+-static void ggp_login(PurpleAccount *account)
+-{
+- PurpleConnection *gc;
+- PurplePresence *presence;
+- PurpleStatus *status;
+- struct gg_login_params *glp;
+- GGPInfo *info;
+- const char *address;
+- const gchar *encryption_type;
+-
+- if (ggp_setup_proxy(account) == -1)
+- return;
+-
+- gc = purple_account_get_connection(account);
+- glp = g_new0(struct gg_login_params, 1);
+- info = g_new0(GGPInfo, 1);
+-
+- /* Probably this should be moved to *_new() function. */
+- info->session = NULL;
+- info->chats = NULL;
+- info->chats_count = 0;
+- info->token = NULL;
+- info->searches = ggp_search_new();
+- info->pending_richtext_messages = NULL;
+- info->pending_images = g_hash_table_new(g_direct_hash, g_direct_equal);
+- info->status_broadcasting = purple_account_get_bool(account, "status_broadcasting", TRUE);
+-
+- gc->proto_data = info;
+-
+- glp->uin = ggp_get_uin(account);
+- glp->password = (char *)purple_account_get_password(account);
+- glp->image_size = 255;
+-
+- presence = purple_account_get_presence(account);
+- status = purple_presence_get_active_status(presence);
+-
+- glp->encoding = GG_ENCODING_UTF8;
+- glp->protocol_features = (GG_FEATURE_STATUS80|GG_FEATURE_DND_FFC
+- |GG_FEATURE_TYPING_NOTIFICATION);
+-
+- glp->async = 1;
+- glp->status = ggp_to_gg_status(status, &glp->status_descr);
+-
+- encryption_type = purple_account_get_string(account, "encryption", "none");
+- purple_debug_info("gg", "Requested encryption type: %s\n", encryption_type);
+- if (strcmp(encryption_type, "opportunistic_tls") == 0)
+- glp->tls = 1;
+- else
+- glp->tls = 0;
+- purple_debug_info("gg", "TLS enabled: %d\n", glp->tls);
+-
+- if (!info->status_broadcasting)
+- glp->status = glp->status|GG_STATUS_FRIENDS_MASK;
+-
+- address = purple_account_get_string(account, "gg_server", "");
+- if (address && *address) {
+- /* TODO: Make this non-blocking */
+- struct in_addr *addr = gg_gethostbyname(address);
+-
+- purple_debug_info("gg", "Using gg server given by user (%s)\n", address);
+-
+- if (addr == NULL) {
+- gchar *tmp = g_strdup_printf(_("Unable to resolve hostname '%s': %s"),
+- address, g_strerror(errno));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, /* should this be a settings error? */
+- tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- glp->server_addr = inet_addr(inet_ntoa(*addr));
+- glp->server_port = 8074;
+- free(addr);
+- } else
+- purple_debug_info("gg", "Trying to retrieve address from gg appmsg service\n");
+-
+- info->session = gg_login(glp);
+- purple_connection_update_progress(gc, _("Connecting"), 0, 2);
+- if (info->session == NULL) {
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Connection failed"));
+- g_free(glp);
+- return;
+- }
+- gc->inpa = purple_input_add(info->session->fd, PURPLE_INPUT_READ,
+- ggp_async_login_handler, gc);
+-}
+-
+-static void ggp_close(PurpleConnection *gc)
+-{
+-
+- if (gc == NULL) {
+- purple_debug_info("gg", "gc == NULL\n");
+- return;
+- }
+-
+- if (gc->proto_data) {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleStatus *status;
+- GGPInfo *info = gc->proto_data;
+-
+- status = purple_account_get_active_status(account);
+-
+- if (info->session != NULL) {
+- ggp_set_status(account, status);
+- gg_logoff(info->session);
+- gg_free_session(info->session);
+- }
+-
+- purple_account_set_bool(account, "status_broadcasting", info->status_broadcasting);
+-
+- /* Immediately close any notifications on this handle since that process depends
+- * upon the contents of info->searches, which we are about to destroy.
+- */
+- purple_notify_close_with_handle(gc);
+-
+- ggp_search_destroy(info->searches);
+- g_list_free(info->pending_richtext_messages);
+- g_hash_table_destroy(info->pending_images);
+- g_free(info);
+- gc->proto_data = NULL;
+- }
+-
+- if (gc->inpa > 0)
+- purple_input_remove(gc->inpa);
+-
+- purple_debug_info("gg", "Connection closed.\n");
+-}
+-
+-static int ggp_send_im(PurpleConnection *gc, const char *who, const char *msg,
+- PurpleMessageFlags flags)
+-{
+- GGPInfo *info = gc->proto_data;
+- char *tmp, *plain;
+- int ret = 1;
+- unsigned char format[1024];
+- unsigned int format_length = sizeof(struct gg_msg_richtext);
+- gint pos = 0;
+- GData *attribs;
+- const char *start, *end = NULL, *last;
+-
+- if (msg == NULL || *msg == '\0') {
+- return 0;
+- }
+-
+- last = msg;
+-
+- /* Check if the message is richtext */
+- /* TODO: Check formatting, too */
+- if(purple_markup_find_tag("img", last, &start, &end, &attribs)) {
+-
+- GString *string_buffer = g_string_new(NULL);
+- struct gg_msg_richtext fmt;
+-
+- do {
+- PurpleStoredImage *image;
+- const char *id;
+-
+- /* Add text before the image */
+- if(start - last) {
+- pos = pos + g_utf8_strlen(last, start - last);
+- g_string_append_len(string_buffer, last, start - last);
+- }
+-
+- if((id = g_datalist_get_data(&attribs, "id")) && (image = purple_imgstore_find_by_id(atoi(id)))) {
+- struct gg_msg_richtext_format actformat;
+- struct gg_msg_richtext_image actimage;
+- gint image_size = purple_imgstore_get_size(image);
+- gconstpointer image_bin = purple_imgstore_get_data(image);
+- const char *image_filename = purple_imgstore_get_filename(image);
+- uint32_t crc32 = gg_crc32(0, image_bin, image_size);
+-
+- g_hash_table_insert(info->pending_images, GINT_TO_POINTER(crc32), GINT_TO_POINTER(atoi(id)));
+- purple_imgstore_ref(image);
+- purple_debug_info("gg", "ggp_send_im_richtext: got crc: %u for imgid: %i\n", crc32, atoi(id));
+-
+- actformat.font = GG_FONT_IMAGE;
+- actformat.position = pos;
+-
+- actimage.unknown1 = 0x0109;
+- actimage.size = gg_fix32(image_size);
+- actimage.crc32 = gg_fix32(crc32);
+-
+- if (actimage.size > 255000) {
+- purple_debug_warning("gg", "ggp_send_im_richtext: image over 255kb!\n");
+- } else {
+- purple_debug_info("gg", "ggp_send_im_richtext: adding images to richtext, size: %i, crc32: %u, name: %s\n", actimage.size, actimage.crc32, image_filename);
+-
+- memcpy(format + format_length, &actformat, sizeof(actformat));
+- format_length += sizeof(actformat);
+- memcpy(format + format_length, &actimage, sizeof(actimage));
+- format_length += sizeof(actimage);
+- }
+- } else {
+- purple_debug_error("gg", "ggp_send_im_richtext: image not found in the image store!");
+- }
+-
+- last = end + 1;
+- g_datalist_clear(&attribs);
+-
+- } while(purple_markup_find_tag("img", last, &start, &end, &attribs));
+-
+- /* Add text after the images */
+- if(last && *last) {
+- pos = pos + g_utf8_strlen(last, -1);
+- g_string_append(string_buffer, last);
+- }
+-
+- fmt.flag = 2;
+- fmt.length = format_length - sizeof(fmt);
+- memcpy(format, &fmt, sizeof(fmt));
+-
+- purple_debug_info("gg", "ggp_send_im: richtext msg = %s\n", string_buffer->str);
+- plain = purple_unescape_html(string_buffer->str);
+- g_string_free(string_buffer, TRUE);
+- } else {
+- purple_debug_info("gg", "ggp_send_im: msg = %s\n", msg);
+- plain = purple_unescape_html(msg);
+- }
+-
+- /*
+- tmp = charset_convert(plain, "UTF-8", "CP1250");
+- */
+- tmp = g_strdup_printf("%s", plain);
+-
+- if (tmp && (format_length - sizeof(struct gg_msg_richtext))) {
+- if(gg_send_message_richtext(info->session, GG_CLASS_CHAT, ggp_str_to_uin(who), (unsigned char *)tmp, format, format_length) < 0) {
+- ret = -1;
+- } else {
+- ret = 1;
+- }
+- } else if (NULL == tmp || *tmp == 0) {
+- ret = 0;
+- } else if (strlen(tmp) > GG_MSG_MAXSIZE) {
+- ret = -E2BIG;
+- } else if (gg_send_message(info->session, GG_CLASS_CHAT,
+- ggp_str_to_uin(who), (unsigned char *)tmp) < 0) {
+- ret = -1;
+- } else {
+- ret = 1;
+- }
+-
+- g_free(plain);
+- g_free(tmp);
+-
+- return ret;
+-}
+-
+-static unsigned int ggp_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
+-{
+- int dummy_length; // we don't send real length of typed message
+-
+- if (state == PURPLE_TYPED) // not supported
+- return 1;
+-
+- if (state == PURPLE_TYPING)
+- dummy_length = (int)g_random_int();
+- else // PURPLE_NOT_TYPING
+- dummy_length = 0;
+-
+- gg_typing_notification(
+- ((GGPInfo*)gc->proto_data)->session,
+- ggp_str_to_uin(name),
+- dummy_length);
+-
+- return 1; // wait 1 second before another notification
+-}
+-
+-static void ggp_get_info(PurpleConnection *gc, const char *name)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPSearchForm *form;
+- guint32 seq;
+-
+- form = ggp_search_form_new(GGP_SEARCH_TYPE_INFO);
+-
+- form->user_data = info;
+- form->uin = g_strdup(name);
+-
+- seq = ggp_search_start(gc, form);
+- ggp_search_add(info->searches, seq, form);
+- purple_debug_info("gg", "ggp_get_info(): Added seq %u", seq);
+-}
+-
+-static int ggp_to_gg_status(PurpleStatus *status, char **msg)
+-{
+- const char *status_id = purple_status_get_id(status);
+- int new_status, new_status_descr;
+- const char *new_msg;
+-
+- g_return_val_if_fail(msg != NULL, 0);
+-
+- purple_debug_info("gg", "ggp_to_gg_status: Requested status = %s\n",
+- status_id);
+-
+- if (strcmp(status_id, "available") == 0) {
+- new_status = GG_STATUS_AVAIL;
+- new_status_descr = GG_STATUS_AVAIL_DESCR;
+- } else if (strcmp(status_id, "away") == 0) {
+- new_status = GG_STATUS_BUSY;
+- new_status_descr = GG_STATUS_BUSY_DESCR;
+- } else if (strcmp(status_id, "unavailable") == 0) {
+- new_status = GG_STATUS_DND;
+- new_status_descr = GG_STATUS_DND_DESCR;
+- } else if (strcmp(status_id, "invisible") == 0) {
+- new_status = GG_STATUS_INVISIBLE;
+- new_status_descr = GG_STATUS_INVISIBLE_DESCR;
+- } else if (strcmp(status_id, "offline") == 0) {
+- new_status = GG_STATUS_NOT_AVAIL;
+- new_status_descr = GG_STATUS_NOT_AVAIL_DESCR;
+- } else {
+- new_status = GG_STATUS_AVAIL;
+- new_status_descr = GG_STATUS_AVAIL_DESCR;
+- purple_debug_info("gg",
+- "ggp_set_status: unknown status requested (status_id=%s)\n",
+- status_id);
+- }
+-
+- new_msg = purple_status_get_attr_string(status, "message");
+-
+- if(new_msg) {
+- /*
+- char *tmp = purple_markup_strip_html(new_msg);
+- *msg = charset_convert(tmp, "UTF-8", "CP1250");
+- g_free(tmp);
+- */
+- *msg = purple_markup_strip_html(new_msg);
+-
+- return new_status_descr;
+- } else {
+- *msg = NULL;
+- return new_status;
+- }
+-}
+-
+-static void ggp_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleConnection *gc;
+- GGPInfo *info;
+- int new_status;
+- char *new_msg = NULL;
+-
+- if (!purple_status_is_active(status))
+- return;
+-
+- gc = purple_account_get_connection(account);
+- info = gc->proto_data;
+-
+- new_status = ggp_to_gg_status(status, &new_msg);
+-
+- if (!info->status_broadcasting)
+- new_status = new_status|GG_STATUS_FRIENDS_MASK;
+-
+- if (new_msg == NULL) {
+- gg_change_status(info->session, new_status);
+- } else {
+- gg_change_status_descr(info->session, new_status, new_msg);
+- g_free(new_msg);
+- }
+-
+- ggp_status_fake_to_self(account);
+-
+-}
+-
+-static void ggp_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- PurpleAccount *account;
+- GGPInfo *info = gc->proto_data;
+- const gchar *name = purple_buddy_get_name(buddy);
+-
+- gg_add_notify(info->session, ggp_str_to_uin(name));
+-
+- account = purple_connection_get_account(gc);
+- if (strcmp(purple_account_get_username(account), name) == 0) {
+- ggp_status_fake_to_self(account);
+- }
+-}
+-
+-static void ggp_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy,
+- PurpleGroup *group)
+-{
+- GGPInfo *info = gc->proto_data;
+-
+- gg_remove_notify(info->session, ggp_str_to_uin(purple_buddy_get_name(buddy)));
+-}
+-
+-static void ggp_join_chat(PurpleConnection *gc, GHashTable *data)
+-{
+- GGPInfo *info = gc->proto_data;
+- GGPChat *chat;
+- char *chat_name;
+- GList *l;
+- PurpleConversation *conv;
+- PurpleAccount *account = purple_connection_get_account(gc);
+-
+- chat_name = g_hash_table_lookup(data, "name");
+-
+- if (chat_name == NULL)
+- return;
+-
+- purple_debug_info("gg", "joined %s chat\n", chat_name);
+-
+- for (l = info->chats; l != NULL; l = l->next) {
+- chat = l->data;
+-
+- if (chat != NULL && g_utf8_collate(chat->name, chat_name) == 0) {
+- purple_notify_error(gc, _("Chat error"),
+- _("This chat name is already in use"), NULL);
+- return;
+- }
+- }
+-
+- ggp_confer_add_new(gc, chat_name);
+- conv = serv_got_joined_chat(gc, info->chats_count, chat_name);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(conv),
+- purple_account_get_username(account), NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-static char *ggp_get_chat_name(GHashTable *data) {
+- return g_strdup(g_hash_table_lookup(data, "name"));
+-}
+-
+-static int ggp_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
+-{
+- PurpleConversation *conv;
+- GGPInfo *info = gc->proto_data;
+- GGPChat *chat = NULL;
+- GList *l;
+- /* char *msg, *plain; */
+- gchar *msg;
+- uin_t *uins;
+- int count = 0;
+-
+- if ((conv = purple_find_chat(gc, id)) == NULL)
+- return -EINVAL;
+-
+- for (l = info->chats; l != NULL; l = l->next) {
+- chat = l->data;
+-
+- if (g_utf8_collate(chat->name, conv->name) == 0) {
+- break;
+- }
+-
+- chat = NULL;
+- }
+-
+- if (chat == NULL) {
+- purple_debug_error("gg",
+- "ggp_chat_send: Hm... that's strange. No such chat?\n");
+- return -EINVAL;
+- }
+-
+- uins = g_new0(uin_t, g_list_length(chat->participants));
+-
+- for (l = chat->participants; l != NULL; l = l->next) {
+- uin_t uin = GPOINTER_TO_INT(l->data);
+-
+- uins[count++] = uin;
+- }
+-
+- /*
+- plain = purple_unescape_html(message);
+- msg = charset_convert(plain, "UTF-8", "CP1250");
+- g_free(plain);
+- */
+- msg = purple_unescape_html(message);
+- gg_send_message_confer(info->session, GG_CLASS_CHAT, count, uins,
+- (unsigned char *)msg);
+- g_free(msg);
+- g_free(uins);
+-
+- serv_got_chat_in(gc, id,
+- purple_account_get_username(purple_connection_get_account(gc)),
+- flags, message, time(NULL));
+-
+- return 0;
+-}
+-
+-static void ggp_keepalive(PurpleConnection *gc)
+-{
+- GGPInfo *info = gc->proto_data;
+-
+- /* purple_debug_info("gg", "Keeping connection alive....\n"); */
+-
+- if (gg_ping(info->session) < 0) {
+- purple_debug_info("gg", "Not connected to the server "
+- "or gg_session is not correct\n");
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Not connected to the server"));
+- }
+-}
+-
+-static void ggp_register_user(PurpleAccount *account)
+-{
+- PurpleConnection *gc = purple_account_get_connection(account);
+-
+- ggp_token_request(gc, ggp_register_user_dialog);
+-}
+-
+-static GList *ggp_actions(PurplePlugin *plugin, gpointer context)
+-{
+- GList *m = NULL;
+- PurplePluginAction *act;
+-
+- act = purple_plugin_action_new(_("Find buddies..."),
+- ggp_find_buddies);
+- m = g_list_append(m, act);
+-
+- m = g_list_append(m, NULL);
+-
+- act = purple_plugin_action_new(_("Change password..."),
+- ggp_change_passwd);
+- m = g_list_append(m, act);
+-
+- m = g_list_append(m, NULL);
+-
+- act = purple_plugin_action_new(_("Upload buddylist to Server"),
+- ggp_action_buddylist_put);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Download buddylist from Server"),
+- ggp_action_buddylist_get);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Delete buddylist from Server"),
+- ggp_action_buddylist_delete);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Save buddylist to file..."),
+- ggp_action_buddylist_save);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Load buddylist from file..."),
+- ggp_action_buddylist_load);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Change status broadcasting"),
+- ggp_action_change_status_broadcasting);
+- m = g_list_append(m, act);
+-
+- return m;
+-}
+-
+-static gboolean ggp_offline_message(const PurpleBuddy *buddy)
+-{
+- return TRUE;
+-}
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_IM_IMAGE,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"png", 32, 32, 96, 96, 0, PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+- ggp_list_icon, /* list_icon */
+- NULL, /* list_emblem */
+- ggp_status_text, /* status_text */
+- ggp_tooltip_text, /* tooltip_text */
+- ggp_status_types, /* status_types */
+- ggp_blist_node_menu, /* blist_node_menu */
+- ggp_chat_info, /* chat_info */
+- NULL, /* chat_info_defaults */
+- ggp_login, /* login */
+- ggp_close, /* close */
+- ggp_send_im, /* send_im */
+- NULL, /* set_info */
+- ggp_send_typing, /* send_typing */
+- ggp_get_info, /* get_info */
+- ggp_set_status, /* set_away */
+- NULL, /* set_idle */
+- NULL, /* change_passwd */
+- ggp_add_buddy, /* add_buddy */
+- NULL, /* add_buddies */
+- ggp_remove_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- ggp_add_deny, /* add_deny */
+- NULL, /* rem_permit */
+- ggp_rem_deny, /* rem_deny */
+- NULL, /* set_permit_deny */
+- ggp_join_chat, /* join_chat */
+- NULL, /* reject_chat */
+- ggp_get_chat_name, /* get_chat_name */
+- NULL, /* chat_invite */
+- NULL, /* chat_leave */
+- NULL, /* chat_whisper */
+- ggp_chat_send, /* chat_send */
+- ggp_keepalive, /* keepalive */
+- ggp_register_user, /* 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 */
+- NULL, /* set_buddy_icon */
+- NULL, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- NULL, /* can_receive_file */
+- NULL, /* send_file */
+- NULL, /* new_xfer */
+- ggp_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- NULL, /* send_attention */
+- NULL, /* get_attention_types */
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- NULL, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* can_do_media */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- NULL, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-static PurplePluginInfo info = {
+- PURPLE_PLUGIN_MAGIC, /* magic */
+- PURPLE_MAJOR_VERSION, /* major_version */
+- PURPLE_MINOR_VERSION, /* minor_version */
+- PURPLE_PLUGIN_PROTOCOL, /* plugin type */
+- NULL, /* ui_requirement */
+- 0, /* flags */
+- NULL, /* dependencies */
+- PURPLE_PRIORITY_DEFAULT, /* priority */
+-
+- "prpl-gg", /* id */
+- "Gadu-Gadu", /* name */
+- DISPLAY_VERSION, /* version */
+-
+- N_("Gadu-Gadu Protocol Plugin"), /* summary */
+- N_("Polish popular IM"), /* description */
+- "boler@sourceforge.net", /* author */
+- PURPLE_WEBSITE, /* homepage */
+-
+- NULL, /* load */
+- NULL, /* unload */
+- NULL, /* destroy */
+-
+- NULL, /* ui_info */
+- &prpl_info, /* extra_info */
+- NULL, /* prefs_info */
+- ggp_actions, /* actions */
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void purple_gg_debug_handler(int level, const char * format, va_list args) {
+- PurpleDebugLevel purple_level;
+- char *msg = g_strdup_vprintf(format, args);
+-
+- /* This is pretty pointless since the GG_DEBUG levels don't correspond to
+- * the purple ones */
+- switch (level) {
+- case GG_DEBUG_FUNCTION:
+- purple_level = PURPLE_DEBUG_INFO;
+- break;
+- case GG_DEBUG_MISC:
+- case GG_DEBUG_NET:
+- case GG_DEBUG_DUMP:
+- case GG_DEBUG_TRAFFIC:
+- default:
+- purple_level = PURPLE_DEBUG_MISC;
+- break;
+- }
+-
+- purple_debug(purple_level, "gg", "%s", msg);
+- g_free(msg);
+-}
+-
+-static void init_plugin(PurplePlugin *plugin)
+-{
+- PurpleAccountOption *option;
+- GList *encryption_options = NULL;
+-
+- option = purple_account_option_string_new(_("Nickname"),
+- "nick", _("Gadu-Gadu User"));
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_string_new(_("GG server"),
+- "gg_server", "");
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+-#define ADD_VALUE(list, desc, v) { \
+- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1); \
+- kvp->key = g_strdup((desc)); \
+- kvp->value = g_strdup((v)); \
+- list = g_list_append(list, kvp); \
+-}
+-
+- ADD_VALUE(encryption_options, _("Don't use encryption"), "none");
+- ADD_VALUE(encryption_options, _("Use encryption if available"),
+- "opportunistic_tls");
+-#if 0
+- /* TODO */
+- ADD_VALUE(encryption_options, _("Require encryption"), "require_tls");
+-#endif
+-
+- option = purple_account_option_list_new(_("Connection security"),
+- "encryption", encryption_options);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- my_protocol = plugin;
+-
+- gg_debug_handler = purple_gg_debug_handler;
+-}
+-
+-PURPLE_INIT_PLUGIN(gg, init_plugin, info);
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.h
+--- pidgin-2.10.7/libpurple/protocols/gg/gg.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,72 +0,0 @@
+-/**
+- * @file gg.h
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#ifndef _PURPLE_GG_H
+-#define _PURPLE_GG_H
+-
+-#include <libgadu.h>
+-#include "internal.h"
+-#include "search.h"
+-#include "connection.h"
+-
+-
+-#define PUBDIR_RESULTS_MAX 20
+-
+-
+-typedef struct
+-{
+- char *name;
+- GList *participants;
+-
+-} GGPChat;
+-
+-typedef void (*GGPTokenCallback)(PurpleConnection *);
+-
+-typedef struct
+-{
+- char *id;
+- char *data;
+- unsigned int size;
+-
+- struct gg_http *req;
+- guint inpa;
+-
+- GGPTokenCallback cb;
+-
+-} GGPToken;
+-
+-typedef struct {
+-
+- struct gg_session *session;
+- GGPToken *token;
+- GList *chats;
+- GGPSearches *searches;
+- int chats_count;
+- GList *pending_richtext_messages;
+- GHashTable *pending_images;
+- gboolean status_broadcasting; //When TRUE status is visible to all, when FALSE status is visible only to friends.
+-} GGPInfo;
+-
+-#endif /* _PURPLE_GG_H */
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg-utils.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.c
+--- pidgin-2.10.7/libpurple/protocols/gg/gg-utils.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,147 +0,0 @@
+-/**
+- * @file gg-utils.c
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#include "gg-utils.h"
+-
+-
+-/* uin_t ggp_str_to_uin(const char *str) {{{ */
+-uin_t ggp_str_to_uin(const char *str)
+-{
+- char *tmp;
+- long num;
+-
+- if (!str)
+- return 0;
+-
+- errno = 0;
+- num = strtol(str, &tmp, 10);
+-
+- if (*str == '\0' || *tmp != '\0')
+- return 0;
+-
+- if ((errno == ERANGE || (num == LONG_MAX || num == LONG_MIN))
+-#if (LONG_MAX > UINT_MAX)
+- || num > (long)UINT_MAX
+-#endif
+- || num < 0)
+- return 0;
+-
+- return (uin_t) num;
+-}
+-/* }}} */
+-
+-/* unsigned int ggp_array_size(char **array) {{{ */
+-unsigned int ggp_array_size(char **array)
+-{
+- unsigned int i;
+-
+- for (i = 0; array[i] != NULL && i < UINT_MAX; i++)
+- {}
+-
+- return i;
+-}
+-/* }}} */
+-
+-/* char *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst) {{{ */
+-char *charset_convert(const gchar *locstr, const char *encsrc, const char *encdst)
+-{
+- gchar *msg;
+- GError *err = NULL;
+-
+- if (locstr == NULL)
+- return NULL;
+-
+- msg = g_convert_with_fallback(locstr, strlen(locstr), encdst, encsrc,
+- "?", NULL, NULL, &err);
+- if (err != NULL) {
+- purple_debug_error("gg", "Error converting from %s to %s: %s\n",
+- encsrc, encdst, err->message);
+- g_error_free(err);
+- }
+-
+- /* Just in case? */
+- if (msg == NULL)
+- msg = g_strdup(locstr);
+-
+- return msg;
+-}
+-/* }}} */
+-
+-/* ggp_get_uin(PurpleAccount *account) {{{ */
+-uin_t ggp_get_uin(PurpleAccount *account)
+-{
+- return ggp_str_to_uin(purple_account_get_username(account));
+-}
+-/* }}} */
+-
+-/* char *ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin) {{{ */
+-char *ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin)
+-{
+- PurpleBuddy *buddy;
+- gchar *str_uin;
+-
+- str_uin = g_strdup_printf("%lu", (unsigned long int)uin);
+-
+- buddy = purple_find_buddy(purple_connection_get_account(gc), str_uin);
+- if (buddy != NULL) {
+- g_free(str_uin);
+- return g_strdup(purple_buddy_get_alias(buddy));
+- } else {
+- return str_uin;
+- }
+-}
+-/* }}} */
+-
+-void ggp_status_fake_to_self(PurpleAccount *account)
+-{
+- PurplePresence *presence;
+- PurpleStatus *status;
+- const char *status_id;
+- const char *msg;
+-
+- if (! purple_find_buddy(account, purple_account_get_username(account)))
+- return;
+-
+- presence = purple_account_get_presence(account);
+- status = purple_presence_get_active_status(presence);
+- msg = purple_status_get_attr_string(status, "message");
+- if (msg && !*msg)
+- msg = NULL;
+-
+- status_id = purple_status_get_id(status);
+- if (strcmp(status_id, "invisible") == 0) {
+- status_id = "offline";
+- }
+-
+- if (msg) {
+- if (strlen(msg) > GG_STATUS_DESCR_MAXSIZE) {
+- msg = purple_markup_slice(msg, 0, GG_STATUS_DESCR_MAXSIZE);
+- }
+- }
+- purple_prpl_got_user_status(account, purple_account_get_username(account),
+- status_id,
+- msg ? "message" : NULL, msg, NULL);
+-}
+-
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/gg-utils.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.h
+--- pidgin-2.10.7/libpurple/protocols/gg/gg-utils.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/gg-utils.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,106 +0,0 @@
+-/**
+- * @file gg-utils.h
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _PURPLE_GG_UTILS_H
+-#define _PURPLE_GG_UTILS_H
+-
+-#include "internal.h"
+-
+-#include "plugin.h"
+-#include "version.h"
+-#include "notify.h"
+-#include "status.h"
+-#include "blist.h"
+-#include "accountopt.h"
+-#include "debug.h"
+-#include "util.h"
+-#include "request.h"
+-
+-#include "gg.h"
+-
+-
+-/**
+- * Convert a base 10 string to a UIN.
+- *
+- * @param str The string to convert
+- *
+- * @return UIN or 0 if an error occurred.
+- */
+-uin_t
+-ggp_str_to_uin(const char *str);
+-
+-/**
+- * Calculate size of a NULL-terminated array.
+- *
+- * @param array The array.
+- *
+- * @return Size of the array.
+- */
+-unsigned int
+-ggp_array_size(char **array);
+-
+-/**
+- * Convert enconding of a given string.
+- *
+- * @param locstr Input string.
+- * @param encsrc Current encoding of the string.
+- * @param encdst Target encoding of the string.
+- *
+- * @return Converted string (it must be g_free()ed when not used. Or NULL if
+- * locstr is NULL.
+- */
+-char *
+-charset_convert(const gchar *locstr, const char *encsrc, const char *encdst);
+-
+-/**
+- * Get UIN of a given account.
+- *
+- * @param account Current account.
+- *
+- * @return UIN of an account.
+- */
+-uin_t
+-ggp_get_uin(PurpleAccount *account);
+-
+-/**
+- * Returns the best name of a buddy from the buddylist.
+- *
+- * @param gc PurpleConnection instance.
+- * @param uin UIN of the buddy.
+- *
+- * @return Name of the buddy, or UIN converted to string.
+- */
+-char *
+-ggp_buddy_get_name(PurpleConnection *gc, const uin_t uin);
+-
+-/**
+- * Manages the display of account's status in the buddylist.
+- *
+- * @param account Current account.
+- */
+-void
+-ggp_status_fake_to_self(PurpleAccount *account);
+-
+-
+-#endif /* _PURPLE_GG_UTILS_H */
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/common.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/common.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/common.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/common.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,685 +0,0 @@
+-/* $Id: common.c 1101 2011-05-05 21:17:28Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file common.c
+- *
+- * \brief Funkcje wykorzystywane przez różne moduły biblioteki
+- */
+-#ifndef _WIN32
+-# include <sys/types.h>
+-# include <sys/ioctl.h>
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-# ifdef sun
+-# include <sys/filio.h>
+-# endif
+-#endif
+-
+-#include <errno.h>
+-#include <fcntl.h>
+-#ifndef _WIN32
+-# include <netdb.h>
+-#endif
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-
+-#include "libgadu.h"
+-
+-/**
+- * \internal Odpowiednik funkcji \c vsprintf alokujący miejsce na wynik.
+- *
+- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
+- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
+- *
+- * \param format Format wiadomości (zgodny z \c printf)
+- * \param ap Lista argumentów (zgodna z \c printf)
+- *
+- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
+- *
+- * \ingroup helper
+- */
+-char *gg_vsaprintf(const char *format, va_list ap)
+-{
+- int size = 0;
+- char *buf = NULL;
+-
+-#ifdef GG_CONFIG_HAVE_VA_COPY
+- va_list aq;
+-
+- va_copy(aq, ap);
+-#else
+-# ifdef GG_CONFIG_HAVE___VA_COPY
+- va_list aq;
+-
+- __va_copy(aq, ap);
+-# endif
+-#endif
+-
+-#ifndef GG_CONFIG_HAVE_C99_VSNPRINTF
+- {
+- int res;
+- char *tmp;
+-
+- size = 128;
+- do {
+- size *= 2;
+- if (!(tmp = realloc(buf, size + 1))) {
+- free(buf);
+- return NULL;
+- }
+- buf = tmp;
+- res = vsnprintf(buf, size, format, ap);
+- } while (res == size - 1 || res == -1);
+- }
+-#else
+- {
+- char tmp[2];
+-
+- /* libce Solarisa przy buforze NULL zawsze zwracają -1, więc
+- * musimy podać coś istniejącego jako cel printf()owania. */
+- size = vsnprintf(tmp, sizeof(tmp), format, ap);
+- if (!(buf = malloc(size + 1)))
+- return NULL;
+- }
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_VA_COPY
+- vsnprintf(buf, size + 1, format, aq);
+- va_end(aq);
+-#else
+-# ifdef GG_CONFIG_HAVE___VA_COPY
+- vsnprintf(buf, size + 1, format, aq);
+- va_end(aq);
+-# else
+- vsnprintf(buf, size + 1, format, ap);
+-# endif
+-#endif
+-
+- return buf;
+-}
+-
+-/**
+- * \internal Odpowiednik funkcji \c sprintf alokujący miejsce na wynik.
+- *
+- * Funkcja korzysta z funkcji \c vsnprintf, sprawdzając czy dostępna funkcja
+- * systemowa jest zgodna ze standardem C99 czy wcześniejszymi.
+- *
+- * \param format Format wiadomości (zgodny z \c printf)
+- *
+- * \return Zaalokowany bufor lub NULL, jeśli zabrakło pamięci.
+- *
+- * \ingroup helper
+- */
+-char *gg_saprintf(const char *format, ...)
+-{
+- va_list ap;
+- char *res;
+-
+- va_start(ap, format);
+- res = gg_vsaprintf(format, ap);
+- va_end(ap);
+-
+- return res;
+-}
+-
+-/**
+- * \internal Pobiera linię tekstu z bufora.
+- *
+- * Funkcja niszczy bufor źródłowy bezpowrotnie, dzieląc go na kolejne ciągi
+- * znaków i obcina znaki końca linii.
+- *
+- * \param ptr Wskaźnik do zmiennej, która przechowuje aktualne położenie
+- * w analizowanym buforze
+- *
+- * \return Wskaźnik do kolejnej linii tekstu lub NULL, jeśli to już koniec
+- * bufora.
+- */
+-char *gg_get_line(char **ptr)
+-{
+- char *foo, *res;
+-
+- if (!ptr || !*ptr || !strcmp(*ptr, ""))
+- return NULL;
+-
+- res = *ptr;
+-
+- if (!(foo = strchr(*ptr, '\n')))
+- *ptr += strlen(*ptr);
+- else {
+- size_t len;
+- *ptr = foo + 1;
+- *foo = 0;
+-
+- len = strlen(res);
+-
+- if (len > 1 && res[len - 1] == '\r')
+- res[len - 1] = 0;
+- }
+-
+- return res;
+-}
+-
+-/**
+- * \internal Czyta linię tekstu z gniazda.
+- *
+- * Funkcja czyta tekst znak po znaku, więc nie jest efektywna, ale dzięki
+- * brakowi buforowania, nie koliduje z innymi funkcjami odczytu.
+- *
+- * \param sock Deskryptor gniazda
+- * \param buf Wskaźnik do bufora
+- * \param length Długość bufora
+- *
+- * \return Zwraca \c buf jeśli się powiodło, lub \c NULL w przypadku błędu.
+- */
+-char *gg_read_line(int sock, char *buf, int length)
+-{
+- int ret;
+-
+- if (!buf || length < 0)
+- return NULL;
+-
+- for (; length > 1; buf++, length--) {
+- do {
+- if ((ret = read(sock, buf, 1)) == -1 && errno != EINTR && errno != EAGAIN) {
+- gg_debug(GG_DEBUG_MISC, "// gg_read_line() error on read (errno=%d, %s)\n", errno, strerror(errno));
+- *buf = 0;
+- return NULL;
+- } else if (ret == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_read_line() eof reached\n");
+- *buf = 0;
+- return NULL;
+- }
+- } while (ret == -1 && (errno == EINTR || errno == EAGAIN));
+-
+- if (*buf == '\n') {
+- buf++;
+- break;
+- }
+- }
+-
+- *buf = 0;
+- return buf;
+-}
+-
+-/**
+- * \internal Nawiązuje połączenie TCP.
+- *
+- * \param addr Wskaźnik na strukturę \c in_addr z adresem serwera
+- * \param port Port serwera
+- * \param async Flaga asynchronicznego połączenia
+- *
+- * \return Deskryptor gniazda lub -1 w przypadku błędu
+- *
+- * \ingroup helper
+- */
+-int gg_connect(void *addr, int port, int async)
+-{
+- int sock, one = 1, errno2;
+- struct sockaddr_in sin;
+- struct in_addr *a = addr;
+- struct sockaddr_in myaddr;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_connect(%s, %d, %d);\n", inet_ntoa(*a), port, async);
+-
+- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_connect() socket() failed (errno=%d, %s)\n", errno, strerror(errno));
+- return -1;
+- }
+-
+- memset(&myaddr, 0, sizeof(myaddr));
+- myaddr.sin_family = AF_INET;
+-
+- myaddr.sin_addr.s_addr = gg_local_ip;
+-
+- if (bind(sock, (struct sockaddr *) &myaddr, sizeof(myaddr)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_connect() bind() failed (errno=%d, %s)\n", errno, strerror(errno));
+- errno2 = errno;
+- close(sock);
+- errno = errno2;
+- return -1;
+- }
+-
+- if (async) {
+-#ifdef FIONBIO
+- if (ioctl(sock, FIONBIO, &one) == -1) {
+-#else
+- if (fcntl(sock, F_SETFL, O_NONBLOCK) == -1) {
+-#endif
+- gg_debug(GG_DEBUG_MISC, "// gg_connect() ioctl() failed (errno=%d, %s)\n", errno, strerror(errno));
+- errno2 = errno;
+- close(sock);
+- errno = errno2;
+- return -1;
+- }
+- }
+-
+- memset(&sin, 0, sizeof(sin));
+- sin.sin_port = htons(port);
+- sin.sin_family = AF_INET;
+- sin.sin_addr.s_addr = a->s_addr;
+-
+- if (connect(sock, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
+- if (errno && (!async || errno != EINPROGRESS)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() failed (errno=%d, %s)\n", errno, strerror(errno));
+- errno2 = errno;
+- close(sock);
+- errno = errno2;
+- return -1;
+- }
+- gg_debug(GG_DEBUG_MISC, "// gg_connect() connect() in progress\n");
+- }
+-
+- return sock;
+-}
+-
+-/**
+- * \internal Usuwa znaki końca linii.
+- *
+- * Funkcja działa bezpośrednio na buforze.
+- *
+- * \param line Bufor z tekstem
+- *
+- * \ingroup helper
+- */
+-void gg_chomp(char *line)
+-{
+- int len;
+-
+- if (!line)
+- return;
+-
+- len = strlen(line);
+-
+- if (len > 0 && line[len - 1] == '\n')
+- line[--len] = 0;
+- if (len > 0 && line[len - 1] == '\r')
+- line[--len] = 0;
+-}
+-
+-/**
+- * \internal Koduje ciąg znaków do postacji adresu HTTP.
+- *
+- * Zamienia znaki niedrukowalne, spoza ASCII i mające specjalne znaczenie
+- * dla protokołu HTTP na encje postaci \c %XX, gdzie \c XX jest szesnastkową
+- * wartością znaku.
+- *
+- * \param str Ciąg znaków do zakodowania
+- *
+- * \return Zaalokowany bufor lub \c NULL w przypadku błędu.
+- *
+- * \ingroup helper
+- */
+-char *gg_urlencode(const char *str)
+-{
+- char *q, *buf;
+- const char hex[] = "0123456789abcdef";
+- const char *p;
+- unsigned int size = 0;
+-
+- if (!str)
+- str = "";
+-
+- for (p = str; *p; p++, size++) {
+- if (!((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || *p == ' ') || (*p == '@') || (*p == '.') || (*p == '-'))
+- size += 2;
+- }
+-
+- if (!(buf = malloc(size + 1)))
+- return NULL;
+-
+- for (p = str, q = buf; *p; p++, q++) {
+- if ((*p >= 'a' && *p <= 'z') || (*p >= 'A' && *p <= 'Z') || (*p >= '0' && *p <= '9') || (*p == '@') || (*p == '.') || (*p == '-'))
+- *q = *p;
+- else {
+- if (*p == ' ')
+- *q = '+';
+- else {
+- *q++ = '%';
+- *q++ = hex[*p >> 4 & 15];
+- *q = hex[*p & 15];
+- }
+- }
+- }
+-
+- *q = 0;
+-
+- return buf;
+-}
+-
+-/**
+- * \internal Wyznacza skrót dla usług HTTP.
+- *
+- * Funkcja jest wykorzystywana do wyznaczania skrótu adresu e-mail, hasła
+- * i innych wartości przekazywanych jako parametry usług HTTP.
+- *
+- * W parametrze \c format należy umieścić znaki określające postać kolejnych
+- * parametrów: \c 's' jeśli parametr jest ciągiem znaków, \c 'u' jeśli jest
+- * liczbą.
+- *
+- * \param format Format kolejnych parametrów (niezgodny z \c printf)
+- *
+- * \return Wartość skrótu
+- */
+-int gg_http_hash(const char *format, ...)
+-{
+- unsigned int a, c, i, j;
+- va_list ap;
+- int b = -1;
+-
+- va_start(ap, format);
+-
+- for (j = 0; j < strlen(format); j++) {
+- char *arg, buf[16];
+-
+- if (format[j] == 'u') {
+- snprintf(buf, sizeof(buf), "%d", va_arg(ap, uin_t));
+- arg = buf;
+- } else {
+- if (!(arg = va_arg(ap, char*)))
+- arg = "";
+- }
+-
+- i = 0;
+- while ((c = (unsigned char) arg[i++]) != 0) {
+- a = (c ^ b) + (c << 8);
+- b = (a >> 24) | (a << 8);
+- }
+- }
+-
+- va_end(ap);
+-
+- return (b < 0 ? -b : b);
+-}
+-
+-/**
+- * \internal Zestaw znaków kodowania base64.
+- */
+-static char gg_base64_charset[] =
+- "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+-
+-/**
+- * \internal Koduje ciąg znaków do base64.
+- *
+- * Wynik funkcji należy zwolnić za pomocą \c free.
+- *
+- * \param buf Bufor z danami do zakodowania
+- *
+- * \return Zaalokowany bufor z zakodowanymi danymi
+- *
+- * \ingroup helper
+- */
+-char *gg_base64_encode(const char *buf)
+-{
+- char *out, *res;
+- unsigned int i = 0, j = 0, k = 0, len = strlen(buf);
+-
+- res = out = malloc((len / 3 + 1) * 4 + 2);
+-
+- if (!res)
+- return NULL;
+-
+- while (j <= len) {
+- switch (i % 4) {
+- case 0:
+- k = (buf[j] & 252) >> 2;
+- break;
+- case 1:
+- if (j < len)
+- k = ((buf[j] & 3) << 4) | ((buf[j + 1] & 240) >> 4);
+- else
+- k = (buf[j] & 3) << 4;
+-
+- j++;
+- break;
+- case 2:
+- if (j < len)
+- k = ((buf[j] & 15) << 2) | ((buf[j + 1] & 192) >> 6);
+- else
+- k = (buf[j] & 15) << 2;
+-
+- j++;
+- break;
+- case 3:
+- k = buf[j++] & 63;
+- break;
+- }
+- *out++ = gg_base64_charset[k];
+- i++;
+- }
+-
+- if (i % 4)
+- for (j = 0; j < 4 - (i % 4); j++, out++)
+- *out = '=';
+-
+- *out = 0;
+-
+- return res;
+-}
+-
+-/**
+- * \internal Dekoduje ciąg znaków zapisany w base64.
+- *
+- * Wynik funkcji należy zwolnić za pomocą \c free.
+- *
+- * \param buf Bufor źródłowy z danymi do zdekodowania
+- *
+- * \return Zaalokowany bufor ze zdekodowanymi danymi
+- *
+- * \ingroup helper
+- */
+-char *gg_base64_decode(const char *buf)
+-{
+- char *res, *save, *foo, val;
+- const char *end;
+- unsigned int index = 0;
+-
+- if (!buf)
+- return NULL;
+-
+- save = res = calloc(1, (strlen(buf) / 4 + 1) * 3 + 2);
+-
+- if (!save)
+- return NULL;
+-
+- end = buf + strlen(buf);
+-
+- while (*buf && buf < end) {
+- if (*buf == '\r' || *buf == '\n') {
+- buf++;
+- continue;
+- }
+- if (!(foo = strchr(gg_base64_charset, *buf)))
+- foo = gg_base64_charset;
+- val = (int)(foo - gg_base64_charset);
+- buf++;
+- switch (index) {
+- case 0:
+- *res |= val << 2;
+- break;
+- case 1:
+- *res++ |= val >> 4;
+- *res |= val << 4;
+- break;
+- case 2:
+- *res++ |= val >> 2;
+- *res |= val << 6;
+- break;
+- case 3:
+- *res++ |= val;
+- break;
+- }
+- index++;
+- index %= 4;
+- }
+- *res = 0;
+-
+- return save;
+-}
+-
+-/**
+- * \internal Tworzy nagłówek autoryzacji serwera pośredniczącego.
+- *
+- * Dane pobiera ze zmiennych globalnych \c gg_proxy_username i
+- * \c gg_proxy_password.
+- *
+- * \return Zaalokowany bufor z tekstem lub NULL, jeśli serwer pośredniczący
+- * nie jest używany lub nie wymaga autoryzacji.
+- */
+-char *gg_proxy_auth(void)
+-{
+- char *tmp, *enc, *out;
+- unsigned int tmp_size;
+-
+- if (!gg_proxy_enabled || !gg_proxy_username || !gg_proxy_password)
+- return NULL;
+-
+- if (!(tmp = malloc((tmp_size = strlen(gg_proxy_username) + strlen(gg_proxy_password) + 2))))
+- return NULL;
+-
+- snprintf(tmp, tmp_size, "%s:%s", gg_proxy_username, gg_proxy_password);
+-
+- if (!(enc = gg_base64_encode(tmp))) {
+- free(tmp);
+- return NULL;
+- }
+-
+- free(tmp);
+-
+- if (!(out = malloc(strlen(enc) + 40))) {
+- free(enc);
+- return NULL;
+- }
+-
+- snprintf(out, strlen(enc) + 40, "Proxy-Authorization: Basic %s\r\n", enc);
+-
+- free(enc);
+-
+- return out;
+-}
+-
+-/**
+- * \internal Tablica pomocnicza do wyznaczania sumy kontrolnej.
+- */
+-static const uint32_t gg_crc32_table[256] =
+-{
+- 0x00000000, 0x77073096, 0xee0e612c, 0x990951ba,
+- 0x076dc419, 0x706af48f, 0xe963a535, 0x9e6495a3,
+- 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
+- 0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91,
+- 0x1db71064, 0x6ab020f2, 0xf3b97148, 0x84be41de,
+- 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
+- 0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec,
+- 0x14015c4f, 0x63066cd9, 0xfa0f3d63, 0x8d080df5,
+- 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
+- 0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b,
+- 0x35b5a8fa, 0x42b2986c, 0xdbbbc9d6, 0xacbcf940,
+- 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
+- 0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116,
+- 0x21b4f4b5, 0x56b3c423, 0xcfba9599, 0xb8bda50f,
+- 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
+- 0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d,
+- 0x76dc4190, 0x01db7106, 0x98d220bc, 0xefd5102a,
+- 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
+- 0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818,
+- 0x7f6a0dbb, 0x086d3d2d, 0x91646c97, 0xe6635c01,
+- 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
+- 0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457,
+- 0x65b0d9c6, 0x12b7e950, 0x8bbeb8ea, 0xfcb9887c,
+- 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
+- 0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2,
+- 0x4adfa541, 0x3dd895d7, 0xa4d1c46d, 0xd3d6f4fb,
+- 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
+- 0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9,
+- 0x5005713c, 0x270241aa, 0xbe0b1010, 0xc90c2086,
+- 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
+- 0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4,
+- 0x59b33d17, 0x2eb40d81, 0xb7bd5c3b, 0xc0ba6cad,
+- 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
+- 0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683,
+- 0xe3630b12, 0x94643b84, 0x0d6d6a3e, 0x7a6a5aa8,
+- 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
+- 0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe,
+- 0xf762575d, 0x806567cb, 0x196c3671, 0x6e6b06e7,
+- 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
+- 0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5,
+- 0xd6d6a3e8, 0xa1d1937e, 0x38d8c2c4, 0x4fdff252,
+- 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
+- 0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60,
+- 0xdf60efc3, 0xa867df55, 0x316e8eef, 0x4669be79,
+- 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
+- 0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f,
+- 0xc5ba3bbe, 0xb2bd0b28, 0x2bb45a92, 0x5cb36a04,
+- 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
+- 0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a,
+- 0x9c0906a9, 0xeb0e363f, 0x72076785, 0x05005713,
+- 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
+- 0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21,
+- 0x86d3d2d4, 0xf1d4e242, 0x68ddb3f8, 0x1fda836e,
+- 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
+- 0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c,
+- 0x8f659eff, 0xf862ae69, 0x616bffd3, 0x166ccf45,
+- 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
+- 0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db,
+- 0xaed16a4a, 0xd9d65adc, 0x40df0b66, 0x37d83bf0,
+- 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
+- 0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6,
+- 0xbad03605, 0xcdd70693, 0x54de5729, 0x23d967bf,
+- 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
+- 0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
+-};
+-
+-/**
+- * Wyznacza sumę kontrolną CRC32.
+- *
+- * \param crc Suma kontrola poprzedniego bloku danych lub 0 jeśli liczona
+- * jest suma kontrolna pierwszego bloku
+- * \param buf Bufor danych
+- * \param len Długość bufora danych
+- *
+- * \return Suma kontrolna.
+- */
+-uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len)
+-{
+- if (buf == NULL || len < 0)
+- return crc;
+-
+- crc ^= 0xffffffffL;
+-
+- while (len--)
+- crc = (crc >> 8) ^ gg_crc32_table[(crc ^ *buf++) & 0xff];
+-
+- return crc ^ 0xffffffffL;
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/compat.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/compat.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/compat.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/compat.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,35 +0,0 @@
+-/* $Id: compat.h 506 2008-01-14 22:15:05Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file compat.h
+- *
+- * \brief Makra zapewniające kompatybilność API na różnych systemach
+- */
+-
+-#ifndef __COMPAT_H
+-#define __COMPAT_H
+-
+-#ifdef sun
+-# define INADDR_NONE ((in_addr_t) 0xffffffff)
+-#endif
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/COPYING pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/COPYING
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/COPYING 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/COPYING 1969-12-31 21:00:00.000000000 -0300
+@@ -1,504 +0,0 @@
+- GNU LESSER GENERAL PUBLIC LICENSE
+- Version 2.1, February 1999
+-
+- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+- 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+- Everyone is permitted to copy and distribute verbatim copies
+- of this license document, but changing it is not allowed.
+-
+-[This is the first released version of the Lesser GPL. It also counts
+- as the successor of the GNU Library Public License, version 2, hence
+- the version number 2.1.]
+-
+- Preamble
+-
+- The licenses for most software are designed to take away your
+-freedom to share and change it. By contrast, the GNU General Public
+-Licenses are intended to guarantee your freedom to share and change
+-free software--to make sure the software is free for all its users.
+-
+- This license, the Lesser General Public License, applies to some
+-specially designated software packages--typically libraries--of the
+-Free Software Foundation and other authors who decide to use it. You
+-can use it too, but we suggest you first think carefully about whether
+-this license or the ordinary General Public License is the better
+-strategy to use in any particular case, based on the explanations below.
+-
+- When we speak of free software, we are referring to freedom of use,
+-not price. Our General Public Licenses are designed to make sure that
+-you have the freedom to distribute copies of free software (and charge
+-for this service if you wish); that you receive source code or can get
+-it if you want it; that you can change the software and use pieces of
+-it in new free programs; and that you are informed that you can do
+-these things.
+-
+- To protect your rights, we need to make restrictions that forbid
+-distributors to deny you these rights or to ask you to surrender these
+-rights. These restrictions translate to certain responsibilities for
+-you if you distribute copies of the library or if you modify it.
+-
+- For example, if you distribute copies of the library, whether gratis
+-or for a fee, you must give the recipients all the rights that we gave
+-you. You must make sure that they, too, receive or can get the source
+-code. If you link other code with the library, you must provide
+-complete object files to the recipients, so that they can relink them
+-with the library after making changes to the library and recompiling
+-it. And you must show them these terms so they know their rights.
+-
+- We protect your rights with a two-step method: (1) we copyright the
+-library, and (2) we offer you this license, which gives you legal
+-permission to copy, distribute and/or modify the library.
+-
+- To protect each distributor, we want to make it very clear that
+-there is no warranty for the free library. Also, if the library is
+-modified by someone else and passed on, the recipients should know
+-that what they have is not the original version, so that the original
+-author's reputation will not be affected by problems that might be
+-introduced by others.
+-
+- Finally, software patents pose a constant threat to the existence of
+-any free program. We wish to make sure that a company cannot
+-effectively restrict the users of a free program by obtaining a
+-restrictive license from a patent holder. Therefore, we insist that
+-any patent license obtained for a version of the library must be
+-consistent with the full freedom of use specified in this license.
+-
+- Most GNU software, including some libraries, is covered by the
+-ordinary GNU General Public License. This license, the GNU Lesser
+-General Public License, applies to certain designated libraries, and
+-is quite different from the ordinary General Public License. We use
+-this license for certain libraries in order to permit linking those
+-libraries into non-free programs.
+-
+- When a program is linked with a library, whether statically or using
+-a shared library, the combination of the two is legally speaking a
+-combined work, a derivative of the original library. The ordinary
+-General Public License therefore permits such linking only if the
+-entire combination fits its criteria of freedom. The Lesser General
+-Public License permits more lax criteria for linking other code with
+-the library.
+-
+- We call this license the "Lesser" General Public License because it
+-does Less to protect the user's freedom than the ordinary General
+-Public License. It also provides other free software developers Less
+-of an advantage over competing non-free programs. These disadvantages
+-are the reason we use the ordinary General Public License for many
+-libraries. However, the Lesser license provides advantages in certain
+-special circumstances.
+-
+- For example, on rare occasions, there may be a special need to
+-encourage the widest possible use of a certain library, so that it becomes
+-a de-facto standard. To achieve this, non-free programs must be
+-allowed to use the library. A more frequent case is that a free
+-library does the same job as widely used non-free libraries. In this
+-case, there is little to gain by limiting the free library to free
+-software only, so we use the Lesser General Public License.
+-
+- In other cases, permission to use a particular library in non-free
+-programs enables a greater number of people to use a large body of
+-free software. For example, permission to use the GNU C Library in
+-non-free programs enables many more people to use the whole GNU
+-operating system, as well as its variant, the GNU/Linux operating
+-system.
+-
+- Although the Lesser General Public License is Less protective of the
+-users' freedom, it does ensure that the user of a program that is
+-linked with the Library has the freedom and the wherewithal to run
+-that program using a modified version of the Library.
+-
+- The precise terms and conditions for copying, distribution and
+-modification follow. Pay close attention to the difference between a
+-"work based on the library" and a "work that uses the library". The
+-former contains code derived from the library, whereas the latter must
+-be combined with the library in order to run.
+-
+- GNU LESSER GENERAL PUBLIC LICENSE
+- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+-
+- 0. This License Agreement applies to any software library or other
+-program which contains a notice placed by the copyright holder or
+-other authorized party saying it may be distributed under the terms of
+-this Lesser General Public License (also called "this License").
+-Each licensee is addressed as "you".
+-
+- A "library" means a collection of software functions and/or data
+-prepared so as to be conveniently linked with application programs
+-(which use some of those functions and data) to form executables.
+-
+- The "Library", below, refers to any such software library or work
+-which has been distributed under these terms. A "work based on the
+-Library" means either the Library or any derivative work under
+-copyright law: that is to say, a work containing the Library or a
+-portion of it, either verbatim or with modifications and/or translated
+-straightforwardly into another language. (Hereinafter, translation is
+-included without limitation in the term "modification".)
+-
+- "Source code" for a work means the preferred form of the work for
+-making modifications to it. For a library, complete source code means
+-all the source code for all modules it contains, plus any associated
+-interface definition files, plus the scripts used to control compilation
+-and installation of the library.
+-
+- Activities other than copying, distribution and modification are not
+-covered by this License; they are outside its scope. The act of
+-running a program using the Library is not restricted, and output from
+-such a program is covered only if its contents constitute a work based
+-on the Library (independent of the use of the Library in a tool for
+-writing it). Whether that is true depends on what the Library does
+-and what the program that uses the Library does.
+-
+- 1. You may copy and distribute verbatim copies of the Library's
+-complete source code as you receive it, in any medium, provided that
+-you conspicuously and appropriately publish on each copy an
+-appropriate copyright notice and disclaimer of warranty; keep intact
+-all the notices that refer to this License and to the absence of any
+-warranty; and distribute a copy of this License along with the
+-Library.
+-
+- You may charge a fee for the physical act of transferring a copy,
+-and you may at your option offer warranty protection in exchange for a
+-fee.
+-
+- 2. You may modify your copy or copies of the Library or any portion
+-of it, thus forming a work based on the Library, and copy and
+-distribute such modifications or work under the terms of Section 1
+-above, provided that you also meet all of these conditions:
+-
+- a) The modified work must itself be a software library.
+-
+- b) You must cause the files modified to carry prominent notices
+- stating that you changed the files and the date of any change.
+-
+- c) You must cause the whole of the work to be licensed at no
+- charge to all third parties under the terms of this License.
+-
+- d) If a facility in the modified Library refers to a function or a
+- table of data to be supplied by an application program that uses
+- the facility, other than as an argument passed when the facility
+- is invoked, then you must make a good faith effort to ensure that,
+- in the event an application does not supply such function or
+- table, the facility still operates, and performs whatever part of
+- its purpose remains meaningful.
+-
+- (For example, a function in a library to compute square roots has
+- a purpose that is entirely well-defined independent of the
+- application. Therefore, Subsection 2d requires that any
+- application-supplied function or table used by this function must
+- be optional: if the application does not supply it, the square
+- root function must still compute square roots.)
+-
+-These requirements apply to the modified work as a whole. If
+-identifiable sections of that work are not derived from the Library,
+-and can be reasonably considered independent and separate works in
+-themselves, then this License, and its terms, do not apply to those
+-sections when you distribute them as separate works. But when you
+-distribute the same sections as part of a whole which is a work based
+-on the Library, the distribution of the whole must be on the terms of
+-this License, whose permissions for other licensees extend to the
+-entire whole, and thus to each and every part regardless of who wrote
+-it.
+-
+-Thus, it is not the intent of this section to claim rights or contest
+-your rights to work written entirely by you; rather, the intent is to
+-exercise the right to control the distribution of derivative or
+-collective works based on the Library.
+-
+-In addition, mere aggregation of another work not based on the Library
+-with the Library (or with a work based on the Library) on a volume of
+-a storage or distribution medium does not bring the other work under
+-the scope of this License.
+-
+- 3. You may opt to apply the terms of the ordinary GNU General Public
+-License instead of this License to a given copy of the Library. To do
+-this, you must alter all the notices that refer to this License, so
+-that they refer to the ordinary GNU General Public License, version 2,
+-instead of to this License. (If a newer version than version 2 of the
+-ordinary GNU General Public License has appeared, then you can specify
+-that version instead if you wish.) Do not make any other change in
+-these notices.
+-
+- Once this change is made in a given copy, it is irreversible for
+-that copy, so the ordinary GNU General Public License applies to all
+-subsequent copies and derivative works made from that copy.
+-
+- This option is useful when you wish to copy part of the code of
+-the Library into a program that is not a library.
+-
+- 4. You may copy and distribute the Library (or a portion or
+-derivative of it, under Section 2) in object code or executable form
+-under the terms of Sections 1 and 2 above provided that you accompany
+-it with the complete corresponding machine-readable source code, which
+-must be distributed under the terms of Sections 1 and 2 above on a
+-medium customarily used for software interchange.
+-
+- If distribution of object code is made by offering access to copy
+-from a designated place, then offering equivalent access to copy the
+-source code from the same place satisfies the requirement to
+-distribute the source code, even though third parties are not
+-compelled to copy the source along with the object code.
+-
+- 5. A program that contains no derivative of any portion of the
+-Library, but is designed to work with the Library by being compiled or
+-linked with it, is called a "work that uses the Library". Such a
+-work, in isolation, is not a derivative work of the Library, and
+-therefore falls outside the scope of this License.
+-
+- However, linking a "work that uses the Library" with the Library
+-creates an executable that is a derivative of the Library (because it
+-contains portions of the Library), rather than a "work that uses the
+-library". The executable is therefore covered by this License.
+-Section 6 states terms for distribution of such executables.
+-
+- When a "work that uses the Library" uses material from a header file
+-that is part of the Library, the object code for the work may be a
+-derivative work of the Library even though the source code is not.
+-Whether this is true is especially significant if the work can be
+-linked without the Library, or if the work is itself a library. The
+-threshold for this to be true is not precisely defined by law.
+-
+- If such an object file uses only numerical parameters, data
+-structure layouts and accessors, and small macros and small inline
+-functions (ten lines or less in length), then the use of the object
+-file is unrestricted, regardless of whether it is legally a derivative
+-work. (Executables containing this object code plus portions of the
+-Library will still fall under Section 6.)
+-
+- Otherwise, if the work is a derivative of the Library, you may
+-distribute the object code for the work under the terms of Section 6.
+-Any executables containing that work also fall under Section 6,
+-whether or not they are linked directly with the Library itself.
+-
+- 6. As an exception to the Sections above, you may also combine or
+-link a "work that uses the Library" with the Library to produce a
+-work containing portions of the Library, and distribute that work
+-under terms of your choice, provided that the terms permit
+-modification of the work for the customer's own use and reverse
+-engineering for debugging such modifications.
+-
+- You must give prominent notice with each copy of the work that the
+-Library is used in it and that the Library and its use are covered by
+-this License. You must supply a copy of this License. If the work
+-during execution displays copyright notices, you must include the
+-copyright notice for the Library among them, as well as a reference
+-directing the user to the copy of this License. Also, you must do one
+-of these things:
+-
+- a) Accompany the work with the complete corresponding
+- machine-readable source code for the Library including whatever
+- changes were used in the work (which must be distributed under
+- Sections 1 and 2 above); and, if the work is an executable linked
+- with the Library, with the complete machine-readable "work that
+- uses the Library", as object code and/or source code, so that the
+- user can modify the Library and then relink to produce a modified
+- executable containing the modified Library. (It is understood
+- that the user who changes the contents of definitions files in the
+- Library will not necessarily be able to recompile the application
+- to use the modified definitions.)
+-
+- b) Use a suitable shared library mechanism for linking with the
+- Library. A suitable mechanism is one that (1) uses at run time a
+- copy of the library already present on the user's computer system,
+- rather than copying library functions into the executable, and (2)
+- will operate properly with a modified version of the library, if
+- the user installs one, as long as the modified version is
+- interface-compatible with the version that the work was made with.
+-
+- c) Accompany the work with a written offer, valid for at
+- least three years, to give the same user the materials
+- specified in Subsection 6a, above, for a charge no more
+- than the cost of performing this distribution.
+-
+- d) If distribution of the work is made by offering access to copy
+- from a designated place, offer equivalent access to copy the above
+- specified materials from the same place.
+-
+- e) Verify that the user has already received a copy of these
+- materials or that you have already sent this user a copy.
+-
+- For an executable, the required form of the "work that uses the
+-Library" must include any data and utility programs needed for
+-reproducing the executable from it. However, as a special exception,
+-the materials to be distributed need not include anything that is
+-normally distributed (in either source or binary form) with the major
+-components (compiler, kernel, and so on) of the operating system on
+-which the executable runs, unless that component itself accompanies
+-the executable.
+-
+- It may happen that this requirement contradicts the license
+-restrictions of other proprietary libraries that do not normally
+-accompany the operating system. Such a contradiction means you cannot
+-use both them and the Library together in an executable that you
+-distribute.
+-
+- 7. You may place library facilities that are a work based on the
+-Library side-by-side in a single library together with other library
+-facilities not covered by this License, and distribute such a combined
+-library, provided that the separate distribution of the work based on
+-the Library and of the other library facilities is otherwise
+-permitted, and provided that you do these two things:
+-
+- a) Accompany the combined library with a copy of the same work
+- based on the Library, uncombined with any other library
+- facilities. This must be distributed under the terms of the
+- Sections above.
+-
+- b) Give prominent notice with the combined library of the fact
+- that part of it is a work based on the Library, and explaining
+- where to find the accompanying uncombined form of the same work.
+-
+- 8. You may not copy, modify, sublicense, link with, or distribute
+-the Library except as expressly provided under this License. Any
+-attempt otherwise to copy, modify, sublicense, link with, or
+-distribute the Library is void, and will automatically terminate your
+-rights under this License. However, parties who have received copies,
+-or rights, from you under this License will not have their licenses
+-terminated so long as such parties remain in full compliance.
+-
+- 9. You are not required to accept this License, since you have not
+-signed it. However, nothing else grants you permission to modify or
+-distribute the Library or its derivative works. These actions are
+-prohibited by law if you do not accept this License. Therefore, by
+-modifying or distributing the Library (or any work based on the
+-Library), you indicate your acceptance of this License to do so, and
+-all its terms and conditions for copying, distributing or modifying
+-the Library or works based on it.
+-
+- 10. Each time you redistribute the Library (or any work based on the
+-Library), the recipient automatically receives a license from the
+-original licensor to copy, distribute, link with or modify the Library
+-subject to these terms and conditions. You may not impose any further
+-restrictions on the recipients' exercise of the rights granted herein.
+-You are not responsible for enforcing compliance by third parties with
+-this License.
+-
+- 11. If, as a consequence of a court judgment or allegation of patent
+-infringement or for any other reason (not limited to patent issues),
+-conditions are imposed on you (whether by court order, agreement or
+-otherwise) that contradict the conditions of this License, they do not
+-excuse you from the conditions of this License. If you cannot
+-distribute so as to satisfy simultaneously your obligations under this
+-License and any other pertinent obligations, then as a consequence you
+-may not distribute the Library at all. For example, if a patent
+-license would not permit royalty-free redistribution of the Library by
+-all those who receive copies directly or indirectly through you, then
+-the only way you could satisfy both it and this License would be to
+-refrain entirely from distribution of the Library.
+-
+-If any portion of this section is held invalid or unenforceable under any
+-particular circumstance, the balance of the section is intended to apply,
+-and the section as a whole is intended to apply in other circumstances.
+-
+-It is not the purpose of this section to induce you to infringe any
+-patents or other property right claims or to contest validity of any
+-such claims; this section has the sole purpose of protecting the
+-integrity of the free software distribution system which is
+-implemented by public license practices. Many people have made
+-generous contributions to the wide range of software distributed
+-through that system in reliance on consistent application of that
+-system; it is up to the author/donor to decide if he or she is willing
+-to distribute software through any other system and a licensee cannot
+-impose that choice.
+-
+-This section is intended to make thoroughly clear what is believed to
+-be a consequence of the rest of this License.
+-
+- 12. If the distribution and/or use of the Library is restricted in
+-certain countries either by patents or by copyrighted interfaces, the
+-original copyright holder who places the Library under this License may add
+-an explicit geographical distribution limitation excluding those countries,
+-so that distribution is permitted only in or among countries not thus
+-excluded. In such case, this License incorporates the limitation as if
+-written in the body of this License.
+-
+- 13. The Free Software Foundation may publish revised and/or new
+-versions of the Lesser General Public License from time to time.
+-Such new versions will be similar in spirit to the present version,
+-but may differ in detail to address new problems or concerns.
+-
+-Each version is given a distinguishing version number. If the Library
+-specifies a version number of this License which applies to it and
+-"any later version", you have the option of following the terms and
+-conditions either of that version or of any later version published by
+-the Free Software Foundation. If the Library does not specify a
+-license version number, you may choose any version ever published by
+-the Free Software Foundation.
+-
+- 14. If you wish to incorporate parts of the Library into other free
+-programs whose distribution conditions are incompatible with these,
+-write to the author to ask for permission. For software which is
+-copyrighted by the Free Software Foundation, write to the Free
+-Software Foundation; we sometimes make exceptions for this. Our
+-decision will be guided by the two goals of preserving the free status
+-of all derivatives of our free software and of promoting the sharing
+-and reuse of software generally.
+-
+- NO WARRANTY
+-
+- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+-
+- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+-DAMAGES.
+-
+- END OF TERMS AND CONDITIONS
+-
+- How to Apply These Terms to Your New Libraries
+-
+- If you develop a new library, and you want it to be of the greatest
+-possible use to the public, we recommend making it free software that
+-everyone can redistribute and change. You can do so by permitting
+-redistribution under these terms (or, alternatively, under the terms of the
+-ordinary General Public License).
+-
+- To apply these terms, attach the following notices to the library. It is
+-safest to attach them to the start of each source file to most effectively
+-convey the exclusion of warranty; and each file should have at least the
+-"copyright" line and a pointer to where the full notice is found.
+-
+- <one line to give the library's name and a brief idea of what it does.>
+- Copyright (C) <year> <name of author>
+-
+- This library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2.1 of the License, or (at your option) any later version.
+-
+- This library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with this library; if not, write to the Free Software
+- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+-
+-Also add information on how to contact you by electronic and paper mail.
+-
+-You should also get your employer (if you work as a programmer) or your
+-school, if any, to sign a "copyright disclaimer" for the library, if
+-necessary. Here is a sample; alter the names:
+-
+- Yoyodyne, Inc., hereby disclaims all copyright interest in the
+- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+-
+- <signature of Ty Coon>, 1 April 1990
+- Ty Coon, President of Vice
+-
+-That's all there is to it!
+-
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/dcc7.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc7.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/dcc7.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc7.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1541 +0,0 @@
+-/* $Id: dcc7.c 1087 2011-04-14 20:53:25Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- * Bartłomiej Zimoń <uzi18@o2.pl>
+- *
+- * Thanks to Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110,
+- * USA.
+- */
+-
+-/**
+- * \file dcc7.c
+- *
+- * \brief Obsługa połączeń bezpośrednich od wersji Gadu-Gadu 7.x
+- */
+-
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#ifndef _WIN32
+-# include <sys/ioctl.h>
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-# ifdef sun
+-# include <sys/filio.h>
+-# endif
+-#endif
+-#include <time.h>
+-
+-#include <ctype.h>
+-#include <errno.h>
+-#include <fcntl.h>
+-#include <stdarg.h>
+-#include <string.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <unistd.h>
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-#include "protocol.h"
+-#include "resolver.h"
+-#include "libgadu-internal.h"
+-#include "libgadu-debug.h"
+-
+-#define gg_debug_dcc(dcc, level, fmt...) \
+- gg_debug_session(((dcc) != NULL) ? (dcc)->sess : NULL, level, fmt)
+-
+-#define gg_debug_dump_dcc(dcc, level, buf, len) \
+- gg_debug_dump(((dcc) != NULL) ? (dcc)->sess : NULL, level, buf, len)
+-
+-/**
+- * \internal Dodaje połączenie bezpośrednie do sesji.
+- *
+- * \param sess Struktura sesji
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_session_add(struct gg_session *sess, struct gg_dcc7 *dcc)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_add(%p, %p)\n", sess, dcc);
+-
+- if (!sess || !dcc || dcc->next) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_add() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- dcc->next = sess->dcc7_list;
+- sess->dcc7_list = dcc;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Usuwa połączenie bezpośrednie z sesji.
+- *
+- * \param sess Struktura sesji
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_session_remove(struct gg_session *sess, struct gg_dcc7 *dcc)
+-{
+- struct gg_dcc7 *tmp;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_remove(%p, %p)\n", sess, dcc);
+-
+- if (sess == NULL || dcc == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_session_remove() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (sess->dcc7_list == dcc) {
+- sess->dcc7_list = dcc->next;
+- dcc->next = NULL;
+- return 0;
+- }
+-
+- for (tmp = sess->dcc7_list; tmp != NULL; tmp = tmp->next) {
+- if (tmp->next == dcc) {
+- tmp->next = dcc->next;
+- dcc->next = NULL;
+- return 0;
+- }
+- }
+-
+- errno = ENOENT;
+- return -1;
+-}
+-
+-/**
+- * \internal Zwraca strukturę połączenia o danym identyfikatorze.
+- *
+- * \param sess Struktura sesji
+- * \param id Identyfikator połączenia
+- * \param uin Numer nadawcy lub odbiorcy
+- *
+- * \return Struktura połączenia lub \c NULL jeśli nie znaleziono
+- */
+-static struct gg_dcc7 *gg_dcc7_session_find(struct gg_session *sess, gg_dcc7_id_t id, uin_t uin)
+-{
+- struct gg_dcc7 *tmp;
+- int empty;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_session_find(%p, ..., %d)\n", sess, (int) uin);
+-
+- empty = !memcmp(&id, "\0\0\0\0\0\0\0\0", 8);
+-
+- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
+- if (empty) {
+- if (tmp->peer_uin == uin /*&& tmp->state != GG_STATE_WAITING_FOR_ACCEPT*/)
+- return tmp;
+- } else {
+- if (!memcmp(&tmp->cid, &id, sizeof(id)))
+- return tmp;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * \internal Rozpoczyna proces pobierania adresu
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_get_relay_addr(struct gg_dcc7 *dcc)
+-{
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_get_relay_addr(%p)\n", dcc);
+-
+- if (dcc == NULL || dcc->sess == NULL) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (dcc->sess->resolver_start(&dcc->fd, &dcc->resolver, GG_RELAY_HOST) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_get_relay_addr() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
+- return -1;
+- }
+-
+- dcc->state = GG_STATE_RESOLVING_RELAY;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Nawiązuje połączenie bezpośrednie
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_connect(struct gg_dcc7 *dcc)
+-{
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_connect(%p)\n", dcc);
+-
+- if (dcc == NULL) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if ((dcc->fd = gg_connect(&dcc->remote_addr, dcc->remote_port, 1)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_connect() connection failed\n");
+- return -1;
+- }
+-
+- dcc->state = GG_STATE_CONNECTING;
+- dcc->check = GG_CHECK_WRITE;
+- dcc->timeout = GG_DCC7_TIMEOUT_CONNECT;
+- dcc->soft_timeout = 1;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Tworzy gniazdo nasłuchujące dla połączenia bezpośredniego
+- *
+- * \param dcc Struktura połączenia
+- * \param addr Preferowany adres (jeśli równy 0, nasłuchujemy na wszystkich interfejsach)
+- * \param port Preferowany port (jeśli równy 0, nasłuchujemy na losowym)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_listen(struct gg_dcc7 *dcc, uint32_t addr, uint16_t port)
+-{
+- struct sockaddr_in sin;
+- socklen_t sin_len = sizeof(sin);
+- int errsv;
+- int fd;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen(%p, %d)\n", dcc, port);
+-
+- if (!dcc) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if ((fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() can't create socket (%s)\n", strerror(errno));
+- return -1;
+- }
+-
+- memset(&sin, 0, sizeof(sin));
+- sin.sin_family = AF_INET;
+- sin.sin_addr.s_addr = addr;
+- sin.sin_port = htons(port);
+-
+- if (bind(fd, (struct sockaddr*) &sin, sizeof(sin)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to %s:%d\n", inet_ntoa(sin.sin_addr), port);
+- goto fail;
+- }
+-
+- if (port == 0 && getsockname(fd, (struct sockaddr*) &sin, &sin_len) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to bind to port %d\n", port);
+- goto fail;
+- }
+-
+- if (listen(fd, 1)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_listen() unable to listen (%s)\n", strerror(errno));
+- goto fail;
+- }
+-
+- dcc->fd = fd;
+- dcc->local_addr = sin.sin_addr.s_addr;
+- dcc->local_port = ntohs(sin.sin_port);
+-
+- dcc->state = GG_STATE_LISTENING;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
+-
+- return 0;
+-
+-fail:
+- errsv = errno;
+- close(fd);
+- errno = errsv;
+- return -1;
+-}
+-
+-/**
+- * \internal Tworzy gniazdo nasłuchujące i wysyła jego parametry
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_listen_and_send_info(struct gg_dcc7 *dcc)
+-{
+- struct gg_dcc7_info pkt;
+- uint16_t external_port;
+- uint32_t external_addr;
+- struct in_addr addr;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_listen_and_send_info(%p)\n", dcc);
+-
+- if (gg_dcc7_listen(dcc, dcc->sess->client_addr, dcc->sess->client_port) == -1)
+- return -1;
+-
+- if (dcc->sess->external_port != 0)
+- external_port = dcc->sess->external_port;
+- else
+- external_port = dcc->local_port;
+-
+- if (dcc->sess->external_addr != 0)
+- external_addr = dcc->sess->external_addr;
+- else
+- external_addr = dcc->local_addr;
+-
+- addr.s_addr = external_addr;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// dcc7_listen_and_send_info() sending IP address %s and port %d\n", inet_ntoa(addr), external_port);
+-
+- memset(&pkt, 0, sizeof(pkt));
+- pkt.uin = gg_fix32(dcc->peer_uin);
+- pkt.type = GG_DCC7_TYPE_P2P;
+- pkt.id = dcc->cid;
+- snprintf((char*) pkt.info, sizeof(pkt.info), "%s %d", inet_ntoa(addr), external_port);
+- snprintf((char*) pkt.hash, sizeof(pkt.hash), "%u", external_addr + external_port * rand());
+-
+- return gg_send_packet(dcc->sess, GG_DCC7_INFO, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/**
+- * \internal Odwraca połączenie po nieudanym connect()
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_reverse_connect(struct gg_dcc7 *dcc)
+-{
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reverse_connect(%p)\n", dcc);
+-
+- if (dcc->reverse) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() already reverse connection\n");
+- return -1;
+- }
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reverse_connect() timeout, trying reverse connection\n");
+- close(dcc->fd);
+- dcc->fd = -1;
+- dcc->reverse = 1;
+-
+- return gg_dcc7_listen_and_send_info(dcc);
+-}
+-
+-/**
+- * \internal Wysyła do serwera żądanie nadania identyfikatora sesji
+- *
+- * \param sess Struktura sesji
+- * \param type Rodzaj połączenia (\c GG_DCC7_TYPE_FILE lub \c GG_DCC7_TYPE_VOICE)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc7_request_id(struct gg_session *sess, uint32_t type)
+-{
+- struct gg_dcc7_id_request pkt;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_request_id(%p, %d)\n", sess, type);
+-
+- if (!sess) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid parameters\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() not connected\n");
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (type != GG_DCC7_TYPE_VOICE && type != GG_DCC7_TYPE_FILE) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_request_id() invalid transfer type (%d)\n", type);
+- errno = EINVAL;
+- return -1;
+- }
+-
+- memset(&pkt, 0, sizeof(pkt));
+- pkt.type = gg_fix32(type);
+-
+- return gg_send_packet(sess, GG_DCC7_ID_REQUEST, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/**
+- * \internal Rozpoczyna wysyłanie pliku.
+- *
+- * Funkcja jest wykorzystywana przez \c gg_dcc7_send_file() oraz
+- * \c gg_dcc_send_file_fd().
+- *
+- * \param sess Struktura sesji
+- * \param rcpt Numer odbiorcy
+- * \param fd Deskryptor pliku
+- * \param size Rozmiar pliku
+- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
+- * \param hash Skrót SHA-1 pliku
+- * \param seek Flaga mówiąca, czy można używać lseek()
+- *
+- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc7
+- */
+-static struct gg_dcc7 *gg_dcc7_send_file_common(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash, int seek)
+-{
+- struct gg_dcc7 *dcc = NULL;
+-
+- if (!sess || !rcpt || !filename1250 || !hash || fd == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() invalid parameters\n");
+- errno = EINVAL;
+- goto fail;
+- }
+-
+- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file_common() not enough memory\n");
+- goto fail;
+- }
+-
+- if (gg_dcc7_request_id(sess, GG_DCC7_TYPE_FILE) == -1)
+- goto fail;
+-
+- memset(dcc, 0, sizeof(struct gg_dcc7));
+- dcc->type = GG_SESSION_DCC7_SEND;
+- dcc->dcc_type = GG_DCC7_TYPE_FILE;
+- dcc->state = GG_STATE_REQUESTING_ID;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- dcc->sess = sess;
+- dcc->fd = -1;
+- dcc->uin = sess->uin;
+- dcc->peer_uin = rcpt;
+- dcc->file_fd = fd;
+- dcc->size = size;
+- dcc->seek = seek;
+-
+- strncpy((char*) dcc->filename, filename1250, GG_DCC7_FILENAME_LEN - 1);
+- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
+-
+- memcpy(dcc->hash, hash, GG_DCC7_HASH_LEN);
+-
+- if (gg_dcc7_session_add(sess, dcc) == -1)
+- goto fail;
+-
+- return dcc;
+-
+-fail:
+- free(dcc);
+- return NULL;
+-}
+-
+-/**
+- * Rozpoczyna wysyłanie pliku o danej nazwie.
+- *
+- * \param sess Struktura sesji
+- * \param rcpt Numer odbiorcy
+- * \param filename Nazwa pliku w lokalnym systemie plików
+- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
+- * \param hash Skrót SHA-1 pliku (lub \c NULL jeśli ma być wyznaczony)
+- *
+- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc7
+- */
+-struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash)
+-{
+- struct gg_dcc7 *dcc = NULL;
+- const char *tmp;
+- char hash_buf[GG_DCC7_HASH_LEN];
+- struct stat st;
+- int fd = -1;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file(%p, %d, \"%s\", %p)\n", sess, rcpt, filename, hash);
+-
+- if (!sess || !rcpt || !filename) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() invalid parameters\n");
+- errno = EINVAL;
+- goto fail;
+- }
+-
+- if (!filename1250)
+- filename1250 = filename;
+-
+- if (stat(filename, &st) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() stat() failed (%s)\n", strerror(errno));
+- goto fail;
+- }
+-
+- if ((st.st_mode & S_IFDIR)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() that's a directory\n");
+- errno = EINVAL;
+- goto fail;
+- }
+-
+- if ((fd = open(filename, O_RDONLY)) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_send_file() open() failed (%s)\n", strerror(errno));
+- goto fail;
+- }
+-
+- if (!hash) {
+- if (gg_file_hash_sha1(fd, (uint8_t*) hash_buf) == -1)
+- goto fail;
+-
+- hash = hash_buf;
+- }
+-
+- if ((tmp = strrchr(filename1250, '/')))
+- filename1250 = tmp + 1;
+-
+- if (!(dcc = gg_dcc7_send_file_common(sess, rcpt, fd, st.st_size, filename1250, hash, 1)))
+- goto fail;
+-
+- return dcc;
+-
+-fail:
+- if (fd != -1) {
+- int errsv = errno;
+- close(fd);
+- errno = errsv;
+- }
+-
+- free(dcc);
+- return NULL;
+-}
+-
+-/**
+- * \internal Rozpoczyna wysyłanie pliku o danym deskryptorze.
+- *
+- * \note Wysyłanie pliku nie będzie działać poprawnie, jeśli deskryptor
+- * źródłowy jest w trybie nieblokującym i w pewnym momencie zabraknie danych.
+- *
+- * \param sess Struktura sesji
+- * \param rcpt Numer odbiorcy
+- * \param fd Deskryptor pliku
+- * \param size Rozmiar pliku
+- * \param filename1250 Nazwa pliku w kodowaniu CP-1250
+- * \param hash Skrót SHA-1 pliku
+- *
+- * \return Struktura \c gg_dcc7 lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc7
+- */
+-struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_send_file_fd(%p, %d, %d, %u, \"%s\", %p)\n", sess, rcpt, fd, size, filename1250, hash);
+-
+- return gg_dcc7_send_file_common(sess, rcpt, fd, size, filename1250, hash, 0);
+-}
+-
+-
+-/**
+- * Potwierdza chęć odebrania pliku.
+- *
+- * \param dcc Struktura połączenia
+- * \param offset Początkowy offset przy wznawianiu przesyłania pliku
+- *
+- * \note Biblioteka nie zmienia położenia w odbieranych plikach. Jeśli offset
+- * początkowy jest różny od zera, należy ustawić go funkcją \c lseek() lub
+- * podobną.
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup dcc7
+- */
+-int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset)
+-{
+- struct gg_dcc7_accept pkt;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_accept(%p, %d)\n", dcc, offset);
+-
+- if (!dcc || !dcc->sess) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_accept() invalid parameters\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- memset(&pkt, 0, sizeof(pkt));
+- pkt.uin = gg_fix32(dcc->peer_uin);
+- pkt.id = dcc->cid;
+- pkt.offset = gg_fix32(offset);
+-
+- if (gg_send_packet(dcc->sess, GG_DCC7_ACCEPT, &pkt, sizeof(pkt), NULL) == -1)
+- return -1;
+-
+- dcc->offset = offset;
+-
+- return gg_dcc7_listen_and_send_info(dcc);
+-}
+-
+-/**
+- * Odrzuca próbę przesłania pliku.
+- *
+- * \param dcc Struktura połączenia
+- * \param reason Powód odrzucenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup dcc7
+- */
+-int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason)
+-{
+- struct gg_dcc7_reject pkt;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_reject(%p, %d)\n", dcc, reason);
+-
+- if (!dcc || !dcc->sess) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_reject() invalid parameters\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- memset(&pkt, 0, sizeof(pkt));
+- pkt.uin = gg_fix32(dcc->peer_uin);
+- pkt.id = dcc->cid;
+- pkt.reason = gg_fix32(reason);
+-
+- return gg_send_packet(dcc->sess, GG_DCC7_REJECT, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet identyfikatora połączenia bezpośredniego.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param payload Treść pakietu
+- * \param len Długość pakietu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
+-{
+- const struct gg_dcc7_id_reply *p = payload;
+- struct gg_dcc7 *tmp;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_id(%p, %p, %p, %d)\n", sess, e, payload, len);
+-
+- for (tmp = sess->dcc7_list; tmp; tmp = tmp->next) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// checking dcc %p, state %d, type %d\n", tmp, tmp->state, tmp->dcc_type);
+-
+- if (tmp->state != GG_STATE_REQUESTING_ID || tmp->dcc_type != gg_fix32(p->type))
+- continue;
+-
+- tmp->cid = p->id;
+-
+- switch (tmp->dcc_type) {
+- case GG_DCC7_TYPE_FILE:
+- {
+- struct gg_dcc7_new s;
+-
+- memset(&s, 0, sizeof(s));
+- s.id = tmp->cid;
+- s.type = gg_fix32(GG_DCC7_TYPE_FILE);
+- s.uin_from = gg_fix32(tmp->uin);
+- s.uin_to = gg_fix32(tmp->peer_uin);
+- s.size = gg_fix32(tmp->size);
+-
+- memcpy((char*) s.filename, (char*) tmp->filename, GG_DCC7_FILENAME_LEN);
+-
+- tmp->state = GG_STATE_WAITING_FOR_ACCEPT;
+- tmp->timeout = GG_DCC7_TIMEOUT_FILE_ACK;
+-
+- return gg_send_packet(sess, GG_DCC7_NEW, &s, sizeof(s), NULL);
+- }
+- }
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet akceptacji połączenia bezpośredniego.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param payload Treść pakietu
+- * \param len Długość pakietu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
+-{
+- const struct gg_dcc7_accept *p = payload;
+- struct gg_dcc7 *dcc;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_accept(%p, %p, %p, %d)\n", sess, e, payload, len);
+-
+- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() unknown dcc session\n");
+- // XXX wysłać reject?
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_accept() invalid state\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- // XXX czy dla odwrotnego połączenia powinniśmy wywołać już zdarzenie GG_DCC7_ACCEPT?
+-
+- dcc->offset = gg_fix32(p->offset);
+- dcc->state = GG_STATE_WAITING_FOR_INFO;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet informacji o połączeniu bezpośrednim.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param payload Treść pakietu
+- * \param len Długość pakietu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
+-{
+- const struct gg_dcc7_info *p = payload;
+- struct gg_dcc7 *dcc;
+- char *tmp;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_info(%p, %p, %p, %d)\n", sess, e, payload, len);
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "// gg_dcc7_handle_info() received address: %s, hash: %s\n", p->info, p->hash);
+-
+- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown dcc session\n");
+- return 0;
+- }
+-
+- if (dcc->state == GG_STATE_CONNECTED) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() state is already connected\n");
+- return 0;
+- }
+-
+- switch (p->type)
+- {
+- case GG_DCC7_TYPE_P2P:
+- if ((dcc->remote_addr = inet_addr(p->info)) == INADDR_NONE) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP address\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- if (!(tmp = strchr(p->info, ' ')) || !(dcc->remote_port = atoi(tmp + 1))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid IP port\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- if (dcc->state == GG_STATE_WAITING_FOR_INFO) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() waiting for info so send one\n");
+- gg_dcc7_listen_and_send_info(dcc);
+- e->type = GG_EVENT_DCC7_PENDING;
+- e->event.dcc7_pending.dcc7 = dcc;
+- return 0;
+- }
+-
+- break;
+-
+- case GG_DCC7_TYPE_SERVER:
+- if (!(tmp = strstr(p->info, "GG"))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unknown info packet\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+-#if defined(HAVE_UINT64_T) && defined(HAVE_STRTOULL)
+- {
+- uint64_t cid;
+-
+- cid = strtoull(tmp + 2, NULL, 0);
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() info.str=%s, info.id=%llu, sess.id=%llu\n", tmp + 2, cid, *((unsigned long long*) &dcc->cid));
+-
+- cid = gg_fix64(cid);
+-
+- if (memcmp(&dcc->cid, &cid, sizeof(cid)) != 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid session id\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+- }
+-#endif
+-
+- if (gg_dcc7_get_relay_addr(dcc) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unable to retrieve relay address\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_RELAY;
+- return 0;
+- }
+-
+- // XXX wysyłać dopiero jeśli uda się połączyć z serwerem?
+-
+- gg_send_packet(dcc->sess, GG_DCC7_INFO, payload, len, NULL);
+-
+- return 0;
+-
+- default:
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() unhandled transfer type (%d)\n", p->type);
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- // jeśli nadal czekamy na połączenie przychodzące, a druga strona nie
+- // daje rady i oferuje namiary na siebie, bierzemy co dają.
+-
+-// if (dcc->state != GG_STATE_WAITING_FOR_INFO && (dcc->state != GG_STATE_LISTENING || dcc->reverse)) {
+-// gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_info() invalid state\n");
+-// e->type = GG_EVENT_DCC7_ERROR;
+-// e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+-// return 0;
+-// }
+-
+- if (dcc->state == GG_STATE_LISTENING) {
+- close(dcc->fd);
+- dcc->fd = -1;
+- dcc->reverse = 1;
+- }
+-
+- if (dcc->type == GG_SESSION_DCC7_SEND) {
+- e->type = GG_EVENT_DCC7_ACCEPT;
+- e->event.dcc7_accept.dcc7 = dcc;
+- e->event.dcc7_accept.type = gg_fix32(p->type);
+- e->event.dcc7_accept.remote_ip = dcc->remote_addr;
+- e->event.dcc7_accept.remote_port = dcc->remote_port;
+- } else {
+- e->type = GG_EVENT_DCC7_PENDING;
+- e->event.dcc7_pending.dcc7 = dcc;
+- }
+-
+- if (gg_dcc7_connect(dcc) == -1) {
+- if (gg_dcc7_reverse_connect(dcc) == -1) {
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_NET;
+- return 0;
+- }
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet odrzucenia połączenia bezpośredniego.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param payload Treść pakietu
+- * \param len Długość pakietu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
+-{
+- const struct gg_dcc7_reject *p = payload;
+- struct gg_dcc7 *dcc;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_reject(%p, %p, %p, %d)\n", sess, e, payload, len);
+-
+- if (!(dcc = gg_dcc7_session_find(sess, p->id, gg_fix32(p->uin)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() unknown dcc session\n");
+- return 0;
+- }
+-
+- if (dcc->state != GG_STATE_WAITING_FOR_ACCEPT) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_reject() invalid state\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc7_error = GG_ERROR_DCC7_HANDSHAKE;
+- return 0;
+- }
+-
+- e->type = GG_EVENT_DCC7_REJECT;
+- e->event.dcc7_reject.dcc7 = dcc;
+- e->event.dcc7_reject.reason = gg_fix32(p->reason);
+-
+- // XXX ustawić state na rejected?
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet nowego połączenia bezpośredniego.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param payload Treść pakietu
+- * \param len Długość pakietu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len)
+-{
+- const struct gg_dcc7_new *p = payload;
+- struct gg_dcc7 *dcc;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_dcc7_handle_new(%p, %p, %p, %d)\n", sess, e, payload, len);
+-
+- switch (gg_fix32(p->type)) {
+- case GG_DCC7_TYPE_FILE:
+- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() not enough memory\n");
+- return -1;
+- }
+-
+- memset(dcc, 0, sizeof(struct gg_dcc7));
+- dcc->type = GG_SESSION_DCC7_GET;
+- dcc->dcc_type = GG_DCC7_TYPE_FILE;
+- dcc->fd = -1;
+- dcc->file_fd = -1;
+- dcc->uin = sess->uin;
+- dcc->peer_uin = gg_fix32(p->uin_from);
+- dcc->cid = p->id;
+- dcc->sess = sess;
+-
+- if (gg_dcc7_session_add(sess, dcc) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n");
+- gg_dcc7_free(dcc);
+- return -1;
+- }
+-
+- dcc->size = gg_fix32(p->size);
+- strncpy((char*) dcc->filename, (char*) p->filename, GG_DCC7_FILENAME_LEN - 1);
+- dcc->filename[GG_DCC7_FILENAME_LEN] = 0;
+- memcpy(dcc->hash, p->hash, GG_DCC7_HASH_LEN);
+-
+- e->type = GG_EVENT_DCC7_NEW;
+- e->event.dcc7_new = dcc;
+-
+- break;
+-
+- case GG_DCC7_TYPE_VOICE:
+- if (!(dcc = malloc(sizeof(struct gg_dcc7)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_packet() not enough memory\n");
+- return -1;
+- }
+-
+- memset(dcc, 0, sizeof(struct gg_dcc7));
+-
+- dcc->type = GG_SESSION_DCC7_VOICE;
+- dcc->dcc_type = GG_DCC7_TYPE_VOICE;
+- dcc->fd = -1;
+- dcc->file_fd = -1;
+- dcc->uin = sess->uin;
+- dcc->peer_uin = gg_fix32(p->uin_from);
+- dcc->cid = p->id;
+- dcc->sess = sess;
+-
+- if (gg_dcc7_session_add(sess, dcc) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unable to add to session\n");
+- gg_dcc7_free(dcc);
+- return -1;
+- }
+-
+- e->type = GG_EVENT_DCC7_NEW;
+- e->event.dcc7_new = dcc;
+-
+- break;
+-
+- default:
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_dcc7_handle_new() unknown dcc type (%d) from %ld\n", gg_fix32(p->type), gg_fix32(p->uin_from));
+-
+- break;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Ustawia odpowiednie stany wewnętrzne w zależności od rodzaju
+- * połączenia.
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu.
+- */
+-static int gg_dcc7_postauth_fixup(struct gg_dcc7 *dcc)
+-{
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_postauth_fixup(%p)\n", dcc);
+-
+- if (!dcc) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_postauth_fixup() invalid parameters\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- switch (dcc->type) {
+- case GG_SESSION_DCC7_GET:
+- dcc->state = GG_STATE_GETTING_FILE;
+- dcc->check = GG_CHECK_READ;
+- return 0;
+-
+- case GG_SESSION_DCC7_SEND:
+- dcc->state = GG_STATE_SENDING_FILE;
+- dcc->check = GG_CHECK_WRITE;
+- return 0;
+-
+- case GG_SESSION_DCC7_VOICE:
+- dcc->state = GG_STATE_READING_VOICE_DATA;
+- dcc->check = GG_CHECK_READ;
+- return 0;
+- }
+-
+- errno = EINVAL;
+-
+- return -1;
+-}
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
+- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
+- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
+- *
+- * \ingroup dcc7
+- */
+-struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *dcc)
+-{
+- struct gg_event *e;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_watch_fd(%p)\n", dcc);
+-
+- if (!dcc || (dcc->type != GG_SESSION_DCC7_SEND && dcc->type != GG_SESSION_DCC7_GET && dcc->type != GG_SESSION_DCC7_VOICE)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid parameters\n");
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- if (!(e = malloc(sizeof(struct gg_event)))) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory\n");
+- return NULL;
+- }
+-
+- memset(e, 0, sizeof(struct gg_event));
+- e->type = GG_EVENT_NONE;
+-
+- switch (dcc->state) {
+- case GG_STATE_LISTENING:
+- {
+- struct sockaddr_in sin;
+- int fd, one = 1;
+- socklen_t sin_len = sizeof(sin);
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_LISTENING\n");
+-
+- if ((fd = accept(dcc->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() accept() failed (%s)\n", strerror(errno));
+- return e;
+- }
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+-
+-#ifdef FIONBIO
+- if (ioctl(fd, FIONBIO, &one) == -1) {
+-#else
+- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+-#endif
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() can't set nonblocking (%s)\n", strerror(errno));
+- close(fd);
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+-
+- close(dcc->fd);
+- dcc->fd = fd;
+-
+- dcc->state = GG_STATE_READING_ID;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- dcc->incoming = 1;
+-
+- dcc->remote_port = ntohs(sin.sin_port);
+- dcc->remote_addr = sin.sin_addr.s_addr;
+-
+- e->type = GG_EVENT_DCC7_CONNECTED;
+- e->event.dcc7_connected.dcc7 = dcc;
+-
+- return e;
+- }
+-
+- case GG_STATE_CONNECTING:
+- {
+- int res = 0, error = 0;
+- unsigned int error_size = sizeof(error);
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING\n");
+-
+- dcc->soft_timeout = 0;
+-
+- if (dcc->timeout == 0)
+- error = ETIMEDOUT;
+-
+- if (error || (res = getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &error, &error_size)) == -1 || error != 0) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (%s)\n", (res == -1) ? strerror(errno) : strerror(error));
+-
+- if (dcc->relay) {
+- for (dcc->relay_index++; dcc->relay_index < dcc->relay_count; dcc->relay_index++) {
+- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
+- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
+-
+- if (gg_dcc7_connect(dcc) == 0)
+- break;
+- }
+-
+- if (dcc->relay_index >= dcc->relay_count) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+- } else {
+- if (gg_dcc7_reverse_connect(dcc) != -1) {
+- e->type = GG_EVENT_DCC7_PENDING;
+- e->event.dcc7_pending.dcc7 = dcc;
+- } else {
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_NET;
+- }
+-
+- return e;
+- }
+- }
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connected, sending id\n");
+-
+- dcc->state = GG_STATE_SENDING_ID;
+- dcc->check = GG_CHECK_WRITE;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- dcc->incoming = 0;
+-
+- return e;
+- }
+-
+- case GG_STATE_READING_ID:
+- {
+- int res;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_ID\n");
+-
+- if (!dcc->relay) {
+- struct gg_dcc7_welcome_p2p welcome, welcome_ok;
+- welcome_ok.id = dcc->cid;
+-
+- if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+-
+- if (memcmp(&welcome, &welcome_ok, sizeof(welcome))) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+- } else {
+- struct gg_dcc7_welcome_server welcome, welcome_ok;
+- welcome_ok.magic = GG_DCC7_WELCOME_SERVER;
+- welcome_ok.id = dcc->cid;
+-
+- if ((res = read(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+-
+- if (memcmp(&welcome, &welcome_ok, sizeof(welcome)) != 0) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() invalid id\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+- }
+-
+- if (dcc->incoming) {
+- dcc->state = GG_STATE_SENDING_ID;
+- dcc->check = GG_CHECK_WRITE;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- } else {
+- gg_dcc7_postauth_fixup(dcc);
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- }
+-
+- return e;
+- }
+-
+- case GG_STATE_SENDING_ID:
+- {
+- int res;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_SENDING_ID\n");
+-
+- if (!dcc->relay) {
+- struct gg_dcc7_welcome_p2p welcome;
+-
+- welcome.id = dcc->cid;
+-
+- if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+- } else {
+- struct gg_dcc7_welcome_server welcome;
+-
+- welcome.magic = gg_fix32(GG_DCC7_WELCOME_SERVER);
+- welcome.id = dcc->cid;
+-
+- if ((res = write(dcc->fd, &welcome, sizeof(welcome))) != sizeof(welcome)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+- return e;
+- }
+- }
+-
+- if (dcc->incoming) {
+- gg_dcc7_postauth_fixup(dcc);
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- } else {
+- dcc->state = GG_STATE_READING_ID;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+- }
+-
+- return e;
+- }
+-
+- case GG_STATE_SENDING_FILE:
+- {
+- char buf[1024];
+- int chunk, res;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_SENDING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size);
+-
+- if (dcc->offset >= dcc->size) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() offset >= size, finished\n");
+- e->type = GG_EVENT_DCC7_DONE;
+- e->event.dcc7_done.dcc7 = dcc;
+- return e;
+- }
+-
+- if (dcc->seek && lseek(dcc->file_fd, dcc->offset, SEEK_SET) == (off_t) -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() lseek() failed (%s)\n", strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_FILE;
+- return e;
+- }
+-
+- if ((chunk = dcc->size - dcc->offset) > sizeof(buf))
+- chunk = sizeof(buf);
+-
+- if ((res = read(dcc->file_fd, buf, chunk)) < 1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (res=%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_FILE : GG_ERROR_DCC7_EOF;
+- return e;
+- }
+-
+- if ((res = write(dcc->fd, buf, res)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (%s)\n", strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_NET;
+- return e;
+- }
+-
+- dcc->offset += res;
+-
+- if (dcc->offset >= dcc->size) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
+- e->type = GG_EVENT_DCC7_DONE;
+- e->event.dcc7_done.dcc7 = dcc;
+- return e;
+- }
+-
+- dcc->state = GG_STATE_SENDING_FILE;
+- dcc->check = GG_CHECK_WRITE;
+- dcc->timeout = GG_DCC7_TIMEOUT_SEND;
+-
+- return e;
+- }
+-
+- case GG_STATE_GETTING_FILE:
+- {
+- char buf[1024];
+- int res, wres;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_GETTING_FILE (offset=%d, size=%d)\n", dcc->offset, dcc->size);
+-
+- if (dcc->offset >= dcc->size) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
+- e->type = GG_EVENT_DCC7_DONE;
+- e->event.dcc7_done.dcc7 = dcc;
+- return e;
+- }
+-
+- if ((res = read(dcc->fd, buf, sizeof(buf))) < 1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (fd=%d, res=%d, %s)\n", dcc->fd, res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = (res == -1) ? GG_ERROR_DCC7_NET : GG_ERROR_DCC7_EOF;
+- return e;
+- }
+-
+- // XXX zapisywać do skutku?
+-
+- if ((wres = write(dcc->file_fd, buf, res)) < res) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() write() failed (fd=%d, res=%d, %s)\n", dcc->file_fd, wres, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_FILE;
+- return e;
+- }
+-
+- dcc->offset += res;
+-
+- if (dcc->offset >= dcc->size) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() finished\n");
+- e->type = GG_EVENT_DCC7_DONE;
+- e->event.dcc7_done.dcc7 = dcc;
+- return e;
+- }
+-
+- dcc->state = GG_STATE_GETTING_FILE;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DCC7_TIMEOUT_GET;
+-
+- return e;
+- }
+-
+- case GG_STATE_RESOLVING_RELAY:
+- {
+- struct in_addr addr;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_RESOLVING_RELAY\n");
+-
+- if (read(dcc->fd, &addr, sizeof(addr)) < sizeof(addr) || addr.s_addr == INADDR_NONE) {
+- int errno_save = errno;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolving failed\n");
+- close(dcc->fd);
+- dcc->fd = -1;
+- dcc->sess->resolver_cleanup(&dcc->resolver, 0);
+- errno = errno_save;
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), GG_RELAY_PORT);
+-
+- if ((dcc->fd = gg_connect(&addr, GG_RELAY_PORT, 1)) == -1) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- dcc->state = GG_STATE_CONNECTING_RELAY;
+- dcc->check = GG_CHECK_WRITE;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+-
+- e->type = GG_EVENT_DCC7_PENDING;
+- e->event.dcc7_pending.dcc7 = dcc;
+-
+- return e;
+- }
+-
+- case GG_STATE_CONNECTING_RELAY:
+- {
+- int res;
+- unsigned int res_size = sizeof(res);
+- struct gg_dcc7_relay_req pkt;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_CONNECTING_RELAY\n");
+-
+- if (getsockopt(dcc->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) != 0 || res != 0) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- memset(&pkt, 0, sizeof(pkt));
+- pkt.magic = gg_fix32(GG_DCC7_RELAY_REQUEST);
+- pkt.len = gg_fix32(sizeof(pkt));
+- pkt.id = dcc->cid;
+- pkt.type = gg_fix16(GG_DCC7_RELAY_TYPE_SERVER);
+- pkt.dunno1 = gg_fix16(GG_DCC7_RELAY_DUNNO1);
+-
+- gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_watch_fd() send pkt(0x%.2x)\n", gg_fix32(pkt.magic));
+- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, (const char*) &pkt, sizeof(pkt));
+-
+- if ((res = write(dcc->fd, &pkt, sizeof(pkt))) != sizeof(pkt)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() sending failed\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- dcc->state = GG_STATE_READING_RELAY;
+- dcc->check = GG_CHECK_READ;
+- dcc->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+- }
+-
+- case GG_STATE_READING_RELAY:
+- {
+- char buf[256];
+- struct gg_dcc7_relay_reply *pkt;
+- struct gg_dcc7_relay_reply_server srv;
+- int res;
+- int i;
+-
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_READING_RELAY\n");
+-
+- if ((res = read(dcc->fd, buf, sizeof(buf))) < sizeof(*pkt)) {
+- if (res == 0)
+- errno = ECONNRESET;
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() read() failed (%d, %s)\n", res, strerror(errno));
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- pkt = (struct gg_dcc7_relay_reply*) buf;
+-
+- if (gg_fix32(pkt->magic) != GG_DCC7_RELAY_REPLY || gg_fix32(pkt->rcount) < 1 || gg_fix32(pkt->rcount > 256) || gg_fix32(pkt->len) < sizeof(*pkt) + gg_fix32(pkt->rcount) * sizeof(srv)) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_wathc_fd() invalid reply\n");
+- errno = EINVAL;
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- gg_debug_dcc(dcc, GG_DEBUG_DUMP, "// gg_dcc7_get_relay() read pkt(0x%.2x)\n", gg_fix32(pkt->magic));
+- gg_debug_dump_dcc(dcc, GG_DEBUG_DUMP, buf, res);
+-
+- free(dcc->relay_list);
+-
+- dcc->relay_index = 0;
+- dcc->relay_count = gg_fix32(pkt->rcount);
+- dcc->relay_list = malloc(dcc->relay_count * sizeof(gg_dcc7_relay_t));
+-
+- if (dcc->relay_list == NULL) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() not enough memory");
+- dcc->relay_count = 0;
+- free(e);
+- return NULL;
+- }
+-
+- for (i = 0; i < dcc->relay_count; i++) {
+- struct in_addr addr;
+-
+- memcpy(&srv, buf + sizeof(*pkt) + i * sizeof(srv), sizeof(srv));
+- dcc->relay_list[i].addr = srv.addr;
+- dcc->relay_list[i].port = gg_fix16(srv.port);
+- dcc->relay_list[i].family = srv.family;
+-
+- addr.s_addr = srv.addr;
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// %s %d %d\n", inet_ntoa(addr), gg_fix16(srv.port), srv.family);
+- }
+-
+- dcc->relay = 1;
+-
+- for (; dcc->relay_index < dcc->relay_count; dcc->relay_index++) {
+- dcc->remote_addr = dcc->relay_list[dcc->relay_index].addr;
+- dcc->remote_port = dcc->relay_list[dcc->relay_index].port;
+-
+- if (gg_dcc7_connect(dcc) == 0)
+- break;
+- }
+-
+- if (dcc->relay_index >= dcc->relay_count) {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() no relay available");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_RELAY;
+- return e;
+- }
+-
+- return e;
+- }
+-
+- default:
+- {
+- gg_debug_dcc(dcc, GG_DEBUG_MISC, "// gg_dcc7_watch_fd() GG_STATE_???\n");
+- e->type = GG_EVENT_DCC7_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC7_HANDSHAKE;
+-
+- return e;
+- }
+- }
+-
+- return e;
+-}
+-
+-/**
+- * Zwalnia zasoby używane przez połączenie bezpośrednie.
+- *
+- * \param dcc Struktura połączenia
+- *
+- * \ingroup dcc7
+- */
+-void gg_dcc7_free(struct gg_dcc7 *dcc)
+-{
+- gg_debug_dcc(dcc, GG_DEBUG_FUNCTION, "** gg_dcc7_free(%p)\n", dcc);
+-
+- if (!dcc)
+- return;
+-
+- if (dcc->fd != -1)
+- close(dcc->fd);
+-
+- if (dcc->file_fd != -1)
+- close(dcc->file_fd);
+-
+- if (dcc->sess)
+- gg_dcc7_session_remove(dcc->sess, dcc);
+-
+- free(dcc->relay_list);
+-
+- free(dcc);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/dcc.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/dcc.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/dcc.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1345 +0,0 @@
+-/* $Id: dcc.c 1023 2010-11-16 18:27:35Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2008 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file dcc.c
+- *
+- * \brief Obsługa połączeń bezpośrednich do wersji Gadu-Gadu 6.x
+- */
+-
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#ifndef _WIN32
+-# include <sys/ioctl.h>
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-# ifdef sun
+-# include <sys/filio.h>
+-# endif
+-#endif
+-
+-#include <ctype.h>
+-#include <errno.h>
+-#include <fcntl.h>
+-#include <stdarg.h>
+-#include <string.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <unistd.h>
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-
+-#ifndef GG_DEBUG_DISABLE
+-
+-/**
+- * \internal Przekazuje zawartość pakietu do odpluskwiania.
+- *
+- * \param prefix Prefiks informacji
+- * \param fd Deskryptor gniazda
+- * \param buf Bufor z danumi
+- * \param size Rozmiar bufora z danymi
+- */
+-static void gg_dcc_debug_data(const char *prefix, int fd, const void *buf, unsigned int size)
+-{
+- unsigned int i;
+-
+- gg_debug(GG_DEBUG_MISC, "++ gg_dcc %s (fd=%d,len=%d)", prefix, fd, size);
+-
+- for (i = 0; i < size; i++)
+- gg_debug(GG_DEBUG_MISC, " %.2x", ((unsigned char*) buf)[i]);
+-
+- gg_debug(GG_DEBUG_MISC, "\n");
+-}
+-#else
+-#define gg_dcc_debug_data(a,b,c,d) do { } while (0)
+-#endif
+-
+-/**
+- * Wysyła żądanie zwrotnego połączenia bezpośredniego.
+- *
+- * Funkcję wykorzystuje się, jeśli nie ma możliwości połączenia się z odbiorcą
+- * pliku lub rozmowy głosowej. Po otrzymaniu żądania druga strona spróbuje
+- * nawiązać zwrotne połączenie bezpośrednie z nadawcą.
+- * gg_dcc_request()
+- *
+- * \param sess Struktura sesji
+- * \param uin Numer odbiorcy
+- *
+- * \return Patrz \c gg_send_message_ctcp()
+- *
+- * \ingroup dcc6
+- */
+-int gg_dcc_request(struct gg_session *sess, uin_t uin)
+-{
+- return gg_send_message_ctcp(sess, GG_CLASS_CTCP, uin, (unsigned char*) "\002", 1);
+-}
+-
+-/**
+- * \internal Zamienia znacznik czasu w postaci uniksowej na format API WIN32.
+- *
+- * \note Funkcja działa jedynie gdy kompilator obsługuje typ danych
+- * \c long \c long.
+- *
+- * \param ut Czas w postaci uniksowej
+- * \param ft Czas w postaci API WIN32
+- */
+-static void gg_dcc_fill_filetime(uint32_t ut, uint32_t *ft)
+-{
+-#ifdef GG_CONFIG_HAVE_LONG_LONG
+- unsigned long long tmp;
+-
+- tmp = ut;
+- tmp += 11644473600LL;
+- tmp *= 10000000LL;
+-
+-#ifndef GG_CONFIG_BIGENDIAN
+- ft[0] = (uint32_t) tmp;
+- ft[1] = (uint32_t) (tmp >> 32);
+-#else
+- ft[0] = gg_fix32((uint32_t) (tmp >> 32));
+- ft[1] = gg_fix32((uint32_t) tmp);
+-#endif
+-
+-#endif
+-}
+-
+-/**
+- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
+- *
+- * \note Większą funkcjonalność zapewnia funkcja \c gg_dcc_fill_file_info2().
+- *
+- * \param d Struktura połączenia
+- * \param filename Nazwa pliku
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename)
+-{
+- return gg_dcc_fill_file_info2(d, filename, filename);
+-}
+-
+-/**
+- * Wypełnia pola struktury \c gg_dcc niezbędne do wysłania pliku.
+- *
+- * \param d Struktura połączenia
+- * \param filename Nazwa pliku zapisywana w strukturze
+- * \param local_filename Nazwa pliku w lokalnym systemie plików
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename)
+-{
+- struct stat st;
+- const char *name, *ext, *p;
+- unsigned char *q;
+- int i, j;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_fill_file_info2(%p, \"%s\", \"%s\");\n", d, filename, local_filename);
+-
+- if (!d || d->type != GG_SESSION_DCC_SEND) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() invalid arguments\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (stat(local_filename, &st) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() stat() failed (%s)\n", strerror(errno));
+- return -1;
+- }
+-
+- if ((st.st_mode & S_IFDIR)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() that's a directory\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if ((d->file_fd = open(local_filename, O_RDONLY)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() open() failed (%s)\n", strerror(errno));
+- return -1;
+- }
+-
+- memset(&d->file_info, 0, sizeof(d->file_info));
+-
+- if (!(st.st_mode & S_IWUSR))
+- d->file_info.mode |= gg_fix32(GG_DCC_FILEATTR_READONLY);
+-
+- gg_dcc_fill_filetime(st.st_atime, d->file_info.atime);
+- gg_dcc_fill_filetime(st.st_mtime, d->file_info.mtime);
+- gg_dcc_fill_filetime(st.st_ctime, d->file_info.ctime);
+-
+- d->file_info.size = gg_fix32(st.st_size);
+- d->file_info.mode = gg_fix32(0x20); /* FILE_ATTRIBUTE_ARCHIVE */
+-
+- if (!(name = strrchr(filename, '/')))
+- name = filename;
+- else
+- name++;
+-
+- if (!(ext = strrchr(name, '.')))
+- ext = name + strlen(name);
+-
+- for (i = 0, p = name; i < 8 && p < ext; i++, p++)
+- d->file_info.short_filename[i] = toupper(name[i]);
+-
+- if (i == 8 && p < ext) {
+- d->file_info.short_filename[6] = '~';
+- d->file_info.short_filename[7] = '1';
+- }
+-
+- if (strlen(ext) > 0) {
+- for (j = 0; *ext && j < 4; j++, p++)
+- d->file_info.short_filename[i + j] = toupper(ext[j]);
+- }
+-
+- for (q = d->file_info.short_filename; *q; q++) {
+- if (*q == 185) {
+- *q = 165;
+- } else if (*q == 230) {
+- *q = 198;
+- } else if (*q == 234) {
+- *q = 202;
+- } else if (*q == 179) {
+- *q = 163;
+- } else if (*q == 241) {
+- *q = 209;
+- } else if (*q == 243) {
+- *q = 211;
+- } else if (*q == 156) {
+- *q = 140;
+- } else if (*q == 159) {
+- *q = 143;
+- } else if (*q == 191) {
+- *q = 175;
+- }
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_fill_file_info2() short name \"%s\", dos name \"%s\"\n", name, d->file_info.short_filename);
+- strncpy((char*) d->file_info.filename, name, sizeof(d->file_info.filename) - 1);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Rozpoczyna połączenie bezpośrednie z danym klientem.
+- *
+- * \param ip Adres IP odbiorcy
+- * \param port Port odbiorcy
+- * \param my_uin Własny numer
+- * \param peer_uin Numer odbiorcy
+- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub \c GG_SESSION_DCC_GET)
+- *
+- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
+- */
+-static struct gg_dcc *gg_dcc_transfer(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin, int type)
+-{
+- struct gg_dcc *d = NULL;
+- struct in_addr addr;
+-
+- addr.s_addr = ip;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_transfer(%s, %d, %ld, %ld, %s);\n", inet_ntoa(addr), port, my_uin, peer_uin, (type == GG_SESSION_DCC_SEND) ? "SEND" : "GET");
+-
+- if (!ip || ip == INADDR_NONE || !port || !my_uin || !peer_uin) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() invalid arguments\n");
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- if (!(d = (void*) calloc(1, sizeof(*d)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() not enough memory\n");
+- return NULL;
+- }
+-
+- d->check = GG_CHECK_WRITE;
+- d->state = GG_STATE_CONNECTING;
+- d->type = type;
+- d->timeout = GG_DEFAULT_TIMEOUT;
+- d->file_fd = -1;
+- d->active = 1;
+- d->fd = -1;
+- d->uin = my_uin;
+- d->peer_uin = peer_uin;
+-
+- if ((d->fd = gg_connect(&addr, port, 1)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_transfer() connection failed\n");
+- free(d);
+- return NULL;
+- }
+-
+- return d;
+-}
+-
+-/**
+- * Rozpoczyna odbieranie pliku przez zwrotne połączenie bezpośrednie.
+- *
+- * \param ip Adres IP nadawcy
+- * \param port Port nadawcy
+- * \param my_uin Własny numer
+- * \param peer_uin Numer nadawcy
+- *
+- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_get_file() handing over to gg_dcc_transfer()\n");
+-
+- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_GET);
+-}
+-
+-/**
+- * Rozpoczyna wysyłanie pliku.
+- *
+- * \param ip Adres IP odbiorcy
+- * \param port Port odbiorcy
+- * \param my_uin Własny numer
+- * \param peer_uin Numer odbiorcy
+- *
+- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_send_file() handing over to gg_dcc_transfer()\n");
+-
+- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_SEND);
+-}
+-
+-/**
+- * Rozpoczyna połączenie głosowe.
+- *
+- * \param ip Adres IP odbiorcy
+- * \param port Port odbiorcy
+- * \param my_uin Własny numer
+- * \param peer_uin Numer odbiorcy
+- *
+- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_chat() handing over to gg_dcc_transfer()\n");
+-
+- return gg_dcc_transfer(ip, port, my_uin, peer_uin, GG_SESSION_DCC_VOICE);
+-}
+-
+-/**
+- * Ustawia typ przychodzącego połączenia bezpośredniego.
+- *
+- * Funkcję należy wywołać po otrzymaniu zdarzenia \c GG_EVENT_DCC_CALLBACK.
+- *
+- * \param d Struktura połączenia
+- * \param type Rodzaj połączenia (\c GG_SESSION_DCC_SEND lub
+- * \c GG_SESSION_DCC_VOICE)
+- *
+- * \ingroup dcc6
+- */
+-void gg_dcc_set_type(struct gg_dcc *d, int type)
+-{
+- d->type = type;
+- d->state = (type == GG_SESSION_DCC_SEND) ? GG_STATE_SENDING_FILE_INFO : GG_STATE_SENDING_VOICE_REQUEST;
+-}
+-
+-/**
+- * \internal Funkcja zwrotna połączenia bezpośredniego.
+- *
+- * Pole \c callback struktury \c gg_dcc zawiera wskaźnik do tej funkcji.
+- * Wywołuje ona \c gg_watch_fd() i zachowuje wynik w polu \c event.
+- *
+- * \note Funkcjonalność funkcjo zwrotnej nie jest już wspierana.
+- *
+- * \param d Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_dcc_callback(struct gg_dcc *d)
+-{
+- struct gg_event *e = gg_dcc_watch_fd(d);
+-
+- d->event = e;
+-
+- return (e != NULL) ? 0 : -1;
+-}
+-
+-/**
+- * Tworzy gniazdo nasłuchujące dla połączeń bezpośrednich.
+- *
+- * Funkcja przywiązuje gniazdo do pierwszego wolnego portu TCP.
+- *
+- * \param uin Własny numer
+- * \param port Preferowany port (jeśli równy 0 lub -1, próbuje się domyślnego)
+- *
+- * \return Struktura \c gg_dcc lub \c NULL w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port)
+-{
+- struct gg_dcc *c;
+- struct sockaddr_in sin;
+- int sock, bound = 0, errno2;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_create_dcc_socket(%d, %d);\n", uin, port);
+-
+- if (!uin) {
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() invalid arguments\n");
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- if ((sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() can't create socket (%s)\n", strerror(errno));
+- return NULL;
+- }
+-
+- if (port == 0 || port == (uint16_t)-1) /* XXX: port is unsigned */
+- port = GG_DEFAULT_DCC_PORT;
+-
+- while (!bound) {
+- memset(&sin, 0, sizeof(sin));
+- sin.sin_family = AF_INET;
+- sin.sin_addr.s_addr = INADDR_ANY;
+- sin.sin_port = htons(port);
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() trying port %d\n", port);
+- if (!bind(sock, (struct sockaddr*) &sin, sizeof(sin)))
+- bound = 1;
+- else {
+- if (++port == 65535) {
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() no free port found\n");
+- close(sock);
+- return NULL;
+- }
+- }
+- }
+-
+- if (listen(sock, 10)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() unable to listen (%s)\n", strerror(errno));
+- errno2 = errno;
+- close(sock);
+- errno = errno2;
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() bound to port %d\n", port);
+-
+- if (!(c = malloc(sizeof(*c)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_create_dcc_socket() not enough memory for struct\n");
+- close(sock);
+- return NULL;
+- }
+- memset(c, 0, sizeof(*c));
+-
+- c->port = c->id = port;
+- c->fd = sock;
+- c->type = GG_SESSION_DCC_SOCKET;
+- c->uin = uin;
+- c->timeout = -1;
+- c->state = GG_STATE_LISTENING;
+- c->check = GG_CHECK_READ;
+- c->callback = gg_dcc_callback;
+- c->destroy = gg_dcc_free;
+-
+- return c;
+-}
+-
+-/**
+- * Wysyła ramkę danych połączenia głosowego.
+- *
+- * \param d Struktura połączenia
+- * \param buf Bufor z danymi
+- * \param length Długość bufora z danymi
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup dcc6
+- */
+-int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length)
+-{
+- struct packet_s {
+- uint8_t type;
+- uint32_t length;
+- } GG_PACKED;
+- struct packet_s packet;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "++ gg_dcc_voice_send(%p, %p, %d);\n", d, buf, length);
+- if (!d || !buf || length < 0 || d->type != GG_SESSION_DCC_VOICE) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() invalid argument\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- packet.type = 0x03; /* XXX */
+- packet.length = gg_fix32(length);
+-
+- if (write(d->fd, &packet, sizeof(packet)) < (signed)sizeof(packet)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n");
+- return -1;
+- }
+- gg_dcc_debug_data("write", d->fd, &packet, sizeof(packet));
+-
+- if (write(d->fd, buf, length) < length) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_voice_send() write() failed\n");
+- return -1;
+- }
+- gg_dcc_debug_data("write", d->fd, buf, length);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Odbiera dane z połączenia bezpośredniego z obsługą błędów.
+- *
+- * \param fd Deskryptor gniazda
+- * \param buf Bufor na dane
+- * \param size Rozmiar bufora na dane
+- */
+-#define gg_dcc_read(fd, buf, size) \
+-{ \
+- int tmp = read(fd, buf, size); \
+- \
+- if (tmp < (int) size) { \
+- if (tmp == -1) { \
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno)); \
+- } else if (tmp == 0) { \
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n"); \
+- } else { \
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (%d bytes, %d needed)\n", tmp, size); \
+- } \
+- e->type = GG_EVENT_DCC_ERROR; \
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
+- return e; \
+- } \
+- gg_dcc_debug_data("read", fd, buf, size); \
+-}
+-
+-/**
+- * \internal Wysyła dane do połączenia bezpośredniego z obsługą błędów.
+- *
+- * \param fd Deskryptor gniazda
+- * \param buf Bufor z danymi
+- * \param size Rozmiar bufora z danymi
+- */
+-#define gg_dcc_write(fd, buf, size) \
+-{ \
+- int tmp; \
+- gg_dcc_debug_data("write", fd, buf, size); \
+- tmp = write(fd, buf, size); \
+- if (tmp < (int) size) { \
+- if (tmp == -1) { \
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno)); \
+- } else { \
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d needed, %d done)\n", size, tmp); \
+- } \
+- e->type = GG_EVENT_DCC_ERROR; \
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE; \
+- return e; \
+- } \
+-}
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
+- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
+- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free.
+- *
+- * \param h Struktura połączenia
+- *
+- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
+- *
+- * \ingroup dcc6
+- */
+-struct gg_event *gg_dcc_watch_fd(struct gg_dcc *h)
+-{
+- struct gg_event *e;
+- int foo;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_watch_fd(%p);\n", h);
+-
+- if (!h || (h->type != GG_SESSION_DCC && h->type != GG_SESSION_DCC_SOCKET && h->type != GG_SESSION_DCC_SEND && h->type != GG_SESSION_DCC_GET && h->type != GG_SESSION_DCC_VOICE)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid argument\n");
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- if (!(e = (void*) calloc(1, sizeof(*e)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory\n");
+- return NULL;
+- }
+-
+- e->type = GG_EVENT_NONE;
+-
+- if (h->type == GG_SESSION_DCC_SOCKET) {
+- struct sockaddr_in sin;
+- struct gg_dcc *c;
+- int fd, one = 1;
+- unsigned int sin_len = sizeof(sin);
+-
+- if ((fd = accept(h->fd, (struct sockaddr*) &sin, &sin_len)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't accept() new connection (errno=%d, %s)\n", errno, strerror(errno));
+- return e;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() new direct connection from %s:%d\n", inet_ntoa(sin.sin_addr), htons(sin.sin_port));
+-
+-#ifdef FIONBIO
+- if (ioctl(fd, FIONBIO, &one) == -1) {
+-#else
+- if (fcntl(fd, F_SETFL, O_NONBLOCK) == -1) {
+-#endif
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() can't set nonblocking (errno=%d, %s)\n", errno, strerror(errno));
+- close(fd);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- return e;
+- }
+-
+- if (!(c = (void*) calloc(1, sizeof(*c)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() not enough memory for client data\n");
+-
+- free(e);
+- close(fd);
+- return NULL;
+- }
+-
+- c->fd = fd;
+- c->check = GG_CHECK_READ;
+- c->state = GG_STATE_READING_UIN_1;
+- c->type = GG_SESSION_DCC;
+- c->timeout = GG_DEFAULT_TIMEOUT;
+- c->file_fd = -1;
+- c->remote_addr = sin.sin_addr.s_addr;
+- c->remote_port = ntohs(sin.sin_port);
+-
+- e->type = GG_EVENT_DCC_NEW;
+- e->event.dcc_new = c;
+-
+- return e;
+- } else {
+- struct gg_dcc_tiny_packet tiny;
+- struct gg_dcc_small_packet small;
+- struct gg_dcc_big_packet big;
+- int size, tmp, res;
+- unsigned int utmp, res_size = sizeof(res);
+- char buf[1024], ack[] = "UDAG";
+-
+- struct gg_dcc_file_info_packet {
+- struct gg_dcc_big_packet big;
+- struct gg_file_info file_info;
+- } GG_PACKED;
+- struct gg_dcc_file_info_packet file_info_packet;
+-
+- switch (h->state) {
+- case GG_STATE_READING_UIN_1:
+- case GG_STATE_READING_UIN_2:
+- {
+- uin_t uin;
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_READING_UIN_%d\n", (h->state == GG_STATE_READING_UIN_1) ? 1 : 2);
+-
+- gg_dcc_read(h->fd, &uin, sizeof(uin));
+-
+- if (h->state == GG_STATE_READING_UIN_1) {
+- h->state = GG_STATE_READING_UIN_2;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->peer_uin = gg_fix32(uin);
+- } else {
+- h->state = GG_STATE_SENDING_ACK;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->uin = gg_fix32(uin);
+- e->type = GG_EVENT_DCC_CLIENT_ACCEPT;
+- }
+-
+- return e;
+- }
+-
+- case GG_STATE_SENDING_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_SENDING_ACK\n");
+-
+- gg_dcc_write(h->fd, ack, 4);
+-
+- h->state = GG_STATE_READING_TYPE;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+-
+- case GG_STATE_READING_TYPE:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_TYPE\n");
+-
+- gg_dcc_read(h->fd, &small, sizeof(small));
+-
+- small.type = gg_fix32(small.type);
+-
+- switch (small.type) {
+- case 0x0003: /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() callback\n");
+- h->type = GG_SESSION_DCC_SEND;
+- h->state = GG_STATE_SENDING_FILE_INFO;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- e->type = GG_EVENT_DCC_CALLBACK;
+-
+- break;
+-
+- case 0x0002: /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() dialin\n");
+- h->type = GG_SESSION_DCC_GET;
+- h->state = GG_STATE_READING_REQUEST;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->incoming = 1;
+-
+- break;
+-
+- default:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc type (%.4x) from %ld\n", small.type, h->peer_uin);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- }
+-
+- return e;
+-
+- case GG_STATE_READING_REQUEST:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_REQUEST\n");
+-
+- gg_dcc_read(h->fd, &small, sizeof(small));
+-
+- small.type = gg_fix32(small.type);
+-
+- switch (small.type) {
+- case 0x0001: /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() file transfer request\n");
+- h->state = GG_STATE_READING_FILE_INFO;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- break;
+-
+- case 0x0003: /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() voice chat request\n");
+- h->state = GG_STATE_SENDING_VOICE_ACK;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DCC_TIMEOUT_VOICE_ACK;
+- h->type = GG_SESSION_DCC_VOICE;
+- e->type = GG_EVENT_DCC_NEED_VOICE_ACK;
+-
+- break;
+-
+- default:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown dcc request (%.4x) from %ld\n", small.type, h->peer_uin);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- }
+-
+- return e;
+-
+- case GG_STATE_READING_FILE_INFO:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_INFO\n");
+-
+- gg_dcc_read(h->fd, &file_info_packet, sizeof(file_info_packet));
+-
+- memcpy(&h->file_info, &file_info_packet.file_info, sizeof(h->file_info));
+-
+- h->file_info.mode = gg_fix32(h->file_info.mode);
+- h->file_info.size = gg_fix32(h->file_info.size);
+-
+- h->state = GG_STATE_SENDING_FILE_ACK;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
+-
+- e->type = GG_EVENT_DCC_NEED_FILE_ACK;
+-
+- return e;
+-
+- case GG_STATE_SENDING_FILE_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_ACK\n");
+-
+- big.type = gg_fix32(0x0006); /* XXX */
+- big.dunno1 = gg_fix32(h->offset);
+- big.dunno2 = 0;
+-
+- gg_dcc_write(h->fd, &big, sizeof(big));
+-
+- h->state = GG_STATE_READING_FILE_HEADER;
+- h->chunk_size = sizeof(big);
+- h->chunk_offset = 0;
+- if (!(h->chunk_buf = malloc(sizeof(big)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
+- free(e);
+- return NULL;
+- }
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+-
+- case GG_STATE_SENDING_VOICE_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_ACK\n");
+-
+- tiny.type = 0x01; /* XXX */
+-
+- gg_dcc_write(h->fd, &tiny, sizeof(tiny));
+-
+- h->state = GG_STATE_READING_VOICE_HEADER;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- h->offset = 0;
+-
+- return e;
+-
+- case GG_STATE_READING_FILE_HEADER:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_HEADER\n");
+-
+- tmp = read(h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
+-
+- if (tmp == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno));
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+- return e;
+- }
+-
+- gg_dcc_debug_data("read", h->fd, h->chunk_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
+-
+- h->chunk_offset += tmp;
+-
+- if (h->chunk_offset < h->chunk_size)
+- return e;
+-
+- memcpy(&big, h->chunk_buf, sizeof(big));
+- free(h->chunk_buf);
+- h->chunk_buf = NULL;
+-
+- big.type = gg_fix32(big.type);
+- h->chunk_size = gg_fix32(big.dunno1);
+- h->chunk_offset = 0;
+-
+- if (big.type == 0x0005) { /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() transfer refused\n");
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
+- return e;
+- }
+-
+- if (h->chunk_size == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() empty chunk, EOF\n");
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+-
+- h->state = GG_STATE_GETTING_FILE;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->established = 1;
+-
+- return e;
+-
+- case GG_STATE_READING_VOICE_HEADER:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_HEADER\n");
+-
+- gg_dcc_read(h->fd, &tiny, sizeof(tiny));
+-
+- switch (tiny.type) {
+- case 0x03: /* XXX */
+- h->state = GG_STATE_READING_VOICE_SIZE;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->established = 1;
+- break;
+- case 0x04: /* XXX */
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() peer breaking connection\n");
+- /* XXX zwracać odpowiedni event */
+- default:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() unknown request (%.2x)\n", tiny.type);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- }
+-
+- return e;
+-
+- case GG_STATE_READING_VOICE_SIZE:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_SIZE\n");
+-
+- gg_dcc_read(h->fd, &small, sizeof(small));
+-
+- small.type = gg_fix32(small.type);
+-
+- if (small.type < 16 || small.type > sizeof(buf)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() invalid voice frame size (%d)\n", small.type);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+-
+- return e;
+- }
+-
+- h->chunk_size = small.type;
+- h->chunk_offset = 0;
+-
+- if (!(h->voice_buf = malloc(h->chunk_size))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory for voice frame\n");
+- free(e);
+- return NULL;
+- }
+-
+- h->state = GG_STATE_READING_VOICE_DATA;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+-
+- case GG_STATE_READING_VOICE_DATA:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_DATA\n");
+-
+- tmp = read(h->fd, h->voice_buf + h->chunk_offset, h->chunk_size - h->chunk_offset);
+- if (tmp < 1) {
+- if (tmp == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed (errno=%d, %s)\n", errno, strerror(errno));
+- } else {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed, connection broken\n");
+- }
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+- return e;
+- }
+-
+- gg_dcc_debug_data("read", h->fd, h->voice_buf + h->chunk_offset, tmp);
+-
+- h->chunk_offset += tmp;
+-
+- if (h->chunk_offset >= h->chunk_size) {
+- e->type = GG_EVENT_DCC_VOICE_DATA;
+- e->event.dcc_voice_data.data = (unsigned char*) h->voice_buf;
+- e->event.dcc_voice_data.length = h->chunk_size;
+- h->state = GG_STATE_READING_VOICE_HEADER;
+- h->voice_buf = NULL;
+- }
+-
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+-
+- case GG_STATE_CONNECTING:
+- {
+- uin_t uins[2];
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_CONNECTING\n");
+-
+- res = 0;
+- if ((foo = getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size)) || res) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connection failed (fd=%d,errno=%d(%s),foo=%d,res=%d(%s))\n", h->fd, errno, strerror(errno), foo, res, strerror(res));
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- return e;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() connected, sending uins\n");
+-
+- uins[0] = gg_fix32(h->uin);
+- uins[1] = gg_fix32(h->peer_uin);
+-
+- gg_dcc_write(h->fd, uins, sizeof(uins));
+-
+- h->state = GG_STATE_READING_ACK;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+- }
+-
+- case GG_STATE_READING_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_ACK\n");
+-
+- gg_dcc_read(h->fd, buf, 4);
+-
+- if (strncmp(buf, ack, 4)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() did't get ack\n");
+-
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+- return e;
+- }
+-
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->state = GG_STATE_SENDING_REQUEST;
+-
+- return e;
+-
+- case GG_STATE_SENDING_VOICE_REQUEST:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_VOICE_REQUEST\n");
+-
+- small.type = gg_fix32(0x0003);
+-
+- gg_dcc_write(h->fd, &small, sizeof(small));
+-
+- h->state = GG_STATE_READING_VOICE_ACK;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return e;
+-
+- case GG_STATE_SENDING_REQUEST:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_REQUEST\n");
+-
+- small.type = (h->type == GG_SESSION_DCC_GET) ? gg_fix32(0x0003) : gg_fix32(0x0002); /* XXX */
+-
+- gg_dcc_write(h->fd, &small, sizeof(small));
+-
+- switch (h->type) {
+- case GG_SESSION_DCC_GET:
+- h->state = GG_STATE_READING_REQUEST;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- break;
+-
+- case GG_SESSION_DCC_SEND:
+- h->state = GG_STATE_SENDING_FILE_INFO;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- if (h->file_fd == -1)
+- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
+- break;
+-
+- case GG_SESSION_DCC_VOICE:
+- h->state = GG_STATE_SENDING_VOICE_REQUEST;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- break;
+- }
+-
+- return e;
+-
+- case GG_STATE_SENDING_FILE_INFO:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_INFO\n");
+-
+- if (h->file_fd == -1) {
+- e->type = GG_EVENT_DCC_NEED_FILE_INFO;
+- return e;
+- }
+-
+- small.type = gg_fix32(0x0001); /* XXX */
+-
+- gg_dcc_write(h->fd, &small, sizeof(small));
+-
+- file_info_packet.big.type = gg_fix32(0x0003); /* XXX */
+- file_info_packet.big.dunno1 = 0;
+- file_info_packet.big.dunno2 = 0;
+-
+- memcpy(&file_info_packet.file_info, &h->file_info, sizeof(h->file_info));
+-
+- /* zostają teraz u nas, więc odwracamy z powrotem */
+- h->file_info.size = gg_fix32(h->file_info.size);
+- h->file_info.mode = gg_fix32(h->file_info.mode);
+-
+- gg_dcc_write(h->fd, &file_info_packet, sizeof(file_info_packet));
+-
+- h->state = GG_STATE_READING_FILE_ACK;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DCC_TIMEOUT_FILE_ACK;
+-
+- return e;
+-
+- case GG_STATE_READING_FILE_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_FILE_ACK\n");
+-
+- gg_dcc_read(h->fd, &big, sizeof(big));
+-
+- /* XXX sprawdzać wynik */
+- h->offset = gg_fix32(big.dunno1);
+-
+- h->state = GG_STATE_SENDING_FILE_HEADER;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- e->type = GG_EVENT_DCC_ACK;
+-
+- return e;
+-
+- case GG_STATE_READING_VOICE_ACK:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_READING_VOICE_ACK\n");
+-
+- gg_dcc_read(h->fd, &tiny, sizeof(tiny));
+-
+- if (tiny.type != 0x01) {
+- gg_debug(GG_DEBUG_MISC, "// invalid reply (%.2x), connection refused\n", tiny.type);
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_REFUSED;
+- return e;
+- }
+-
+- h->state = GG_STATE_READING_VOICE_HEADER;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- e->type = GG_EVENT_DCC_ACK;
+-
+- return e;
+-
+- case GG_STATE_SENDING_FILE_HEADER:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE_HEADER\n");
+-
+- h->chunk_offset = 0;
+-
+- if ((h->chunk_size = h->file_info.size - h->offset) > 4096) {
+- h->chunk_size = 4096;
+- big.type = gg_fix32(0x0003); /* XXX */
+- } else
+- big.type = gg_fix32(0x0002); /* XXX */
+-
+- big.dunno1 = gg_fix32(h->chunk_size);
+- big.dunno2 = 0;
+-
+- gg_dcc_write(h->fd, &big, sizeof(big));
+-
+- h->state = GG_STATE_SENDING_FILE;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->established = 1;
+-
+- return e;
+-
+- case GG_STATE_SENDING_FILE:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_SENDING_FILE\n");
+-
+- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
+- utmp = sizeof(buf);
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset=%d, size=%d\n", h->offset, h->file_info.size);
+-
+- /* koniec pliku? */
+- if (h->file_info.size == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof on empty file\n");
+- e->type = GG_EVENT_DCC_DONE;
+-
+- return e;
+- }
+-
+- if (h->offset >= h->file_info.size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+-
+- lseek(h->file_fd, h->offset, SEEK_SET);
+-
+- size = read(h->file_fd, buf, utmp);
+-
+- /* błąd */
+- if (size == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno));
+-
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_FILE;
+-
+- return e;
+- }
+-
+- /* koniec pliku? */
+- if (size == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n");
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_EOF;
+-
+- return e;
+- }
+-
+- /* jeśli wczytaliśmy więcej, utnijmy. */
+- if (h->offset + size > h->file_info.size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() too much (read=%d, ofs=%d, size=%d)\n", size, h->offset, h->file_info.size);
+- size = h->file_info.size - h->offset;
+-
+- if (size < 1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() reached EOF after cutting\n");
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+- }
+-
+- tmp = write(h->fd, buf, size);
+-
+- if (tmp == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%s)\n", strerror(errno));
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+- return e;
+- }
+-
+- if (tmp == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (connection reset)\n");
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+- return e;
+- }
+-
+- h->offset += tmp;
+-
+- if (h->offset >= h->file_info.size) {
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+-
+- h->chunk_offset += tmp;
+-
+- if (h->chunk_offset >= h->chunk_size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
+- h->state = GG_STATE_SENDING_FILE_HEADER;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- } else {
+- h->state = GG_STATE_SENDING_FILE;
+- h->timeout = GG_DCC_TIMEOUT_SEND;
+- }
+-
+- h->check = GG_CHECK_WRITE;
+-
+- return e;
+-
+- case GG_STATE_GETTING_FILE:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_GETTING_FILE\n");
+-
+- if ((utmp = h->chunk_size - h->chunk_offset) > sizeof(buf))
+- utmp = sizeof(buf);
+-
+- if (h->offset >= h->file_info.size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() offset >= size, finished\n");
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+-
+- size = read(h->fd, buf, utmp);
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() ofs=%d, size=%d, read()=%d\n", h->offset, h->file_info.size, size);
+-
+- /* błąd */
+- if (size == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() failed. (errno=%d, %s)\n", errno, strerror(errno));
+-
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+-
+- return e;
+- }
+-
+- /* koniec? */
+- if (size == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() read() reached eof\n");
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_EOF;
+-
+- return e;
+- }
+-
+- tmp = write(h->file_fd, buf, size);
+-
+- if (tmp == -1 || tmp < size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() write() failed (%d:fd=%d:res=%d:%s)\n", tmp, h->file_fd, size, strerror(errno));
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_NET;
+- return e;
+- }
+-
+- h->offset += size;
+-
+- if (h->offset >= h->file_info.size) {
+- e->type = GG_EVENT_DCC_DONE;
+- return e;
+- }
+-
+- h->chunk_offset += size;
+-
+- if (h->chunk_offset >= h->chunk_size) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() chunk finished\n");
+- h->state = GG_STATE_READING_FILE_HEADER;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- h->chunk_offset = 0;
+- h->chunk_size = sizeof(big);
+- if (!(h->chunk_buf = malloc(sizeof(big)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() out of memory\n");
+- free(e);
+- return NULL;
+- }
+- } else {
+- h->state = GG_STATE_GETTING_FILE;
+- h->timeout = GG_DCC_TIMEOUT_GET;
+- }
+-
+- h->check = GG_CHECK_READ;
+-
+- return e;
+-
+- default:
+- gg_debug(GG_DEBUG_MISC, "// gg_dcc_watch_fd() GG_STATE_???\n");
+- e->type = GG_EVENT_DCC_ERROR;
+- e->event.dcc_error = GG_ERROR_DCC_HANDSHAKE;
+-
+- return e;
+- }
+- }
+-
+- return e;
+-}
+-
+-/**
+- * Zwalnia zasoby używane przez połączenie bezpośrednie.
+- *
+- * \param d Struktura połączenia
+- *
+- * \ingroup dcc6
+- */
+-void gg_dcc_free(struct gg_dcc *d)
+-{
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_dcc_free(%p);\n", d);
+-
+- if (!d)
+- return;
+-
+- if (d->fd != -1)
+- close(d->fd);
+-
+- free(d->chunk_buf);
+- free(d);
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/debug.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/debug.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/debug.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/debug.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,364 +0,0 @@
+-/*
+- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file debug.c
+- *
+- * \brief Funkcje odpluskwiania
+- */
+-#include <sys/types.h>
+-#include <errno.h>
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <string.h>
+-
+-#include "libgadu.h"
+-#include "libgadu-debug.h"
+-
+-/**
+- * Poziom rejestracji informacji odpluskwiających. Zmienna jest maską bitową
+- * składającą się ze stałych \c GG_DEBUG_...
+- *
+- * \ingroup debug
+- */
+-int gg_debug_level = 0;
+-
+-/**
+- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
+- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
+- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu (\c stderr).
+- *
+- * \param level Poziom rejestracji
+- * \param format Format wiadomości (zgodny z \c printf)
+- * \param ap Lista argumentów (zgodna z \c printf)
+- *
+- * \note Funkcja jest przesłaniana przez \c gg_debug_handler_session.
+- *
+- * \ingroup debug
+- */
+-void (*gg_debug_handler)(int level, const char *format, va_list ap) = NULL;
+-
+-/**
+- * Funkcja, do której są przekazywane informacje odpluskwiające. Jeśli zarówno
+- * ten \c gg_debug_handler, jak i \c gg_debug_handler_session, są równe
+- * \c NULL, informacje są wysyłane do standardowego wyjścia błędu.
+- *
+- * \param sess Sesja której dotyczy informacja lub \c NULL
+- * \param level Poziom rejestracji
+- * \param format Format wiadomości (zgodny z \c printf)
+- * \param ap Lista argumentów (zgodna z \c printf)
+- *
+- * \note Funkcja przesłania przez \c gg_debug_handler_session.
+- *
+- * \ingroup debug
+- */
+-void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap) = NULL;
+-
+-/**
+- * Plik, do którego będą przekazywane informacje odpluskwiania.
+- *
+- * Funkcja \c gg_debug() i pochodne mogą być przechwytywane przez aplikację
+- * korzystającą z biblioteki, by wyświetlić je na żądanie użytkownika lub
+- * zapisać do późniejszej analizy. Jeśli nie określono pliku, wybrane
+- * informacje będą wysyłane do standardowego wyjścia błędu (\c stderr).
+- *
+- * \ingroup debug
+- */
+-FILE *gg_debug_file = NULL;
+-
+-#ifndef GG_DEBUG_DISABLE
+-
+-/**
+- * \internal Przekazuje informacje odpluskwiania do odpowiedniej funkcji.
+- *
+- * Jeśli aplikacja ustawiła odpowiednią funkcję obsługi w
+- * \c gg_debug_handler_session lub \c gg_debug_handler, jest ona wywoływana.
+- * W przeciwnym wypadku wynik jest wysyłany do standardowego wyjścia błędu.
+- *
+- * \param sess Struktura sesji (może być \c NULL)
+- * \param level Poziom informacji
+- * \param format Format wiadomości (zgodny z \c printf)
+- * \param ap Lista argumentów (zgodna z \c printf)
+- */
+-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
+-{
+- if (gg_debug_handler_session != NULL)
+- (*gg_debug_handler_session)(sess, level, format, ap);
+- else if (gg_debug_handler != NULL)
+- (*gg_debug_handler)(level, format, ap);
+- else if ((gg_debug_level & level) != 0)
+- vfprintf((gg_debug_file) ? gg_debug_file : stderr, format, ap);
+-}
+-
+-
+-/**
+- * \internal Przekazuje informację odpluskawiania.
+- *
+- * \param level Poziom wiadomości
+- * \param format Format wiadomości (zgodny z \c printf)
+- *
+- * \ingroup debug
+- */
+-void gg_debug(int level, const char *format, ...)
+-{
+- va_list ap;
+- int old_errno = errno;
+-
+- va_start(ap, format);
+- gg_debug_common(NULL, level, format, ap);
+- va_end(ap);
+- errno = old_errno;
+-}
+-
+-/**
+- * \internal Przekazuje informację odpluskwiania związaną z sesją.
+- *
+- * \param gs Struktura sesji
+- * \param level Poziom wiadomości
+- * \param format Format wiadomości (zgodny z \c printf)
+- *
+- * \ingroup debug
+- */
+-void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
+-{
+- va_list ap;
+- int old_errno = errno;
+-
+- va_start(ap, format);
+- gg_debug_common(gs, level, format, ap);
+- va_end(ap);
+- errno = old_errno;
+-}
+-
+-/**
+- * \internal Przekazuje zrzut bufora do odpluskwiania.
+- *
+- * \param gs Struktura sesji
+- * \param level Poziom wiadomości
+- * \param buf Bufor danych
+- * \param len Długość bufora danych
+- *
+- * \ingroup debug
+- */
+-void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
+-{
+- char line[80];
+- int i, j;
+-
+- for (i = 0; i < len; i += 16) {
+- int ofs;
+-
+- sprintf(line, "%.4x: ", i);
+- ofs = 6;
+-
+- for (j = 0; j < 16; j++) {
+- if (i + j < len)
+- sprintf(line + ofs, " %02x", (unsigned char) buf[i + j]);
+- else
+- sprintf(line + ofs, " ");
+-
+- ofs += 3;
+- }
+-
+- sprintf(line + ofs, " ");
+- ofs += 2;
+-
+- for (j = 0; j < 16; j++) {
+- unsigned char ch;
+-
+- if (i + j < len) {
+- ch = buf[i + j];
+-
+- if (ch < 32 || ch > 126)
+- ch = '.';
+- } else {
+- ch = ' ';
+- }
+-
+- line[ofs++] = ch;
+- }
+-
+- line[ofs++] = '\n';
+- line[ofs++] = 0;
+-
+- gg_debug_session(gs, level, "%s", line);
+- }
+-}
+-
+-/**
+- * \internal Zwraca ciąg z nazwą podanego stanu sesji.
+- *
+- * \param state Stan sesji.
+- *
+- * \return Ciąg z nazwą stanu
+- *
+- * \ingroup debug
+- */
+-const char *gg_debug_state(enum gg_state_t state)
+-{
+- switch (state) {
+-#define GG_DEBUG_STATE(x) case x: return #x;
+- GG_DEBUG_STATE(GG_STATE_IDLE)
+- GG_DEBUG_STATE(GG_STATE_RESOLVING)
+- GG_DEBUG_STATE(GG_STATE_CONNECTING)
+- GG_DEBUG_STATE(GG_STATE_READING_DATA)
+- GG_DEBUG_STATE(GG_STATE_ERROR)
+- GG_DEBUG_STATE(GG_STATE_CONNECTING_HUB)
+- GG_DEBUG_STATE(GG_STATE_CONNECTING_GG)
+- GG_DEBUG_STATE(GG_STATE_READING_KEY)
+- GG_DEBUG_STATE(GG_STATE_READING_REPLY)
+- GG_DEBUG_STATE(GG_STATE_CONNECTED)
+- GG_DEBUG_STATE(GG_STATE_SENDING_QUERY)
+- GG_DEBUG_STATE(GG_STATE_READING_HEADER)
+- GG_DEBUG_STATE(GG_STATE_PARSING)
+- GG_DEBUG_STATE(GG_STATE_DONE)
+- GG_DEBUG_STATE(GG_STATE_LISTENING)
+- GG_DEBUG_STATE(GG_STATE_READING_UIN_1)
+- GG_DEBUG_STATE(GG_STATE_READING_UIN_2)
+- GG_DEBUG_STATE(GG_STATE_SENDING_ACK)
+- GG_DEBUG_STATE(GG_STATE_READING_ACK)
+- GG_DEBUG_STATE(GG_STATE_READING_REQUEST)
+- GG_DEBUG_STATE(GG_STATE_SENDING_REQUEST)
+- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_INFO)
+- GG_DEBUG_STATE(GG_STATE_READING_PRE_FILE_INFO)
+- GG_DEBUG_STATE(GG_STATE_READING_FILE_INFO)
+- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_ACK)
+- GG_DEBUG_STATE(GG_STATE_READING_FILE_ACK)
+- GG_DEBUG_STATE(GG_STATE_SENDING_FILE_HEADER)
+- GG_DEBUG_STATE(GG_STATE_READING_FILE_HEADER)
+- GG_DEBUG_STATE(GG_STATE_GETTING_FILE)
+- GG_DEBUG_STATE(GG_STATE_SENDING_FILE)
+- GG_DEBUG_STATE(GG_STATE_READING_VOICE_ACK)
+- GG_DEBUG_STATE(GG_STATE_READING_VOICE_HEADER)
+- GG_DEBUG_STATE(GG_STATE_READING_VOICE_SIZE)
+- GG_DEBUG_STATE(GG_STATE_READING_VOICE_DATA)
+- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_ACK)
+- GG_DEBUG_STATE(GG_STATE_SENDING_VOICE_REQUEST)
+- GG_DEBUG_STATE(GG_STATE_READING_TYPE)
+- GG_DEBUG_STATE(GG_STATE_TLS_NEGOTIATION)
+- GG_DEBUG_STATE(GG_STATE_REQUESTING_ID)
+- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_ACCEPT)
+- GG_DEBUG_STATE(GG_STATE_WAITING_FOR_INFO)
+- GG_DEBUG_STATE(GG_STATE_READING_ID)
+- GG_DEBUG_STATE(GG_STATE_SENDING_ID)
+- GG_DEBUG_STATE(GG_STATE_RESOLVING_GG)
+- GG_DEBUG_STATE(GG_STATE_RESOLVING_RELAY)
+- GG_DEBUG_STATE(GG_STATE_CONNECTING_RELAY)
+- GG_DEBUG_STATE(GG_STATE_READING_RELAY)
+- GG_DEBUG_STATE(GG_STATE_DISCONNECTING)
+-#undef GG_DEBUG_STATE
+-
+- /* Celowo nie ma default, żeby kompilator wyłapał brakujące stany */
+-
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * \internal Zwraca ciąg z nazwą podanego zdarzenia.
+- *
+- * \param event Zdarzenie.
+- *
+- * \return Ciąg z nazwą zdarzenia
+- *
+- * \ingroup debug
+- */
+-const char *gg_debug_event(enum gg_event_t event)
+-{
+- switch (event) {
+-#define GG_DEBUG_EVENT(x) case x: return #x;
+- GG_DEBUG_EVENT(GG_EVENT_NONE)
+- GG_DEBUG_EVENT(GG_EVENT_MSG)
+- GG_DEBUG_EVENT(GG_EVENT_NOTIFY)
+- GG_DEBUG_EVENT(GG_EVENT_NOTIFY_DESCR)
+- GG_DEBUG_EVENT(GG_EVENT_STATUS)
+- GG_DEBUG_EVENT(GG_EVENT_ACK)
+- GG_DEBUG_EVENT(GG_EVENT_PONG)
+- GG_DEBUG_EVENT(GG_EVENT_CONN_FAILED)
+- GG_DEBUG_EVENT(GG_EVENT_CONN_SUCCESS)
+- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_NEW)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_ERROR)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_DONE)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_CLIENT_ACCEPT)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_CALLBACK)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_INFO)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_FILE_ACK)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_NEED_VOICE_ACK)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_VOICE_DATA)
+- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_SEARCH_REPLY)
+- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_READ)
+- GG_DEBUG_EVENT(GG_EVENT_PUBDIR50_WRITE)
+- GG_DEBUG_EVENT(GG_EVENT_STATUS60)
+- GG_DEBUG_EVENT(GG_EVENT_NOTIFY60)
+- GG_DEBUG_EVENT(GG_EVENT_USERLIST)
+- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REQUEST)
+- GG_DEBUG_EVENT(GG_EVENT_IMAGE_REPLY)
+- GG_DEBUG_EVENT(GG_EVENT_DCC_ACK)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_NEW)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_ACCEPT)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_REJECT)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_CONNECTED)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_ERROR)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_DONE)
+- GG_DEBUG_EVENT(GG_EVENT_DCC7_PENDING)
+- GG_DEBUG_EVENT(GG_EVENT_XML_EVENT)
+- GG_DEBUG_EVENT(GG_EVENT_DISCONNECT_ACK)
+- GG_DEBUG_EVENT(GG_EVENT_TYPING_NOTIFICATION)
+- GG_DEBUG_EVENT(GG_EVENT_USER_DATA)
+- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_MSG)
+- GG_DEBUG_EVENT(GG_EVENT_MULTILOGON_INFO)
+- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_VERSION)
+- GG_DEBUG_EVENT(GG_EVENT_USERLIST100_REPLY)
+-#undef GG_DEBUG_EVENT
+-
+- /* Celowo nie ma default, żeby kompilator wyłapał brakujące zdarzenia */
+-
+- }
+-
+- return NULL;
+-}
+-
+-#else
+-
+-#undef gg_debug_common
+-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap)
+-{
+-}
+-
+-#undef gg_debug
+-void gg_debug(int level, const char *format, ...)
+-{
+-}
+-
+-#undef gg_debug_session
+-void gg_debug_session(struct gg_session *gs, int level, const char *format, ...)
+-{
+-}
+-
+-#undef gg_debug_dump
+-void gg_debug_dump(struct gg_session *gs, int level, const char *buf, size_t len)
+-{
+-}
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,219 +0,0 @@
+-/* $Id$ */
+-
+-/*
+- * (C) Copyright 2011 Bartosz Brachaczek <b.brachaczek@gmail.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file deflate.c
+- *
+- * \brief Funkcje kompresji Deflate
+- */
+-
+-#include <stdlib.h>
+-#include <string.h>
+-
+-#include "libgadu.h"
+-#include "deflate.h"
+-
+-#ifdef GG_CONFIG_HAVE_ZLIB
+-#include <zlib.h>
+-#endif
+-
+-/**
+- * \internal Kompresuje dane wejściowe algorytmem Deflate z najwyższym
+- * stopniem kompresji, tak samo jak oryginalny klient.
+- *
+- * Wynik funkcji należy zwolnić za pomocą \c free.
+- *
+- * \param in Ciąg znaków do skompresowania, zakończony \c \\0
+- * \param out_lenp Wskaźnik na zmienną, do której zostanie zapisana
+- * długość bufora wynikowego
+- *
+- * \return Skompresowany ciąg znaków lub \c NULL w przypadku niepowodzenia.
+- */
+-unsigned char *gg_deflate(const char *in, size_t *out_lenp)
+-{
+-#ifdef GG_CONFIG_HAVE_ZLIB
+- int ret;
+- z_stream strm;
+- unsigned char *out, *out2;
+- size_t out_len;
+-
+- if (in == NULL || out_lenp == NULL)
+- return NULL;
+-
+- strm.zalloc = Z_NULL;
+- strm.zfree = Z_NULL;
+- strm.opaque = Z_NULL;
+- strm.avail_in = strlen(in);
+- strm.next_in = (unsigned char*) in;
+-
+- ret = deflateInit(&strm, Z_BEST_COMPRESSION);
+- if (ret != Z_OK) {
+- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflateInit() failed (%d)\n", ret);
+- return NULL;
+- }
+-
+- out_len = deflateBound(&strm, strm.avail_in);
+- out = malloc(out_len);
+-
+- if (out == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+- goto fail;
+- }
+-
+- strm.avail_out = out_len;
+- strm.next_out = out;
+-
+- for (;;) {
+- ret = deflate(&strm, Z_FINISH);
+-
+- if (ret == Z_STREAM_END)
+- break;
+-
+- /* raczej nie powinno się zdarzyć przy Z_FINISH i out_len == deflateBound(),
+- * ale dokumentacja zlib nie wyklucza takiej możliwości */
+- if (ret == Z_OK) {
+- out_len *= 2;
+- out2 = realloc(out, out_len);
+-
+- if (out2 == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+- goto fail;
+- }
+-
+- out = out2;
+-
+- strm.avail_out = out_len / 2;
+- strm.next_out = out + out_len / 2;
+- } else {
+- gg_debug(GG_DEBUG_MISC, "// gg_deflate() deflate() failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error message provided");
+- goto fail;
+- }
+- }
+-
+- out_len = strm.total_out;
+- out2 = realloc(out, out_len);
+-
+- if (out2 == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_deflate() not enough memory for output data (%d)\n", out_len);
+- goto fail;
+- }
+-
+- *out_lenp = out_len;
+- deflateEnd(&strm);
+-
+- return out2;
+-
+-fail:
+- *out_lenp = 0;
+- deflateEnd(&strm);
+- free(out);
+-#endif
+- return NULL;
+-}
+-
+-/**
+- * \internal Dekompresuje dane wejściowe w formacie Deflate.
+- *
+- * Wynik funkcji należy zwolnić za pomocą \c free.
+- *
+- * \param in Bufor danych skompresowanych algorytmem Deflate
+- * \param length Długość bufora wejściowego
+- *
+- * \note Dokleja \c \\0 na końcu bufora wynikowego.
+- *
+- * \return Zdekompresowany ciąg znaków, zakończony \c \\0,
+- * lub \c NULL w przypadku niepowodzenia.
+- */
+-char *gg_inflate(const unsigned char *in, size_t length)
+-{
+-#ifdef GG_CONFIG_HAVE_ZLIB
+- int ret;
+- z_stream strm;
+- char *out = NULL, *out2;
+- size_t out_len = 1024;
+- int first = 1;
+-
+- if (in == NULL)
+- return NULL;
+-
+- strm.zalloc = Z_NULL;
+- strm.zfree = Z_NULL;
+- strm.opaque = Z_NULL;
+- strm.avail_in = length;
+- strm.next_in = (unsigned char*) in;
+-
+- ret = inflateInit(&strm);
+- if (ret != Z_OK) {
+- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflateInit() failed (%d)\n", ret);
+- return NULL;
+- }
+-
+- do {
+- out_len *= 2;
+- out2 = realloc(out, out_len);
+-
+- if (out2 == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
+- goto fail;
+- }
+-
+- out = out2;
+-
+- if (first) {
+- strm.avail_out = out_len;
+- strm.next_out = (unsigned char*) out;
+- } else {
+- strm.avail_out = out_len / 2;
+- strm.next_out = (unsigned char*) out + out_len / 2;
+- }
+-
+- ret = inflate(&strm, Z_NO_FLUSH);
+-
+- if (ret != Z_OK && ret != Z_STREAM_END) {
+- gg_debug(GG_DEBUG_MISC, "// gg_inflate() inflate() failed (ret=%d, msg=%s)\n", ret, strm.msg != NULL ? strm.msg : "no error message provided");
+- goto fail;
+- }
+-
+- first = 0;
+- } while (ret != Z_STREAM_END);
+-
+- /* rezerwujemy ostatni znak na NULL-a */
+- out_len = strm.total_out + 1;
+- out2 = realloc(out, out_len);
+-
+- if (out2 == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_inflate() not enough memory for output data (%d)\n", out_len);
+- goto fail;
+- }
+-
+- out = out2;
+- out[out_len - 1] = '\0';
+-
+- inflateEnd(&strm);
+-
+- return out;
+-
+-fail:
+- inflateEnd(&strm);
+- free(out);
+-#endif
+- return NULL;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/deflate.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/deflate.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,29 +0,0 @@
+-/* $Id$ */
+-
+-/*
+- * (C) Copyright 2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_DEFLATE_H
+-#define LIBGADU_DEFLATE_H
+-
+-#include "libgadu.h"
+-
+-unsigned char *gg_deflate(const char *in, size_t *out_lenp);
+-char *gg_inflate(const unsigned char *in, size_t length);
+-
+-#endif /* LIBGADU_DEFLATE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,275 +0,0 @@
+-/*
+- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- * Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 <stdlib.h>
+-#include <string.h>
+-#include <errno.h>
+-
+-#include "libgadu.h"
+-#include "encoding.h"
+-
+-/**
+- * \file encoding.c
+- *
+- * \brief Funkcje konwersji kodowania tekstu
+- */
+-
+-/**
+- * \internal Tablica konwersji CP1250 na Unikod.
+- */
+-static const uint16_t table_cp1250[] =
+-{
+- 0x20ac, '?', 0x201a, '?', 0x201e, 0x2026, 0x2020, 0x2021,
+- '?', 0x2030, 0x0160, 0x2039, 0x015a, 0x0164, 0x017d, 0x0179,
+- '?', 0x2018, 0x2019, 0x201c, 0x201d, 0x2022, 0x2013, 0x2014,
+- '?', 0x2122, 0x0161, 0x203a, 0x015b, 0x0165, 0x017e, 0x017a,
+- 0x00a0, 0x02c7, 0x02d8, 0x0141, 0x00a4, 0x0104, 0x00a6, 0x00a7,
+- 0x00a8, 0x00a9, 0x015e, 0x00ab, 0x00ac, 0x00ad, 0x00ae, 0x017b,
+- 0x00b0, 0x00b1, 0x02db, 0x0142, 0x00b4, 0x00b5, 0x00b6, 0x00b7,
+- 0x00b8, 0x0105, 0x015f, 0x00bb, 0x013d, 0x02dd, 0x013e, 0x017c,
+- 0x0154, 0x00c1, 0x00c2, 0x0102, 0x00c4, 0x0139, 0x0106, 0x00c7,
+- 0x010c, 0x00c9, 0x0118, 0x00cb, 0x011a, 0x00cd, 0x00ce, 0x010e,
+- 0x0110, 0x0143, 0x0147, 0x00d3, 0x00d4, 0x0150, 0x00d6, 0x00d7,
+- 0x0158, 0x016e, 0x00da, 0x0170, 0x00dc, 0x00dd, 0x0162, 0x00df,
+- 0x0155, 0x00e1, 0x00e2, 0x0103, 0x00e4, 0x013a, 0x0107, 0x00e7,
+- 0x010d, 0x00e9, 0x0119, 0x00eb, 0x011b, 0x00ed, 0x00ee, 0x010f,
+- 0x0111, 0x0144, 0x0148, 0x00f3, 0x00f4, 0x0151, 0x00f6, 0x00f7,
+- 0x0159, 0x016f, 0x00fa, 0x0171, 0x00fc, 0x00fd, 0x0163, 0x02d9,
+-};
+-
+-/**
+- * \internal Zamienia tekst kodowany CP1250 na UTF-8.
+- *
+- * \param src Tekst źródłowy w CP1250.
+- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
+- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
+- *
+- * \return Zaalokowany bufor z tekstem w UTF-8.
+- */
+-static char *gg_encoding_convert_cp1250_utf8(const char *src, int src_length, int dst_length)
+-{
+- int i, j, len;
+- char *result = NULL;
+-
+- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
+- uint16_t uc;
+-
+- if ((unsigned char) src[i] < 0x80)
+- uc = (unsigned char) src[i];
+- else
+- uc = table_cp1250[(unsigned char) src[i] - 128];
+-
+- if (uc < 0x80)
+- len += 1;
+- else if (uc < 0x800)
+- len += 2;
+- else
+- len += 3;
+- }
+-
+- if ((dst_length != -1) && (len > dst_length))
+- len = dst_length;
+-
+- result = malloc(len + 1);
+-
+- if (result == NULL)
+- return NULL;
+-
+- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
+- uint16_t uc;
+-
+- if ((unsigned char) src[i] < 0x80)
+- uc = (unsigned char) src[i];
+- else
+- uc = table_cp1250[(unsigned char) src[i] - 128];
+-
+- if (uc < 0x80)
+- result[j++] = uc;
+- else if (uc < 0x800) {
+- if (j + 1 > len)
+- break;
+- result[j++] = 0xc0 | ((uc >> 6) & 0x1f);
+- result[j++] = 0x80 | (uc & 0x3f);
+- } else {
+- if (j + 2 > len)
+- break;
+- result[j++] = 0xe0 | ((uc >> 12) & 0x1f);
+- result[j++] = 0x80 | ((uc >> 6) & 0x3f);
+- result[j++] = 0x80 | (uc & 0x3f);
+- }
+- }
+-
+- result[j] = 0;
+-
+- return result;
+-}
+-
+-/**
+- * \internal Zamienia tekst kodowany UTF-8 na CP1250.
+- *
+- * \param src Tekst źródłowy w UTF-8.
+- * \param src_length Długość ciągu źródłowego (nigdy ujemna).
+- * \param dst_length Długość ciągu docelowego (jeśli -1, nieograniczona).
+- *
+- * \return Zaalokowany bufor z tekstem w CP1250.
+- */
+-static char *gg_encoding_convert_utf8_cp1250(const char *src, int src_length, int dst_length)
+-{
+- char *result;
+- int i, j, len, uc_left = 0;
+- uint32_t uc = 0, uc_min = 0;
+-
+- for (i = 0, len = 0; (src[i] != 0) && (i < src_length); i++) {
+- if ((src[i] & 0xc0) == 0xc0) {
+- len++;
+- } else if ((src[i] & 0x80) == 0x00) {
+- len++;
+- }
+- }
+-
+- if ((dst_length != -1) && (len > dst_length))
+- len = dst_length;
+-
+- result = malloc(len + 1);
+-
+- if (result == NULL)
+- return NULL;
+-
+- for (i = 0, j = 0; (src[i] != 0) && (i < src_length) && (j < len); i++) {
+- if ((unsigned char) src[i] >= 0xf5) {
+- if (uc_left != 0)
+- result[j++] = '?';
+- /* Restricted sequences */
+- result[j++] = '?';
+- uc_left = 0;
+- } else if ((src[i] & 0xf8) == 0xf0) {
+- if (uc_left != 0)
+- result[j++] = '?';
+- uc = src[i] & 0x07;
+- uc_left = 3;
+- uc_min = 0x10000;
+- } else if ((src[i] & 0xf0) == 0xe0) {
+- if (uc_left != 0)
+- result[j++] = '?';
+- uc = src[i] & 0x0f;
+- uc_left = 2;
+- uc_min = 0x800;
+- } else if ((src[i] & 0xe0) == 0xc0) {
+- if (uc_left != 0)
+- result[j++] = '?';
+- uc = src[i] & 0x1f;
+- uc_left = 1;
+- uc_min = 0x80;
+- } else if ((src[i] & 0xc0) == 0x80) {
+- if (uc_left > 0) {
+- uc <<= 6;
+- uc |= src[i] & 0x3f;
+- uc_left--;
+-
+- if (uc_left == 0) {
+- int valid = 0;
+- int k;
+-
+- if (uc >= uc_min) {
+- for (k = 0; k < 128; k++) {
+- if (uc == table_cp1250[k]) {
+- result[j++] = k + 128;
+- valid = 1;
+- break;
+- }
+- }
+- }
+-
+- if (!valid && uc != 0xfeff) /* Byte Order Mark */
+- result[j++] = '?';
+- }
+- }
+- } else {
+- if (uc_left != 0) {
+- result[j++] = '?';
+- uc_left = 0;
+- }
+- result[j++] = src[i];
+- }
+- }
+-
+- if ((uc_left != 0) && (src[i] == 0))
+- result[j++] = '?';
+-
+- result[j] = 0;
+-
+- return result;
+-}
+-
+-/**
+- * \internal Zamienia kodowanie tekstu.
+- *
+- * \param src Tekst źródłowy.
+- * \param src_encoding Kodowanie tekstu źródłowego.
+- * \param dst_encoding Kodowanie tekstu docelowego.
+- * \param src_length Długość ciągu źródłowego w bajtach (nigdy ujemna).
+- * \param dst_length Długość ciągu docelowego w bajtach (jeśli -1, nieograniczona).
+- *
+- * \return Zaalokowany bufor z tekstem w kodowaniu docelowym.
+- */
+-char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding, gg_encoding_t dst_encoding, int src_length, int dst_length)
+-{
+- char *result;
+-
+- if (src == NULL) {
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- // specjalny przypadek obsługiwany ekspresowo
+- if ((dst_encoding == src_encoding) && (dst_length == -1) && (src_length == -1))
+- return strdup(src);
+-
+- if (src_length == -1)
+- src_length = strlen(src);
+-
+- if (dst_encoding == src_encoding) {
+- int len;
+-
+- if (dst_length == -1)
+- len = src_length;
+- else
+- len = (src_length < dst_length) ? src_length : dst_length;
+-
+- result = malloc(len + 1);
+-
+- if (result == NULL)
+- return NULL;
+-
+- strncpy(result, src, len);
+- result[len] = 0;
+-
+- return result;
+- }
+-
+- if (dst_encoding == GG_ENCODING_CP1250 && src_encoding == GG_ENCODING_UTF8)
+- return gg_encoding_convert_utf8_cp1250(src, src_length, dst_length);
+-
+- if (dst_encoding == GG_ENCODING_UTF8 && src_encoding == GG_ENCODING_CP1250)
+- return gg_encoding_convert_cp1250_utf8(src, src_length, dst_length);
+-
+- errno = EINVAL;
+- return NULL;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/encoding.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/encoding.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-/*
+- * (C) Copyright 2008-2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- * Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_ENCODING_H
+-#define LIBGADU_ENCODING_H
+-
+-#include "libgadu.h"
+-
+-char *gg_encoding_convert(const char *src, gg_encoding_t src_encoding, gg_encoding_t dst_encoding, int src_length, int dst_length);
+-
+-#endif /* LIBGADU_SESSION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/events.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/events.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/events.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/events.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1027 +0,0 @@
+-/* $Id: events.c 1105 2011-05-25 21:34:50Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file events.c
+- *
+- * \brief Obsługa zdarzeń
+- */
+-
+-#include <sys/types.h>
+-#ifndef _WIN32
+-# include <sys/ioctl.h>
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-#endif
+-#include <ctype.h>
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-#include "protocol.h"
+-#include "libgadu-internal.h"
+-#include "encoding.h"
+-#include "libgadu-debug.h"
+-#include "session.h"
+-
+-#include <errno.h>
+-#include <stdio.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <time.h>
+-#include <unistd.h>
+-#include <ctype.h>
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+-# include <gnutls/gnutls.h>
+-# include <gnutls/x509.h>
+-#endif
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-# include <openssl/err.h>
+-# include <openssl/x509.h>
+-#endif
+-
+-/**
+- * Zwalnia pamięć zajmowaną przez informację o zdarzeniu.
+- *
+- * Funkcję należy wywoływać za każdym razem gdy funkcja biblioteki zwróci
+- * strukturę \c gg_event.
+- *
+- * \param e Struktura zdarzenia
+- *
+- * \ingroup events
+- */
+-void gg_event_free(struct gg_event *e)
+-{
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_event_free(%p);\n", e);
+-
+- if (!e)
+- return;
+-
+- switch (e->type) {
+- case GG_EVENT_MSG:
+- case GG_EVENT_MULTILOGON_MSG:
+- free(e->event.msg.message);
+- free(e->event.msg.formats);
+- free(e->event.msg.recipients);
+- free(e->event.msg.xhtml_message);
+- break;
+-
+- case GG_EVENT_NOTIFY:
+- free(e->event.notify);
+- break;
+-
+- case GG_EVENT_NOTIFY60:
+- {
+- int i;
+-
+- for (i = 0; e->event.notify60[i].uin; i++)
+- free(e->event.notify60[i].descr);
+-
+- free(e->event.notify60);
+-
+- break;
+- }
+-
+- case GG_EVENT_STATUS60:
+- free(e->event.status60.descr);
+- break;
+-
+- case GG_EVENT_STATUS:
+- free(e->event.status.descr);
+- break;
+-
+- case GG_EVENT_NOTIFY_DESCR:
+- free(e->event.notify_descr.notify);
+- free(e->event.notify_descr.descr);
+- break;
+-
+- case GG_EVENT_DCC_VOICE_DATA:
+- free(e->event.dcc_voice_data.data);
+- break;
+-
+- case GG_EVENT_PUBDIR50_SEARCH_REPLY:
+- case GG_EVENT_PUBDIR50_READ:
+- case GG_EVENT_PUBDIR50_WRITE:
+- gg_pubdir50_free(e->event.pubdir50);
+- break;
+-
+- case GG_EVENT_USERLIST:
+- free(e->event.userlist.reply);
+- break;
+-
+- case GG_EVENT_IMAGE_REPLY:
+- free(e->event.image_reply.filename);
+- free(e->event.image_reply.image);
+- break;
+-
+- case GG_EVENT_XML_EVENT:
+- free(e->event.xml_event.data);
+- break;
+-
+- case GG_EVENT_USER_DATA:
+- {
+- int i, j;
+-
+- for (i = 0; i < e->event.user_data.user_count; i++) {
+- for (j = 0; j < e->event.user_data.users[i].attr_count; j++) {
+- free(e->event.user_data.users[i].attrs[j].key);
+- free(e->event.user_data.users[i].attrs[j].value);
+- }
+-
+- free(e->event.user_data.users[i].attrs);
+- }
+-
+- free(e->event.user_data.users);
+-
+- break;
+- }
+-
+- case GG_EVENT_MULTILOGON_INFO:
+- {
+- int i;
+-
+- for (i = 0; i < e->event.multilogon_info.count; i++)
+- free(e->event.multilogon_info.sessions[i].name);
+-
+- free(e->event.multilogon_info.sessions);
+-
+- break;
+- }
+-
+- case GG_EVENT_USERLIST100_REPLY:
+- free(e->event.userlist100_reply.reply);
+- break;
+- }
+-
+- free(e);
+-}
+-
+-/** \cond internal */
+-
+-/**
+- * \internal Usuwa obrazek z kolejki do wysłania.
+- *
+- * \param s Struktura sesji
+- * \param q Struktura obrazka
+- * \param freeq Flaga zwolnienia elementu kolejki
+- *
+- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
+- */
+-int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq)
+-{
+- if (!s || !q) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (s->images == q)
+- s->images = q->next;
+- else {
+- struct gg_image_queue *qq;
+-
+- for (qq = s->images; qq; qq = qq->next) {
+- if (qq->next == q) {
+- qq->next = q->next;
+- break;
+- }
+- }
+- }
+-
+- if (freeq) {
+- free(q->image);
+- free(q->filename);
+- free(q);
+- }
+-
+- return 0;
+-}
+-
+-/** \endcond */
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze sesji.
+- *
+- * Funkcja zwraca strukturę zdarzenia \c gg_event. Jeśli rodzaj zdarzenia
+- * to \c GG_EVENT_NONE, nie wydarzyło się jeszcze nic wartego odnotowania.
+- * Strukturę zdarzenia należy zwolnić funkcja \c gg_event_free().
+- *
+- * \param sess Struktura sesji
+- *
+- * \return Struktura zdarzenia lub \c NULL jeśli wystąpił błąd
+- *
+- * \ingroup events
+- */
+-struct gg_event *gg_watch_fd(struct gg_session *sess)
+-{
+- struct gg_event *e;
+- int res = 0;
+- int port = 0;
+- int errno2 = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_watch_fd(%p);\n", sess);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- if (!(e = (void*) calloc(1, sizeof(*e)))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() not enough memory for event data\n");
+- return NULL;
+- }
+-
+- e->type = GG_EVENT_NONE;
+-
+- if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending %d bytes of queued data\n", sess->send_left);
+-
+- res = write(sess->fd, sess->send_buf, sess->send_left);
+-
+- if (res == -1 && errno != EAGAIN) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() write() failed (errno=%d, %s)\n", errno, strerror(errno));
+-
+- if (sess->state == GG_STATE_READING_REPLY)
+- e->event.failure = GG_FAILURE_CONNECTING;
+-
+- goto fail;
+- }
+-
+- if (res == sess->send_left) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent all queued data\n");
+- free(sess->send_buf);
+- sess->send_buf = NULL;
+- sess->send_left = 0;
+- } else if (res > 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sent %d bytes of queued data, %d bytes left\n", res, sess->send_left - res);
+-
+- memmove(sess->send_buf, sess->send_buf + res, sess->send_left - res);
+- sess->send_left -= res;
+- }
+-
+- res = 0;
+- }
+-
+- switch (sess->state) {
+- case GG_STATE_RESOLVING:
+- {
+- struct in_addr addr;
+- int failed = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING\n");
+-
+- if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n");
+- failed = 1;
+- errno2 = errno;
+- }
+-
+- close(sess->fd);
+- sess->fd = -1;
+-
+- sess->resolver_cleanup(&sess->resolver, 0);
+-
+- if (failed) {
+- errno = errno2;
+- goto fail_proxy_hub;
+- }
+-
+- /* jeśli jesteśmy w resolverze i mamy ustawiony port
+- * proxy, znaczy, że resolvowaliśmy proxy. zatem
+- * wpiszmy jego adres. */
+- if (sess->proxy_port)
+- sess->proxy_addr = addr.s_addr;
+-
+- /* zapiszmy sobie adres huba i adres serwera (do
+- * bezpośredniego połączenia, jeśli hub leży)
+- * z resolvera. */
+- if (sess->proxy_addr && sess->proxy_port)
+- port = sess->proxy_port;
+- else {
+- sess->server_addr = sess->hub_addr = addr.s_addr;
+- port = GG_APPMSG_PORT;
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolved, connecting to %s:%d\n", inet_ntoa(addr), port);
+-
+- /* łączymy się albo z hubem, albo z proxy, zależnie
+- * od tego, co resolvowaliśmy. */
+- if ((sess->fd = gg_connect(&addr, port, sess->async)) == -1) {
+- /* jeśli w trybie asynchronicznym gg_connect()
+- * zwróci błąd, nie ma sensu próbować dalej. */
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), critical\n", errno, strerror(errno));
+- goto fail_proxy_hub;
+- }
+-
+- /* jeśli podano serwer i łączmy się przez proxy,
+- * jest to bezpośrednie połączenie, inaczej jest
+- * do huba. */
+-
+- if (sess->proxy_addr && sess->proxy_port && sess->server_addr) {
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->soft_timeout = 1;
+- } else
+- sess->state = GG_STATE_CONNECTING_HUB;
+-
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-
+- case GG_STATE_CONNECTING_HUB:
+- {
+- char buf[1024], *client, *auth;
+- int res = 0;
+- socklen_t res_size = sizeof(res);
+- const char *host;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_HUB\n");
+-
+- /* jeśli asynchroniczne, sprawdzamy, czy nie wystąpił
+- * przypadkiem jakiś błąd. */
+- if (sess->async && (getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to %s failed (errno=%d, %s)\n", (sess->proxy_addr && sess->proxy_port) ? "proxy" : "hub", res, strerror(res));
+- goto fail_proxy_hub;
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected to hub, sending query\n");
+-
+- if (sess->client_version != NULL && isdigit(sess->client_version[0]))
+- client = gg_urlencode(sess->client_version);
+- else
+- client = gg_urlencode(GG_DEFAULT_CLIENT_VERSION);
+-
+- if (client == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for client version\n");
+- goto fail;
+- }
+-
+- if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port)
+- host = "http://" GG_APPMSG_HOST;
+- else
+- host = "";
+-
+- auth = gg_proxy_auth();
+-
+-#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
+- if (sess->ssl != NULL) {
+- snprintf(buf, sizeof(buf) - 1,
+- "GET %s/appsvc/appmsg_ver10.asp?fmnumber=%u&fmt=2&lastmsg=%d&version=%s&age=2&gender=1 HTTP/1.0\r\n"
+- "Connection: close\r\n"
+- "Host: " GG_APPMSG_HOST "\r\n"
+- "%s"
+- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
+- } else
+-#endif
+- {
+- snprintf(buf, sizeof(buf) - 1,
+- "GET %s/appsvc/appmsg_ver8.asp?fmnumber=%u&fmt=2&lastmsg=%d&version=%s HTTP/1.0\r\n"
+- "Host: " GG_APPMSG_HOST "\r\n"
+- "%s"
+- "\r\n", host, sess->uin, sess->last_sysmsg, client, (auth) ? auth : "");
+- }
+-
+- free(auth);
+- free(client);
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", buf);
+-
+- /* zapytanie jest krótkie, więc zawsze zmieści się
+- * do bufora gniazda. jeśli write() zwróci mniej,
+- * stało się coś złego. */
+- if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() sending query failed\n");
+- goto fail_proxy_hub;
+- }
+-
+- sess->state = GG_STATE_READING_DATA;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-
+- case GG_STATE_READING_DATA:
+- {
+- char buf[1024], *tmp, *host;
+- int port = GG_DEFAULT_PORT;
+- struct in_addr addr;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_DATA\n");
+-
+- /* czytamy linię z gniazda i obcinamy \r\n. */
+- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
+- gg_chomp(buf);
+- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http header (%s)\n", buf);
+-
+- /* sprawdzamy, czy wszystko w porządku. */
+- if (strncmp(buf, "HTTP/1.", 7) || strncmp(buf + 9, "200", 3)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid http reply, connection failed\n");
+- goto fail_proxy_hub;
+- }
+-
+- /* ignorujemy resztę nagłówka. */
+- while (strcmp(buf, "\r\n") && strcmp(buf, ""))
+- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
+-
+- /* czytamy pierwszą linię danych. */
+- if (gg_read_line(sess->fd, buf, sizeof(buf) - 1) == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() read error\n");
+- goto fail_proxy_hub;
+- }
+- gg_chomp(buf);
+-
+- /* jeśli pierwsza liczba w linii nie jest równa zeru,
+- * oznacza to, że mamy wiadomość systemową. */
+- if (atoi(buf)) {
+- char tmp[1024], *foo, *sysmsg_buf = NULL;
+- int len = 0;
+-
+- while (gg_read_line(sess->fd, tmp, sizeof(tmp) - 1)) {
+- if (!(foo = realloc(sysmsg_buf, len + strlen(tmp) + 2))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() out of memory for system message, ignoring\n");
+- break;
+- }
+-
+- sysmsg_buf = foo;
+-
+- if (!len)
+- strcpy(sysmsg_buf, tmp);
+- else
+- strcat(sysmsg_buf, tmp);
+-
+- len += strlen(tmp);
+- }
+-
+- e->type = GG_EVENT_MSG;
+- e->event.msg.msgclass = atoi(buf);
+- e->event.msg.sender = 0;
+- e->event.msg.message = (unsigned char*) sysmsg_buf;
+- }
+-
+- close(sess->fd);
+- sess->fd = -1;
+-
+- gg_debug_session(sess, GG_DEBUG_TRAFFIC, "// gg_watch_fd() received http data (%s)\n", buf);
+-
+- /* analizujemy otrzymane dane. */
+- tmp = buf;
+-
+- while (*tmp && *tmp != ' ')
+- tmp++;
+- while (*tmp && *tmp == ' ')
+- tmp++;
+- while (*tmp && *tmp != ' ')
+- tmp++;
+- while (*tmp && *tmp == ' ')
+- tmp++;
+- host = tmp;
+- while (*tmp && *tmp != ' ')
+- tmp++;
+- *tmp = 0;
+-
+- if ((tmp = strchr(host, ':'))) {
+- *tmp = 0;
+- port = atoi(tmp + 1);
+- }
+-
+- if (strcmp(host, "") == 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() invalid response\n");
+- e->event.failure = GG_FAILURE_HUB;
+- goto fail;
+- }
+-
+- if (!strcmp(host, "notoperating")) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() service unavailable\n", errno, strerror(errno));
+- e->event.failure = GG_FAILURE_UNAVAILABLE;
+- goto fail;
+- }
+-
+- addr.s_addr = inet_addr(host);
+- sess->server_addr = addr.s_addr;
+-
+- if (!gg_proxy_http_only && sess->proxy_addr && sess->proxy_port) {
+- /* jeśli mamy proxy, łączymy się z nim. */
+- if ((sess->fd = gg_connect(&sess->proxy_addr, sess->proxy_port, sess->async)) == -1) {
+- /* nie wyszło? trudno. */
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", errno, strerror(errno));
+- e->event.failure = GG_FAILURE_PROXY;
+- goto fail;
+- }
+-
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- sess->soft_timeout = 1;
+- break;
+- }
+-
+- sess->port = port;
+-
+- /* Jeśli podano nazwę, nie adres serwera... */
+- if (sess->server_addr == INADDR_NONE) {
+- if (sess->resolver_start(&sess->fd, &sess->resolver, host) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
+- goto fail;
+- }
+-
+- sess->state = GG_STATE_RESOLVING_GG;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- break;
+- }
+-
+- /* łączymy się z właściwym serwerem. */
+- if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno));
+-
+- sess->port = GG_HTTPS_PORT;
+-
+- /* nie wyszło? próbujemy portu 443. */
+- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) {
+- /* ostatnia deska ratunku zawiodła?
+- * w takim razie zwijamy manatki. */
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- e->event.failure = GG_FAILURE_CONNECTING;
+- goto fail;
+- }
+- }
+-
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- sess->soft_timeout = 1;
+-
+- break;
+- }
+-
+- case GG_STATE_RESOLVING_GG:
+- {
+- struct in_addr addr;
+- int failed = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_RESOLVING_GG\n");
+-
+- if (read(sess->fd, &addr, sizeof(addr)) < (signed)sizeof(addr) || addr.s_addr == INADDR_NONE) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() resolving failed\n");
+- failed = 1;
+- errno2 = errno;
+- }
+-
+- close(sess->fd);
+- sess->fd = -1;
+-
+- sess->resolver_cleanup(&sess->resolver, 0);
+-
+- if (failed) {
+- errno = errno2;
+- e->event.failure = GG_FAILURE_RESOLVING;
+- goto fail;
+- }
+-
+- sess->server_addr = addr.s_addr;
+-
+- /* łączymy się z właściwym serwerem. */
+- if ((sess->fd = gg_connect(&addr, sess->port, sess->async)) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", errno, strerror(errno));
+-
+- sess->port = GG_HTTPS_PORT;
+-
+- /* nie wyszło? próbujemy portu 443. */
+- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, sess->async)) == -1) {
+- /* ostatnia deska ratunku zawiodła?
+- * w takim razie zwijamy manatki. */
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- e->event.failure = GG_FAILURE_CONNECTING;
+- goto fail;
+- }
+- }
+-
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- sess->soft_timeout = 1;
+-
+- break;
+- }
+-
+- case GG_STATE_CONNECTING_GG:
+- {
+- int res = 0;
+- socklen_t res_size = sizeof(res);
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTING_GG\n");
+-
+- sess->soft_timeout = 0;
+-
+- /* jeśli wystąpił błąd podczas łączenia się... */
+- if (sess->async && (sess->timeout == 0 || getsockopt(sess->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
+- /* jeśli nie udało się połączenie z proxy,
+- * nie mamy czego próbować więcej. */
+- if (sess->proxy_addr && sess->proxy_port) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection to proxy failed (errno=%d, %s)\n", res, strerror(res));
+- e->event.failure = GG_FAILURE_PROXY;
+- goto fail;
+- }
+-
+- close(sess->fd);
+- sess->fd = -1;
+-
+-#ifdef ETIMEDOUT
+- if (sess->timeout == 0)
+- errno = ETIMEDOUT;
+-#endif
+-
+-#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
+- /* jeśli logujemy się po TLS, nie próbujemy
+- * się łączyć już z niczym innym w przypadku
+- * błędu. nie dość, że nie ma sensu, to i
+- * trzeba by się bawić w tworzenie na nowo
+- * SSL i SSL_CTX. */
+-
+- if (sess->ssl) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", res, strerror(res));
+- e->event.failure = GG_FAILURE_CONNECTING;
+- goto fail;
+- }
+-#endif
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s), trying https\n", res, strerror(res));
+-
+- if (sess->port == GG_HTTPS_PORT) {
+- e->event.failure = GG_FAILURE_CONNECTING;
+- goto fail;
+- }
+-
+- sess->port = GG_HTTPS_PORT;
+-
+- /* próbujemy na port 443. */
+- if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- e->event.failure = GG_FAILURE_CONNECTING;
+- goto fail;
+- }
+-
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- sess->soft_timeout = 1;
+-
+- break;
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() connected\n");
+-
+- if (gg_proxy_http_only)
+- sess->proxy_port = 0;
+-
+- /* jeśli mamy proxy, wyślijmy zapytanie. */
+- if (sess->proxy_addr && sess->proxy_port) {
+- char buf[100], *auth = gg_proxy_auth();
+- struct in_addr addr;
+-
+- if (sess->server_addr)
+- addr.s_addr = sess->server_addr;
+- else
+- addr.s_addr = sess->hub_addr;
+-
+- snprintf(buf, sizeof(buf), "CONNECT %s:%d HTTP/1.0\r\n", inet_ntoa(addr), sess->port);
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() proxy request:\n// %s", buf);
+-
+- /* wysyłamy zapytanie. jest ono na tyle krótkie,
+- * że musi się zmieścić w buforze gniazda. jeśli
+- * write() zawiedzie, stało się coś złego. */
+- if (write(sess->fd, buf, strlen(buf)) < (signed)strlen(buf)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
+- free(auth);
+- e->event.failure = GG_FAILURE_PROXY;
+- goto fail;
+- }
+-
+- if (auth) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// %s", auth);
+- if (write(sess->fd, auth, strlen(auth)) < (signed)strlen(auth)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
+- free(auth);
+- e->event.failure = GG_FAILURE_PROXY;
+- goto fail;
+- }
+-
+- free(auth);
+- }
+-
+- if (write(sess->fd, "\r\n", 2) < 2) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() can't send proxy request\n");
+- e->event.failure = GG_FAILURE_PROXY;
+- goto fail;
+- }
+- }
+-
+-#if defined(GG_CONFIG_HAVE_GNUTLS) || defined(GG_CONFIG_HAVE_OPENSSL)
+- if (sess->ssl != NULL) {
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- gnutls_transport_set_ptr(GG_SESSION_GNUTLS(sess), (gnutls_transport_ptr_t) sess->fd);
+-#endif
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- SSL_set_fd(sess->ssl, sess->fd);
+-#endif
+-
+- sess->state = GG_STATE_TLS_NEGOTIATION;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-#endif
+-
+- sess->state = GG_STATE_READING_KEY;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- case GG_STATE_TLS_NEGOTIATION:
+- {
+- int res;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n");
+-
+-gnutls_handshake_repeat:
+- res = gnutls_handshake(GG_SESSION_GNUTLS(sess));
+-
+- if (res == GNUTLS_E_AGAIN) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_AGAIN\n");
+-
+- sess->state = GG_STATE_TLS_NEGOTIATION;
+- if (gnutls_record_get_direction(GG_SESSION_GNUTLS(sess)) == 0)
+- sess->check = GG_CHECK_READ;
+- else
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- break;
+- }
+-
+- if (res == GNUTLS_E_INTERRUPTED) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake GNUTLS_E_INTERRUPTED\n");
+- goto gnutls_handshake_repeat;
+- }
+-
+- if (res != 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS handshake error %d\n", res);
+- e->type = GG_EVENT_CONN_FAILED;
+- e->event.failure = GG_FAILURE_TLS;
+- sess->state = GG_STATE_IDLE;
+- close(sess->fd);
+- sess->fd = -1;
+- break;
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n");
+- gg_debug_session(sess, GG_DEBUG_MISC, "// cipher: VERS-%s:%s:%s:%s:COMP-%s\n",
+- gnutls_protocol_get_name(gnutls_protocol_get_version(GG_SESSION_GNUTLS(sess))),
+- gnutls_cipher_get_name(gnutls_cipher_get(GG_SESSION_GNUTLS(sess))),
+- gnutls_kx_get_name(gnutls_kx_get(GG_SESSION_GNUTLS(sess))),
+- gnutls_mac_get_name(gnutls_mac_get(GG_SESSION_GNUTLS(sess))),
+- gnutls_compression_get_name(gnutls_compression_get(GG_SESSION_GNUTLS(sess))));
+-
+- if (gnutls_certificate_type_get(GG_SESSION_GNUTLS(sess)) == GNUTLS_CRT_X509) {
+- unsigned int peer_count;
+- const gnutls_datum_t *peers;
+- gnutls_x509_crt_t cert;
+-
+- if (gnutls_x509_crt_init(&cert) >= 0) {
+- peers = gnutls_certificate_get_peers(GG_SESSION_GNUTLS(sess), &peer_count);
+-
+- if (peers != NULL) {
+- char buf[256];
+- size_t size;
+-
+- if (gnutls_x509_crt_import(cert, &peers[0], GNUTLS_X509_FMT_DER) >= 0) {
+- size = sizeof(buf);
+- gnutls_x509_crt_get_dn(cert, buf, &size);
+- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
+- size = sizeof(buf);
+- gnutls_x509_crt_get_issuer_dn(cert, buf, &size);
+- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
+- }
+- }
+- }
+- }
+-
+- sess->state = GG_STATE_READING_KEY;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- case GG_STATE_TLS_NEGOTIATION:
+- {
+- int res;
+- X509 *peer;
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_TLS_NEGOTIATION\n");
+-
+- if ((res = SSL_connect(sess->ssl)) <= 0) {
+- int err = SSL_get_error(sess->ssl, res);
+-
+- if (res == 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() disconnected during TLS negotiation\n");
+-
+- e->type = GG_EVENT_CONN_FAILED;
+- e->event.failure = GG_FAILURE_TLS;
+- sess->state = GG_STATE_IDLE;
+- close(sess->fd);
+- sess->fd = -1;
+- break;
+- }
+-
+- if (err == SSL_ERROR_WANT_READ) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to read\n");
+-
+- sess->state = GG_STATE_TLS_NEGOTIATION;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- } else if (err == SSL_ERROR_WANT_WRITE) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() wants to write\n");
+-
+- sess->state = GG_STATE_TLS_NEGOTIATION;
+- sess->check = GG_CHECK_WRITE;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- } else {
+- char buf[256];
+-
+- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() SSL_connect() bailed out: %s\n", buf);
+-
+- e->type = GG_EVENT_CONN_FAILED;
+- e->event.failure = GG_FAILURE_TLS;
+- sess->state = GG_STATE_IDLE;
+- close(sess->fd);
+- sess->fd = -1;
+- break;
+- }
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() TLS negotiation succeded:\n// cipher: %s\n", SSL_get_cipher_name(sess->ssl));
+-
+- peer = SSL_get_peer_certificate(sess->ssl);
+-
+- if (!peer)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// WARNING! unable to get peer certificate!\n");
+- else {
+- char buf[256];
+-
+- X509_NAME_oneline(X509_get_subject_name(peer), buf, sizeof(buf));
+- gg_debug_session(sess, GG_DEBUG_MISC, "// cert subject: %s\n", buf);
+-
+- X509_NAME_oneline(X509_get_issuer_name(peer), buf, sizeof(buf));
+- gg_debug_session(sess, GG_DEBUG_MISC, "// cert issuer: %s\n", buf);
+- }
+-
+- sess->state = GG_STATE_READING_KEY;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+-
+- break;
+- }
+-#endif
+-
+- case GG_STATE_READING_KEY:
+- case GG_STATE_READING_REPLY:
+- case GG_STATE_CONNECTED:
+- case GG_STATE_DISCONNECTING:
+- {
+- struct gg_header *gh;
+-
+- if (sess->state == GG_STATE_READING_KEY)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_KEY\n");
+- else if (sess->state == GG_STATE_READING_REPLY)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_READING_REPLY\n");
+- else if (sess->state == GG_STATE_CONNECTED)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_CONNECTED\n");
+- else if (sess->state == GG_STATE_DISCONNECTING)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() GG_STATE_DISCONNECTING\n");
+-
+- /* XXX bardzo, bardzo, bardzo głupi pomysł na pozbycie
+- * się tekstu wrzucanego przez proxy. */
+- if (sess->state == GG_STATE_READING_KEY && sess->proxy_addr && sess->proxy_port) {
+- char buf[100];
+-
+- strcpy(buf, "");
+- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
+- gg_chomp(buf);
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd() proxy response:\n// %s\n", buf);
+-
+- while (strcmp(buf, "")) {
+- gg_read_line(sess->fd, buf, sizeof(buf) - 1);
+- gg_chomp(buf);
+- if (strcmp(buf, ""))
+- gg_debug_session(sess, GG_DEBUG_MISC, "// %s\n", buf);
+- }
+-
+- /* XXX niech czeka jeszcze raz w tej samej
+- * fazie. głupio, ale działa. */
+- sess->proxy_port = 0;
+-
+- break;
+- }
+-
+- sess->last_event = time(NULL);
+-
+- gh = gg_recv_packet(sess);
+-
+- if (gh == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_watch_fd_connected() gg_recv_packet failed (errno=%d, %s)\n", errno, strerror(errno));
+-
+- if (errno != EAGAIN)
+- goto fail;
+- } else {
+- if (gg_session_handle_packet(sess, gh->type, (const char *) gh + sizeof(struct gg_header), gh->length, e) == -1) {
+- free(gh);
+- goto fail;
+- }
+-
+- free(gh);
+- }
+-
+- sess->check = GG_CHECK_READ;
+-
+- break;
+- }
+- }
+-
+- if (sess->send_buf && (sess->state == GG_STATE_READING_REPLY || sess->state == GG_STATE_CONNECTED))
+- sess->check |= GG_CHECK_WRITE;
+-
+- return e;
+-
+-fail_proxy_hub:
+- if (sess->proxy_port)
+- e->event.failure = GG_FAILURE_PROXY;
+- else
+- e->event.failure = GG_FAILURE_HUB;
+-
+-fail:
+- sess->resolver_cleanup(&sess->resolver, 1);
+-
+- sess->state = GG_STATE_IDLE;
+-
+- if (sess->fd != -1) {
+- int errno2;
+-
+- errno2 = errno;
+- close(sess->fd);
+- errno = errno2;
+- sess->fd = -1;
+- }
+-
+- if (e->event.failure != 0) {
+- e->type = GG_EVENT_CONN_FAILED;
+- return e;
+- } else {
+- free(e);
+- return NULL;
+- }
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/handlers.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/handlers.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/handlers.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/handlers.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1857 +0,0 @@
+-/*
+- * (C) Copyright 2001-2011 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file handlers.c
+- *
+- * \brief Funkcje obsługi przychodzących pakietów
+- */
+-
+-#include <sys/types.h>
+-#ifndef _WIN32
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-#endif
+-#include <ctype.h>
+-#ifndef _WIN32
+-# ifdef sun
+-# include <sys/filio.h>
+-# endif
+-#endif
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-#include "resolver.h"
+-#include "session.h"
+-#include "protocol.h"
+-#include "encoding.h"
+-#include "message.h"
+-#include "libgadu-internal.h"
+-#include "deflate.h"
+-
+-#include <errno.h>
+-#ifndef _WIN32
+-# include <netdb.h>
+-#endif
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <signal.h>
+-#include <unistd.h>
+-#include <time.h>
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-# include <openssl/err.h>
+-# include <openssl/rand.h>
+-#endif
+-
+-/**
+- * \internal Struktura opisująca funkcję obsługi pakietu.
+- */
+-typedef struct {
+- /* Typ pakietu */
+- uint32_t type;
+- /* Stan w którym pakiet jest obsługiwany */
+- int state;
+- /* Minimalny rozmiar danych pakietu */
+- int min_length;
+- /* Funkcja obsługująca pakiet. Patrz gg_session_handle_packet(). */
+- int (*handler)(struct gg_session *, uint32_t, const char *, size_t, struct gg_event *);
+-} gg_packet_handler_t;
+-
+-/**
+- * \internal Obsługuje pakiet GG_WELCOME.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_welcome(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_welcome *w;
+- int ret;
+- uint8_t hash_buf[64];
+- uint32_t local_ip;
+- struct sockaddr_in sin;
+- unsigned int sin_len = sizeof(sin);
+-
+- if (len < sizeof(struct gg_welcome)) {
+- ge->type = GG_EVENT_CONN_FAILED;
+- ge->event.failure = GG_FAILURE_INVALID;
+- gs->state = GG_STATE_IDLE;
+- close(gs->fd);
+- gs->fd = -1;
+- return 0;
+- }
+-
+- w = (struct gg_welcome*) ptr;
+- w->key = gg_fix32(w->key);
+-
+- memset(hash_buf, 0, sizeof(hash_buf));
+-
+- switch (gs->hash_type) {
+- case GG_LOGIN_HASH_GG32:
+- {
+- uint32_t hash;
+-
+- hash = gg_fix32(gg_login_hash((unsigned char*) gs->password, w->key));
+- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> GG32 hash %.8x\n", w->key, hash);
+- memcpy(hash_buf, &hash, sizeof(hash));
+-
+- break;
+- }
+-
+- case GG_LOGIN_HASH_SHA1:
+- {
+-#ifndef GG_DEBUG_DISABLE
+- char tmp[41];
+- int i;
+-#endif
+-
+- gg_login_hash_sha1(gs->password, w->key, hash_buf);
+-
+-#ifndef GG_DEBUG_DISABLE
+- for (i = 0; i < 40; i += 2)
+- snprintf(tmp + i, sizeof(tmp) - i, "%02x", hash_buf[i / 2]);
+-
+- gg_debug_session(gs, GG_DEBUG_DUMP, "// gg_watch_fd() challenge %.4x --> SHA1 hash: %s\n", w->key, tmp);
+-#endif
+-
+- break;
+- }
+-
+- default:
+- break;
+- }
+-
+-#if 0
+- if (gs->password != NULL && (gs->flags & (1 << GG_SESSION_FLAG_CLEAR_PASSWORD))) {
+- memset(gs->password, 0, strlen(gs->password));
+- free(gs->password);
+- gs->password = NULL;
+- }
+-#endif
+-
+- if (!getsockname(gs->fd, (struct sockaddr*) &sin, &sin_len)) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() detected address to %s\n", inet_ntoa(sin.sin_addr));
+- local_ip = sin.sin_addr.s_addr;
+- } else {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() unable to detect address\n");
+- local_ip = 0;
+- }
+-
+- if (GG_SESSION_IS_PROTOCOL_8_0(gs)) {
+- struct gg_login80 l80;
+- const char *client_name, *version, *descr;
+- uint32_t client_name_len, version_len, descr_len;
+-
+- if (gs->external_addr == 0)
+- gs->external_addr = local_ip;
+-
+- memset(&l80, 0, sizeof(l80));
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN80 packet\n");
+- l80.uin = gg_fix32(gs->uin);
+- memcpy(l80.language, GG8_LANG, sizeof(l80.language));
+- l80.hash_type = gs->hash_type;
+- memcpy(l80.hash, hash_buf, sizeof(l80.hash));
+- l80.status = gg_fix32(gs->initial_status ? gs->initial_status : GG_STATUS_AVAIL);
+- l80.flags = gg_fix32(gs->status_flags);
+- l80.features = gg_fix32(gs->protocol_features);
+- l80.image_size = gs->image_size;
+- l80.dunno2 = 0x64;
+-
+- if (gs->client_version != NULL && !isdigit(gs->client_version[0])) {
+- client_name = "";
+- client_name_len = 0;
+- } else {
+- client_name = GG8_VERSION;
+- client_name_len = strlen(GG8_VERSION);
+- }
+-
+- version = (gs->client_version != NULL) ? gs->client_version : GG_DEFAULT_CLIENT_VERSION;
+- version_len = gg_fix32(client_name_len + strlen(version));
+-
+- descr = (gs->initial_descr != NULL) ? gs->initial_descr : "";
+- descr_len = (gs->initial_descr != NULL) ? gg_fix32(strlen(gs->initial_descr)) : 0;
+-
+- ret = gg_send_packet(gs,
+- GG_LOGIN80,
+- &l80, sizeof(l80),
+- &version_len, sizeof(version_len),
+- client_name, client_name_len,
+- version, strlen(version),
+- &descr_len, sizeof(descr_len),
+- descr, strlen(descr),
+- NULL);
+- } else {
+- struct gg_login70 l70;
+-
+- if (gg_dcc_ip != (unsigned long) inet_addr("255.255.255.255"))
+- local_ip = gg_dcc_ip;
+-
+- gs->client_addr = local_ip;
+-
+- memset(&l70, 0, sizeof(l70));
+- l70.uin = gg_fix32(gs->uin);
+- l70.hash_type = gs->hash_type;
+- memcpy(l70.hash, hash_buf, sizeof(l70.hash));
+- l70.status = gg_fix32(gs->initial_status ? gs->initial_status : GG_STATUS_AVAIL);
+- l70.version = gg_fix32(gs->protocol_version | gs->protocol_flags);
+- if (gs->external_addr && gs->external_port > 1023) {
+- l70.local_ip = gs->external_addr;
+- l70.local_port = gg_fix16(gs->external_port);
+- } else {
+- l70.local_ip = local_ip;
+- l70.local_port = gg_fix16(gg_dcc_port);
+- }
+-
+- l70.image_size = gs->image_size;
+- l70.dunno2 = 0xbe;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending GG_LOGIN70 packet\n");
+- ret = gg_send_packet(gs, GG_LOGIN70, &l70, sizeof(l70), gs->initial_descr, (gs->initial_descr) ? strlen(gs->initial_descr) : 0, NULL);
+- }
+-
+- if (ret == -1) {
+- int errno_copy;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() sending packet failed. (errno=%d, %s)\n", errno, strerror(errno));
+- errno_copy = errno;
+- close(gs->fd);
+- errno = errno_copy;
+- gs->fd = -1;
+- ge->type = GG_EVENT_CONN_FAILED;
+- ge->event.failure = GG_FAILURE_WRITING;
+- gs->state = GG_STATE_IDLE;
+- return -1;
+- }
+-
+- gs->state = GG_STATE_READING_REPLY;
+- gs->check = GG_CHECK_READ;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_LOGIN_OK.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_login_ok(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login succeded\n");
+- ge->type = GG_EVENT_CONN_SUCCESS;
+- gs->state = GG_STATE_CONNECTED;
+- gs->check = GG_CHECK_READ;
+- gs->timeout = -1;
+- gs->status = (gs->initial_status) ? gs->initial_status : GG_STATUS_AVAIL;
+-#if 0
+- free(gs->status_descr);
+- gs->status_descr = gs->initial_descr;
+-#else
+- free(gs->initial_descr);
+-#endif
+- gs->initial_descr = NULL;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_LOGIN_FAILED.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_login_failed(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- if (type != GG_DISCONNECTING)
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() login failed\n");
+- else
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd() too many incorrect password attempts\n");
+- ge->type = GG_EVENT_CONN_FAILED;
+- ge->event.failure = (type != GG_DISCONNECTING) ? GG_FAILURE_PASSWORD : GG_FAILURE_INTRUDER;
+- gs->state = GG_STATE_IDLE;
+- close(gs->fd);
+- gs->fd = -1;
+- errno = EACCES;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_SEND_MSG_ACK.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_send_msg_ack(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_send_msg_ack *s = (struct gg_send_msg_ack*) ptr;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a message ack\n");
+-
+- ge->type = GG_EVENT_ACK;
+- ge->event.ack.status = gg_fix32(s->status);
+- ge->event.ack.recipient = gg_fix32(s->recipient);
+- ge->event.ack.seq = gg_fix32(s->seq);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_PONG.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_pong(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a pong\n");
+-
+- ge->type = GG_EVENT_PONG;
+-
+- gs->last_pong = time(NULL);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DISCONNECTING.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_disconnecting(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received disconnection warning\n");
+-
+- ge->type = GG_EVENT_DISCONNECT;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DISCONNECT_ACK.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_disconnect_ack(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received logoff acknowledge\n");
+-
+- ge->type = GG_EVENT_DISCONNECT_ACK;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiety GG_XML_EVENT i GG_XML_ACTION.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_xml_event(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received XML event\n");
+-
+- ge->type = GG_EVENT_XML_EVENT;
+- ge->event.xml_event.data = malloc(len + 1);
+-
+- if (ge->event.xml_event.data == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- memcpy(ge->event.xml_event.data, ptr, len);
+- ge->event.xml_event.data[len] = 0;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_PUBDIR50_REPLY.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_pubdir50_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received pubdir/search reply\n");
+-
+- return gg_pubdir50_handle_reply_sess(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_USERLIST_REPLY.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_userlist_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- char reply_type;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist reply\n");
+-
+- reply_type = ptr[0];
+-
+- /* jeśli odpowiedź na eksport, wywołaj zdarzenie tylko
+- * gdy otrzymano wszystkie odpowiedzi */
+- if (reply_type == GG_USERLIST_PUT_REPLY || reply_type == GG_USERLIST_PUT_MORE_REPLY) {
+- if (--gs->userlist_blocks)
+- return 0;
+-
+- reply_type = GG_USERLIST_PUT_REPLY;
+- }
+-
+- if (len > 1) {
+- unsigned int reply_len = (gs->userlist_reply != NULL) ? strlen(gs->userlist_reply) : 0;
+- char *tmp;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "userlist_reply=%p, len=%d\n", gs->userlist_reply, len);
+-
+- tmp = realloc(gs->userlist_reply, reply_len + len);
+-
+- if (tmp == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- gs->userlist_reply = tmp;
+- memcpy(gs->userlist_reply + reply_len, ptr + 1, len - 1);
+- gs->userlist_reply[reply_len + len - 1] = 0;
+- }
+-
+- if (reply_type == GG_USERLIST_GET_MORE_REPLY)
+- return 0;
+-
+- ge->type = GG_EVENT_USERLIST;
+- ge->event.userlist.type = reply_type;
+- ge->event.userlist.reply = gs->userlist_reply;
+-
+- gs->userlist_reply = NULL;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DCC7_ID_REPLY.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_dcc7_id_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 id packet\n");
+-
+- return gg_dcc7_handle_id(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DCC7_ACCEPT.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_dcc7_accept(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 accept\n");
+-
+- return gg_dcc7_handle_accept(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DCC7_NEW.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_dcc7_new(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 request\n");
+-
+- return gg_dcc7_handle_new(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DCC7_REJECT.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_dcc7_reject(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 reject\n");
+-
+- return gg_dcc7_handle_reject(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_DCC7_INFO.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_dcc7_info(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received dcc7 info\n");
+-
+- return gg_dcc7_handle_info(gs, ge, ptr, len);
+-}
+-
+-/**
+- * \internal Analizuje przychodzący pakiet z obrazkiem.
+- *
+- * \param e Struktura zdarzenia
+- * \param p Bufor z danymi
+- * \param len Długość bufora
+- * \param sess Struktura sesji
+- * \param sender Numer nadawcy
+- */
+-static void gg_image_queue_parse(struct gg_event *e, const char *p, unsigned int len, struct gg_session *sess, uin_t sender)
+-{
+- struct gg_msg_image_reply *i = (void*) p;
+- struct gg_image_queue *q, *qq;
+-
+- if (!p || !sess || !e) {
+- errno = EFAULT;
+- return;
+- }
+-
+- /* znajdź dany obrazek w kolejce danej sesji */
+-
+- for (qq = sess->images, q = NULL; qq; qq = qq->next) {
+- if (sender == qq->sender && i->size == qq->size && i->crc32 == qq->crc32) {
+- q = qq;
+- break;
+- }
+- }
+-
+- if (!q) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() unknown image from %d, size=%d, crc32=%.8x\n", sender, i->size, i->crc32);
+- return;
+- }
+-
+- if (p[0] == GG_MSG_OPTION_IMAGE_REPLY) {
+- q->done = 0;
+-
+- len -= sizeof(struct gg_msg_image_reply);
+- p += sizeof(struct gg_msg_image_reply);
+-
+- if (memchr(p, 0, len) == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() malformed packet from %d, unlimited filename\n", sender);
+- return;
+- }
+-
+- if (!(q->filename = strdup(p))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_queue_parse() out of memory\n");
+- return;
+- }
+-
+- len -= strlen(p) + 1;
+- p += strlen(p) + 1;
+- } else {
+- len -= sizeof(struct gg_msg_image_reply);
+- p += sizeof(struct gg_msg_image_reply);
+- }
+-
+- if (q->done + len > q->size)
+- len = q->size - q->done;
+-
+- memcpy(q->image + q->done, p, len);
+- q->done += len;
+-
+- /* jeśli skończono odbierać obrazek, wygeneruj zdarzenie */
+-
+- if (q->done >= q->size) {
+- e->type = GG_EVENT_IMAGE_REPLY;
+- e->event.image_reply.sender = sender;
+- e->event.image_reply.size = q->size;
+- e->event.image_reply.crc32 = q->crc32;
+- e->event.image_reply.filename = q->filename;
+- e->event.image_reply.image = q->image;
+-
+- gg_image_queue_remove(sess, q, 0);
+-
+- free(q);
+- }
+-}
+-
+-/**
+- * \internal Analizuje informacje rozszerzone wiadomości.
+- *
+- * \param sess Struktura sesji.
+- * \param e Struktura zdarzenia.
+- * \param sender Numer nadawcy.
+- * \param p Wskaźnik na dane rozszerzone.
+- * \param packet_end Wskaźnik na koniec pakietu.
+- *
+- * \return 0 jeśli się powiodło, -1 jeśli wiadomość obsłużono i wynik ma
+- * zostać przekazany aplikacji, -2 jeśli wystąpił błąd ogólny, -3 jeśli
+- * wiadomość jest niepoprawna.
+- */
+-static int gg_handle_recv_msg_options(struct gg_session *sess, struct gg_event *e, uin_t sender, const char *p, const char *packet_end)
+-{
+- while (p < packet_end) {
+- switch (*p) {
+- case GG_MSG_OPTION_CONFERENCE:
+- {
+- struct gg_msg_recipients *m = (void*) p;
+- uint32_t i, count;
+-
+- p += sizeof(*m);
+-
+- if (p > packet_end) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (1)\n");
+- goto malformed;
+- }
+-
+- count = gg_fix32(m->count);
+-
+- if (p + count * sizeof(uin_t) > packet_end || p + count * sizeof(uin_t) < p || count > 0xffff) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (1.5)\n");
+- goto malformed;
+- }
+-
+- if (e->event.msg.recipients != NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() e->event.msg.recipients already exist\n");
+- goto malformed;
+- }
+-
+- e->event.msg.recipients = malloc(count * sizeof(uin_t));
+-
+- if (e->event.msg.recipients == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() not enough memory for recipients data\n");
+- goto fail;
+- }
+-
+- memcpy(e->event.msg.recipients, p, count * sizeof(uin_t));
+- p += count * sizeof(uin_t);
+-
+- for (i = 0; i < count; i++)
+- e->event.msg.recipients[i] = gg_fix32(e->event.msg.recipients[i]);
+-
+- e->event.msg.recipients_count = count;
+-
+- break;
+- }
+-
+- case GG_MSG_OPTION_ATTRIBUTES:
+- {
+- uint16_t len;
+- char *buf;
+-
+- if (p + 3 > packet_end) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (2)\n");
+- goto malformed;
+- }
+-
+- memcpy(&len, p + 1, sizeof(uint16_t));
+- len = gg_fix16(len);
+-
+- if (e->event.msg.formats != NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() e->event.msg.formats already exist\n");
+- goto malformed;
+- }
+-
+- buf = malloc(len);
+-
+- if (buf == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() not enough memory for richtext data\n");
+- goto fail;
+- }
+-
+- p += 3;
+-
+- if (p + len > packet_end) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() packet out of bounds (3)\n");
+- free(buf);
+- goto malformed;
+- }
+-
+- memcpy(buf, p, len);
+-
+- e->event.msg.formats = buf;
+- e->event.msg.formats_length = len;
+-
+- p += len;
+-
+- break;
+- }
+-
+- case GG_MSG_OPTION_IMAGE_REQUEST:
+- {
+- struct gg_msg_image_request *i = (void*) p;
+-
+- if (p + sizeof(*i) > packet_end) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (3)\n");
+- goto malformed;
+- }
+-
+- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() mixed options (1)\n");
+- goto malformed;
+- }
+-
+- e->event.image_request.sender = sender;
+- e->event.image_request.size = gg_fix32(i->size);
+- e->event.image_request.crc32 = gg_fix32(i->crc32);
+-
+- e->type = GG_EVENT_IMAGE_REQUEST;
+-
+- goto handled;
+- }
+-
+- case GG_MSG_OPTION_IMAGE_REPLY:
+- case GG_MSG_OPTION_IMAGE_REPLY_MORE:
+- {
+- struct gg_msg_image_reply *rep = (void*) p;
+-
+- if (e->event.msg.formats != NULL || e->event.msg.recipients != NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg_options() mixed options (2)\n");
+- goto malformed;
+- }
+-
+- if (p + sizeof(struct gg_msg_image_reply) == packet_end) {
+-
+- /* pusta odpowiedź - klient po drugiej stronie nie ma żądanego obrazka */
+-
+- e->type = GG_EVENT_IMAGE_REPLY;
+- e->event.image_reply.sender = sender;
+- e->event.image_reply.size = 0;
+- e->event.image_reply.crc32 = gg_fix32(rep->crc32);
+- e->event.image_reply.filename = NULL;
+- e->event.image_reply.image = NULL;
+- goto handled;
+-
+- } else if (p + sizeof(struct gg_msg_image_reply) + 1 > packet_end) {
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() packet out of bounds (4)\n");
+- goto malformed;
+- }
+-
+- rep->size = gg_fix32(rep->size);
+- rep->crc32 = gg_fix32(rep->crc32);
+- gg_image_queue_parse(e, p, (unsigned int)(packet_end - p), sess, sender);
+-
+- goto handled;
+- }
+-
+- default:
+- {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() unknown payload 0x%.2x\n", *p);
+- p = packet_end;
+- }
+- }
+- }
+-
+- return 0;
+-
+-handled:
+- return -1;
+-
+-fail:
+- return -2;
+-
+-malformed:
+- return -3;
+-}
+-
+-/**
+- * \internal Wysyła potwierdzenie odebrania wiadomości.
+- *
+- * \param gs Struktura sesji
+- * \param seq Numer sekwencyjny odebranej wiadomości
+- *
+- * \return 0 jeśli się powiodło, -1 jeśli wystąpił błąd
+- */
+-static int gg_session_send_msg_ack(struct gg_session *gs, uint32_t seq)
+-{
+- struct gg_recv_msg_ack pkt;
+-
+- gg_debug_session(gs, GG_DEBUG_FUNCTION, "** gg_session_send_msg_ack(%p);\n", gs);
+-
+- if ((gs->protocol_features & GG_FEATURE_MSG_ACK) == 0)
+- return 0;
+-
+- /* Kiedyś zdawało nam się, że mamy wysyłać liczbę odebranych
+- * wiadomości, ale okazało się, że numer sekwencyjny. */
+- gs->recv_msg_count++;
+-
+- pkt.seq = gg_fix32(seq);
+-
+- return gg_send_packet(gs, GG_RECV_MSG_ACK, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_RECV_MSG.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_recv_msg(struct gg_session *sess, uint32_t type, const char *packet, size_t length, struct gg_event *e)
+-{
+- const struct gg_recv_msg *r = (const struct gg_recv_msg*) packet;
+- const char *payload = packet + sizeof(struct gg_recv_msg);
+- const char *payload_end = packet + length;
+- char *tmp;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg(%p, %d, %p);\n", packet, length, e);
+-
+- if ((r->seq == 0) && (r->msgclass == 0)) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() oops, silently ignoring the bait\n");
+- goto malformed;
+- }
+-
+- // jednobajtowa wiadomość o treści \x02 to żądanie połączenia DCC
+- if (*payload == GG_MSG_CALLBACK && payload == payload_end - 1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() received ctcp packet\n");
+- length = 1;
+- } else {
+- const char *options;
+-
+- options = memchr(payload, 0, (size_t) (payload_end - payload));
+-
+- if (options == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg() malformed packet, message out of bounds (0)\n");
+- goto malformed;
+- }
+-
+- length = (size_t) (options - payload);
+-
+- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender), options + 1, payload_end)) {
+- case -1: // handled
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-
+- case -2: // failed
+- goto fail;
+-
+- case -3: // malformed
+- goto malformed;
+- }
+- }
+-
+- e->type = GG_EVENT_MSG;
+- e->event.msg.msgclass = gg_fix32(r->msgclass);
+- e->event.msg.sender = gg_fix32(r->sender);
+- e->event.msg.time = gg_fix32(r->time);
+- e->event.msg.seq = gg_fix32(r->seq);
+-
+- tmp = gg_encoding_convert(payload, GG_ENCODING_CP1250, sess->encoding, length, -1);
+- if (tmp == NULL)
+- goto fail;
+- e->event.msg.message = (unsigned char*) tmp;
+-
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-
+-fail:
+- free(e->event.msg.message);
+- free(e->event.msg.recipients);
+- free(e->event.msg.formats);
+- return -1;
+-
+-malformed:
+- e->type = GG_EVENT_NONE;
+- free(e->event.msg.message);
+- free(e->event.msg.xhtml_message);
+- free(e->event.msg.recipients);
+- free(e->event.msg.formats);
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_RECV_MSG80.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_recv_msg_80(struct gg_session *sess, uint32_t type, const char *packet, size_t length, struct gg_event *e)
+-{
+- const struct gg_recv_msg80 *r = (const struct gg_recv_msg80*) packet;
+- uint32_t offset_plain;
+- uint32_t offset_attr;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_handle_recv_msg80(%p, %d, %p);\n", packet, length, e);
+-
+- if (r->seq == 0 && r->msgclass == 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() oops, silently ignoring the bait\n");
+- goto malformed;
+- }
+-
+- offset_plain = gg_fix32(r->offset_plain);
+- offset_attr = gg_fix32(r->offset_attr);
+-
+- if (offset_plain < sizeof(struct gg_recv_msg80) || offset_plain >= length) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (0)\n");
+- goto malformed;
+- }
+-
+- if (offset_attr < sizeof(struct gg_recv_msg80) || offset_attr > length) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, attr out of bounds (1)\n");
+- offset_attr = 0; /* nie parsuj attr. */
+- }
+-
+- /* Normalna sytuacja, więc nie podpada pod powyższy warunek. */
+- if (offset_attr == length)
+- offset_attr = 0;
+-
+- if (memchr(packet + offset_plain, 0, length - offset_plain) == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (2)\n");
+- goto malformed;
+- }
+-
+- if (offset_plain > sizeof(struct gg_recv_msg80) && memchr(packet + sizeof(struct gg_recv_msg80), 0, offset_plain - sizeof(struct gg_recv_msg80)) == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_handle_recv_msg80() malformed packet, message out of bounds (3)\n");
+- goto malformed;
+- }
+-
+- e->type = (type != GG_RECV_OWN_MSG) ? GG_EVENT_MSG : GG_EVENT_MULTILOGON_MSG;
+- e->event.msg.msgclass = gg_fix32(r->msgclass);
+- e->event.msg.sender = gg_fix32(r->sender);
+- e->event.msg.time = gg_fix32(r->time);
+- e->event.msg.seq = gg_fix32(r->seq);
+-
+- if (offset_attr != 0) {
+- switch (gg_handle_recv_msg_options(sess, e, gg_fix32(r->sender), packet + offset_attr, packet + length)) {
+- case -1: // handled
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-
+- case -2: // failed
+- goto fail;
+-
+- case -3: // malformed
+- goto malformed;
+- }
+- }
+-
+- if (sess->encoding == GG_ENCODING_CP1250) {
+- e->event.msg.message = (unsigned char*) strdup(packet + offset_plain);
+- } else {
+- if (offset_plain > sizeof(struct gg_recv_msg80)) {
+- int len;
+-
+- len = gg_message_html_to_text(NULL, packet + sizeof(struct gg_recv_msg80));
+- e->event.msg.message = malloc(len + 1);
+-
+- if (e->event.msg.message == NULL)
+- goto fail;
+-
+- gg_message_html_to_text((char*) e->event.msg.message, packet + sizeof(struct gg_recv_msg80));
+- } else {
+- e->event.msg.message = (unsigned char*) gg_encoding_convert(packet + offset_plain, GG_ENCODING_CP1250, sess->encoding, -1, -1);
+- }
+- }
+-
+- if (offset_plain > sizeof(struct gg_recv_msg80))
+- e->event.msg.xhtml_message = gg_encoding_convert(packet + sizeof(struct gg_recv_msg80), GG_ENCODING_UTF8, sess->encoding, -1, -1);
+- else
+- e->event.msg.xhtml_message = NULL;
+-
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-
+-fail:
+- free(e->event.msg.message);
+- free(e->event.msg.xhtml_message);
+- free(e->event.msg.recipients);
+- free(e->event.msg.formats);
+- return -1;
+-
+-malformed:
+- e->type = GG_EVENT_NONE;
+- free(e->event.msg.message);
+- free(e->event.msg.xhtml_message);
+- free(e->event.msg.recipients);
+- free(e->event.msg.formats);
+- gg_session_send_msg_ack(sess, gg_fix32(r->seq));
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_STATUS.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_status(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_status *s = (void*) ptr;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
+-
+- ge->type = GG_EVENT_STATUS;
+- ge->event.status.uin = gg_fix32(s->uin);
+- ge->event.status.status = gg_fix32(s->status);
+- ge->event.status.descr = NULL;
+-
+- if (len > sizeof(*s)) {
+- ge->event.status.descr = gg_encoding_convert(ptr + sizeof(*s), GG_ENCODING_CP1250, gs->encoding, len - sizeof(*s), -1);
+-
+- if (ge->event.status.descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiety GG_STATUS60, GG_STATUS77 i GG_STATUS80BETA.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_status_60_77_80beta(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_status60 *s60 = (void*) ptr;
+- struct gg_status77 *s77 = (void*) ptr;
+- size_t struct_len;
+- uint32_t uin;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
+-
+- ge->type = GG_EVENT_STATUS60;
+- ge->event.status60.descr = NULL;
+- ge->event.status60.time = 0;
+-
+- if (type == GG_STATUS60) {
+- uin = gg_fix32(s60->uin);
+- ge->event.status60.status = s60->status;
+- ge->event.status60.remote_ip = s60->remote_ip;
+- ge->event.status60.remote_port = gg_fix16(s60->remote_port);
+- ge->event.status60.version = s60->version;
+- ge->event.status60.image_size = s60->image_size;
+- struct_len = sizeof(*s60);
+- } else {
+- uin = gg_fix32(s77->uin);
+- ge->event.status60.status = s77->status;
+- ge->event.status60.remote_ip = s77->remote_ip;
+- ge->event.status60.remote_port = gg_fix16(s77->remote_port);
+- ge->event.status60.version = s77->version;
+- ge->event.status60.image_size = s77->image_size;
+- struct_len = sizeof(*s77);
+- }
+-
+- ge->event.status60.uin = uin & 0x00ffffff;
+-
+- if (uin & 0x40000000)
+- ge->event.status60.version |= GG_HAS_AUDIO_MASK;
+- if (uin & 0x20000000)
+- ge->event.status60.version |= GG_HAS_AUDIO7_MASK;
+- if (uin & 0x08000000)
+- ge->event.status60.version |= GG_ERA_OMNIX_MASK;
+-
+- if (len > struct_len) {
+- size_t descr_len;
+-
+- descr_len = len - struct_len;
+-
+- ge->event.status60.descr = gg_encoding_convert(ptr + struct_len, (type == GG_STATUS80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
+-
+- if (ge->event.status60.descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- if (descr_len > 4 && ptr[len - 5] == 0) {
+- uint32_t t;
+- memcpy(&t, ptr + len - 4, sizeof(uint32_t));
+- ge->event.status60.time = gg_fix32(t);
+- }
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_NOTIFY_REPLY.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_notify_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_notify_reply *n = (void*) ptr;
+- char *descr;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
+-
+- if (gg_fix32(n->status) == GG_STATUS_BUSY_DESCR || gg_fix32(n->status) == GG_STATUS_NOT_AVAIL_DESCR || gg_fix32(n->status) == GG_STATUS_AVAIL_DESCR) {
+- size_t descr_len;
+-
+- ge->type = GG_EVENT_NOTIFY_DESCR;
+-
+- if (!(ge->event.notify_descr.notify = (void*) malloc(sizeof(*n) * 2))) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+- ge->event.notify_descr.notify[1].uin = 0;
+- memcpy(ge->event.notify_descr.notify, ptr, sizeof(*n));
+- ge->event.notify_descr.notify[0].uin = gg_fix32(ge->event.notify_descr.notify[0].uin);
+- ge->event.notify_descr.notify[0].status = gg_fix32(ge->event.notify_descr.notify[0].status);
+- ge->event.notify_descr.notify[0].remote_port = gg_fix16(ge->event.notify_descr.notify[0].remote_port);
+- ge->event.notify_descr.notify[0].version = gg_fix32(ge->event.notify_descr.notify[0].version);
+-
+- descr_len = len - sizeof(*n);
+-
+- descr = gg_encoding_convert(ptr + sizeof(*n), GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
+-
+- if (descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- ge->event.notify_descr.descr = descr;
+-
+- } else {
+- unsigned int i, count;
+-
+- ge->type = GG_EVENT_NOTIFY;
+-
+- if (!(ge->event.notify = (void*) malloc(len + 2 * sizeof(*n)))) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- memcpy(ge->event.notify, ptr, len);
+- count = len / sizeof(*n);
+- ge->event.notify[count].uin = 0;
+-
+- for (i = 0; i < count; i++) {
+- ge->event.notify[i].uin = gg_fix32(ge->event.notify[i].uin);
+- ge->event.notify[i].status = gg_fix32(ge->event.notify[i].status);
+- ge->event.notify[i].remote_port = gg_fix16(ge->event.notify[i].remote_port);
+- ge->event.notify[i].version = gg_fix32(ge->event.notify[i].version);
+- }
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_STATUS80.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_status_80(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_notify_reply80 *n = (void*) ptr;
+- size_t descr_len;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a status change\n");
+-
+- ge->type = GG_EVENT_STATUS60;
+- ge->event.status60.uin = gg_fix32(n->uin);
+- ge->event.status60.status = gg_fix32(n->status);
+- ge->event.status60.remote_ip = n->remote_ip;
+- ge->event.status60.remote_port = gg_fix16(n->remote_port);
+- ge->event.status60.version = 0;
+- ge->event.status60.image_size = n->image_size;
+- ge->event.status60.descr = NULL;
+- ge->event.status60.time = 0;
+-
+- descr_len = gg_fix32(n->descr_len);
+-
+- if (descr_len != 0 && sizeof(struct gg_notify_reply80) + descr_len <= len) {
+- ge->event.status60.descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply80), GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
+-
+- if (ge->event.status60.descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- /* XXX czas */
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_NOTIFY_REPLY80.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_notify_reply_80(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_notify_reply80 *n = (void*) ptr;
+- unsigned int length = len, i = 0;
+-
+- // TODO: najpierw przeanalizować strukturę i określić
+- // liczbę rekordów, żeby obyć się bez realloc()
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
+-
+- ge->type = GG_EVENT_NOTIFY60;
+- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
+-
+- if (!ge->event.notify60) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- ge->event.notify60[0].uin = 0;
+-
+- while (length >= sizeof(struct gg_notify_reply80)) {
+- uin_t uin = gg_fix32(n->uin);
+- int descr_len;
+- char *tmp;
+-
+- ge->event.notify60[i].uin = uin;
+- ge->event.notify60[i].status = gg_fix32(n->status);
+- ge->event.notify60[i].remote_ip = n->remote_ip;
+- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
+- ge->event.notify60[i].version = 0;
+- ge->event.notify60[i].image_size = n->image_size;
+- ge->event.notify60[i].descr = NULL;
+- ge->event.notify60[i].time = 0;
+-
+- descr_len = gg_fix32(n->descr_len);
+-
+- if (descr_len != 0) {
+- if (sizeof(struct gg_notify_reply80) + descr_len <= length) {
+- ge->event.notify60[i].descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply80), GG_ENCODING_UTF8, gs->encoding, descr_len, -1);
+-
+- if (ge->event.notify60[i].descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- /* XXX czas */
+-
+- length -= sizeof(struct gg_notify_reply80) + descr_len;
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply80) + descr_len);
+- } else {
+- length = 0;
+- }
+-
+- } else {
+- length -= sizeof(struct gg_notify_reply80);
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply80));
+- }
+-
+- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- free(ge->event.notify60);
+- return -1;
+- }
+-
+- ge->event.notify60 = (void*) tmp;
+- ge->event.notify60[++i].uin = 0;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiety GG_NOTIFY_REPLY77 i GG_NOTIFY_REPLY80BETA.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_notify_reply_77_80beta(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_notify_reply77 *n = (void*) ptr;
+- unsigned int length = len, i = 0;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
+-
+- ge->type = GG_EVENT_NOTIFY60;
+- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
+-
+- if (ge->event.notify60 == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- ge->event.notify60[0].uin = 0;
+-
+- while (length >= sizeof(struct gg_notify_reply77)) {
+- uin_t uin = gg_fix32(n->uin);
+- char *tmp;
+-
+- ge->event.notify60[i].uin = uin & 0x00ffffff;
+- ge->event.notify60[i].status = n->status;
+- ge->event.notify60[i].remote_ip = n->remote_ip;
+- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
+- ge->event.notify60[i].version = n->version;
+- ge->event.notify60[i].image_size = n->image_size;
+- ge->event.notify60[i].descr = NULL;
+- ge->event.notify60[i].time = 0;
+-
+- if (uin & 0x40000000)
+- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
+- if (uin & 0x20000000)
+- ge->event.notify60[i].version |= GG_HAS_AUDIO7_MASK;
+- if (uin & 0x08000000)
+- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
+-
+- if (GG_S_D(n->status)) {
+- unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply77));
+-
+- if (sizeof(struct gg_notify_reply77) + descr_len <= length) {
+- ge->event.notify60[i].descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply77) + 1, (type == GG_NOTIFY_REPLY80BETA) ? GG_ENCODING_UTF8 : GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
+-
+- if (ge->event.notify60[i].descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- /* XXX czas */
+-
+- length -= sizeof(struct gg_notify_reply77) + descr_len + 1;
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply77) + descr_len + 1);
+- } else {
+- length = 0;
+- }
+-
+- } else {
+- length -= sizeof(struct gg_notify_reply77);
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply77));
+- }
+-
+- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- free(ge->event.notify60);
+- return -1;
+- }
+-
+- ge->event.notify60 = (void*) tmp;
+- ge->event.notify60[++i].uin = 0;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_NOTIFY_REPLY60.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_notify_reply_60(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_notify_reply60 *n = (void*) ptr;
+- unsigned int length = len, i = 0;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received a notify reply\n");
+-
+- ge->type = GG_EVENT_NOTIFY60;
+- ge->event.notify60 = malloc(sizeof(*ge->event.notify60));
+-
+- if (ge->event.notify60 == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- ge->event.notify60[0].uin = 0;
+-
+- while (length >= sizeof(struct gg_notify_reply60)) {
+- uin_t uin = gg_fix32(n->uin);
+- char *tmp;
+-
+- ge->event.notify60[i].uin = uin & 0x00ffffff;
+- ge->event.notify60[i].status = n->status;
+- ge->event.notify60[i].remote_ip = n->remote_ip;
+- ge->event.notify60[i].remote_port = gg_fix16(n->remote_port);
+- ge->event.notify60[i].version = n->version;
+- ge->event.notify60[i].image_size = n->image_size;
+- ge->event.notify60[i].descr = NULL;
+- ge->event.notify60[i].time = 0;
+-
+- if (uin & 0x40000000)
+- ge->event.notify60[i].version |= GG_HAS_AUDIO_MASK;
+- if (uin & 0x08000000)
+- ge->event.notify60[i].version |= GG_ERA_OMNIX_MASK;
+-
+- if (GG_S_D(n->status)) {
+- unsigned char descr_len = *((char*) n + sizeof(struct gg_notify_reply60));
+-
+- if (sizeof(struct gg_notify_reply60) + descr_len <= length) {
+- char *descr;
+-
+- descr = gg_encoding_convert((char*) n + sizeof(struct gg_notify_reply60) + 1, GG_ENCODING_CP1250, gs->encoding, descr_len, -1);
+-
+- if (descr == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- return -1;
+- }
+-
+- ge->event.notify60[i].descr = descr;
+-
+- /* XXX czas */
+-
+- length -= sizeof(struct gg_notify_reply60) + descr_len + 1;
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply60) + descr_len + 1);
+- } else {
+- length = 0;
+- }
+-
+- } else {
+- length -= sizeof(struct gg_notify_reply60);
+- n = (void*) ((char*) n + sizeof(struct gg_notify_reply60));
+- }
+-
+- if (!(tmp = realloc(ge->event.notify60, (i + 2) * sizeof(*ge->event.notify60)))) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() out of memory\n");
+- free(ge->event.notify60);
+- return -1;
+- }
+-
+- ge->event.notify60 = (void*) tmp;
+- ge->event.notify60[++i].uin = 0;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_USER_DATA.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_user_data(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_user_data d;
+- char *p = (char*) ptr;
+- char *packet_end = (char*) ptr + len;
+- struct gg_event_user_data_user *users;
+- int i, j;
+- int res = 0;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received user data\n");
+-
+- ge->event.user_data.user_count = 0;
+- ge->event.user_data.users = NULL;
+-
+- if (ptr + sizeof(d) > packet_end)
+- goto malformed;
+-
+- memcpy(&d, p, sizeof(d));
+- p += sizeof(d);
+-
+- d.type = gg_fix32(d.type);
+- d.user_count = gg_fix32(d.user_count);
+-
+- if (d.user_count > 0xffff) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (1)\n");
+- goto malformed;
+- }
+-
+- if (d.user_count > 0) {
+- users = calloc(d.user_count, sizeof(struct gg_event_user_data_user));
+-
+- if (users == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d*%d)\n", d.user_count, sizeof(struct gg_event_user_data_user));
+- goto fail;
+- }
+- } else {
+- users = NULL;
+- }
+-
+- ge->type = GG_EVENT_USER_DATA;
+- ge->event.user_data.type = d.type;
+- ge->event.user_data.user_count = d.user_count;
+- ge->event.user_data.users = users;
+-
+- gg_debug_session(gs, GG_DEBUG_DUMP, "type=%d, count=%d\n", d.type, d.user_count);
+-
+- for (i = 0; i < d.user_count; i++) {
+- struct gg_user_data_user u;
+- struct gg_event_user_data_attr *attrs;
+-
+- if (p + sizeof(u) > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
+- goto malformed;
+- }
+-
+- memcpy(&u, p, sizeof(u));
+- p += sizeof(u);
+-
+- u.uin = gg_fix32(u.uin);
+- u.attr_count = gg_fix32(u.attr_count);
+-
+- if (u.attr_count > 0xffff) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (2)\n");
+- goto malformed;
+- }
+-
+- if (u.attr_count > 0) {
+- attrs = calloc(u.attr_count, sizeof(struct gg_event_user_data_attr));
+-
+- if (attrs == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d*%d)\n", u.attr_count, sizeof(struct gg_event_user_data_attr));
+- goto fail;
+- }
+- } else {
+- attrs = NULL;
+- }
+-
+- users[i].uin = u.uin;
+- users[i].attr_count = u.attr_count;
+- users[i].attrs = attrs;
+-
+- gg_debug_session(gs, GG_DEBUG_DUMP, " uin=%d, count=%d\n", u.uin, u.attr_count);
+-
+- for (j = 0; j < u.attr_count; j++) {
+- uint32_t key_size;
+- uint32_t attr_type;
+- uint32_t value_size;
+- char *key;
+- char *value;
+-
+- if (p + sizeof(key_size) > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (3)\n");
+- goto malformed;
+- }
+-
+- memcpy(&key_size, p, sizeof(key_size));
+- p += sizeof(key_size);
+-
+- key_size = gg_fix32(key_size);
+-
+- if (key_size > 0xffff || p + key_size > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (3)\n");
+- goto malformed;
+- }
+-
+- key = malloc(key_size + 1);
+-
+- if (key == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d)\n", key_size + 1);
+- goto fail;
+- }
+-
+- memcpy(key, p, key_size);
+- p += key_size;
+-
+- key[key_size] = 0;
+-
+- attrs[j].key = key;
+-
+- if (p + sizeof(attr_type) + sizeof(value_size) > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (4)\n");
+- goto malformed;
+- }
+-
+- memcpy(&attr_type, p, sizeof(attr_type));
+- p += sizeof(attr_type);
+- memcpy(&value_size, p, sizeof(value_size));
+- p += sizeof(value_size);
+-
+- attrs[j].type = gg_fix32(attr_type);
+- value_size = gg_fix32(value_size);
+-
+- if (value_size > 0xffff || p + value_size > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() malformed packet (5)\n");
+- goto malformed;
+- }
+-
+- value = malloc(value_size + 1);
+-
+- if (value == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_user_data() out of memory (%d)\n", value_size + 1);
+- goto fail;
+- }
+-
+- memcpy(value, p, value_size);
+- p += value_size;
+-
+- value[value_size] = 0;
+-
+- attrs[j].value = value;
+-
+- gg_debug_session(gs, GG_DEBUG_DUMP, " key=\"%s\", type=%d, value=\"%s\"\n", key, attr_type, value);
+- }
+- }
+-
+- return 0;
+-
+-fail:
+- res = -1;
+-
+-malformed:
+- ge->type = GG_EVENT_NONE;
+-
+- for (i = 0; i < ge->event.user_data.user_count; i++) {
+- for (j = 0; j < ge->event.user_data.users[i].attr_count; j++) {
+- free(ge->event.user_data.users[i].attrs[j].key);
+- free(ge->event.user_data.users[i].attrs[j].value);
+- }
+-
+- free(ge->event.user_data.users[i].attrs);
+- }
+-
+- free(ge->event.user_data.users);
+-
+- return res;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_TYPING_NOTIFICATION.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_typing_notification(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_typing_notification *n = (void*) ptr;
+- uin_t uin;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received typing notification\n");
+-
+- memcpy(&uin, &n->uin, sizeof(uin_t));
+-
+- ge->type = GG_EVENT_TYPING_NOTIFICATION;
+- ge->event.typing_notification.uin = gg_fix32(uin);
+- ge->event.typing_notification.length = gg_fix16(n->length);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_MULTILOGON_INFO.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_multilogon_info(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- char *packet_end = (char*) ptr + len;
+- struct gg_multilogon_info *info = (struct gg_multilogon_info*) ptr;
+- char *p = (char*) ptr + sizeof(*info);
+- struct gg_multilogon_session *sessions = NULL;
+- size_t count;
+- size_t i;
+- int res = 0;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received multilogon info\n");
+-
+- count = gg_fix32(info->count);
+-
+- if (count > 0xffff) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (1)\n");
+- goto malformed;
+- }
+-
+- sessions = calloc(count, sizeof(struct gg_multilogon_session));
+-
+- if (sessions == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() out of memory (%d*%d)\n", count, sizeof(struct gg_multilogon_session));
+- return -1;
+- }
+-
+- ge->type = GG_EVENT_MULTILOGON_INFO;
+- ge->event.multilogon_info.count = count;
+- ge->event.multilogon_info.sessions = sessions;
+-
+- for (i = 0; i < count; i++) {
+- struct gg_multilogon_info_item item;
+- size_t name_size;
+-
+- if (p + sizeof(item) > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (2)\n");
+- goto malformed;
+- }
+-
+- memcpy(&item, p, sizeof(item));
+-
+- sessions[i].id = item.conn_id;
+- sessions[i].remote_addr = item.addr;
+- sessions[i].status_flags = gg_fix32(item.flags);
+- sessions[i].protocol_features = gg_fix32(item.features);
+- sessions[i].logon_time = gg_fix32(item.logon_time);
+-
+- p += sizeof(item);
+-
+- name_size = gg_fix32(item.name_size);
+-
+- if (name_size > 0xffff || p + name_size > packet_end) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() malformed packet (3)\n");
+- goto malformed;
+- }
+-
+- sessions[i].name = malloc(name_size + 1);
+-
+- if (sessions[i].name == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_multilogon_info() out of memory (%d)\n", name_size);
+- goto fail;
+- }
+-
+- memcpy(sessions[i].name, p, name_size);
+- sessions[i].name[name_size] = 0;
+-
+- p += name_size;
+- }
+-
+- return 0;
+-
+-fail:
+- res = -1;
+-
+-malformed:
+- ge->type = GG_EVENT_NONE;
+-
+- for (i = 0; i < ge->event.multilogon_info.count; i++)
+- free(ge->event.multilogon_info.sessions[i].name);
+-
+- free(ge->event.multilogon_info.sessions);
+-
+- return res;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_USERLIST100_VERSION.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_userlist_100_version(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_userlist100_version *version = (struct gg_userlist100_version*) ptr;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 version\n");
+-
+- ge->type = GG_EVENT_USERLIST100_VERSION;
+- ge->event.userlist100_version.version = gg_fix32(version->version);
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Obsługuje pakiet GG_USERLIST100_REPLY.
+- *
+- * Patrz gg_packet_handler_t
+- */
+-static int gg_session_handle_userlist_100_reply(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- struct gg_userlist100_reply *reply = (struct gg_userlist100_reply*) ptr;
+- char *data = NULL;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_watch_fd_connected() received userlist 100 reply\n");
+-
+- if (len > sizeof(*reply)) {
+- data = gg_inflate((const unsigned char*) ptr + sizeof(*reply), len - sizeof(*reply));
+-
+- if (data == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_handle_userlist_100_reply() gg_inflate() failed\n");
+- return -1;
+- }
+- }
+-
+- ge->type = GG_EVENT_USERLIST100_REPLY;
+- ge->event.userlist100_reply.type = reply->type;
+- ge->event.userlist100_reply.version = gg_fix32(reply->version);
+- ge->event.userlist100_reply.format_type = reply->format_type;
+- ge->event.userlist100_reply.reply = data;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Tablica obsługiwanych pakietów
+- */
+-static const gg_packet_handler_t handlers[] =
+-{
+- { GG_WELCOME, GG_STATE_READING_KEY, 0, gg_session_handle_welcome },
+- { GG_LOGIN_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
+- { GG_LOGIN80_OK, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
+- { GG_NEED_EMAIL, GG_STATE_READING_REPLY, 0, gg_session_handle_login_ok },
+- { GG_LOGIN_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
+- { GG_LOGIN80_FAILED, GG_STATE_READING_REPLY, 0, gg_session_handle_login_failed },
+- { GG_SEND_MSG_ACK, GG_STATE_CONNECTED, sizeof(struct gg_send_msg_ack), gg_session_handle_send_msg_ack },
+- { GG_PONG, GG_STATE_CONNECTED, 0, gg_session_handle_pong },
+- { GG_DISCONNECTING, GG_STATE_CONNECTED, 0, gg_session_handle_disconnecting },
+- { GG_DISCONNECT_ACK, GG_STATE_DISCONNECTING, 0, gg_session_handle_disconnect_ack },
+- { GG_XML_EVENT, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
+- { GG_PUBDIR50_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_pubdir50_reply },
+- { GG_USERLIST_REPLY, GG_STATE_CONNECTED, 0, gg_session_handle_userlist_reply },
+- { GG_DCC7_ID_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_id_reply), gg_session_handle_dcc7_id_reply },
+- { GG_DCC7_ACCEPT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_accept), gg_session_handle_dcc7_accept },
+- { GG_DCC7_NEW, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_new), gg_session_handle_dcc7_new },
+- { GG_DCC7_REJECT, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_reject), gg_session_handle_dcc7_reject },
+- { GG_DCC7_INFO, GG_STATE_CONNECTED, sizeof(struct gg_dcc7_info), gg_session_handle_dcc7_info },
+- { GG_RECV_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg), gg_session_handle_recv_msg },
+- { GG_RECV_MSG80, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
+- { GG_STATUS, GG_STATE_CONNECTED, sizeof(struct gg_status), gg_session_handle_status },
+- { GG_STATUS60, GG_STATE_CONNECTED, sizeof(struct gg_status60), gg_session_handle_status_60_77_80beta },
+- { GG_STATUS77, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
+- { GG_STATUS80BETA, GG_STATE_CONNECTED, sizeof(struct gg_status77), gg_session_handle_status_60_77_80beta },
+- { GG_STATUS80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_status_80 },
+- { GG_NOTIFY_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply), gg_session_handle_notify_reply },
+- { GG_NOTIFY_REPLY60, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply60), gg_session_handle_notify_reply_60 },
+- { GG_NOTIFY_REPLY77, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
+- { GG_NOTIFY_REPLY80BETA, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply77), gg_session_handle_notify_reply_77_80beta },
+- { GG_NOTIFY_REPLY80, GG_STATE_CONNECTED, sizeof(struct gg_notify_reply80), gg_session_handle_notify_reply_80 },
+- { GG_USER_DATA, GG_STATE_CONNECTED, sizeof(struct gg_user_data), gg_session_handle_user_data },
+- { GG_TYPING_NOTIFICATION, GG_STATE_CONNECTED, sizeof(struct gg_typing_notification), gg_session_handle_typing_notification },
+- { GG_MULTILOGON_INFO, GG_STATE_CONNECTED, sizeof(struct gg_multilogon_info), gg_session_handle_multilogon_info },
+- { GG_XML_ACTION, GG_STATE_CONNECTED, 0, gg_session_handle_xml_event },
+- { GG_RECV_OWN_MSG, GG_STATE_CONNECTED, sizeof(struct gg_recv_msg80), gg_session_handle_recv_msg_80 },
+- { GG_USERLIST100_VERSION, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_version), gg_session_handle_userlist_100_version },
+- { GG_USERLIST100_REPLY, GG_STATE_CONNECTED, sizeof(struct gg_userlist100_reply), gg_session_handle_userlist_100_reply },
+-};
+-
+-/**
+- * \internal Analizuje przychodzący pakiet danych.
+- *
+- * \param gs Struktura sesji
+- * \param type Typ pakietu
+- * \param ptr Wskaźnik do bufora pakietu
+- * \param len Długość bufora pakietu
+- * \param[out] ge Struktura zdarzenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge)
+-{
+- int i;
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet(%d, %p, %d)\n", type, ptr, len);
+-
+- gs->last_event = time(NULL);
+-
+-#if 0
+- if ((gs->flags & (1 << GG_SESSION_FLAG_RAW_PACKET)) != 0) {
+- char *tmp;
+-
+- tmp = malloc(len);
+-
+- if (tmp == NULL) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() out of memory (%d bytes)\n", len);
+- return -1;
+- }
+-
+- memcpy(tmp, ptr, len);
+-
+- ge->type = GG_EVENT_RAW_PACKET;
+- ge->event.raw_packet.type = type;
+- ge->event.raw_packet.length = len;
+- ge->event.raw_packet.data = tmp;
+-
+- return 0;
+- }
+-#endif
+-
+- for (i = 0; i < sizeof(handlers) / sizeof(handlers[0]); i++) {
+- if (handlers[i].type != 0 && handlers[i].type != type)
+- continue;
+-
+- if (handlers[i].state != 0 && handlers[i].state != gs->state) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() packet 0x%02x unexpected in state %d\n", type, gs->state);
+- continue;
+- }
+-
+- if (len < handlers[i].min_length) {
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() packet 0x%02x too short (%d bytes)\n", type, len);
+- continue;
+- }
+-
+- return (*handlers[i].handler)(gs, type, ptr, len, ge);
+- }
+-
+- gg_debug_session(gs, GG_DEBUG_MISC, "// gg_session_handle_packet() unhandled packet 0x%02x, len %d, state %d\n", type, len, gs->state);
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/http.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/http.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/http.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/http.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,544 +0,0 @@
+-/* $Id: http.c 1036 2010-12-15 00:02:28Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2002 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file http.c
+- *
+- * \brief Obsługa połączeń HTTP
+- */
+-
+-#include <sys/types.h>
+-#ifndef _WIN32
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-#endif
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-#include "resolver.h"
+-
+-#include <ctype.h>
+-#include <errno.h>
+-#ifndef _WIN32
+-# include <netdb.h>
+-#endif
+-#include <signal.h>
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-
+-/**
+- * Rozpoczyna połączenie HTTP.
+- *
+- * Funkcja przeprowadza połączenie HTTP przy połączeniu synchronicznym,
+- * zwracając wynik w polach struktury \c gg_http, lub błąd, gdy sesja się
+- * nie powiedzie.
+- *
+- * Przy połączeniu asynchronicznym, funkcja rozpoczyna połączenie, a dalsze
+- * etapy będą przeprowadzane po wykryciu zmian (\c watch) na obserwowanym
+- * deskryptorze (\c fd) i wywołaniu funkcji \c gg_http_watch_fd().
+- *
+- * Po zakończeniu, należy zwolnić strukturę za pomocą funkcji
+- * \c gg_http_free(). Połączenie asynchroniczne można zatrzymać w każdej
+- * chwili za pomocą \c gg_http_stop().
+- *
+- * \param hostname Adres serwera
+- * \param port Port serwera
+- * \param async Flaga asynchronicznego połączenia
+- * \param method Metoda HTTP
+- * \param path Ścieżka do zasobu (musi być poprzedzona znakiem '/')
+- * \param header Nagłówek zapytania plus ewentualne dane dla POST
+- *
+- * \return Zaalokowana struktura \c gg_http lub NULL, jeśli wystąpił błąd.
+- *
+- * \ingroup http
+- */
+-struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header)
+-{
+- struct gg_http *h;
+-
+- if (!hostname || !port || !method || !path || !header) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() invalid arguments\n");
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- if (!(h = malloc(sizeof(*h))))
+- return NULL;
+- memset(h, 0, sizeof(*h));
+-
+- h->async = async;
+- h->port = port;
+- h->fd = -1;
+- h->type = GG_SESSION_HTTP;
+-
+- gg_http_set_resolver(h, GG_RESOLVER_DEFAULT);
+-
+- if (gg_proxy_enabled) {
+- char *auth = gg_proxy_auth();
+-
+- h->query = gg_saprintf("%s http://%s:%d%s HTTP/1.0\r\n%s%s",
+- method, hostname, port, path, (auth) ? auth :
+- "", header);
+- hostname = gg_proxy_host;
+- h->port = port = gg_proxy_port;
+- free(auth);
+-
+- } else {
+- h->query = gg_saprintf("%s %s HTTP/1.0\r\n%s",
+- method, path, header);
+- }
+-
+- if (!h->query) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() not enough memory for query\n");
+- free(h);
+- errno = ENOMEM;
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-QUERY-----\n%s\n=> -----END-HTTP-QUERY-----\n", h->query);
+-
+- if (async) {
+- if (h->resolver_start(&h->fd, &h->resolver, hostname) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver failed\n");
+- gg_http_free(h);
+- errno = ENOENT;
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() resolver = %p\n", h->resolver);
+-
+- h->state = GG_STATE_RESOLVING;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- } else {
+- struct in_addr *addr_list = NULL;
+- int addr_count;
+-
+- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() host not found\n");
+- gg_http_free(h);
+- free(addr_list);
+- errno = ENOENT;
+- return NULL;
+- }
+-
+- if ((h->fd = gg_connect(&addr_list[0], port, 0)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- gg_http_free(h);
+- free(addr_list);
+- return NULL;
+- }
+-
+- free(addr_list);
+-
+- h->state = GG_STATE_CONNECTING;
+-
+- while (h->state != GG_STATE_ERROR && h->state != GG_STATE_PARSING) {
+- if (gg_http_watch_fd(h) == -1)
+- break;
+- }
+-
+- if (h->state != GG_STATE_PARSING) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_connect() some strange error\n");
+- gg_http_free(h);
+- return NULL;
+- }
+- }
+-
+- h->callback = gg_http_watch_fd;
+- h->destroy = gg_http_free;
+-
+- return h;
+-}
+-
+-#ifndef DOXYGEN
+-
+-#define gg_http_error(x) \
+- close(h->fd); \
+- h->fd = -1; \
+- h->state = GG_STATE_ERROR; \
+- h->error = x; \
+- return 0;
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe
+- * \c GG_STATE_PARSING. W tym miejscu działanie przejmuje zwykle funkcja
+- * korzystająca z \c gg_http_watch_fd(). W przypadku błędu połączenia,
+- * pole \c state będzie równe \c GG_STATE_ERROR, a kod błędu znajdzie się
+- * w polu \c error.
+- *
+- * \param h Struktura połączenia
+- *
+- * \return \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup http
+- */
+-int gg_http_watch_fd(struct gg_http *h)
+-{
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_http_watch_fd(%p);\n", h);
+-
+- if (!h) {
+- gg_debug(GG_DEBUG_MISC, "// gg_http_watch_fd() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (h->state == GG_STATE_RESOLVING) {
+- struct in_addr a;
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, resolving done\n");
+-
+- if (read(h->fd, &a, sizeof(a)) < (signed)sizeof(a) || a.s_addr == INADDR_NONE) {
+- gg_debug(GG_DEBUG_MISC, "=> http, resolver thread failed\n");
+- gg_http_error(GG_ERROR_RESOLVING);
+- }
+-
+- close(h->fd);
+- h->fd = -1;
+-
+- h->resolver_cleanup(&h->resolver, 0);
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, connecting to %s:%d\n", inet_ntoa(a), h->port);
+-
+- if ((h->fd = gg_connect(&a, h->port, h->async)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "=> http, connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- gg_http_error(GG_ERROR_CONNECTING);
+- }
+-
+- h->state = GG_STATE_CONNECTING;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+-
+- return 0;
+- }
+-
+- if (h->state == GG_STATE_CONNECTING) {
+- int res = 0;
+- socklen_t res_size = sizeof(res);
+-
+- if (h->async && (getsockopt(h->fd, SOL_SOCKET, SO_ERROR, &res, &res_size) || res)) {
+- gg_debug(GG_DEBUG_MISC, "=> http, async connection failed (errno=%d, %s)\n", (res) ? res : errno , strerror((res) ? res : errno));
+- close(h->fd);
+- h->fd = -1;
+- h->state = GG_STATE_ERROR;
+- h->error = GG_ERROR_CONNECTING;
+- if (res)
+- errno = res;
+- return 0;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, connected, sending request\n");
+-
+- h->state = GG_STATE_SENDING_QUERY;
+- }
+-
+- if (h->state == GG_STATE_SENDING_QUERY) {
+- size_t res;
+-
+- if ((res = write(h->fd, h->query, strlen(h->query))) < 1) {
+- gg_debug(GG_DEBUG_MISC, "=> http, write() failed (len=%d, res=%d, errno=%d)\n", strlen(h->query), res, errno);
+- gg_http_error(GG_ERROR_WRITING);
+- }
+-
+- if (res < strlen(h->query)) {
+- gg_debug(GG_DEBUG_MISC, "=> http, partial header sent (led=%d, sent=%d)\n", strlen(h->query), res);
+-
+- memmove(h->query, h->query + res, strlen(h->query) - res + 1);
+- h->state = GG_STATE_SENDING_QUERY;
+- h->check = GG_CHECK_WRITE;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- } else {
+- gg_debug(GG_DEBUG_MISC, "=> http, request sent (len=%d)\n", strlen(h->query));
+- free(h->query);
+- h->query = NULL;
+-
+- h->state = GG_STATE_READING_HEADER;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- }
+-
+- return 0;
+- }
+-
+- if (h->state == GG_STATE_READING_HEADER) {
+- char buf[1024], *tmp;
+- int res;
+-
+- if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
+- gg_debug(GG_DEBUG_MISC, "=> http, reading header failed (errno=%d)\n", errno);
+- if (h->header) {
+- free(h->header);
+- h->header = NULL;
+- }
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- if (!res) {
+- gg_debug(GG_DEBUG_MISC, "=> http, connection reset by peer\n");
+- if (h->header) {
+- free(h->header);
+- h->header = NULL;
+- }
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of header\n", res);
+-
+- if (!(tmp = realloc(h->header, h->header_size + res + 1))) {
+- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for header\n");
+- free(h->header);
+- h->header = NULL;
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- h->header = tmp;
+-
+- memcpy(h->header + h->header_size, buf, res);
+- h->header_size += res;
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, header_buf=%p, header_size=%d\n", h->header, h->header_size);
+-
+- h->header[h->header_size] = 0;
+-
+- if ((tmp = strstr(h->header, "\r\n\r\n")) || (tmp = strstr(h->header, "\n\n"))) {
+- int sep_len = (*tmp == '\r') ? 4 : 2;
+- unsigned int left;
+- char *line;
+-
+- left = h->header_size - ((long)(tmp) - (long)(h->header) + sep_len);
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, got all header (%d bytes, %d left)\n", h->header_size - left, left);
+-
+- /* HTTP/1.1 200 OK */
+- if (strlen(h->header) < 16 || strncmp(h->header + 9, "200", 3)) {
+- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header);
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, didn't get 200 OK -- no results\n");
+- free(h->header);
+- h->header = NULL;
+- gg_http_error(GG_ERROR_CONNECTING);
+- }
+-
+- h->body_size = 0;
+- line = h->header;
+- *tmp = 0;
+-
+- gg_debug(GG_DEBUG_MISC, "=> -----BEGIN-HTTP-HEADER-----\n%s\n=> -----END-HTTP-HEADER-----\n", h->header);
+-
+- while (line) {
+- if (!strncasecmp(line, "Content-length: ", 16)) {
+- h->body_size = atoi(line + 16);
+- }
+- line = strchr(line, '\n');
+- if (line)
+- line++;
+- }
+-
+- if (h->body_size <= 0) {
+- gg_debug(GG_DEBUG_MISC, "=> http, content-length not found\n");
+- h->body_size = left;
+- }
+-
+- if (left > h->body_size) {
+- gg_debug(GG_DEBUG_MISC, "=> http, oversized reply (%d bytes needed, %d bytes left)\n", h->body_size, left);
+- h->body_size = left;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, body_size=%d\n", h->body_size);
+-
+- if (!(h->body = malloc(h->body_size + 1))) {
+- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory (%d bytes for body_buf)\n", h->body_size + 1);
+- free(h->header);
+- h->header = NULL;
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- if (left) {
+- memcpy(h->body, tmp + sep_len, left);
+- h->body_done = left;
+- }
+-
+- h->body[left] = 0;
+-
+- h->state = GG_STATE_READING_DATA;
+- h->check = GG_CHECK_READ;
+- h->timeout = GG_DEFAULT_TIMEOUT;
+- }
+-
+- return 0;
+- }
+-
+- if (h->state == GG_STATE_READING_DATA) {
+- char buf[1024];
+- int res;
+-
+- if ((res = read(h->fd, buf, sizeof(buf))) == -1) {
+- gg_debug(GG_DEBUG_MISC, "=> http, reading body failed (errno=%d)\n", errno);
+- if (h->body) {
+- free(h->body);
+- h->body = NULL;
+- }
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- if (!res) {
+- if (h->body_done >= h->body_size) {
+- gg_debug(GG_DEBUG_MISC, "=> http, we're done, closing socket\n");
+- h->state = GG_STATE_PARSING;
+- close(h->fd);
+- h->fd = -1;
+- } else {
+- gg_debug(GG_DEBUG_MISC, "=> http, connection closed while reading (have %d, need %d)\n", h->body_done, h->body_size);
+- if (h->body) {
+- free(h->body);
+- h->body = NULL;
+- }
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- return 0;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, read %d bytes of body\n", res);
+-
+- if (h->body_done + res > h->body_size) {
+- char *tmp;
+-
+- gg_debug(GG_DEBUG_MISC, "=> http, too much data (%d bytes, %d needed), enlarging buffer\n", h->body_done + res, h->body_size);
+-
+- if (!(tmp = realloc(h->body, h->body_done + res + 1))) {
+- gg_debug(GG_DEBUG_MISC, "=> http, not enough memory for data (%d needed)\n", h->body_done + res + 1);
+- free(h->body);
+- h->body = NULL;
+- gg_http_error(GG_ERROR_READING);
+- }
+-
+- h->body = tmp;
+- h->body_size = h->body_done + res;
+- }
+-
+- h->body[h->body_done + res] = 0;
+- memcpy(h->body + h->body_done, buf, res);
+- h->body_done += res;
+-
+- gg_debug(GG_DEBUG_MISC, "=> body_done=%d, body_size=%d\n", h->body_done, h->body_size);
+-
+- return 0;
+- }
+-
+- if (h->fd != -1)
+- close(h->fd);
+-
+- h->fd = -1;
+- h->state = GG_STATE_ERROR;
+- h->error = 0;
+-
+- return -1;
+-}
+-
+-/**
+- * Kończy asynchroniczne połączenie HTTP.
+- *
+- * Po zatrzymaniu należy zwolnić zasoby funkcją \c gg_http_free().
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup http
+- */
+-void gg_http_stop(struct gg_http *h)
+-{
+- if (!h)
+- return;
+-
+- if (h->state == GG_STATE_ERROR || h->state == GG_STATE_DONE)
+- return;
+-
+- if (h->fd != -1) {
+- close(h->fd);
+- h->fd = -1;
+- }
+-
+- h->resolver_cleanup(&h->resolver, 1);
+-}
+-
+-/**
+- * \internal Zwalnia pola struktury \c gg_http.
+- *
+- * Funkcja zwalnia same pola, nie zwalnia struktury.
+- *
+- * \param h Struktura połączenia
+- */
+-void gg_http_free_fields(struct gg_http *h)
+-{
+- if (!h)
+- return;
+-
+- if (h->body) {
+- free(h->body);
+- h->body = NULL;
+- }
+-
+- if (h->query) {
+- free(h->query);
+- h->query = NULL;
+- }
+-
+- if (h->header) {
+- free(h->header);
+- h->header = NULL;
+- }
+-}
+-
+-/**
+- * Zwalnia zasoby po połączeniu HTTP.
+- *
+- * Jeśli połączenie nie zostało jeszcze zakończone, jest przerywane.
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup http
+- */
+-void gg_http_free(struct gg_http *h)
+-{
+- if (!h)
+- return;
+-
+- gg_http_stop(h);
+- gg_http_free_fields(h);
+- free(h);
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2320 +0,0 @@
+-/* $Id: libgadu.c 1102 2011-05-05 21:17:57Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file libgadu.c
+- *
+- * \brief Główny moduł biblioteki
+- */
+-
+-#include <sys/types.h>
+-#ifdef _WIN32
+-# include <io.h>
+-# include <fcntl.h>
+-# include <errno.h>
+-# define SHUT_RDWR SD_BOTH
+-#else
+-# include <sys/socket.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-# ifdef sun
+-# include <sys/filio.h>
+-# endif
+-#endif
+-
+-#include "compat.h"
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-#include "protocol.h"
+-#include "resolver.h"
+-#include "libgadu-internal.h"
+-#include "encoding.h"
+-#include "libgadu-debug.h"
+-#include "session.h"
+-#include "message.h"
+-#include "deflate.h"
+-
+-#ifndef _WIN32
+-# include <errno.h> /* on Win32 this is included above */
+-# include <netdb.h>
+-#endif
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <signal.h>
+-#include <time.h>
+-#include <unistd.h>
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+-# include <gnutls/gnutls.h>
+-#endif
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-# include <openssl/err.h>
+-# include <openssl/rand.h>
+-#endif
+-
+-#define GG_LIBGADU_VERSION "1.11.0"
+-
+-/**
+- * Port gniazda nasłuchującego dla połączeń bezpośrednich.
+- *
+- * \ingroup ip
+- */
+-int gg_dcc_port = 0;
+-
+-/**
+- * Adres IP gniazda nasłuchującego dla połączeń bezpośrednich.
+- *
+- * \ingroup ip
+- */
+-unsigned long gg_dcc_ip = 0;
+-
+-/**
+- * Adres lokalnego interfejsu IP, z którego wywoływane są wszystkie połączenia.
+- *
+- * \ingroup ip
+- */
+-unsigned long gg_local_ip = 0;
+-
+-/**
+- * Flaga włączenia połączeń przez serwer pośredniczący.
+- *
+- * \ingroup proxy
+- */
+-int gg_proxy_enabled = 0;
+-
+-/**
+- * Adres serwera pośredniczącego.
+- *
+- * \ingroup proxy
+- */
+-char *gg_proxy_host = NULL;
+-
+-/**
+- * Port serwera pośredniczącego.
+- *
+- * \ingroup proxy
+- */
+-int gg_proxy_port = 0;
+-
+-/**
+- * Flaga używania serwera pośredniczącego jedynie dla usług HTTP.
+- *
+- * \ingroup proxy
+- */
+-int gg_proxy_http_only = 0;
+-
+-/**
+- * Nazwa użytkownika do autoryzacji serwera pośredniczącego.
+- *
+- * \ingroup proxy
+- */
+-char *gg_proxy_username = NULL;
+-
+-/**
+- * Hasło użytkownika do autoryzacji serwera pośredniczącego.
+- *
+- * \ingroup proxy
+- */
+-char *gg_proxy_password = NULL;
+-
+-#ifndef DOXYGEN
+-
+-#ifndef lint
+-static char rcsid[]
+-#ifdef __GNUC__
+-__attribute__ ((unused))
+-#endif
+-= "$Id: libgadu.c 1102 2011-05-05 21:17:57Z wojtekka $";
+-#endif
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Zwraca wersję biblioteki.
+- *
+- * \return Wskaźnik na statyczny bufor z wersją biblioteki.
+- *
+- * \ingroup version
+- */
+-const char *gg_libgadu_version()
+-{
+- return GG_LIBGADU_VERSION;
+-}
+-
+-#ifdef GG_CONFIG_HAVE_UINT64_T
+-/**
+- * \internal Zamienia kolejność bajtów w 64-bitowym słowie.
+- *
+- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
+- * big-endianowych odwraca kolejność bajtów w słowie.
+- *
+- * \param x Liczba do zamiany
+- *
+- * \return Liczba z odpowiednią kolejnością bajtów
+- *
+- * \ingroup helper
+- */
+-uint64_t gg_fix64(uint64_t x)
+-{
+-#ifndef GG_CONFIG_BIGENDIAN
+- return x;
+-#else
+- return (uint64_t)
+- (((x & (uint64_t) 0x00000000000000ffULL) << 56) |
+- ((x & (uint64_t) 0x000000000000ff00ULL) << 40) |
+- ((x & (uint64_t) 0x0000000000ff0000ULL) << 24) |
+- ((x & (uint64_t) 0x00000000ff000000ULL) << 8) |
+- ((x & (uint64_t) 0x000000ff00000000ULL) >> 8) |
+- ((x & (uint64_t) 0x0000ff0000000000ULL) >> 24) |
+- ((x & (uint64_t) 0x00ff000000000000ULL) >> 40) |
+- ((x & (uint64_t) 0xff00000000000000ULL) >> 56));
+-#endif
+-}
+-#endif /* GG_CONFIG_HAVE_UINT64_T */
+-
+-/**
+- * \internal Zamienia kolejność bajtów w 32-bitowym słowie.
+- *
+- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
+- * big-endianowych odwraca kolejność bajtów w słowie.
+- *
+- * \param x Liczba do zamiany
+- *
+- * \return Liczba z odpowiednią kolejnością bajtów
+- *
+- * \ingroup helper
+- */
+-uint32_t gg_fix32(uint32_t x)
+-{
+-#ifndef GG_CONFIG_BIGENDIAN
+- return x;
+-#else
+- return (uint32_t)
+- (((x & (uint32_t) 0x000000ffU) << 24) |
+- ((x & (uint32_t) 0x0000ff00U) << 8) |
+- ((x & (uint32_t) 0x00ff0000U) >> 8) |
+- ((x & (uint32_t) 0xff000000U) >> 24));
+-#endif
+-}
+-
+-/**
+- * \internal Zamienia kolejność bajtów w 16-bitowym słowie.
+- *
+- * Ze względu na little-endianowość protokołu Gadu-Gadu, na maszynach
+- * big-endianowych zamienia kolejność bajtów w słowie.
+- *
+- * \param x Liczba do zamiany
+- *
+- * \return Liczba z odpowiednią kolejnością bajtów
+- *
+- * \ingroup helper
+- */
+-uint16_t gg_fix16(uint16_t x)
+-{
+-#ifndef GG_CONFIG_BIGENDIAN
+- return x;
+-#else
+- return (uint16_t)
+- (((x & (uint16_t) 0x00ffU) << 8) |
+- ((x & (uint16_t) 0xff00U) >> 8));
+-#endif
+-}
+-
+-/**
+- * \internal Liczy skrót z hasła i ziarna.
+- *
+- * \param password Hasło
+- * \param seed Ziarno podane przez serwer
+- *
+- * \return Wartość skrótu
+- */
+-unsigned int gg_login_hash(const unsigned char *password, unsigned int seed)
+-{
+- unsigned int x, y, z;
+-
+- y = seed;
+-
+- for (x = 0; *password; password++) {
+- x = (x & 0xffffff00) | *password;
+- y ^= x;
+- y += x;
+- x <<= 8;
+- y ^= x;
+- x <<= 8;
+- y -= x;
+- x <<= 8;
+- y ^= x;
+-
+- z = y & 0x1F;
+- y = (y << z) | (y >> (32 - z));
+- }
+-
+- return y;
+-}
+-
+-/**
+- * \internal Odbiera od serwera dane binarne.
+- *
+- * Funkcja odbiera dane od serwera zajmując się SSL/TLS w razie konieczności.
+- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
+- * wywołaniami systemowymi.
+- *
+- * \param sess Struktura sesji
+- * \param buf Bufor na danymi
+- * \param length Długość bufora
+- *
+- * \return To samo co funkcja systemowa \c read
+- */
+-int gg_read(struct gg_session *sess, char *buf, int length)
+-{
+- int res;
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- if (sess->ssl != NULL) {
+- for (;;) {
+- res = gnutls_record_recv(GG_SESSION_GNUTLS(sess), buf, length);
+-
+- if (res < 0) {
+- if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
+- continue;
+-
+- if (res == GNUTLS_E_AGAIN)
+- errno = EAGAIN;
+- else
+- errno = EINVAL;
+-
+- return -1;
+- }
+-
+- return res;
+- }
+- }
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- if (sess->ssl != NULL) {
+- for (;;) {
+- int err;
+-
+- res = SSL_read(sess->ssl, buf, length);
+-
+- if (res < 0) {
+- err = SSL_get_error(sess->ssl, res);
+-
+- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
+- continue;
+-
+- if (err == SSL_ERROR_WANT_READ)
+- errno = EAGAIN;
+- else if (err != SSL_ERROR_SYSCALL)
+- errno = EINVAL;
+-
+- return -1;
+- }
+-
+- return res;
+- }
+- }
+-#endif
+-
+- for (;;) {
+- res = read(sess->fd, buf, length);
+-
+- if (res == -1 && errno == EINTR)
+- continue;
+-
+- return res;
+- }
+-}
+-
+-/**
+- * \internal Wysyła do serwera dane binarne.
+- *
+- * Funkcja wysyła dane do serwera zajmując się SSL/TLS w razie konieczności.
+- * Obsługuje EINTR, więc użytkownik nie musi się przejmować przerwanymi
+- * wywołaniami systemowymi.
+- *
+- * \note Funkcja nie zajmuje się buforowaniem wysyłanych danych (patrz
+- * gg_write()).
+- *
+- * \param sess Struktura sesji
+- * \param buf Bufor z danymi
+- * \param length Długość bufora
+- *
+- * \return To samo co funkcja systemowa \c write
+- */
+-static int gg_write_common(struct gg_session *sess, const char *buf, int length)
+-{
+- int res;
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- if (sess->ssl != NULL) {
+- for (;;) {
+- res = gnutls_record_send(GG_SESSION_GNUTLS(sess), buf, length);
+-
+- if (res < 0) {
+- if (!gnutls_error_is_fatal(res) || res == GNUTLS_E_INTERRUPTED)
+- continue;
+-
+- if (res == GNUTLS_E_AGAIN)
+- errno = EAGAIN;
+- else
+- errno = EINVAL;
+-
+- return -1;
+- }
+-
+- return res;
+- }
+- }
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- if (sess->ssl != NULL) {
+- for (;;) {
+- int err;
+-
+- res = SSL_write(sess->ssl, buf, length);
+-
+- if (res < 0) {
+- err = SSL_get_error(sess->ssl, res);
+-
+- if (err == SSL_ERROR_SYSCALL && errno == EINTR)
+- continue;
+-
+- if (err == SSL_ERROR_WANT_WRITE)
+- errno = EAGAIN;
+- else if (err != SSL_ERROR_SYSCALL)
+- errno = EINVAL;
+-
+- return -1;
+- }
+-
+- return res;
+- }
+- }
+-#endif
+-
+- for (;;) {
+- res = write(sess->fd, buf, length);
+-
+- if (res == -1 && errno == EINTR)
+- continue;
+-
+- return res;
+- }
+-}
+-
+-
+-
+-/**
+- * \internal Wysyła do serwera dane binarne.
+- *
+- * Funkcja wysyła dane do serwera zajmując się TLS w razie konieczności.
+- *
+- * \param sess Struktura sesji
+- * \param buf Bufor z danymi
+- * \param length Długość bufora
+- *
+- * \return To samo co funkcja systemowa \c write
+- */
+-int gg_write(struct gg_session *sess, const char *buf, int length)
+-{
+- int res = 0;
+-
+- if (!sess->async) {
+- int written = 0;
+-
+- while (written < length) {
+- res = gg_write_common(sess, buf + written, length - written);
+-
+- if (res == -1)
+- return -1;
+-
+- written += res;
+- res = written;
+- }
+- } else {
+- res = 0;
+-
+- if (sess->send_buf == NULL) {
+- res = gg_write_common(sess, buf, length);
+-
+- if (res == -1)
+- return -1;
+- }
+-
+- if (res < length) {
+- char *tmp;
+-
+- if (!(tmp = realloc(sess->send_buf, sess->send_left + length - res))) {
+- errno = ENOMEM;
+- return -1;
+- }
+-
+- sess->send_buf = tmp;
+-
+- memcpy(sess->send_buf + sess->send_left, buf + res, length - res);
+-
+- sess->send_left += length - res;
+- }
+- }
+-
+- return res;
+-}
+-
+-/**
+- * \internal Odbiera pakiet od serwera.
+- *
+- * Funkcja odczytuje nagłówek pakietu, a następnie jego zawartość i zwraca
+- * w zaalokowanym buforze.
+- *
+- * Przy połączeniach asynchronicznych, funkcja może nie być w stanie
+- * skompletować całego pakietu -- w takim przypadku zwróci -1, a kodem błędu
+- * będzie \c EAGAIN.
+- *
+- * \param sess Struktura sesji
+- *
+- * \return Wskaźnik do zaalokowanego bufora
+- */
+-void *gg_recv_packet(struct gg_session *sess)
+-{
+- struct gg_header h;
+- char *packet;
+- int ret = 0;
+- unsigned int offset, size = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_recv_packet(%p);\n", sess);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- if (sess->recv_left < 1) {
+- if (sess->header_buf) {
+- memcpy(&h, sess->header_buf, sess->header_done);
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv: resuming last read (%d bytes left)\n", sizeof(h) - sess->header_done);
+- free(sess->header_buf);
+- sess->header_buf = NULL;
+- } else
+- sess->header_done = 0;
+-
+- while (sess->header_done < sizeof(h)) {
+- ret = gg_read(sess, (char*) &h + sess->header_done, sizeof(h) - sess->header_done);
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv(%d,%p,%d) = %d\n", sess->fd, (char*)&h + sess->header_done, sizeof(h) - sess->header_done, ret);
+-
+- if (!ret) {
+- errno = ECONNRESET;
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: connection broken\n");
+- return NULL;
+- }
+-
+- if (ret == -1) {
+- if (errno == EAGAIN) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() incomplete header received\n");
+-
+- if (!(sess->header_buf = malloc(sess->header_done))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() not enough memory\n");
+- return NULL;
+- }
+-
+- memcpy(sess->header_buf, &h, sess->header_done);
+-
+- errno = EAGAIN;
+-
+- return NULL;
+- }
+-
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() header recv() failed: errno=%d, %s\n", errno, strerror(errno));
+-
+- return NULL;
+- }
+-
+- sess->header_done += ret;
+- }
+-
+- h.type = gg_fix32(h.type);
+- h.length = gg_fix32(h.length);
+- } else
+- memcpy(&h, sess->recv_buf, sizeof(h));
+-
+- /* jakieś sensowne limity na rozmiar pakietu */
+- if (h.length > 65535) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() invalid packet length (%d)\n", h.length);
+- errno = ERANGE;
+- return NULL;
+- }
+-
+- if (sess->recv_left > 0) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() resuming last gg_recv_packet()\n");
+- size = sess->recv_left;
+- offset = sess->recv_done;
+- } else {
+- if (!(sess->recv_buf = malloc(sizeof(h) + h.length + 1))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() not enough memory for packet data\n");
+- return NULL;
+- }
+-
+- memcpy(sess->recv_buf, &h, sizeof(h));
+-
+- offset = 0;
+- size = h.length;
+- }
+-
+- while (size > 0) {
+- ret = gg_read(sess, sess->recv_buf + sizeof(h) + offset, size);
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv(%d,%p,%d) = %d\n", sess->fd, sess->recv_buf + sizeof(h) + offset, size, ret);
+- if (!ret) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed: connection broken\n");
+- errno = ECONNRESET;
+- goto fail;
+- }
+- if (ret > -1 && ret <= size) {
+- offset += ret;
+- size -= ret;
+- } else if (ret == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() body recv() failed (errno=%d, %s)\n", errno, strerror(errno));
+-
+- if (errno == EAGAIN) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_recv_packet() %d bytes received, %d left\n", offset, size);
+- sess->recv_left = size;
+- sess->recv_done = offset;
+- return NULL;
+- }
+-
+- goto fail;
+- }
+- }
+-
+- packet = sess->recv_buf;
+- sess->recv_buf = NULL;
+- sess->recv_left = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_recv_packet(type=0x%.2x, length=%d)\n", h.type, h.length);
+- gg_debug_dump(sess, GG_DEBUG_DUMP, packet, sizeof(h) + h.length);
+-
+- return packet;
+-
+-fail:
+- free(sess->recv_buf);
+- sess->recv_buf = NULL;
+- sess->recv_left = 0;
+-
+- return NULL;
+-}
+-
+-/**
+- * \internal Wysyła pakiet do serwera.
+- *
+- * Funkcja konstruuje pakiet do wysłania z dowolnej liczby fragmentów. Jeśli
+- * rozmiar pakietu jest za duży, by móc go wysłać za jednym razem, pozostała
+- * część zostanie zakolejkowana i wysłana, gdy będzie to możliwe.
+- *
+- * \param sess Struktura sesji
+- * \param type Rodzaj pakietu
+- * \param ... Lista kolejnych części pakietu (wskaźnik na bufor i długość
+- * typu \c int) zakończona \c NULL
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_send_packet(struct gg_session *sess, int type, ...)
+-{
+- struct gg_header *h;
+- char *tmp;
+- unsigned int tmp_length;
+- void *payload;
+- unsigned int payload_length;
+- va_list ap;
+- int res;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_packet(%p, 0x%.2x, ...);\n", sess, type);
+-
+- tmp_length = sizeof(struct gg_header);
+-
+- if (!(tmp = malloc(tmp_length))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for packet header\n");
+- return -1;
+- }
+-
+- va_start(ap, type);
+-
+- payload = va_arg(ap, void *);
+-
+- while (payload) {
+- char *tmp2;
+-
+- payload_length = va_arg(ap, unsigned int);
+-
+- if (!(tmp2 = realloc(tmp, tmp_length + payload_length))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() not enough memory for payload\n");
+- free(tmp);
+- va_end(ap);
+- return -1;
+- }
+-
+- tmp = tmp2;
+-
+- memcpy(tmp + tmp_length, payload, payload_length);
+- tmp_length += payload_length;
+-
+- payload = va_arg(ap, void *);
+- }
+-
+- va_end(ap);
+-
+- h = (struct gg_header*) tmp;
+- h->type = gg_fix32(type);
+- h->length = gg_fix32(tmp_length - sizeof(struct gg_header));
+-
+- gg_debug_session(sess, GG_DEBUG_DUMP, "// gg_send_packet(type=0x%.2x, length=%d)\n", gg_fix32(h->type), gg_fix32(h->length));
+- gg_debug_dump(sess, GG_DEBUG_DUMP, tmp, tmp_length);
+-
+- res = gg_write(sess, tmp, tmp_length);
+-
+- free(tmp);
+-
+- if (res == -1) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() write() failed. res = %d, errno = %d (%s)\n", res, errno, strerror(errno));
+- return -1;
+- }
+-
+- if (sess->async)
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_send_packet() partial write(), %d sent, %d left, %d total left\n", res, tmp_length - res, sess->send_left);
+-
+- if (sess->send_buf)
+- sess->check |= GG_CHECK_WRITE;
+-
+- return 0;
+-}
+-
+-/**
+- * \internal Funkcja zwrotna sesji.
+- *
+- * Pole \c callback struktury \c gg_session zawiera wskaźnik do tej funkcji.
+- * Wywołuje ona \c gg_watch_fd i zachowuje wynik w polu \c event.
+- *
+- * \note Korzystanie z tej funkcjonalności nie jest już zalecane.
+- *
+- * \param sess Struktura sesji
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_session_callback(struct gg_session *sess)
+-{
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- return ((sess->event = gg_watch_fd(sess)) != NULL) ? 0 : -1;
+-}
+-
+-/**
+- * Łączy się z serwerem Gadu-Gadu.
+- *
+- * Przy połączeniu synchronicznym funkcja zakończy działanie po nawiązaniu
+- * połączenia lub gdy wystąpi błąd. Po udanym połączeniu należy wywoływać
+- * funkcję \c gg_watch_fd(), która odbiera informacje od serwera i zwraca
+- * informacje o zdarzeniach.
+- *
+- * Przy połączeniu asynchronicznym funkcja rozpocznie procedurę połączenia
+- * i zwróci zaalokowaną strukturę. Pole \c fd struktury \c gg_session zawiera
+- * deskryptor, który należy obserwować funkcją \c select, \c poll lub za
+- * pomocą mechanizmów użytej pętli zdarzeń (Glib, Qt itp.). Pole \c check
+- * jest maską bitową mówiącą, czy biblioteka chce być informowana o możliwości
+- * odczytu danych (\c GG_CHECK_READ) czy zapisu danych (\c GG_CHECK_WRITE).
+- * Po zaobserwowaniu zmian na deskryptorze należy wywołać funkcję
+- * \c gg_watch_fd(). Podczas korzystania z połączeń asynchronicznych, w trakcie
+- * połączenia może zostać stworzony dodatkowy proces rozwiązujący nazwę
+- * serwera -- z tego powodu program musi poprawnie obsłużyć sygnał SIGCHLD.
+- *
+- * \note Po nawiązaniu połączenia z serwerem należy wysłać listę kontaktów
+- * za pomocą funkcji \c gg_notify() lub \c gg_notify_ex().
+- *
+- * \note Funkcja zwróci błąd ENOSYS jeśli połączenie SSL było wymagane, ale
+- * obsługa SSL nie jest wkompilowana.
+- *
+- * \param p Struktura opisująca parametry połączenia. Wymagane pola: uin,
+- * password, async.
+- *
+- * \return Wskaźnik do zaalokowanej struktury sesji \c gg_session lub NULL
+- * w przypadku błędu.
+- *
+- * \ingroup login
+- */
+-struct gg_session *gg_login(const struct gg_login_params *p)
+-{
+- struct gg_session *sess = NULL;
+- char *hostname;
+- int port;
+-
+- if (!p) {
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p);\n", p);
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_login(%p: [uin=%u, async=%d, ...]);\n", p, p->uin, p->async);
+-
+- if (!(sess = malloc(sizeof(struct gg_session)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for session data\n");
+- goto fail;
+- }
+-
+- memset(sess, 0, sizeof(struct gg_session));
+-
+- if (!p->password || !p->uin) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. uin and password needed\n");
+- errno = EFAULT;
+- goto fail;
+- }
+-
+- if (!(sess->password = strdup(p->password))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for password\n");
+- goto fail;
+- }
+-
+- if (p->hash_type < 0 || p->hash_type > GG_LOGIN_HASH_SHA1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unknown hash type (%d)\n", p->hash_type);
+- errno = EFAULT;
+- goto fail;
+- }
+-
+- sess->uin = p->uin;
+- sess->state = GG_STATE_RESOLVING;
+- sess->check = GG_CHECK_READ;
+- sess->timeout = GG_DEFAULT_TIMEOUT;
+- sess->async = p->async;
+- sess->type = GG_SESSION_GG;
+- sess->initial_status = p->status;
+- sess->callback = gg_session_callback;
+- sess->destroy = gg_free_session;
+- sess->port = (p->server_port) ? p->server_port : ((gg_proxy_enabled) ? GG_HTTPS_PORT : GG_DEFAULT_PORT);
+- sess->server_addr = p->server_addr;
+- sess->external_port = p->external_port;
+- sess->external_addr = p->external_addr;
+- sess->client_addr = p->client_addr;
+- sess->client_port = p->client_port;
+-
+- if (p->protocol_features == 0) {
+- sess->protocol_features = GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION;
+- } else {
+- sess->protocol_features = (p->protocol_features & ~(GG_FEATURE_STATUS77 | GG_FEATURE_MSG77));
+-
+- if (!(p->protocol_features & GG_FEATURE_STATUS77))
+- sess->protocol_features |= GG_FEATURE_STATUS80;
+-
+- if (!(p->protocol_features & GG_FEATURE_MSG77))
+- sess->protocol_features |= GG_FEATURE_MSG80;
+- }
+-
+- if (!(sess->status_flags = p->status_flags))
+- sess->status_flags = GG_STATUS_FLAG_UNKNOWN | GG_STATUS_FLAG_SPAM;
+-
+- sess->protocol_version = (p->protocol_version) ? p->protocol_version : GG_DEFAULT_PROTOCOL_VERSION;
+-
+- if (p->era_omnix)
+- sess->protocol_flags |= GG_ERA_OMNIX_MASK;
+- if (p->has_audio)
+- sess->protocol_flags |= GG_HAS_AUDIO_MASK;
+- sess->client_version = (p->client_version) ? strdup(p->client_version) : NULL;
+- sess->last_sysmsg = p->last_sysmsg;
+- sess->image_size = p->image_size;
+- sess->pid = -1;
+- sess->encoding = p->encoding;
+-
+- if (gg_session_set_resolver(sess, p->resolver) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() invalid arguments. unsupported resolver type (%d)\n", p->resolver);
+- errno = EFAULT;
+- goto fail;
+- }
+-
+- if (p->status_descr) {
+- int max_length;
+-
+- if (sess->protocol_version >= 0x2d)
+- max_length = GG_STATUS_DESCR_MAXSIZE;
+- else
+- max_length = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
+-
+- if (sess->protocol_version >= 0x2d)
+- sess->initial_descr = gg_encoding_convert(p->status_descr, p->encoding, GG_ENCODING_UTF8, -1, -1);
+- else
+- sess->initial_descr = strdup(p->status_descr);
+-
+- if (!sess->initial_descr) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() not enough memory for status\n");
+- goto fail;
+- }
+-
+- // XXX pamiętać, żeby nie ciąć w środku znaku utf-8
+-
+- if (strlen(sess->initial_descr) > max_length)
+- sess->initial_descr[max_length] = 0;
+- }
+-
+- if (p->tls != GG_SSL_DISABLED) {
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- gg_session_gnutls_t *tmp;
+-
+- tmp = malloc(sizeof(gg_session_gnutls_t));
+-
+- if (tmp == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() out of memory for GnuTLS session\n");
+- goto fail;
+- }
+-
+- sess->ssl = tmp;
+-
+- gnutls_global_init();
+- gnutls_certificate_allocate_credentials(&tmp->xcred);
+- gnutls_init(&tmp->session, GNUTLS_CLIENT);
+- gnutls_set_default_priority(tmp->session);
+- gnutls_credentials_set(tmp->session, GNUTLS_CRD_CERTIFICATE, tmp->xcred);
+-#elif defined(GG_CONFIG_HAVE_OPENSSL)
+- char buf[1024];
+-
+- OpenSSL_add_ssl_algorithms();
+-
+- if (!RAND_status()) {
+- char rdata[1024];
+- struct {
+- time_t time;
+- void *ptr;
+- } rstruct;
+-
+- time(&rstruct.time);
+- rstruct.ptr = (void *) &rstruct;
+-
+- RAND_seed((void *) rdata, sizeof(rdata));
+- RAND_seed((void *) &rstruct, sizeof(rstruct));
+- }
+-
+- sess->ssl_ctx = SSL_CTX_new(SSLv3_client_method());
+-
+- if (!sess->ssl_ctx) {
+- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
+- gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_CTX_new() failed: %s\n", buf);
+- goto fail;
+- }
+-
+- SSL_CTX_set_verify(sess->ssl_ctx, SSL_VERIFY_NONE, NULL);
+-
+- sess->ssl = SSL_new(sess->ssl_ctx);
+-
+- if (!sess->ssl) {
+- ERR_error_string_n(ERR_get_error(), buf, sizeof(buf));
+- gg_debug(GG_DEBUG_MISC, "// gg_login() SSL_new() failed: %s\n", buf);
+- goto fail;
+- }
+-#else
+- gg_debug(GG_DEBUG_MISC, "// gg_login() client requested TLS but no support compiled in\n");
+-
+- if (p->tls == GG_SSL_REQUIRED) {
+- errno = ENOSYS;
+- goto fail;
+- }
+-#endif
+- }
+-
+- if (gg_proxy_enabled) {
+- hostname = gg_proxy_host;
+- sess->proxy_port = port = gg_proxy_port;
+- } else {
+- hostname = GG_APPMSG_HOST;
+- port = GG_APPMSG_PORT;
+- }
+-
+- if (p->hash_type)
+- sess->hash_type = p->hash_type;
+- else
+- sess->hash_type = GG_LOGIN_HASH_SHA1;
+-
+- if (!p->async) {
+- struct in_addr addr;
+-
+- if (!sess->server_addr) {
+- if ((addr.s_addr = inet_addr(hostname)) == INADDR_NONE) {
+- struct in_addr *addr_list = NULL;
+- int addr_count;
+-
+- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 0) == -1 || addr_count == 0) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() host \"%s\" not found\n", hostname);
+- free(addr_list);
+- goto fail;
+- }
+-
+- addr = addr_list[0];
+-
+- free(addr_list);
+- }
+- } else {
+- addr.s_addr = sess->server_addr;
+- port = sess->port;
+- }
+-
+- sess->hub_addr = addr.s_addr;
+-
+- if (gg_proxy_enabled)
+- sess->proxy_addr = addr.s_addr;
+-
+- if ((sess->fd = gg_connect(&addr, port, 0)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+-
+- /* nie wyszło? próbujemy portu 443. */
+- if (sess->server_addr) {
+- sess->port = GG_HTTPS_PORT;
+-
+- if ((sess->fd = gg_connect(&addr, GG_HTTPS_PORT, 0)) == -1) {
+- /* ostatnia deska ratunku zawiodła?
+- * w takim razie zwijamy manatki. */
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_login() connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- goto fail;
+- }
+- } else {
+- goto fail;
+- }
+- }
+-
+- if (sess->server_addr)
+- sess->state = GG_STATE_CONNECTING_GG;
+- else
+- sess->state = GG_STATE_CONNECTING_HUB;
+-
+- while (sess->state != GG_STATE_CONNECTED) {
+- struct gg_event *e;
+-
+- if (!(e = gg_watch_fd(sess))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() critical error in gg_watch_fd()\n");
+- goto fail;
+- }
+-
+- if (e->type == GG_EVENT_CONN_FAILED) {
+- errno = EACCES;
+- gg_debug(GG_DEBUG_MISC, "// gg_login() could not login\n");
+- gg_event_free(e);
+- goto fail;
+- }
+-
+- gg_event_free(e);
+- }
+-
+- return sess;
+- }
+-
+- if (!sess->server_addr || gg_proxy_enabled) {
+- if (sess->resolver_start(&sess->fd, &sess->resolver, hostname) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() resolving failed (errno=%d, %s)\n", errno, strerror(errno));
+- goto fail;
+- }
+- } else {
+- if ((sess->fd = gg_connect(&sess->server_addr, sess->port, sess->async)) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_login() direct connection failed (errno=%d, %s)\n", errno, strerror(errno));
+- goto fail;
+- }
+- sess->state = GG_STATE_CONNECTING_GG;
+- sess->check = GG_CHECK_WRITE;
+- sess->soft_timeout = 1;
+- }
+-
+- return sess;
+-
+-fail:
+- if (sess) {
+- free(sess->password);
+- free(sess->initial_descr);
+- free(sess);
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Wysyła do serwera pakiet utrzymania połączenia.
+- *
+- * Klient powinien regularnie co minutę wysyłać pakiet utrzymania połączenia,
+- * inaczej serwer uzna, że klient stracił łączność z siecią i zerwie
+- * połączenie.
+- *
+- * \param sess Struktura sesji
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup login
+- */
+-int gg_ping(struct gg_session *sess)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_ping(%p);\n", sess);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- return gg_send_packet(sess, GG_PING, NULL);
+-}
+-
+-/**
+- * Kończy połączenie z serwerem.
+- *
+- * Funkcja nie zwalnia zasobów, więc po jej wywołaniu należy użyć
+- * \c gg_free_session(). Jeśli chce się ustawić opis niedostępności, należy
+- * wcześniej wywołać funkcję \c gg_change_status_descr() lub
+- * \c gg_change_status_descr_time().
+- *
+- * \note Jeśli w buforze nadawczym połączenia z serwerem znajdują się jeszcze
+- * dane (np. z powodu strat pakietów na łączu), prawdopodobnie zostaną one
+- * utracone przy zrywaniu połączenia. Aby mieć pewność, że opis statusu
+- * zostanie zachowany, należy ustawić stan \c GG_STATUS_NOT_AVAIL_DESCR
+- * za pomocą funkcji \c gg_change_status_descr() i poczekać na zdarzenie
+- * \c GG_EVENT_DISCONNECT_ACK.
+- *
+- * \param sess Struktura sesji
+- *
+- * \ingroup login
+- */
+-void gg_logoff(struct gg_session *sess)
+-{
+- if (!sess)
+- return;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_logoff(%p);\n", sess);
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- if (sess->ssl != NULL)
+- gnutls_bye(GG_SESSION_GNUTLS(sess), GNUTLS_SHUT_RDWR);
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- if (sess->ssl != NULL)
+- SSL_shutdown(sess->ssl);
+-#endif
+-
+- sess->resolver_cleanup(&sess->resolver, 1);
+-
+- if (sess->fd != -1) {
+- shutdown(sess->fd, SHUT_RDWR);
+- close(sess->fd);
+- sess->fd = -1;
+- }
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+- if (sess->ssl != NULL) {
+- gg_session_gnutls_t *tmp;
+-
+- tmp = (gg_session_gnutls_t*) sess->ssl;
+- gnutls_deinit(tmp->session);
+- gnutls_certificate_free_credentials(tmp->xcred);
+- gnutls_global_deinit();
+- free(sess->ssl);
+- }
+-#endif
+-
+- if (sess->send_buf) {
+- free(sess->send_buf);
+- sess->send_buf = NULL;
+- sess->send_left = 0;
+- }
+-}
+-
+-/**
+- * Zwalnia zasoby używane przez połączenie z serwerem. Funkcję należy wywołać
+- * po zamknięciu połączenia z serwerem, by nie doprowadzić do wycieku zasobów
+- * systemowych.
+- *
+- * \param sess Struktura sesji
+- *
+- * \ingroup login
+- */
+-void gg_free_session(struct gg_session *sess)
+-{
+- struct gg_dcc7 *dcc;
+-
+- if (!sess)
+- return;
+-
+- /* XXX dopisać zwalnianie i zamykanie wszystkiego, co mogło zostać */
+-
+- free(sess->password);
+- free(sess->initial_descr);
+- free(sess->client_version);
+- free(sess->recv_buf);
+- free(sess->header_buf);
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- if (sess->ssl)
+- SSL_free(sess->ssl);
+-
+- if (sess->ssl_ctx)
+- SSL_CTX_free(sess->ssl_ctx);
+-#endif
+-
+- sess->resolver_cleanup(&sess->resolver, 1);
+-
+- if (sess->fd != -1)
+- close(sess->fd);
+-
+- while (sess->images)
+- gg_image_queue_remove(sess, sess->images, 1);
+-
+- free(sess->send_buf);
+-
+- for (dcc = sess->dcc7_list; dcc; dcc = dcc->next)
+- dcc->sess = NULL;
+-
+- free(sess);
+-}
+-
+-#ifndef DOXYGEN
+-
+-/**
+- * \internal Funkcja wysyłająca pakiet zmiany statusu użytkownika.
+- *
+- * \param sess Struktura sesji
+- * \param status Nowy status użytkownika
+- * \param descr Opis statusu użytkownika (lub \c NULL)
+- * \param time Czas powrotu w postaci uniksowego znacznika czasu (lub 0)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup status
+- */
+-static int gg_change_status_common(struct gg_session *sess, int status, const char *descr, int time)
+-{
+- char *new_descr = NULL;
+- uint32_t new_time;
+- int descr_len = 0;
+- int descr_len_max;
+- int packet_type;
+- int append_null = 0;
+- int res;
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- /* XXX, obcinać stany których stary protokół niezna (czyt. dnd->aw; ffc->av) */
+-
+- /* dodaj flagę obsługi połączeń głosowych zgodną z GG 7.x */
+- if ((sess->protocol_version >= 0x2a) && (sess->protocol_version < 0x2d /* ? */ ) && (sess->protocol_flags & GG_HAS_AUDIO_MASK) && !GG_S_I(status))
+- status |= GG_STATUS_VOICE_MASK;
+-
+- sess->status = status;
+-
+- if (sess->protocol_version >= 0x2d) {
+- if (descr != NULL && sess->encoding != GG_ENCODING_UTF8) {
+- new_descr = gg_encoding_convert(descr, GG_ENCODING_CP1250, GG_ENCODING_UTF8, -1, -1);
+-
+- if (!new_descr)
+- return -1;
+- }
+-
+- if (sess->protocol_version >= 0x2e)
+- packet_type = GG_NEW_STATUS80;
+- else /* sess->protocol_version == 0x2d */
+- packet_type = GG_NEW_STATUS80BETA;
+- descr_len_max = GG_STATUS_DESCR_MAXSIZE;
+- append_null = 1;
+-
+- } else {
+- packet_type = GG_NEW_STATUS;
+- descr_len_max = GG_STATUS_DESCR_MAXSIZE_PRE_8_0;
+-
+- if (time != 0)
+- append_null = 1;
+- }
+-
+- if (descr) {
+- descr_len = strlen((new_descr) ? new_descr : descr);
+-
+- if (descr_len > descr_len_max)
+- descr_len = descr_len_max;
+-
+- // XXX pamiętać o tym, żeby nie ucinać w środku znaku utf-8
+- }
+-
+- if (time)
+- new_time = gg_fix32(time);
+-
+- if (packet_type == GG_NEW_STATUS80) {
+- struct gg_new_status80 p;
+-
+- p.status = gg_fix32(status);
+- p.flags = gg_fix32(sess->status_flags);
+- p.description_size = gg_fix32(descr_len);
+- res = gg_send_packet(sess,
+- packet_type,
+- &p,
+- sizeof(p),
+- (new_descr) ? new_descr : descr,
+- descr_len,
+- NULL);
+-
+- } else {
+- struct gg_new_status p;
+-
+- p.status = gg_fix32(status);
+- res = gg_send_packet(sess,
+- packet_type,
+- &p,
+- sizeof(p),
+- (new_descr) ? new_descr : descr,
+- descr_len,
+- (append_null) ? "\0" : NULL,
+- (append_null) ? 1 : 0,
+- (time) ? &new_time : NULL,
+- (time) ? sizeof(new_time) : 0,
+- NULL);
+- }
+-
+- free(new_descr);
+-
+- if (GG_S_NA(status)) {
+- sess->state = GG_STATE_DISCONNECTING;
+- sess->timeout = GG_TIMEOUT_DISCONNECT;
+- }
+-
+- return res;
+-}
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Zmienia status użytkownika.
+- *
+- * \param sess Struktura sesji
+- * \param status Nowy status użytkownika
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup status
+- */
+-int gg_change_status(struct gg_session *sess, int status)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status(%p, %d);\n", sess, status);
+-
+- return gg_change_status_common(sess, status, NULL, 0);
+-}
+-
+-/**
+- * Zmienia status użytkownika na status opisowy.
+- *
+- * \param sess Struktura sesji
+- * \param status Nowy status użytkownika
+- * \param descr Opis statusu użytkownika
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup status
+- */
+-int gg_change_status_descr(struct gg_session *sess, int status, const char *descr)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr(%p, %d, \"%s\");\n", sess, status, descr);
+-
+- return gg_change_status_common(sess, status, descr, 0);
+-}
+-
+-/**
+- * Zmienia status użytkownika na status opisowy z podanym czasem powrotu.
+- *
+- * \param sess Struktura sesji
+- * \param status Nowy status użytkownika
+- * \param descr Opis statusu użytkownika
+- * \param time Czas powrotu w postaci uniksowego znacznika czasu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup status
+- */
+-int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_descr_time(%p, %d, \"%s\", %d);\n", sess, status, descr, time);
+-
+- return gg_change_status_common(sess, status, descr, time);
+-}
+-
+-/**
+- * Funkcja zmieniająca flagi statusu.
+- *
+- * \param sess Struktura sesji
+- * \param flags Nowe flagi statusu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \note Aby zmiany weszły w życie, należy ponownie ustawić status za pomocą
+- * funkcji z rodziny \c gg_change_status().
+- *
+- * \ingroup status
+- */
+-int gg_change_status_flags(struct gg_session *sess, int flags)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_change_status_flags(%p, 0x%08x);\n", sess, flags);
+-
+- if (sess == NULL) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- sess->status_flags = flags;
+-
+- return 0;
+-}
+-
+-/**
+- * Wysyła wiadomość do użytkownika.
+- *
+- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
+- * do potwierdzenia.
+- *
+- * \param sess Struktura sesji
+- * \param msgclass Klasa wiadomości
+- * \param recipient Numer adresata
+- * \param message Treść wiadomości
+- *
+- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
+- *
+- * \ingroup messages
+- */
+-int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message(%p, %d, %u, %p)\n", sess, msgclass, recipient, message);
+-
+- return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, NULL, 0);
+-}
+-
+-/**
+- * Wysyła wiadomość formatowaną.
+- *
+- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
+- * do potwierdzenia.
+- *
+- * \param sess Struktura sesji
+- * \param msgclass Klasa wiadomości
+- * \param recipient Numer adresata
+- * \param message Treść wiadomości
+- * \param format Informacje o formatowaniu
+- * \param formatlen Długość informacji o formatowaniu
+- *
+- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
+- *
+- * \ingroup messages
+- */
+-int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_richtext(%p, %d, %u, %p, %p, %d);\n", sess, msgclass, recipient, message, format, formatlen);
+-
+- return gg_send_message_confer_richtext(sess, msgclass, 1, &recipient, message, format, formatlen);
+-}
+-
+-/**
+- * Wysyła wiadomość w ramach konferencji.
+- *
+- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
+- * do potwierdzenia.
+- *
+- * \param sess Struktura sesji
+- * \param msgclass Klasa wiadomości
+- * \param recipients_count Liczba adresatów
+- * \param recipients Wskaźnik do tablicy z numerami adresatów
+- * \param message Treść wiadomości
+- *
+- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
+- *
+- * \ingroup messages
+- */
+-int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message)
+-{
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer(%p, %d, %d, %p, %p);\n", sess, msgclass, recipients_count, recipients, message);
+-
+- return gg_send_message_confer_richtext(sess, msgclass, recipients_count, recipients, message, NULL, 0);
+-}
+-
+-/**
+- * Wysyła wiadomość formatowaną w ramach konferencji.
+- *
+- * Zwraca losowy numer sekwencyjny, który można zignorować albo wykorzystać
+- * do potwierdzenia.
+- *
+- * \param sess Struktura sesji
+- * \param msgclass Klasa wiadomości
+- * \param recipients_count Liczba adresatów
+- * \param recipients Wskaźnik do tablicy z numerami adresatów
+- * \param message Treść wiadomości
+- * \param format Informacje o formatowaniu
+- * \param formatlen Długość informacji o formatowaniu
+- *
+- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
+- *
+- * \ingroup messages
+- */
+-int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen)
+-{
+- struct gg_send_msg s;
+- struct gg_send_msg80 s80;
+- struct gg_msg_recipients r;
+- char *cp_msg = NULL;
+- char *utf_msg = NULL;
+- char *html_msg = NULL;
+- int seq_no;
+- int i, j, k;
+- uin_t *recps;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_confer_richtext(%p, %d, %d, %p, %p, %p, %d);\n", sess, msgclass, recipients_count, recipients, message, format, formatlen);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (message == NULL || recipients_count <= 0 || recipients_count > 0xffff || (recipients_count != 1 && recipients == NULL)) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (sess->encoding == GG_ENCODING_UTF8) {
+- if (!(cp_msg = gg_encoding_convert((const char *) message, GG_ENCODING_UTF8, GG_ENCODING_CP1250, -1, -1)))
+- return -1;
+-
+- utf_msg = (char*) message;
+- } else {
+- if (sess->protocol_version >= 0x2d) {
+- if (!(utf_msg = gg_encoding_convert((const char *) message, GG_ENCODING_CP1250, GG_ENCODING_UTF8, -1, -1)))
+- return -1;
+- }
+-
+- cp_msg = (char*) message;
+- }
+-
+- if (sess->protocol_version < 0x2d) {
+- if (!sess->seq)
+- sess->seq = 0x01740000 | (rand() & 0xffff);
+- seq_no = sess->seq;
+- sess->seq += (rand() % 0x300) + 0x300;
+-
+- s.msgclass = gg_fix32(msgclass);
+- s.seq = gg_fix32(seq_no);
+- } else {
+- int len;
+-
+- // Drobne odchylenie od protokołu. Jeśli wysyłamy kilka
+- // wiadomości w ciągu jednej sekundy, zwiększamy poprzednią
+- // wartość, żeby każda wiadomość miała unikalny numer.
+-
+- seq_no = time(NULL);
+-
+- if (seq_no <= sess->seq)
+- seq_no = sess->seq + 1;
+-
+- sess->seq = seq_no;
+-
+- if (format == NULL || formatlen < 3) {
+- format = (unsigned char*) "\x02\x06\x00\x00\x00\x08\x00\x00\x00";
+- formatlen = 9;
+- }
+-
+- len = gg_message_text_to_html(NULL, utf_msg, (char*) format + 3, formatlen - 3);
+-
+- html_msg = malloc(len + 1);
+-
+- if (html_msg == NULL) {
+- seq_no = -1;
+- goto cleanup;
+- }
+-
+- gg_message_text_to_html(html_msg, utf_msg, (char*) format + 3, formatlen - 3);
+-
+- s80.seq = gg_fix32(seq_no);
+- s80.msgclass = gg_fix32(msgclass);
+- s80.offset_plain = gg_fix32(sizeof(s80) + strlen(html_msg) + 1);
+- s80.offset_attr = gg_fix32(sizeof(s80) + strlen(html_msg) + 1 + strlen(cp_msg) + 1);
+- }
+-
+- if (recipients_count > 1) {
+- r.flag = 0x01;
+- r.count = gg_fix32(recipients_count - 1);
+-
+- recps = malloc(sizeof(uin_t) * recipients_count);
+-
+- if (!recps) {
+- seq_no = -1;
+- goto cleanup;
+- }
+-
+- for (i = 0; i < recipients_count; i++) {
+- for (j = 0, k = 0; j < recipients_count; j++) {
+- if (recipients[j] != recipients[i]) {
+- recps[k] = gg_fix32(recipients[j]);
+- k++;
+- }
+- }
+-
+- if (sess->protocol_version < 0x2d) {
+- s.recipient = gg_fix32(recipients[i]);
+-
+- if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
+- seq_no = -1;
+- } else {
+- s80.recipient = gg_fix32(recipients[i]);
+-
+- if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, &r, sizeof(r), recps, (recipients_count - 1) * sizeof(uin_t), format, formatlen, NULL) == -1)
+- seq_no = -1;
+- }
+- }
+-
+- free(recps);
+- } else {
+- if (sess->protocol_version < 0x2d) {
+- s.recipient = gg_fix32(recipients[0]);
+-
+- if (gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
+- seq_no = -1;
+- } else {
+- s80.recipient = gg_fix32(recipients[0]);
+-
+- if (gg_send_packet(sess, GG_SEND_MSG80, &s80, sizeof(s80), html_msg, strlen(html_msg) + 1, cp_msg, strlen(cp_msg) + 1, format, formatlen, NULL) == -1)
+- seq_no = -1;
+- }
+- }
+-
+-cleanup:
+- if (cp_msg != (char*) message)
+- free(cp_msg);
+-
+- if (utf_msg != (char*) message)
+- free(utf_msg);
+-
+- free(html_msg);
+-
+- return seq_no;
+-}
+-
+-/**
+- * Wysyła wiadomość binarną przeznaczoną dla klienta.
+- *
+- * Wiadomości między klientami przesyła się np. w celu wywołania zwrotnego
+- * połączenia bezpośredniego. Funkcja zwraca losowy numer sekwencyjny,
+- * który można zignorować albo wykorzystać do potwierdzenia.
+- *
+- * \param sess Struktura sesji
+- * \param msgclass Klasa wiadomości
+- * \param recipient Numer adresata
+- * \param message Treść wiadomości
+- * \param message_len Długość wiadomości
+- *
+- * \return Numer sekwencyjny wiadomości lub -1 w przypadku błędu.
+- *
+- * \ingroup messages
+- */
+-int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len)
+-{
+- struct gg_send_msg s;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_send_message_ctcp(%p, %d, %u, ...);\n", sess, msgclass, recipient);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- s.recipient = gg_fix32(recipient);
+- s.seq = gg_fix32(0);
+- s.msgclass = gg_fix32(msgclass);
+-
+- return gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), message, message_len, NULL);
+-}
+-
+-/**
+- * Wysyła żądanie obrazka o podanych parametrach.
+- *
+- * Wiadomości obrazkowe nie zawierają samych obrazków, a tylko ich rozmiary
+- * i sumy kontrolne. Odbiorca najpierw szuka obrazków w swojej pamięci
+- * podręcznej i dopiero gdy ich nie znajdzie, wysyła żądanie do nadawcy.
+- * Wynik zostanie przekazany zdarzeniem \c GG_EVENT_IMAGE_REPLY.
+- *
+- * \param sess Struktura sesji
+- * \param recipient Numer adresata
+- * \param size Rozmiar obrazka w bajtach
+- * \param crc32 Suma kontrola obrazka
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup messages
+- */
+-int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32)
+-{
+- struct gg_send_msg s;
+- struct gg_msg_image_request r;
+- char dummy = 0;
+- int res;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_request(%p, %d, %u, 0x%.4x);\n", sess, recipient, size, crc32);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (size < 0) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- s.recipient = gg_fix32(recipient);
+- s.seq = gg_fix32(0);
+- s.msgclass = gg_fix32(GG_CLASS_MSG);
+-
+- r.flag = 0x04;
+- r.size = gg_fix32(size);
+- r.crc32 = gg_fix32(crc32);
+-
+- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), &dummy, 1, &r, sizeof(r), NULL);
+-
+- if (!res) {
+- struct gg_image_queue *q = malloc(sizeof(*q));
+- char *buf;
+-
+- if (!q) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image queue\n");
+- return -1;
+- }
+-
+- buf = malloc(size);
+- if (size && !buf)
+- {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_image_request() not enough memory for image\n");
+- free(q);
+- return -1;
+- }
+-
+- memset(q, 0, sizeof(*q));
+-
+- q->sender = recipient;
+- q->size = size;
+- q->crc32 = crc32;
+- q->image = buf;
+-
+- if (!sess->images)
+- sess->images = q;
+- else {
+- struct gg_image_queue *qq;
+-
+- for (qq = sess->images; qq->next; qq = qq->next)
+- ;
+-
+- qq->next = q;
+- }
+- }
+-
+- return res;
+-}
+-
+-/**
+- * Wysyła żądany obrazek.
+- *
+- * \param sess Struktura sesji
+- * \param recipient Numer adresata
+- * \param filename Nazwa pliku
+- * \param image Bufor z obrazkiem
+- * \param size Rozmiar obrazka
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup messages
+- */
+-int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size)
+-{
+- struct gg_msg_image_reply *r;
+- struct gg_send_msg s;
+- const char *tmp;
+- char buf[1910];
+- int res = -1;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_image_reply(%p, %d, \"%s\", %p, %d);\n", sess, recipient, filename, image, size);
+-
+- if (!sess || !filename || !image) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (size < 0) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- /* wytnij ścieżki, zostaw tylko nazwę pliku */
+- while ((tmp = strrchr(filename, '/')) || (tmp = strrchr(filename, '\\')))
+- filename = tmp + 1;
+-
+- if (strlen(filename) < 1 || strlen(filename) > 1024) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- s.recipient = gg_fix32(recipient);
+- s.seq = gg_fix32(0);
+- s.msgclass = gg_fix32(GG_CLASS_MSG);
+-
+- buf[0] = 0;
+- r = (void*) &buf[1];
+-
+- r->flag = 0x05;
+- r->size = gg_fix32(size);
+- r->crc32 = gg_fix32(gg_crc32(0, (unsigned char*) image, size));
+-
+- while (size > 0) {
+- int buflen, chunklen;
+-
+- /* \0 + struct gg_msg_image_reply */
+- buflen = sizeof(struct gg_msg_image_reply) + 1;
+-
+- /* w pierwszym kawałku jest nazwa pliku */
+- if (r->flag == 0x05) {
+- strcpy(buf + buflen, filename);
+- buflen += strlen(filename) + 1;
+- }
+-
+- chunklen = (size >= sizeof(buf) - buflen) ? (sizeof(buf) - buflen) : size;
+-
+- memcpy(buf + buflen, image, chunklen);
+- size -= chunklen;
+- image += chunklen;
+-
+- res = gg_send_packet(sess, GG_SEND_MSG, &s, sizeof(s), buf, buflen + chunklen, NULL);
+-
+- if (res == -1)
+- break;
+-
+- r->flag = 0x06;
+- }
+-
+- return res;
+-}
+-
+-/**
+- * Wysyła do serwera listę kontaktów.
+- *
+- * Funkcja informuje serwer o liście kontaktów, których statusy będą
+- * obserwowane lub kontaktów, które bedą blokowane. Dla każdego z \c count
+- * kontaktów tablica \c userlist zawiera numer, a tablica \c types rodzaj
+- * kontaktu (\c GG_USER_NORMAL, \c GG_USER_OFFLINE, \c GG_USER_BLOCKED).
+- *
+- * Listę kontaktów należy \b zawsze wysyłać po połączeniu, nawet jeśli
+- * jest pusta.
+- *
+- * \param sess Struktura sesji
+- * \param userlist Wskaźnik do tablicy numerów kontaktów
+- * \param types Wskaźnik do tablicy rodzajów kontaktów
+- * \param count Liczba kontaktów
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count)
+-{
+- struct gg_notify *n;
+- uin_t *u;
+- char *t;
+- int i, res = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify_ex(%p, %p, %p, %d);\n", sess, userlist, types, count);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (!userlist || !count)
+- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
+-
+- while (count > 0) {
+- int part_count, packet_type;
+-
+- if (count > 400) {
+- part_count = 400;
+- packet_type = GG_NOTIFY_FIRST;
+- } else {
+- part_count = count;
+- packet_type = GG_NOTIFY_LAST;
+- }
+-
+- if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
+- return -1;
+-
+- for (u = userlist, t = types, i = 0; i < part_count; u++, t++, i++) {
+- n[i].uin = gg_fix32(*u);
+- n[i].dunno1 = *t;
+- }
+-
+- if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
+- free(n);
+- res = -1;
+- break;
+- }
+-
+- count -= part_count;
+- userlist += part_count;
+- types += part_count;
+-
+- free(n);
+- }
+-
+- return res;
+-}
+-
+-/**
+- * Wysyła do serwera listę kontaktów.
+- *
+- * Funkcja jest odpowiednikiem \c gg_notify_ex(), gdzie wszystkie kontakty
+- * są rodzaju \c GG_USER_NORMAL.
+- *
+- * \param sess Struktura sesji
+- * \param userlist Wskaźnik do tablicy numerów kontaktów
+- * \param count Liczba kontaktów
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_notify(struct gg_session *sess, uin_t *userlist, int count)
+-{
+- struct gg_notify *n;
+- uin_t *u;
+- int i, res = 0;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_notify(%p, %p, %d);\n", sess, userlist, count);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (!userlist || !count)
+- return gg_send_packet(sess, GG_LIST_EMPTY, NULL);
+-
+- while (count > 0) {
+- int part_count, packet_type;
+-
+- if (count > 400) {
+- part_count = 400;
+- packet_type = GG_NOTIFY_FIRST;
+- } else {
+- part_count = count;
+- packet_type = GG_NOTIFY_LAST;
+- }
+-
+- if (!(n = (struct gg_notify*) malloc(sizeof(*n) * part_count)))
+- return -1;
+-
+- for (u = userlist, i = 0; i < part_count; u++, i++) {
+- n[i].uin = gg_fix32(*u);
+- n[i].dunno1 = GG_USER_NORMAL;
+- }
+-
+- if (gg_send_packet(sess, packet_type, n, sizeof(*n) * part_count, NULL) == -1) {
+- res = -1;
+- free(n);
+- break;
+- }
+-
+- free(n);
+-
+- userlist += part_count;
+- count -= part_count;
+- }
+-
+- return res;
+-}
+-
+-/**
+- * Dodaje kontakt.
+- *
+- * Dodaje do listy kontaktów dany numer w trakcie połączenia. Aby zmienić
+- * rodzaj kontaktu (np. z normalnego na zablokowany), należy najpierw usunąć
+- * poprzedni rodzaj, ponieważ serwer operuje na maskach bitowych.
+- *
+- * \param sess Struktura sesji
+- * \param uin Numer kontaktu
+- * \param type Rodzaj kontaktu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type)
+-{
+- struct gg_add_remove a;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_add_notify_ex(%p, %u, %d);\n", sess, uin, type);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- a.uin = gg_fix32(uin);
+- a.dunno1 = type;
+-
+- return gg_send_packet(sess, GG_ADD_NOTIFY, &a, sizeof(a), NULL);
+-}
+-
+-/**
+- * Dodaje kontakt.
+- *
+- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
+- * kontaktów to \c GG_USER_NORMAL.
+- *
+- * \param sess Struktura sesji
+- * \param uin Numer kontaktu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_add_notify(struct gg_session *sess, uin_t uin)
+-{
+- return gg_add_notify_ex(sess, uin, GG_USER_NORMAL);
+-}
+-
+-/**
+- * Usuwa kontakt.
+- *
+- * Usuwa z listy kontaktów dany numer w trakcie połączenia.
+- *
+- * \param sess Struktura sesji
+- * \param uin Numer kontaktu
+- * \param type Rodzaj kontaktu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type)
+-{
+- struct gg_add_remove a;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_remove_notify_ex(%p, %u, %d);\n", sess, uin, type);
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- a.uin = gg_fix32(uin);
+- a.dunno1 = type;
+-
+- return gg_send_packet(sess, GG_REMOVE_NOTIFY, &a, sizeof(a), NULL);
+-}
+-
+-/**
+- * Usuwa kontakt.
+- *
+- * Funkcja jest odpowiednikiem \c gg_add_notify_ex(), gdzie rodzaj wszystkich
+- * kontaktów to \c GG_USER_NORMAL.
+- *
+- * \param sess Struktura sesji
+- * \param uin Numer kontaktu
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup contacts
+- */
+-int gg_remove_notify(struct gg_session *sess, uin_t uin)
+-{
+- return gg_remove_notify_ex(sess, uin, GG_USER_NORMAL);
+-}
+-
+-/**
+- * Wysyła do serwera zapytanie dotyczące listy kontaktów.
+- *
+- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
+- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
+- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
+- * listy kontaktów jest ignorowany przez serwer, ale ze względu na
+- * kompatybilność z innymi klientami, należy przechowywać dane w tym samym
+- * formacie co oryginalny klient Gadu-Gadu.
+- *
+- * Program nie musi się przejmować fragmentacją listy kontaktów wynikającą
+- * z protokołu -- wysyła i odbiera kompletną listę.
+- *
+- * \param sess Struktura sesji
+- * \param type Rodzaj zapytania
+- * \param request Treść zapytania (może być równe NULL)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup importexport
+- */
+-int gg_userlist_request(struct gg_session *sess, char type, const char *request)
+-{
+- int len;
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- if (!request) {
+- sess->userlist_blocks = 1;
+- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), NULL);
+- }
+-
+- len = strlen(request);
+-
+- sess->userlist_blocks = 0;
+-
+- while (len > 2047) {
+- sess->userlist_blocks++;
+-
+- if (gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, 2047, NULL) == -1)
+- return -1;
+-
+- if (type == GG_USERLIST_PUT)
+- type = GG_USERLIST_PUT_MORE;
+-
+- request += 2047;
+- len -= 2047;
+- }
+-
+- sess->userlist_blocks++;
+-
+- return gg_send_packet(sess, GG_USERLIST_REQUEST, &type, sizeof(type), request, len, NULL);
+-}
+-
+-/**
+- * Wysyła do serwera zapytanie dotyczące listy kontaktów (10.0).
+- *
+- * Funkcja służy do importu lub eksportu listy kontaktów do serwera.
+- * W odróżnieniu od funkcji \c gg_notify(), ta lista kontaktów jest przez
+- * serwer jedynie przechowywana i nie ma wpływu na połączenie. Format
+- * listy kontaktów jest jednak weryfikowany przez serwer, który stara się
+- * synchronizować listę kontaktów zapisaną w formatach GG 7.0 oraz GG 10.0.
+- * Serwer przyjmuje listy kontaktów przysłane w formacie niezgodnym z podanym
+- * jako \c format_type, ale nie zachowuje ich, a przesłanie takiej listy jest
+- * równoznaczne z usunięciem listy kontaktów.
+- *
+- * Program nie musi się przejmować kompresją listy kontaktów zgodną
+- * z protokołem -- wysyła i odbiera kompletną listę zapisaną czystym tekstem.
+- *
+- * \param sess Struktura sesji
+- * \param type Rodzaj zapytania
+- * \param version Numer ostatniej znanej programowi wersji listy kontaktów lub 0
+- * \param format_type Typ formatu listy kontaktów
+- * \param request Treść zapytania (może być równe NULL)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup importexport
+- */
+-int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request)
+-{
+- struct gg_userlist100_request pkt;
+- unsigned char *zrequest;
+- size_t zrequest_len;
+- int ret;
+-
+- if (!sess) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- errno = ENOTCONN;
+- return -1;
+- }
+-
+- pkt.type = type;
+- pkt.version = gg_fix32(version);
+- pkt.format_type = format_type;
+- pkt.unknown1 = 0x01;
+-
+- if (request == NULL)
+- return gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), NULL);
+-
+- zrequest = gg_deflate(request, &zrequest_len);
+-
+- if (zrequest == NULL) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_userlist100_request() gg_deflate() failed");
+- return -1;
+- }
+-
+- ret = gg_send_packet(sess, GG_USERLIST100_REQUEST, &pkt, sizeof(pkt), zrequest, zrequest_len, NULL);
+-
+- free(zrequest);
+-
+- return ret;
+-}
+-
+-/**
+- * Informuje rozmówcę o pisaniu wiadomości.
+- *
+- * \param sess Struktura sesji
+- * \param recipient Numer adresata
+- * \param length Długość wiadomości lub 0 jeśli jest pusta
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup messages
+- */
+-int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length){
+- struct gg_typing_notification pkt;
+- uin_t uin;
+-
+- pkt.length = gg_fix16(length);
+- uin = gg_fix32(recipient);
+- memcpy(&pkt.uin, &uin, sizeof(uin_t));
+-
+- return gg_send_packet(sess, GG_TYPING_NOTIFICATION, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/**
+- * Rozłącza inną sesję multilogowania.
+- *
+- * \param gs Struktura sesji
+- * \param conn_id Sesja do rozłączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup login
+- */
+-int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id)
+-{
+- struct gg_multilogon_disconnect pkt;
+-
+- pkt.conn_id = conn_id;
+-
+- return gg_send_packet(gs, GG_MULTILOGON_DISCONNECT, &pkt, sizeof(pkt), NULL);
+-}
+-
+-/* @} */
+-
+-/**
+- * Sprawdza czy biblioteka obsługuje daną funkcję.
+- *
+- * \param feature Identyfikator funkcji.
+- *
+- * \return Wartość niezerowa jeśli funkcja jest obsłgiwana.
+- *
+- * \ingroup version
+- */
+-int gg_libgadu_check_feature(gg_libgadu_feature_t feature)
+-{
+- switch (feature)
+- {
+- case GG_LIBGADU_FEATURE_SSL:
+-#if defined(GG_CONFIG_HAVE_OPENSSL) || defined(GG_CONFIG_HAVE_GNUTLS)
+- return 1;
+-#else
+- return 0;
+-#endif
+-
+- case GG_LIBGADU_FEATURE_PTHREAD:
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- return 1;
+-#else
+- return 0;
+-#endif
+-
+- case GG_LIBGADU_FEATURE_USERLIST100:
+-#ifdef GG_CONFIG_HAVE_ZLIB
+- return 1;
+-#else
+- return 0;
+-#endif
+-
+- /* Celowo nie ma default, żeby kompilator wyłapał brakujące funkcje */
+-
+- }
+-
+- return 0;
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-config.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-config.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-config.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-config.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,59 +0,0 @@
+-/* Local libgadu configuration. */
+-
+-#include "config.h"
+-
+-#ifndef __GG_LIBGADU_CONFIG_H
+-#define __GG_LIBGADU_CONFIG_H
+-
+-/* Defined if libgadu was compiled for bigendian machine. */
+-#undef __GG_LIBGADU_BIGENDIAN
+-#ifdef WORDS_BIGENDIAN
+-#define __GG_LIBGADU_BIGENDIAN
+-#endif /* WORDS_BIGENDIAN */
+-
+-/* Defined if this machine has va_copy(). */
+-#define __GG_LIBGADU_HAVE_VA_COPY
+-
+-/* Defined if this machine has __va_copy(). */
+-#define __GG_LIBGADU_HAVE___VA_COPY
+-
+-/* Defined if this machine supports long long. */
+-#undef __GG_LIBGADU_HAVE_LONG_LONG
+-#ifdef HAVE_LONG_LONG
+-#define __GG_LIBGADU_HAVE_LONG_LONG
+-#endif /* HAVE_LONG_LONG */
+-
+-/* Defined if libgadu was compiled and linked with pthread support. */
+-/* We don't like pthreads. */
+-#undef __GG_LIBGADU_HAVE_PTHREAD
+-
+-/* Defined if libgadu was compiled and linked with GnuTLS encryption support. */
+-#ifdef HAVE_GNUTLS
+-# define GG_CONFIG_HAVE_GNUTLS
+-#else
+-# undef GG_CONFIG_HAVE_GNUTLS
+-#endif
+-
+-/* Defined if libgadu was compiled and linked with TLS support. */
+-/* Always undefined in Purple. */
+-#undef __GG_LIBGADU_HAVE_OPENSSL
+-
+-/* Include file containing uintXX_t declarations. */
+-#if HAVE_STDINT_H
+-#include <stdint.h>
+-#endif
+-
+-/* Defined if this machine has C99-compiliant vsnprintf(). */
+-#ifndef _WIN32
+-#define __GG_LIBGADU_HAVE_C99_VSNPRINTF
+-#else
+-#undef __GG_LIBGADU_HAVE_C99_VSNPRINTF
+-#endif
+-
+-#define vnsprintf g_vnsprintf
+-
+-#ifdef _WIN32
+-#define random (long) rand
+-#endif
+-
+-#endif /* __GG_LIBGADU_CONFIG_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-debug.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-debug.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-debug.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-debug.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,29 +0,0 @@
+-/*
+- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_DEBUG_H
+-#define LIBGADU_DEBUG_H
+-
+-#include "libgadu.h"
+-
+-const char *gg_debug_state(enum gg_state_t state);
+-const char *gg_debug_event(enum gg_event_t event);
+-void gg_debug_dump(struct gg_session *sess, int level, const char *buf, size_t len);
+-void gg_debug_common(struct gg_session *sess, int level, const char *format, va_list ap);
+-
+-#endif /* LIBGADU_DEBUG_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2319 +0,0 @@
+-/* $Id: libgadu.h.in 1105 2011-05-25 21:34:50Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Piotr Wysocki <wysek@linux.bydg.org>
+- * Dawid Jarosz <dawjar@poczta.onet.pl>
+- * Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file libgadu.h
+- *
+- * \brief Główny plik nagłówkowy biblioteki
+- */
+-
+-#ifndef __GG_LIBGADU_H
+-#define __GG_LIBGADU_H
+-
+-#ifdef _WIN32
+-#pragma pack(push, 1)
+-#endif
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#include <sys/types.h>
+-#include <stdio.h>
+-#include <stdarg.h>
+-
+-/** \cond ignore */
+-
+-/* Defined if libgadu was compiled for bigendian machine. */
+-#undef GG_CONFIG_BIGENDIAN
+-
+-/* Defined if this machine has gethostbyname_r(). */
+-#undef GG_CONFIG_HAVE_GETHOSTBYNAME_R
+-
+-/* Defined if libgadu was compiled and linked with pthread support. */
+-#undef GG_CONFIG_HAVE_PTHREAD
+-
+-/* Defined if pthread resolver is the default one. */
+-#undef GG_CONFIG_PTHREAD_DEFAULT
+-
+-/* Defined if this machine has C99-compiliant vsnprintf(). */
+-#undef GG_CONFIG_HAVE_C99_VSNPRINTF
+-
+-/* Defined if this machine has va_copy(). */
+-#undef GG_CONFIG_HAVE_VA_COPY
+-
+-/* Defined if this machine has __va_copy(). */
+-#undef GG_CONFIG_HAVE___VA_COPY
+-
+-/* Defined if this machine supports long long. */
+-#undef GG_CONFIG_HAVE_LONG_LONG
+-
+-/* Defined if libgadu was compiled and linked with GnuTLS support. */
+-#undef GG_CONFIG_HAVE_GNUTLS
+-
+-/* Defined if libgadu was compiled and linked with OpenSSL support. */
+-#undef GG_CONFIG_HAVE_OPENSSL
+-
+-/* Defined if libgadu was compiled and linked with zlib support. */
+-#undef GG_CONFIG_HAVE_ZLIB
+-
+-/* Defined if uintX_t types are defined in <stdint.h>. */
+-#undef GG_CONFIG_HAVE_STDINT_H
+-
+-/* Defined if uintX_t types are defined in <inttypes.h>. */
+-#undef GG_CONFIG_HAVE_INTTYPES_H
+-
+-/* Defined if uintX_t types are defined in <sys/inttypes.h>. */
+-#undef GG_CONFIG_HAVE_SYS_INTTYPES_H
+-
+-/* Defined if uintX_t types are defined in <sys/int_types.h>. */
+-#undef GG_CONFIG_HAVE_SYS_INT_TYPES_H
+-
+-/* Defined if uintX_t types are defined in <sys/types.h>. */
+-#undef GG_CONFIG_HAVE_SYS_TYPES_H
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-#include <openssl/ssl.h>
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_STDINT_H
+-#include <stdint.h>
+-#else
+-# ifdef GG_CONFIG_HAVE_INTTYPES_H
+-# include <inttypes.h>
+-# else
+-# ifdef GG_CONFIG_HAVE_SYS_INTTYPES_H
+-# include <sys/inttypes.h>
+-# else
+-# ifdef GG_CONFIG_HAVE_SYS_INT_TYPES_H
+-# include <sys/int_types.h>
+-# else
+-# ifdef GG_CONFIG_HAVE_SYS_TYPES_H
+-# include <sys/types.h>
+-# else
+-
+-#ifndef __AC_STDINT_H
+-#define __AC_STDINT_H
+-
+-/* ISO C 9X: 7.18 Integer types <stdint.h> */
+-
+-typedef unsigned char uint8_t;
+-typedef unsigned short uint16_t;
+-typedef unsigned int uint32_t;
+-
+-#if !defined(__CYGWIN__) && !defined(__SunOS) && !defined(_INCLUDE_HPUX_SOURCE)
+-#define __int8_t_defined
+-typedef signed char int8_t;
+-typedef signed short int16_t;
+-typedef signed int int32_t;
+-#endif
+-
+-#endif /* __AC_STDINT_H */
+-
+-# endif
+-# endif
+-# endif
+-# endif
+-#endif
+-
+-/** \endcond */
+-
+-/**
+- * Numer Gadu-Gadu.
+- */
+-typedef uint32_t uin_t;
+-
+-/**
+- * Identyfikator połączenia bezpośredniego Gadu-Gadu 7.x.
+- */
+-typedef struct {
+- uint8_t id[8];
+-} gg_dcc7_id_t;
+-
+-/**
+- * Identyfikator sesji multilogowania.
+- */
+-typedef struct {
+- uint8_t id[8];
+-} gg_multilogon_id_t;
+-
+-/**
+- * Makro deklarujące pola wspólne dla struktur sesji.
+- */
+-#define gg_common_head(x) \
+- int fd; /**< Obserwowany deskryptor */ \
+- int check; /**< Informacja o żądaniu odczytu/zapisu (patrz \ref gg_check_t) */ \
+- int state; /**< Aktualny stan połączenia (patrz \ref gg_state_t) */ \
+- int error; /**< Kod błędu dla \c GG_STATE_ERROR (patrz \ref gg_error_t) */ \
+- int type; /**< Rodzaj sesji (patrz \ref gg_session_t) */ \
+- int id; /**< Identyfikator sesji */ \
+- int timeout; /**< Czas pozostały do zakończenia stanu */ \
+- int (*callback)(x*); /**< Funkcja zwrotna */ \
+- void (*destroy)(x*); /**< Funkcja zwalniania zasobów */
+-
+-/**
+- * Struktura wspólna dla wszystkich sesji i połączeń. Pozwala na proste
+- * rzutowanie niezależne od rodzaju połączenia.
+- */
+-struct gg_common {
+- gg_common_head(struct gg_common)
+-};
+-
+-struct gg_image_queue;
+-
+-struct gg_dcc7;
+-
+-struct gg_dcc7_relay;
+-
+-/**
+- * Sposób rozwiązywania nazw serwerów.
+- */
+-typedef enum {
+- GG_RESOLVER_DEFAULT = 0, /**< Domyślny sposób rozwiązywania nazw (jeden z poniższych) */
+- GG_RESOLVER_FORK, /**< Rozwiązywanie nazw bazujące na procesach */
+- GG_RESOLVER_PTHREAD, /**< Rozwiązywanie nazw bazujące na wątkach */
+- GG_RESOLVER_WIN32,
+- GG_RESOLVER_CUSTOM, /**< Funkcje rozwiązywania nazw dostarczone przed aplikację */
+- GG_RESOLVER_INVALID = -1 /**< Nieprawidłowy sposób rozwiązywania nazw (wynik \c gg_session_get_resolver) */
+-} gg_resolver_t;
+-
+-/**
+- * Rodzaj kodowania znaków.
+- */
+-typedef enum {
+- GG_ENCODING_CP1250 = 0, /**< Kodowanie CP1250 */
+- GG_ENCODING_UTF8, /**< Kodowanie UTF-8 */
+- GG_ENCODING_INVALID = -1 /**< Nieprawidłowe kodowanie */
+-} gg_encoding_t;
+-
+-/**
+- * Sesja Gadu-Gadu.
+- *
+- * Tworzona przez funkcję \c gg_login(), zwalniana przez \c gg_free_session().
+- *
+- * \ingroup login
+- */
+-struct gg_session {
+- gg_common_head(struct gg_session)
+-
+- int async; /**< Flaga połączenia asynchronicznego */
+- int pid; /**< Numer procesu rozwiązującego nazwę serwera */
+- int port; /**< Port serwera */
+- int seq; /**< Numer sekwencyjny ostatniej wiadomości */
+- int last_pong; /**< Czas otrzymania ostatniej ramki utrzymaniowej */
+- int last_event; /**< Czas otrzymania ostatniego pakietu */
+-
+- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
+-
+- uint32_t proxy_addr; /**< Adres serwera pośredniczącego */
+- uint16_t proxy_port; /**< Port serwera pośredniczącego */
+-
+- uint32_t hub_addr; /**< Adres huba po rozwiązaniu nazwy */
+- uint32_t server_addr; /**< Adres serwera otrzymany od huba */
+-
+- uint32_t client_addr; /**< Adres gniazda dla połączeń bezpośrednich */
+- uint16_t client_port; /**< Port gniazda dla połączeń bezpośrednich */
+-
+- uint32_t external_addr; /**< Publiczny adres dla połączeń bezpośrednich */
+- uint16_t external_port; /**< Publiczny port dla połączeń bezpośrednich */
+-
+- uin_t uin; /**< Własny numer Gadu-Gadu */
+- char *password; /**< Hasło (zwalniane po użyciu) */
+-
+- int initial_status; /**< Początkowy status */
+- int status; /**< Aktualny status */
+-
+- char *recv_buf; /**< Bufor na odbierany pakiety */
+- int recv_done; /**< Liczba wczytanych bajtów pakietu */
+- int recv_left; /**< Liczba pozostałych do wczytania bajtów pakietu */
+-
+- int protocol_version; /**< Wersja protokołu (bez flag) */
+- char *client_version; /**< Wersja klienta */
+- int last_sysmsg; /**< Numer ostatniej wiadomości systemowej */
+-
+- char *initial_descr; /**< Początkowy opis statusu */
+-
+- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę serwera */
+-
+- char *header_buf; /**< Bufor na początek nagłówka pakietu */
+- unsigned int header_done; /**< Liczba wczytanych bajtów nagłówka pakietu */
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+- SSL *ssl; /**< Struktura TLS */
+- SSL_CTX *ssl_ctx; /**< Kontekst sesji TLS */
+-#else
+- void *ssl; /**< Struktura TLS */
+- void *ssl_ctx; /**< Kontekst sesji TLS */
+-#endif
+-
+- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
+-
+- char *userlist_reply; /**< Bufor z odbieraną listą kontaktów */
+-
+- int userlist_blocks; /**< Liczba części listy kontaktów */
+-
+- struct gg_image_queue *images; /**< Lista wczytywanych obrazków */
+-
+- int hash_type; /**< Rodzaj funkcji skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1) */
+-
+- char *send_buf; /**< Bufor z danymi do wysłania */
+- int send_left; /**< Liczba bajtów do wysłania */
+-
+- struct gg_dcc7 *dcc7_list; /**< Lista połączeń bezpośrednich skojarzonych z sesją */
+-
+- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_watch_fd() */
+-
+- int protocol_flags; /**< Flagi protokołu */
+-
+- gg_encoding_t encoding; /**< Rodzaj kodowania znaków */
+-
+- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
+- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynająca rozwiązywanie nazwy */
+- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
+-
+- int protocol_features; /**< Opcje protokołu */
+- int status_flags; /**< Flagi statusu */
+- int recv_msg_count; /**< Liczba odebranych wiadomości */
+-};
+-
+-/**
+- * Połączenie HTTP.
+- *
+- * Tworzone przez \c gg_http_connect(), zwalniane przez \c gg_http_free().
+- *
+- * \ingroup http
+- */
+-struct gg_http {
+- gg_common_head(struct gg_http)
+-
+- int async; /**< Flaga połączenia asynchronicznego */
+- int pid; /**< Identyfikator procesu rozwiązującego nazwę serwera */
+- int port; /**< Port */
+-
+- char *query; /**< Zapytanie HTTP */
+- char *header; /**< Odebrany nagłówek */
+- int header_size; /**< Rozmiar wczytanego nagłówka */
+- char *body; /**< Odebrana strona */
+- unsigned int body_size; /**< Rozmiar strony */
+-
+- void *data; /**< Dane prywatne usługi HTTP */
+-
+- char *user_data; /**< Dane prywatne użytkownika (nie są zwalniane) */
+-
+- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę */
+-
+- unsigned int body_done; /**< Liczba odebranych bajtów strony */
+-
+- gg_resolver_t resolver_type; /**< Sposób rozwiązywania nazw serwerów */
+- int (*resolver_start)(int *fd, void **private_data, const char *hostname); /**< Funkcja rozpoczynająca rozwiązywanie nazwy */
+- void (*resolver_cleanup)(void **private_data, int force); /**< Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
+-};
+-
+-/** \cond ignore */
+-
+-#ifdef __GNUC__
+-#define GG_PACKED __attribute__ ((packed))
+-#ifndef GG_IGNORE_DEPRECATED
+-#define GG_DEPRECATED __attribute__ ((deprecated))
+-#else
+-#define GG_DEPRECATED
+-#endif
+-#else
+-#define GG_PACKED
+-#define GG_DEPRECATED
+-#endif
+-
+-/** \endcond */
+-
+-#define GG_MAX_PATH 276 /**< Maksymalny rozmiar nazwy pliku w strukturze \c gg_file_info */
+-
+-/**
+- * Odpowiednik struktury WIN32_FIND_DATA z API WIN32.
+- *
+- * Wykorzystywana przy połączeniach bezpośrednich do wersji Gadu-Gadu 6.x.
+- */
+-struct gg_file_info {
+- uint32_t mode; /**< dwFileAttributes */
+- uint32_t ctime[2]; /**< ftCreationTime */
+- uint32_t atime[2]; /**< ftLastAccessTime */
+- uint32_t mtime[2]; /**< ftLastWriteTime */
+- uint32_t size_hi; /**< nFileSizeHigh */
+- uint32_t size; /**< nFileSizeLow */
+- uint32_t reserved0; /**< dwReserved0 */
+- uint32_t reserved1; /**< dwReserved1 */
+- unsigned char filename[GG_MAX_PATH - 14]; /**< cFileName */
+- unsigned char short_filename[14]; /**< cAlternateFileName */
+-} /** \cond ignore */ GG_PACKED /** \endcond */;
+-
+-/**
+- * Połączenie bezpośrednie do wersji Gadu-Gadu 6.x.
+- *
+- * Tworzone przez \c gg_dcc_socket_create(), \c gg_dcc_get_file(),
+- * \c gg_dcc_send_file() lub \c gg_dcc_voice_chat(), zwalniane przez
+- * \c gg_dcc_free().
+- *
+- * \ingroup dcc6
+- */
+-struct gg_dcc {
+- gg_common_head(struct gg_dcc)
+-
+- struct gg_event *event; /**< Zdarzenie po wywołaniu \c callback */
+-
+- int active; /**< Flaga połączenia aktywnego (nieużywana) */
+- int port; /**< Port gniazda nasłuchującego */
+- uin_t uin; /**< Własny numer Gadu-Gadu */
+- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
+- int file_fd; /**< deskryptor pliku */
+- unsigned int offset; /**< Położenie w pliku */
+- unsigned int chunk_size;
+- /**< Rozmiar kawałka pliku */
+- unsigned int chunk_offset;
+- /**< Położenie w aktualnym kawałku pliku */
+- struct gg_file_info file_info;
+- /**< Informacje o pliku */
+- int established; /**< Flaga ustanowienia połączenia */
+- char *voice_buf; /**< Bufor na pakiet połączenia głosowego */
+- int incoming; /**< Flaga połączenia przychodzącego */
+- char *chunk_buf; /**< Bufor na fragment danych */
+- uint32_t remote_addr; /**< Adres drugiej strony */
+- uint16_t remote_port; /**< Port drugiej strony */
+-};
+-
+-#define GG_DCC7_HASH_LEN 20 /**< Maksymalny rozmiar skrótu pliku w połączeniach bezpośrenich */
+-#define GG_DCC7_FILENAME_LEN 255 /**< Maksymalny rozmiar nazwy pliku w połączeniach bezpośrednich */
+-#define GG_DCC7_INFO_LEN 32 /**< Maksymalny rozmiar informacji o połączeniach bezpośrednich */
+-#define GG_DCC7_INFO_HASH_LEN 32 /**< Maksymalny rozmiar skrótu ip informacji o połączeniach bezpośrednich */
+-
+-/**
+- * Połączenie bezpośrednie od wersji Gadu-Gadu 7.x.
+- *
+- * \ingroup dcc7
+- */
+-struct gg_dcc7 {
+- gg_common_head(struct gg_dcc7)
+-
+- gg_dcc7_id_t cid; /**< Identyfikator połączenia */
+-
+- struct gg_event *event; /**< Struktura zdarzenia */
+-
+- uin_t uin; /**< Własny numer Gadu-Gadu */
+- uin_t peer_uin; /**< Numer Gadu-Gadu drugiej strony połączenia */
+-
+- int file_fd; /**< Deskryptor przesyłanego pliku */
+- unsigned int offset; /**< Aktualne położenie w przesyłanym pliku */
+- unsigned int size; /**< Rozmiar przesyłanego pliku */
+- unsigned char filename[GG_DCC7_FILENAME_LEN + 1];
+- /**< Nazwa przesyłanego pliku */
+- unsigned char hash[GG_DCC7_HASH_LEN];
+- /**< Skrót SHA1 przesyłanego pliku */
+-
+- int dcc_type; /**< Rodzaj połączenia bezpośredniego */
+- int established; /**< Flaga ustanowienia połączenia */
+- int incoming; /**< Flaga połączenia przychodzącego */
+- int reverse; /**< Flaga połączenia zwrotnego */
+-
+- uint32_t local_addr; /**< Adres lokalny */
+- uint16_t local_port; /**< Port lokalny */
+-
+- uint32_t remote_addr; /**< Adres drugiej strony */
+- uint16_t remote_port; /**< Port drugiej strony */
+-
+- struct gg_session *sess;
+- /**< Sesja do której przypisano połączenie */
+- struct gg_dcc7 *next; /**< Następne połączenie w liście */
+-
+- int soft_timeout; /**< Flaga mówiąca, że po przekroczeniu \c timeout należy wywołać \c gg_dcc7_watch_fd() */
+- int seek; /**< Flaga mówiąca, że można zmieniać położenie w wysyłanym pliku */
+-
+- void *resolver; /**< Dane prywatne procesu lub wątku rozwiązującego nazwę serwera */
+-
+- int relay; /**< Flaga mówiąca, że laczymy sie przez serwer */
+- int relay_index; /**< Numer serwera pośredniczącego, do którego się łączymy */
+- int relay_count; /**< Rozmiar listy serwerów pośredniczących */
+- struct gg_dcc7_relay *relay_list; /**< Lista serwerów pośredniczących */
+-};
+-
+-/**
+- * Rodzaj sesji.
+- */
+-enum gg_session_t {
+- GG_SESSION_GG = 1, /**< Połączenie z serwerem Gadu-Gadu */
+- GG_SESSION_HTTP, /**< Połączenie HTTP */
+- GG_SESSION_SEARCH, /**< Wyszukiwanie w katalogu publicznym (nieaktualne) */
+- GG_SESSION_REGISTER, /**< Rejestracja nowego konta */
+- GG_SESSION_REMIND, /**< Przypominanie hasła */
+- GG_SESSION_PASSWD, /**< Zmiana hasła */
+- GG_SESSION_CHANGE, /**< Zmiana informacji w katalogu publicznym (nieaktualne) */
+- GG_SESSION_DCC, /**< Połączenie bezpośrednie (do wersji 6.x) */
+- GG_SESSION_DCC_SOCKET, /**< Gniazdo nasłuchujące (do wersji 6.x) */
+- GG_SESSION_DCC_SEND, /**< Wysyłanie pliku (do wersji 6.x) */
+- GG_SESSION_DCC_GET, /**< Odbieranie pliku (do wersji 6.x) */
+- GG_SESSION_DCC_VOICE, /**< Rozmowa głosowa (do wersji 6.x) */
+- GG_SESSION_USERLIST_GET, /**< Import listy kontaktów z serwera (nieaktualne) */
+- GG_SESSION_USERLIST_PUT, /**< Eksport listy kontaktów do serwera (nieaktualne) */
+- GG_SESSION_UNREGISTER, /**< Usuwanie konta */
+- GG_SESSION_USERLIST_REMOVE, /**< Usuwanie listy kontaktów z serwera (nieaktualne) */
+- GG_SESSION_TOKEN, /**< Pobieranie tokenu */
+- GG_SESSION_DCC7_SOCKET, /**< Gniazdo nasłuchujące (od wersji 7.x) */
+- GG_SESSION_DCC7_SEND, /**< Wysyłanie pliku (od wersji 7.x) */
+- GG_SESSION_DCC7_GET, /**< Odbieranie pliku (od wersji 7.x) */
+- GG_SESSION_DCC7_VOICE, /**< Rozmowa głosowa (od wersji 7.x) */
+-
+- GG_SESSION_USER0 = 256, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER1, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER2, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER3, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER4, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER5, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER6, /**< Rodzaj zadeklarowany dla użytkownika */
+- GG_SESSION_USER7 /**< Rodzaj zadeklarowany dla użytkownika */
+-};
+-
+-/**
+- * Aktualny stan sesji.
+- */
+-enum gg_state_t {
+- /* wspólne */
+- GG_STATE_IDLE = 0, /**< Nie dzieje się nic */
+- GG_STATE_RESOLVING, /**< Oczekiwanie na rozwiązanie nazwy serwera */
+- GG_STATE_CONNECTING, /**< Oczekiwanie na połączenie */
+- GG_STATE_READING_DATA, /**< Oczekiwanie na dane */
+- GG_STATE_ERROR, /**< Kod błędu w polu \c error */
+-
+- /* gg_session */
+- GG_STATE_CONNECTING_HUB, /**< Oczekiwanie na połączenie z hubem */
+- GG_STATE_CONNECTING_GG, /**< Oczekiwanie na połączenie z serwerem */
+- GG_STATE_READING_KEY, /**< Oczekiwanie na klucz */
+- GG_STATE_READING_REPLY, /**< Oczekiwanie na odpowiedź serwera */
+- GG_STATE_CONNECTED, /**< Połączono z serwerem */
+-
+- /* gg_http */
+- GG_STATE_SENDING_QUERY, /**< Wysłano zapytanie HTTP */
+- GG_STATE_READING_HEADER, /**< Oczekiwanie na nagłówek HTTP */
+- GG_STATE_PARSING, /**< Przetwarzanie danych */
+- GG_STATE_DONE, /**< Połączenie zakończone */
+-
+- /* gg_dcc */
+- GG_STATE_LISTENING, /* czeka na połączenia */
+- GG_STATE_READING_UIN_1, /* czeka na uin peera */
+- GG_STATE_READING_UIN_2, /* czeka na swój uin */
+- GG_STATE_SENDING_ACK, /* wysyła potwierdzenie dcc */
+- GG_STATE_READING_ACK, /* czeka na potwierdzenie dcc */
+- GG_STATE_READING_REQUEST, /* czeka na komendę */
+- GG_STATE_SENDING_REQUEST, /* wysyła komendę */
+- GG_STATE_SENDING_FILE_INFO, /* wysyła informacje o pliku */
+- GG_STATE_READING_PRE_FILE_INFO, /* czeka na pakiet przed file_info */
+- GG_STATE_READING_FILE_INFO, /* czeka na informacje o pliku */
+- GG_STATE_SENDING_FILE_ACK, /* wysyła potwierdzenie pliku */
+- GG_STATE_READING_FILE_ACK, /* czeka na potwierdzenie pliku */
+- GG_STATE_SENDING_FILE_HEADER, /* wysyła nagłówek pliku */
+- GG_STATE_READING_FILE_HEADER, /* czeka na nagłówek */
+- GG_STATE_GETTING_FILE, /* odbiera plik */
+- GG_STATE_SENDING_FILE, /* wysyła plik */
+- GG_STATE_READING_VOICE_ACK, /* czeka na potwierdzenie voip */
+- GG_STATE_READING_VOICE_HEADER, /* czeka na rodzaj bloku voip */
+- GG_STATE_READING_VOICE_SIZE, /* czeka na rozmiar bloku voip */
+- GG_STATE_READING_VOICE_DATA, /* czeka na dane voip */
+- GG_STATE_SENDING_VOICE_ACK, /* wysyła potwierdzenie voip */
+- GG_STATE_SENDING_VOICE_REQUEST, /* wysyła żądanie voip */
+- GG_STATE_READING_TYPE, /* czeka na typ połączenia */
+-
+- /* nowe. bez sensu jest to API. */
+- GG_STATE_TLS_NEGOTIATION, /**< Negocjacja połączenia szyfrowanego */
+-
+- GG_STATE_REQUESTING_ID, /**< Oczekiwanie na nadanie identyfikatora połączenia bezpośredniego */
+- GG_STATE_WAITING_FOR_ACCEPT, /**< Oczekiwanie na potwierdzenie lub odrzucenie połączenia bezpośredniego */
+- GG_STATE_WAITING_FOR_INFO, /**< Oczekiwanie na informacje o połączeniu bezpośrednim */
+-
+- GG_STATE_READING_ID, /**< Odebranie identyfikatora połączenia bezpośredniego */
+- GG_STATE_SENDING_ID, /**< Wysłano identyfikator połączenia bezpośredniego */
+- GG_STATE_RESOLVING_GG, /**< Oczekiwanie na rozwiązanie nazwy serwera Gadu-Gadu */
+-
+- GG_STATE_RESOLVING_RELAY, /**< Oczekiwanie na rozwiązanie nazwy serwera pośredniczącego */
+- GG_STATE_CONNECTING_RELAY, /**< Oczekiwanie na połączenie z serwerem pośredniczącym */
+- GG_STATE_READING_RELAY, /**< Odbieranie danych */
+-
+- GG_STATE_DISCONNECTING, /**< Oczekiwanie na potwierdzenie rozłączenia */
+-};
+-
+-/**
+- * Informacja o tym, czy biblioteka chce zapisywać i/lub czytać
+- * z deskryptora. Maska bitowa.
+- *
+- * \ingroup events
+- */
+-enum gg_check_t {
+- GG_CHECK_NONE = 0, /**< Nie sprawdzaj niczego */
+- GG_CHECK_WRITE = 1, /**< Sprawdź możliwość zapisu */
+- GG_CHECK_READ = 2 /**< Sprawdź możliwość odczytu */
+-};
+-
+-/**
+- * Flaga połączenia szyfrowanego.
+- *
+- * \ingroup login
+- */
+-typedef enum {
+- GG_SSL_DISABLED = 0, /**< Połączenie SSL wyłączone */
+- GG_SSL_ENABLED, /**< Połączenie SSL włączone gdy dostępne */
+- GG_SSL_REQUIRED /**< Połączenie SSL wymagane */
+-} gg_ssl_t;
+-
+-/**
+- * Parametry połączenia z serwerem Gadu-Gadu. Parametry zostały przeniesione
+- * do struktury, by uniknąć zmian API po rozszerzeniu protokołu i dodaniu
+- * kolejnych opcji połączenia. Część parametrów, które nie są już aktualne
+- * lub nie mają znaczenia, została usunięta z dokumentacji.
+- *
+- * \ingroup login
+- */
+-struct gg_login_params {
+- uin_t uin; /**< Numer Gadu-Gadu */
+- char *password; /**< Hasło */
+- int async; /**< Flaga asynchronicznego połączenia (domyślnie nie) */
+- int status; /**< Początkowy status użytkownika (domyślnie \c GG_STATUS_AVAIL) */
+- char *status_descr; /**< Początkowy opis użytkownika (domyślnie brak) */
+- uint32_t server_addr; /**< Adres serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
+- uint16_t server_port; /**< Port serwera Gadu-Gadu (domyślnie pobierany automatycznie) */
+- uint32_t client_addr; /**< Adres połączeń bezpośrednich (domyślnie dobierany automatycznie) */
+- uint16_t client_port; /**< Port połączeń bezpośrednich (domyślnie dobierany automatycznie) */
+- int protocol_version; /**< Wersja protokołu wysyłana do serwera (domyślnie najnowsza obsługiwana) */
+- char *client_version; /**< Wersja klienta wysyłana do serwera (domyślnie najnowsza znana) */
+- int has_audio; /**< Flaga obsługi połączeń głosowych */
+- int last_sysmsg; /**< Numer ostatnio odebranej wiadomości systemowej */
+- uint32_t external_addr; /**< Adres publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
+- uint16_t external_port; /**< Port publiczny dla połączeń bezpośrednich (domyślnie dobierany automatycznie) */
+- int tls; /**< Flaga połączenia szyfrowanego (patrz \ref gg_ssl_t) */
+- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w kilobajtach */
+-#ifndef DOXYGEN
+- int era_omnix; /**< Flaga udawania klienta Era Omnix (nieaktualna) */
+-#endif
+- int hash_type; /**< Rodzaj skrótu hasła (\c GG_LOGIN_HASH_GG32 lub \c GG_LOGIN_HASH_SHA1, domyślnie SHA1) */
+- gg_encoding_t encoding; /**< Rodzaj kodowania używanego w sesji (domyślnie CP1250) */
+- gg_resolver_t resolver; /**< Sposób rozwiązywania nazw (patrz \ref build-resolver) */
+- int protocol_features; /**< Opcje protokołu (flagi GG_FEATURE_*). */
+- int status_flags; /**< Flagi statusu (flagi GG_STATUS_FLAG_*, patrz \ref status). */
+-
+-#ifndef DOXYGEN
+- char dummy[1 * sizeof(int)]; /**< \internal Miejsce na kilka kolejnych
+- parametrów, żeby wraz z dodawaniem kolejnych
+- parametrów nie zmieniał się rozmiar struktury */
+-#endif
+-
+-};
+-
+-struct gg_session *gg_login(const struct gg_login_params *p);
+-void gg_free_session(struct gg_session *sess);
+-void gg_logoff(struct gg_session *sess);
+-int gg_change_status(struct gg_session *sess, int status);
+-int gg_change_status_descr(struct gg_session *sess, int status, const char *descr);
+-int gg_change_status_descr_time(struct gg_session *sess, int status, const char *descr, int time);
+-int gg_change_status_flags(struct gg_session *sess, int flags);
+-int gg_send_message(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message);
+-int gg_send_message_richtext(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, const unsigned char *format, int formatlen);
+-int gg_send_message_confer(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message);
+-int gg_send_message_confer_richtext(struct gg_session *sess, int msgclass, int recipients_count, uin_t *recipients, const unsigned char *message, const unsigned char *format, int formatlen);
+-int gg_send_message_ctcp(struct gg_session *sess, int msgclass, uin_t recipient, const unsigned char *message, int message_len);
+-int gg_ping(struct gg_session *sess);
+-int gg_userlist_request(struct gg_session *sess, char type, const char *request);
+-int gg_userlist100_request(struct gg_session *sess, char type, unsigned int version, char format_type, const char *request);
+-int gg_image_request(struct gg_session *sess, uin_t recipient, int size, uint32_t crc32);
+-int gg_image_reply(struct gg_session *sess, uin_t recipient, const char *filename, const char *image, int size);
+-int gg_typing_notification(struct gg_session *sess, uin_t recipient, int length);
+-
+-uint32_t gg_crc32(uint32_t crc, const unsigned char *buf, int len);
+-
+-int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type);
+-gg_resolver_t gg_session_get_resolver(struct gg_session *gs);
+-int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
+-
+-int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type);
+-gg_resolver_t gg_http_get_resolver(struct gg_http *gh);
+-int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
+-
+-int gg_global_set_resolver(gg_resolver_t type);
+-gg_resolver_t gg_global_get_resolver(void);
+-int gg_global_set_custom_resolver(int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int));
+-
+-int gg_multilogon_disconnect(struct gg_session *gs, gg_multilogon_id_t conn_id);
+-
+-/**
+- * Rodzaj zdarzenia.
+- *
+- * \ingroup events
+- */
+-enum gg_event_t {
+- GG_EVENT_NONE = 0, /**< Nie wydarzyło się nic wartego uwagi */
+- GG_EVENT_MSG, /**< \brief Otrzymano wiadomość. Przekazuje również wiadomości systemowe od numeru 0. */
+- GG_EVENT_NOTIFY, /**< \brief Informacja o statusach osób z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
+- GG_EVENT_NOTIFY_DESCR, /**< \brief Informacja o statusie opisowym osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
+- GG_EVENT_STATUS, /**< \brief Zmiana statusu osoby z listy kontaktów (przed 6.0). Zdarzenie należy obsługiwać, jeśli planuje się używać protokołu w wersji starszej niż domyślna. */
+- GG_EVENT_ACK, /**< Potwierdzenie doręczenia wiadomości */
+- GG_EVENT_PONG, /**< \brief Utrzymanie połączenia. Obecnie serwer nie wysyła już do klienta ramek utrzymania połączenia, polega wyłącznie na wysyłaniu ramek przez klienta. */
+- GG_EVENT_CONN_FAILED, /**< \brief Nie udało się połączyć */
+- GG_EVENT_CONN_SUCCESS, /**< \brief Połączono z serwerem. Pierwszą rzeczą, jaką należy zrobić jest wysłanie listy kontaktów. */
+- GG_EVENT_DISCONNECT, /**< \brief Serwer zrywa połączenie. Zdarza się, gdy równolegle do serwera podłączy się druga sesja i trzeba zerwać połączenie z pierwszą. */
+-
+- GG_EVENT_DCC_NEW, /**< Nowe połączenie bezpośrednie (6.x) */
+- GG_EVENT_DCC_ERROR, /**< Błąd połączenia bezpośredniego (6.x) */
+- GG_EVENT_DCC_DONE, /**< Zakończono połączenie bezpośrednie (6.x) */
+- GG_EVENT_DCC_CLIENT_ACCEPT, /**< Moment akceptacji klienta w połączeniu bezpośrednim (6.x) */
+- GG_EVENT_DCC_CALLBACK, /**< Zwrotne połączenie bezpośrednie (6.x) */
+- GG_EVENT_DCC_NEED_FILE_INFO, /**< Należy wypełnić \c file_info dla połączenia bezpośredniego (6.x) */
+- GG_EVENT_DCC_NEED_FILE_ACK, /**< Czeka na potwierdzenie pliku w połączeniu bezpośrednim (6.x) */
+- GG_EVENT_DCC_NEED_VOICE_ACK, /**< Czeka na potwierdzenie rozmowy w połączeniu bezpośrednim (6.x) */
+- GG_EVENT_DCC_VOICE_DATA, /**< Dane bezpośredniego połączenia głosowego (6.x) */
+-
+- GG_EVENT_PUBDIR50_SEARCH_REPLY, /**< Odpowiedź katalogu publicznego */
+- GG_EVENT_PUBDIR50_READ, /**< Odczytano własne dane z katalogu publicznego */
+- GG_EVENT_PUBDIR50_WRITE, /**< Zmieniono własne dane w katalogu publicznym */
+-
+- GG_EVENT_STATUS60, /**< Zmiana statusu osoby z listy kontaktów */
+- GG_EVENT_NOTIFY60, /**< Informacja o statusach osób z listy kontaktów. Ostatni element tablicy zawiera uin równy 0, a pozostałe pola są niezainicjowane. */
+- GG_EVENT_USERLIST, /**< Wynik importu lub eksportu listy kontaktów */
+- GG_EVENT_IMAGE_REQUEST, /**< Żądanie przesłania obrazka z wiadomości */
+- GG_EVENT_IMAGE_REPLY, /**< Przysłano obrazek z wiadomości */
+- GG_EVENT_DCC_ACK, /**< Potwierdzenie transmisji w połączeniu bezpośrednim (6.x) */
+-
+- GG_EVENT_DCC7_NEW, /**< Nowe połączenie bezpośrednie (7.x) */
+- GG_EVENT_DCC7_ACCEPT, /**< Zaakceptowano połączenie bezpośrednie (7.x), nowy deskryptor */
+- GG_EVENT_DCC7_REJECT, /**< Odrzucono połączenie bezpośrednie (7.x) */
+- GG_EVENT_DCC7_CONNECTED, /**< Zestawiono połączenie bezpośrednie (7.x), nowy deskryptor */
+- GG_EVENT_DCC7_ERROR, /**< Błąd połączenia bezpośredniego (7.x) */
+- GG_EVENT_DCC7_DONE, /**< Zakończono połączenie bezpośrednie (7.x) */
+- GG_EVENT_DCC7_PENDING, /**< Trwa próba połączenia bezpośredniego (7.x), nowy deskryptor */
+-
+- GG_EVENT_XML_EVENT, /**< Otrzymano komunikat systemowy (7.7) */
+- GG_EVENT_DISCONNECT_ACK, /**< \brief Potwierdzenie zakończenia sesji. Informuje o tym, że zmiana stanu na niedostępny z opisem dotarła do serwera i można zakończyć połączenie TCP. */
+- GG_EVENT_TYPING_NOTIFICATION, /**< Powiadomienie o pisaniu */
+- GG_EVENT_USER_DATA, /**< Informacja o kontaktach */
+- GG_EVENT_MULTILOGON_MSG, /**< Wiadomość wysłana z innej sesji multilogowania */
+- GG_EVENT_MULTILOGON_INFO, /**< Informacja o innych sesjach multilogowania */
+-
+- GG_EVENT_USERLIST100_VERSION, /**< Otrzymano numer wersji listy kontaktów na serwerze (10.0) */
+- GG_EVENT_USERLIST100_REPLY, /**< Wynik importu lub eksportu listy kontaktów (10.0) */
+-};
+-
+-#define GG_EVENT_SEARCH50_REPLY GG_EVENT_PUBDIR50_SEARCH_REPLY
+-
+-/**
+- * Powód nieudanego połączenia.
+- */
+-enum gg_failure_t {
+- GG_FAILURE_RESOLVING = 1, /**< Nie znaleziono serwera */
+- GG_FAILURE_CONNECTING, /**< Błąd połączenia */
+- GG_FAILURE_INVALID, /**< Serwer zwrócił nieprawidłowe dane */
+- GG_FAILURE_READING, /**< Zerwano połączenie podczas odczytu */
+- GG_FAILURE_WRITING, /**< Zerwano połączenie podczas zapisu */
+- GG_FAILURE_PASSWORD, /**< Nieprawidłowe hasło */
+- GG_FAILURE_404, /**< Nieużywane */
+- GG_FAILURE_TLS, /**< Błąd negocjacji szyfrowanego połączenia */
+- GG_FAILURE_NEED_EMAIL, /**< Serwer rozłączył nas z prośbą o zmianę adresu e-mail */
+- GG_FAILURE_INTRUDER, /**< Zbyt wiele prób połączenia z nieprawidłowym hasłem */
+- GG_FAILURE_UNAVAILABLE, /**< Serwery są wyłączone */
+- GG_FAILURE_PROXY, /**< Błąd serwera pośredniczącego */
+- GG_FAILURE_HUB, /**< Błąd połączenia z hubem */
+-};
+-
+-/**
+- * Kod błędu danej operacji.
+- *
+- * Nie zawiera przesadnie szczegółowych informacji o powodach błędów, by nie
+- * komplikować ich obsługi. Jeśli wymagana jest większa dokładność, należy
+- * sprawdzić zawartość zmiennej systemowej \c errno.
+- */
+-enum gg_error_t {
+- GG_ERROR_RESOLVING = 1, /**< Nie znaleziono hosta */
+- GG_ERROR_CONNECTING, /**< Błąd połączenia */
+- GG_ERROR_READING, /**< Błąd odczytu/odbierania */
+- GG_ERROR_WRITING, /**< Błąd zapisu/wysyłania */
+-
+- GG_ERROR_DCC_HANDSHAKE, /**< Błąd negocjacji */
+- GG_ERROR_DCC_FILE, /**< Błąd odczytu/zapisu pliku */
+- GG_ERROR_DCC_EOF, /**< Przedwczesny koniec pliku */
+- GG_ERROR_DCC_NET, /**< Błąd wysyłania/odbierania */
+- GG_ERROR_DCC_REFUSED, /**< Połączenie odrzucone */
+-
+- GG_ERROR_DCC7_HANDSHAKE, /**< Błąd negocjacji */
+- GG_ERROR_DCC7_FILE, /**< Błąd odczytu/zapisu pliku */
+- GG_ERROR_DCC7_EOF, /**< Przedwczesny koniec pliku */
+- GG_ERROR_DCC7_NET, /**< Błąd wysyłania/odbierania */
+- GG_ERROR_DCC7_REFUSED, /**< Połączenie odrzucone */
+- GG_ERROR_DCC7_RELAY, /**< Problem z serwerem pośredniczącym */
+-};
+-
+-/**
+- * Pole zapytania lub odpowiedzi katalogu publicznego.
+- */
+-struct gg_pubdir50_entry {
+- int num; /**< Numer wyniku */
+- char *field; /**< Nazwa pola */
+- char *value; /**< Wartość pola */
+-} /* GG_DEPRECATED */;
+-
+-/**
+- * Zapytanie lub odpowiedź katalogu publicznego.
+- *
+- * Patrz \c gg_pubdir50_t.
+- */
+-struct gg_pubdir50_s {
+- int count; /**< Liczba wyników odpowiedzi */
+- uin_t next; /**< Numer początkowy następnego zapytania */
+- int type; /**< Rodzaj zapytania */
+- uint32_t seq; /**< Numer sekwencyjny */
+- struct gg_pubdir50_entry *entries; /**< Pola zapytania lub odpowiedzi */
+- int entries_count; /**< Liczba pól */
+-} /* GG_DEPRECATED */;
+-
+-/**
+- * Zapytanie lub odpowiedź katalogu publicznego.
+- *
+- * Do pól nie należy się odwoływać bezpośrednio -- wszystkie niezbędne
+- * informacje są dostępne za pomocą funkcji \c gg_pubdir50_*
+- */
+-typedef struct gg_pubdir50_s *gg_pubdir50_t;
+-
+-/**
+- * Opis zdarzeń \c GG_EVENT_MSG i \c GG_EVENT_MULTILOGON_MSG.
+- */
+-struct gg_event_msg {
+- uin_t sender; /**< Numer nadawcy/odbiorcy */
+- int msgclass; /**< Klasa wiadomości */
+- time_t time; /**< Czas nadania */
+- unsigned char *message; /**< Treść wiadomości */
+-
+- int recipients_count; /**< Liczba odbiorców konferencji */
+- uin_t *recipients; /**< Odbiorcy konferencji */
+-
+- int formats_length; /**< Długość informacji o formatowaniu tekstu */
+- void *formats; /**< Informacje o formatowaniu tekstu */
+- uint32_t seq; /**< Numer sekwencyjny wiadomości */
+-
+- char *xhtml_message; /**< Treść wiadomości w formacie XHTML (może być równe \c NULL, jeśli wiadomość nie zawiera treści XHTML) */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_NOTIFY_DESCR.
+- */
+-struct gg_event_notify_descr {
+- struct gg_notify_reply *notify; /**< Informacje o liście kontaktów */
+- char *descr; /**< Opis status */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_STATUS.
+- */
+-struct gg_event_status {
+- uin_t uin; /**< Numer Gadu-Gadu */
+- uint32_t status; /**< Nowy status */
+- char *descr; /**< Opis */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_STATUS60.
+- */
+-struct gg_event_status60 {
+- uin_t uin; /**< Numer Gadu-Gadu */
+- int status; /**< Nowy status */
+- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
+- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
+- int version; /**< Wersja protokołu */
+- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
+- char *descr; /**< Opis statusu */
+- time_t time; /**< Czas powrotu */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_NOTIFY_REPLY60.
+- */
+-struct gg_event_notify60 {
+- uin_t uin; /**< Numer Gadu-Gadu. W ostatnim elemencie jest równy 0, a pozostałe pola są niezainicjowane. */
+- int status; /**< Nowy status */
+- uint32_t remote_ip; /**< Adres IP dla połączeń bezpośrednich */
+- uint16_t remote_port; /**< Port dla połączeń bezpośrednich */
+- int version; /**< Wersja protokołu */
+- int image_size; /**< Maksymalny rozmiar obsługiwanych obrazków w KiB */
+- char *descr; /**< Opis statusu */
+- time_t time; /**< Czas powrotu */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_ACK.
+- */
+-struct gg_event_ack {
+- uin_t recipient; /**< Numer odbiorcy */
+- int status; /**< Status doręczenia */
+- int seq; /**< Numer sekwencyjny wiadomości */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_USERLIST.
+- */
+-struct gg_event_userlist {
+- char type; /**< Rodzaj odpowiedzi */
+- char *reply; /**< Treść odpowiedzi */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC_VOICE_DATA.
+- */
+-struct gg_event_dcc_voice_data {
+- uint8_t *data; /**< Dane dźwiękowe */
+- int length; /**< Rozmiar danych dźwiękowych */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_IMAGE_REQUEST.
+- */
+-struct gg_event_image_request {
+- uin_t sender; /**< Nadawca żądania */
+- uint32_t size; /**< Rozmiar obrazka */
+- uint32_t crc32; /**< Suma kontrolna CRC32 */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_IMAGE_REPLY.
+- */
+-struct gg_event_image_reply {
+- uin_t sender; /**< Nadawca obrazka */
+- uint32_t size; /**< Rozmiar obrazka */
+- uint32_t crc32; /**< Suma kontrolna CRC32 */
+- char *filename; /**< Nazwa pliku */
+- char *image; /**< Bufor z obrazkiem */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_XML_EVENT.
+- */
+-struct gg_event_xml_event {
+- char *data; /**< Bufor z komunikatem */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC7_CONNECTED.
+- */
+-struct gg_event_dcc7_connected {
+- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC7_PENDING.
+- */
+-struct gg_event_dcc7_pending {
+- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC7_REJECT.
+- */
+-struct gg_event_dcc7_reject {
+- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
+- int reason; /**< powód odrzucenia */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC7_ACCEPT.
+- */
+-struct gg_event_dcc7_accept {
+- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
+- int type; /**< Sposób połączenia (P2P, przez serwer) */
+- uint32_t remote_ip; /**< Adres zdalnego klienta */
+- uint16_t remote_port; /**< Port zdalnego klienta */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_DCC7_DONE.
+- */
+-struct gg_event_dcc7_done {
+- struct gg_dcc7 *dcc7; /**< Struktura połączenia */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_TYPING_NOTIFICATION.
+- */
+-struct gg_event_typing_notification {
+- uin_t uin; /**< Numer rozmówcy */
+- int length; /**< Długość tekstu */
+-};
+-
+-/**
+- * Atrybut użytkownika.
+- */
+-struct gg_event_user_data_attr {
+- int type; /**< Typ atrybutu */
+- char *key; /**< Klucz */
+- char *value; /**< Wartość */
+-};
+-
+-/**
+- * Struktura opisująca kontakt w zdarzeniu GG_EVENT_USER_DATA.
+- */
+-struct gg_event_user_data_user {
+- uin_t uin; /**< Numer kontaktu */
+- size_t attr_count; /**< Liczba atrybutów */
+- struct gg_event_user_data_attr *attrs; /**< Lista atrybutów */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_USER_DATA.
+- */
+-struct gg_event_user_data {
+- int type; /**< Rodzaj informacji o kontaktach */
+- size_t user_count; /**< Liczba kontaktów */
+- struct gg_event_user_data_user *users; /**< Lista kontaktów */
+-};
+-
+-/**
+- * Struktura opisująca sesję multilogowania.
+- */
+-struct gg_multilogon_session {
+- gg_multilogon_id_t id; /**< Identyfikator sesji */
+- char *name; /**< Nazwa sesji (podana w \c gg_login_params.client_version) */
+- uint32_t remote_addr; /**< Adres sesji */
+- int status_flags; /**< Flagi statusu sesji */
+- int protocol_features; /**< Opcje protokolu sesji */
+- time_t logon_time; /**< Czas zalogowania */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_MULTILOGON_INFO.
+- */
+-struct gg_event_multilogon_info {
+- int count; /**< Liczba sesji */
+- struct gg_multilogon_session *sessions; /** Lista sesji */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_USERLIST100_VERSION.
+- */
+-struct gg_event_userlist100_version {
+- uint32_t version; /**< Numer wersji listy kontaktów na serwerze */
+-};
+-
+-/**
+- * Opis zdarzenia \c GG_EVENT_USERLIST100_REPLY.
+- */
+-struct gg_event_userlist100_reply {
+- char type; /**< Rodzaj odpowiedzi */
+- uint32_t version; /**< Aktualna wersja listy kontaktów na serwerze */
+- char format_type; /**< Typ formatu listy kontaktów (żądany w \c gg_userlist100_request.format_type) */
+- char *reply; /**< Treść listy kontaktów w przesyłanej wersji i formacie */
+-};
+-
+-/**
+- * Unia wszystkich zdarzeń zwracanych przez funkcje \c gg_watch_fd(),
+- * \c gg_dcc_watch_fd() i \c gg_dcc7_watch_fd().
+- *
+- * \ingroup events
+- */
+-union gg_event_union {
+- enum gg_failure_t failure; /**< Błąd połączenia (\c GG_EVENT_CONN_FAILED) */
+- struct gg_notify_reply *notify; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY) */
+- struct gg_event_notify_descr notify_descr; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY_DESCR) */
+- struct gg_event_status status; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS) */
+- struct gg_event_status60 status60; /**< Zmiana statusu kontaktów (\c GG_EVENT_STATUS60) */
+- struct gg_event_notify60 *notify60; /**< Zmiana statusu kontaktów (\c GG_EVENT_NOTIFY60) */
+- struct gg_event_msg msg; /**< Otrzymano wiadomość (\c GG_EVENT_MSG) */
+- struct gg_event_ack ack; /**< Potwierdzenie wiadomości (\c GG_EVENT_ACK) */
+- struct gg_event_image_request image_request; /**< Żądanie wysłania obrazka (\c GG_EVENT_IMAGE_REQUEST) */
+- struct gg_event_image_reply image_reply; /**< Odpowiedź z obrazkiem (\c GG_EVENT_IMAGE_REPLY) */
+- struct gg_event_userlist userlist; /**< Odpowiedź listy kontaktów (\c GG_EVENT_USERLIST) */
+- gg_pubdir50_t pubdir50; /**< Odpowiedź katalogu publicznego (\c GG_EVENT_PUBDIR50_*) */
+- struct gg_event_xml_event xml_event; /**< Zdarzenie systemowe (\c GG_EVENT_XML_EVENT) */
+- struct gg_dcc *dcc_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC_NEW) */
+- enum gg_error_t dcc_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC_ERROR) */
+- struct gg_event_dcc_voice_data dcc_voice_data; /**< Dane połączenia głosowego (\c GG_EVENT_DCC_VOICE_DATA) */
+- struct gg_dcc7 *dcc7_new; /**< Nowe połączenie bezpośrednie (\c GG_EVENT_DCC7_NEW) */
+- enum gg_error_t dcc7_error; /**< Błąd połączenia bezpośredniego (\c GG_EVENT_DCC7_ERROR) */
+- struct gg_event_dcc7_connected dcc7_connected; /**< Informacja o zestawieniu połączenia bezpośredniego (\c GG_EVENT_DCC7_CONNECTED) */
+- struct gg_event_dcc7_pending dcc7_pending; /**< Trwa próba połączenia bezpośredniego (\c GG_EVENT_DCC7_PENDING) */
+- struct gg_event_dcc7_reject dcc7_reject; /**< Odrzucono połączenia bezpośredniego (\c GG_EVENT_DCC7_REJECT) */
+- struct gg_event_dcc7_accept dcc7_accept; /**< Zaakceptowano połączenie bezpośrednie (\c GG_EVENT_DCC7_ACCEPT) */
+- struct gg_event_dcc7_done dcc7_done; /**< Zakończono połączenie bezpośrednie (\c GG_EVENT_DCC7_DONE) */
+- struct gg_event_typing_notification typing_notification; /**< Powiadomienie o pisaniu */
+- struct gg_event_user_data user_data; /**< Informacje o kontaktach */
+- struct gg_event_msg multilogon_msg; /**< Inna sesja wysłała wiadomość (\c GG_EVENT_MULTILOGON_MSG) */
+- struct gg_event_multilogon_info multilogon_info; /**< Informacja o innych sesjach multilogowania (\c GG_EVENT_MULTILOGON_INFO) */
+- struct gg_event_userlist100_version userlist100_version; /**< Informacja o numerze wersji listy kontaktów na serwerze (\c GG_EVENT_USERLIST100_VERSION) */
+- struct gg_event_userlist100_reply userlist100_reply; /**< Odpowiedź listy kontaktów (10.0) (\c GG_EVENT_USERLIST100_REPLY) */
+-};
+-
+-/**
+- * Opis zdarzenia.
+- *
+- * Zwracany przez funkcje \c gg_watch_fd(), \c gg_dcc_watch_fd()
+- * i \c gg_dcc7_watch_fd(). Po przeanalizowaniu należy zwolnić
+- * za pomocą \c gg_event_free().
+- *
+- * \ingroup events
+- */
+-struct gg_event {
+- int type; /**< Rodzaj zdarzenia */
+- union gg_event_union event; /**< Informacja o zdarzeniu */
+-};
+-
+-struct gg_event *gg_watch_fd(struct gg_session *sess);
+-void gg_event_free(struct gg_event *e);
+-
+-int gg_notify_ex(struct gg_session *sess, uin_t *userlist, char *types, int count);
+-int gg_notify(struct gg_session *sess, uin_t *userlist, int count);
+-int gg_add_notify_ex(struct gg_session *sess, uin_t uin, char type);
+-int gg_add_notify(struct gg_session *sess, uin_t uin);
+-int gg_remove_notify_ex(struct gg_session *sess, uin_t uin, char type);
+-int gg_remove_notify(struct gg_session *sess, uin_t uin);
+-
+-struct gg_http *gg_http_connect(const char *hostname, int port, int async, const char *method, const char *path, const char *header);
+-int gg_http_watch_fd(struct gg_http *h);
+-void gg_http_stop(struct gg_http *h);
+-void gg_http_free(struct gg_http *h);
+-
+-uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req);
+-gg_pubdir50_t gg_pubdir50_new(int type);
+-int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value);
+-int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq);
+-const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field);
+-int gg_pubdir50_type(gg_pubdir50_t res);
+-int gg_pubdir50_count(gg_pubdir50_t res);
+-uin_t gg_pubdir50_next(gg_pubdir50_t res);
+-uint32_t gg_pubdir50_seq(gg_pubdir50_t res);
+-void gg_pubdir50_free(gg_pubdir50_t res);
+-
+-#ifndef DOXYGEN
+-
+-#define GG_PUBDIR50_UIN "FmNumber"
+-#define GG_PUBDIR50_STATUS "FmStatus"
+-#define GG_PUBDIR50_FIRSTNAME "firstname"
+-#define GG_PUBDIR50_LASTNAME "lastname"
+-#define GG_PUBDIR50_NICKNAME "nickname"
+-#define GG_PUBDIR50_BIRTHYEAR "birthyear"
+-#define GG_PUBDIR50_CITY "city"
+-#define GG_PUBDIR50_GENDER "gender"
+-#define GG_PUBDIR50_GENDER_FEMALE "1"
+-#define GG_PUBDIR50_GENDER_MALE "2"
+-#define GG_PUBDIR50_GENDER_SET_FEMALE "2"
+-#define GG_PUBDIR50_GENDER_SET_MALE "1"
+-#define GG_PUBDIR50_ACTIVE "ActiveOnly"
+-#define GG_PUBDIR50_ACTIVE_TRUE "1"
+-#define GG_PUBDIR50_START "fmstart"
+-#define GG_PUBDIR50_FAMILYNAME "familyname"
+-#define GG_PUBDIR50_FAMILYCITY "familycity"
+-
+-#else
+-
+-/**
+- * \ingroup pubdir50
+- *
+- * Rodzaj pola zapytania.
+- */
+-enum {
+- GG_PUBDIR50_UIN, /**< Numer Gadu-Gadu */
+- GG_PUBDIR50_STATUS, /**< Status (tylko wynik wyszukiwania) */
+- GG_PUBDIR50_FIRSTNAME, /**< Imię */
+- GG_PUBDIR50_LASTNAME, /**< Nazwisko */
+- GG_PUBDIR50_NICKNAME, /**< Pseudonim */
+- GG_PUBDIR50_BIRTHYEAR, /**< Rok urodzenia lub przedział lat oddzielony spacją */
+- GG_PUBDIR50_CITY, /**< Miejscowość */
+- GG_PUBDIR50_GENDER, /**< Płeć */
+- GG_PUBDIR50_ACTIVE, /**< Osoba dostępna (tylko wyszukiwanie) */
+- GG_PUBDIR50_START, /**< Numer początkowy wyszukiwania (tylko wyszukiwanie) */
+- GG_PUBDIR50_FAMILYNAME, /**< Nazwisko rodowe (tylko wysyłanie informacji o sobie) */
+- GG_PUBDIR50_FAMILYCITY, /**< Miejscowość pochodzenia (tylko wysyłanie informacji o sobie) */
+-};
+-
+-/**
+- * \ingroup pubdir50
+- *
+- * Wartość pola GG_PUBDIR50_GENDER przy wyszukiwaniu. Brak pola oznacza dowolną płeć.
+- */
+-enum {
+- GG_PUBDIR50_GENDER_FEMALE, /**< Kobieta */
+- GG_PUBDIR50_GENDER_MALE, /**< Mężczyzna */
+-};
+-
+-/**
+- * \ingroup pubdir50
+- *
+- * Wartość pola GG_PUBDIR50_GENDER przy wysyłaniu informacji o sobie.
+- */
+-enum {
+- GG_PUBDIR50_GENDER_SET_FEMALE, /**< Kobieta */
+- GG_PUBDIR50_GENDER_SET_MALE, /**< Mężczyzna */
+-};
+-
+-/**
+- * \ingroup pubdir50
+- *
+- * Wartość pola GG_PUBDIR50_ACTIVE.
+- */
+-enum {
+- GG_PUBDIR50_ACTIVE_TRUE, /**< Wyszukaj tylko osoby dostępne */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Wynik operacji na katalogu publicznym.
+- *
+- * \ingroup http
+- */
+-struct gg_pubdir {
+- int success; /**< Flaga powodzenia operacji */
+- uin_t uin; /**< Otrzymany numer lub 0 w przypadku błędu */
+-};
+-
+-int gg_pubdir_watch_fd(struct gg_http *f);
+-void gg_pubdir_free(struct gg_http *f);
+-
+-/**
+- * Token autoryzacji niektórych operacji HTTP.
+- *
+- * \ingroup token
+- */
+-struct gg_token {
+- int width; /**< Szerokość obrazka */
+- int height; /**< Wysokość obrazka */
+- int length; /**< Liczba znaków w tokenie */
+- char *tokenid; /**< Identyfikator tokenu */
+-};
+-
+-struct gg_http *gg_token(int async);
+-int gg_token_watch_fd(struct gg_http *h);
+-void gg_token_free(struct gg_http *h);
+-
+-struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async);
+-#ifndef DOXYGEN
+-#define gg_register_watch_fd gg_pubdir_watch_fd
+-#define gg_register_free gg_pubdir_free
+-#endif
+-
+-struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async);
+-#ifndef DOXYGEN
+-#define gg_unregister_watch_fd gg_pubdir_watch_fd
+-#define gg_unregister_free gg_pubdir_free
+-#endif
+-
+-struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async);
+-#ifndef DOXYGEN
+-#define gg_remind_passwd_watch_fd gg_pubdir_watch_fd
+-#define gg_remind_passwd_free gg_pubdir_free
+-#endif
+-
+-struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async);
+-#ifndef DOXYGEN
+-#define gg_change_passwd_watch_fd gg_pubdir_watch_fd
+-#define gg_change_passwd_free gg_pubdir_free
+-#endif
+-
+-extern int gg_dcc_port;
+-extern unsigned long gg_dcc_ip;
+-
+-int gg_dcc_request(struct gg_session *sess, uin_t uin);
+-
+-struct gg_dcc *gg_dcc_send_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
+-struct gg_dcc *gg_dcc_get_file(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
+-struct gg_dcc *gg_dcc_voice_chat(uint32_t ip, uint16_t port, uin_t my_uin, uin_t peer_uin);
+-void gg_dcc_set_type(struct gg_dcc *d, int type);
+-int gg_dcc_fill_file_info(struct gg_dcc *d, const char *filename);
+-int gg_dcc_fill_file_info2(struct gg_dcc *d, const char *filename, const char *local_filename);
+-int gg_dcc_voice_send(struct gg_dcc *d, char *buf, int length);
+-
+-#define GG_DCC_VOICE_FRAME_LENGTH 195 /**< Rozmiar pakietu głosowego przed wersją Gadu-Gadu 5.0.5 */
+-#define GG_DCC_VOICE_FRAME_LENGTH_505 326 /**< Rozmiar pakietu głosowego od wersji Gadu-Gadu 5.0.5 */
+-
+-struct gg_dcc *gg_dcc_socket_create(uin_t uin, uint16_t port);
+-#ifndef DOXYGEN
+-#define gg_dcc_socket_free gg_dcc_free
+-#define gg_dcc_socket_watch_fd gg_dcc_watch_fd
+-#endif
+-
+-struct gg_event *gg_dcc_watch_fd(struct gg_dcc *d);
+-
+-void gg_dcc_free(struct gg_dcc *c);
+-
+-struct gg_event *gg_dcc7_watch_fd(struct gg_dcc7 *d);
+-struct gg_dcc7 *gg_dcc7_send_file(struct gg_session *sess, uin_t rcpt, const char *filename, const char *filename1250, const char *hash);
+-struct gg_dcc7 *gg_dcc7_send_file_fd(struct gg_session *sess, uin_t rcpt, int fd, size_t size, const char *filename1250, const char *hash);
+-int gg_dcc7_accept(struct gg_dcc7 *dcc, unsigned int offset);
+-int gg_dcc7_reject(struct gg_dcc7 *dcc, int reason);
+-void gg_dcc7_free(struct gg_dcc7 *d);
+-
+-extern int gg_debug_level;
+-
+-extern void (*gg_debug_handler)(int level, const char *format, va_list ap);
+-extern void (*gg_debug_handler_session)(struct gg_session *sess, int level, const char *format, va_list ap);
+-
+-extern FILE *gg_debug_file;
+-
+-/**
+- * \ingroup debug
+- * @{
+- */
+-#define GG_DEBUG_NET 1 /**< Rejestracja zdarzeń związanych z siecią */
+-#define GG_DEBUG_TRAFFIC 2 /**< Rejestracja ruchu sieciowego */
+-#define GG_DEBUG_DUMP 4 /**< Rejestracja zawartości pakietów */
+-#define GG_DEBUG_FUNCTION 8 /**< Rejestracja wywołań funkcji */
+-#define GG_DEBUG_MISC 16 /**< Rejestracja różnych informacji */
+-/** @} */
+-
+-#ifdef GG_DEBUG_DISABLE
+-#define gg_debug(x, y...) do { } while(0)
+-#define gg_debug_session(z, x, y...) do { } while(0)
+-#else
+-void gg_debug(int level, const char *format, ...);
+-void gg_debug_session(struct gg_session *sess, int level, const char *format, ...);
+-#endif
+-
+-const char *gg_libgadu_version(void);
+-
+-/**
+- * Lista funkcji biblioteki, które zależą od zewnętrznych bibliotek.
+- *
+- * \ingroup version
+- */
+-typedef enum {
+- GG_LIBGADU_FEATURE_SSL, /**< Biblioteka obsługuje połączenia szyfrowane */
+- GG_LIBGADU_FEATURE_PTHREAD, /**< Biblioteka obsługuje rozwiązywanie nazw za pomocą wątków */
+- GG_LIBGADU_FEATURE_USERLIST100, /**< Biblioteka obsługuje listę kontaktów zgodną z Gadu-Gadu 10 */
+-} gg_libgadu_feature_t;
+-
+-int gg_libgadu_check_feature(gg_libgadu_feature_t feature);
+-
+-extern int gg_proxy_enabled;
+-extern char *gg_proxy_host;
+-extern int gg_proxy_port;
+-extern char *gg_proxy_username;
+-extern char *gg_proxy_password;
+-extern int gg_proxy_http_only;
+-
+-extern unsigned long gg_local_ip;
+-
+-#define GG_LOGIN_HASH_GG32 0x01 /**< Algorytm Gadu-Gadu */
+-#define GG_LOGIN_HASH_SHA1 0x02 /**< Algorytm SHA1 */
+-
+-#ifndef DOXYGEN
+-
+-#define GG_PUBDIR50_WRITE 0x01
+-#define GG_PUBDIR50_READ 0x02
+-#define GG_PUBDIR50_SEARCH 0x03
+-#define GG_PUBDIR50_SEARCH_REQUEST GG_PUBDIR50_SEARCH
+-#define GG_PUBDIR50_SEARCH_REPLY 0x05
+-
+-#else
+-
+-/**
+- * \ingroup pubdir50
+- *
+- * Rodzaj zapytania lub odpowiedzi katalogu publicznego.
+- */
+-enum {
+- GG_PUBDIR50_WRITE, /**< Wysłanie do serwera informacji o sobie */
+- GG_PUBDIR50_READ, /**< Pobranie z serwera informacji o sobie */
+- GG_PUBDIR50_SEARCH, /**< Wyszukiwanie w katalogu publicznym */
+- GG_PUBDIR50_SEARCH_REPLY, /**< Wynik wyszukiwania w katalogu publicznym */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-/** \cond obsolete */
+-
+-#define gg_free_event gg_event_free
+-#define gg_free_http gg_http_free
+-#define gg_free_pubdir gg_pubdir_free
+-#define gg_free_register gg_pubdir_free
+-#define gg_free_remind_passwd gg_pubdir_free
+-#define gg_free_dcc gg_dcc_free
+-#define gg_free_change_passwd gg_pubdir_free
+-
+-struct gg_search_request {
+- int active;
+- unsigned int start;
+- char *nickname;
+- char *first_name;
+- char *last_name;
+- char *city;
+- int gender;
+- int min_birth;
+- int max_birth;
+- char *email;
+- char *phone;
+- uin_t uin;
+-} /* GG_DEPRECATED */;
+-
+-struct gg_search {
+- int count;
+- struct gg_search_result *results;
+-} GG_DEPRECATED;
+-
+-struct gg_search_result {
+- uin_t uin;
+- char *first_name;
+- char *last_name;
+- char *nickname;
+- int born;
+- int gender;
+- char *city;
+- int active;
+-} GG_DEPRECATED;
+-
+-#define GG_GENDER_NONE 0
+-#define GG_GENDER_FEMALE 1
+-#define GG_GENDER_MALE 2
+-
+-struct gg_http *gg_search(const struct gg_search_request *r, int async) GG_DEPRECATED;
+-int gg_search_watch_fd(struct gg_http *f) GG_DEPRECATED;
+-void gg_free_search(struct gg_http *f) GG_DEPRECATED;
+-#define gg_search_free gg_free_search
+-
+-const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start) GG_DEPRECATED;
+-const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start) GG_DEPRECATED;
+-const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start) GG_DEPRECATED;
+-const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start) GG_DEPRECATED;
+-void gg_search_request_free(struct gg_search_request *r) GG_DEPRECATED;
+-
+-struct gg_http *gg_register(const char *email, const char *password, int async) GG_DEPRECATED;
+-struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async) GG_DEPRECATED;
+-
+-struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async) GG_DEPRECATED;
+-struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async) GG_DEPRECATED;
+-
+-struct gg_http *gg_remind_passwd(uin_t uin, int async) GG_DEPRECATED;
+-struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async) GG_DEPRECATED;
+-
+-struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async) GG_DEPRECATED;
+-struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async) GG_DEPRECATED;
+-struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async) GG_DEPRECATED;
+-
+-struct gg_change_info_request {
+- char *first_name;
+- char *last_name;
+- char *nickname;
+- char *email;
+- int born;
+- int gender;
+- char *city;
+-} /* GG_DEPRECATED */;
+-
+-struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city) GG_DEPRECATED;
+-void gg_change_info_request_free(struct gg_change_info_request *r) GG_DEPRECATED;
+-
+-struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async) GG_DEPRECATED;
+-#define gg_change_pubdir_watch_fd gg_pubdir_watch_fd
+-#define gg_change_pubdir_free gg_pubdir_free
+-#define gg_free_change_pubdir gg_pubdir_free
+-
+-struct gg_http *gg_userlist_get(uin_t uin, const char *password, int async) GG_DEPRECATED;
+-int gg_userlist_get_watch_fd(struct gg_http *f) GG_DEPRECATED;
+-void gg_userlist_get_free(struct gg_http *f) GG_DEPRECATED;
+-
+-struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async) GG_DEPRECATED;
+-int gg_userlist_put_watch_fd(struct gg_http *f) GG_DEPRECATED;
+-void gg_userlist_put_free(struct gg_http *f) GG_DEPRECATED;
+-
+-struct gg_http *gg_userlist_remove(uin_t uin, const char *password, int async) GG_DEPRECATED;
+-int gg_userlist_remove_watch_fd(struct gg_http *f) GG_DEPRECATED;
+-void gg_userlist_remove_free(struct gg_http *f) GG_DEPRECATED;
+-
+-int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length) GG_DEPRECATED;
+-
+-/** \endcond */
+-
+-int gg_file_hash_sha1(int fd, uint8_t *result) GG_DEPRECATED;
+-
+-#undef printf
+-#ifdef __GNUC__
+-char *gg_saprintf(const char *format, ...) __attribute__ ((format (printf, 1, 2))) GG_DEPRECATED;
+-#else
+-char *gg_saprintf(const char *format, ...) GG_DEPRECATED;
+-#endif
+-
+-char *gg_vsaprintf(const char *format, va_list ap) GG_DEPRECATED;
+-
+-#define gg_alloc_sprintf gg_saprintf
+-
+-char *gg_get_line(char **ptr) GG_DEPRECATED;
+-
+-int gg_connect(void *addr, int port, int async) GG_DEPRECATED;
+-struct in_addr *gg_gethostbyname(const char *hostname) GG_DEPRECATED;
+-char *gg_read_line(int sock, char *buf, int length) GG_DEPRECATED;
+-void gg_chomp(char *line) GG_DEPRECATED;
+-char *gg_urlencode(const char *str) GG_DEPRECATED;
+-int gg_http_hash(const char *format, ...) GG_DEPRECATED;
+-void gg_http_free_fields(struct gg_http *h) GG_DEPRECATED;
+-int gg_read(struct gg_session *sess, char *buf, int length) GG_DEPRECATED;
+-int gg_write(struct gg_session *sess, const char *buf, int length) GG_DEPRECATED;
+-void *gg_recv_packet(struct gg_session *sess) GG_DEPRECATED;
+-int gg_send_packet(struct gg_session *sess, int type, ...) GG_DEPRECATED;
+-unsigned int gg_login_hash(const unsigned char *password, unsigned int seed) GG_DEPRECATED;
+-void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result) GG_DEPRECATED;
+-uint32_t gg_fix32(uint32_t x);
+-uint16_t gg_fix16(uint16_t x);
+-#define fix16 gg_fix16
+-#define fix32 gg_fix32
+-char *gg_proxy_auth(void) GG_DEPRECATED;
+-char *gg_base64_encode(const char *buf) GG_DEPRECATED;
+-char *gg_base64_decode(const char *buf) GG_DEPRECATED;
+-int gg_image_queue_remove(struct gg_session *s, struct gg_image_queue *q, int freeq) GG_DEPRECATED;
+-
+-/**
+- * Kolejka odbieranych obrazków.
+- */
+-struct gg_image_queue {
+- uin_t sender; /**< Nadawca obrazka */
+- uint32_t size; /**< Rozmiar obrazka */
+- uint32_t crc32; /**< Suma kontrolna CRC32 */
+- char *filename; /**< Nazwa pliku */
+- char *image; /**< Bufor z odebranymi danymi */
+- uint32_t done; /**< Rozmiar odebranych danych */
+-
+- struct gg_image_queue *next; /**< Kolejny element listy */
+-} GG_DEPRECATED;
+-
+-int gg_dcc7_handle_id(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
+-int gg_dcc7_handle_new(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
+-int gg_dcc7_handle_info(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
+-int gg_dcc7_handle_accept(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
+-int gg_dcc7_handle_reject(struct gg_session *sess, struct gg_event *e, const void *payload, int len) GG_DEPRECATED;
+-
+-#define GG_APPMSG_HOST "appmsg.gadu-gadu.pl"
+-#define GG_APPMSG_PORT 80
+-#define GG_PUBDIR_HOST "pubdir.gadu-gadu.pl"
+-#define GG_PUBDIR_PORT 80
+-#define GG_REGISTER_HOST "register.gadu-gadu.pl"
+-#define GG_REGISTER_PORT 80
+-#define GG_REMIND_HOST "retr.gadu-gadu.pl"
+-#define GG_REMIND_PORT 80
+-#define GG_RELAY_HOST "relay.gadu-gadu.pl"
+-#define GG_RELAY_PORT 80
+-
+-#define GG_DEFAULT_PORT 8074
+-#define GG_HTTPS_PORT 443
+-#define GG_HTTP_USERAGENT "Mozilla/4.7 [en] (Win98; I)"
+-
+-#define GG_DEFAULT_CLIENT_VERSION "10.1.0.11070"
+-#define GG_DEFAULT_PROTOCOL_VERSION 0x2e
+-#define GG_DEFAULT_TIMEOUT 30
+-#define GG_HAS_AUDIO_MASK 0x40000000
+-#define GG_HAS_AUDIO7_MASK 0x20000000
+-#define GG_ERA_OMNIX_MASK 0x04000000
+-#undef GG_LIBGADU_VERSION
+-
+-#ifndef DOXYGEN
+-
+-#define GG_FEATURE_MSG77 0x0001
+-#define GG_FEATURE_STATUS77 0x0002
+-#define GG_FEATURE_UNKNOWN_4 0x0004
+-#define GG_FEATURE_UNKNOWN_8 0x0008
+-#define GG_FEATURE_DND_FFC 0x0010
+-#define GG_FEATURE_IMAGE_DESCR 0x0020
+-#define GG_FEATURE_UNKNOWN_40 0x0040
+-#define GG_FEATURE_UNKNOWN_80 0x0080
+-#define GG_FEATURE_UNKNOWN_100 0x0100
+-#define GG_FEATURE_USER_DATA 0x0200
+-#define GG_FEATURE_MSG_ACK 0x0400
+-#define GG_FEATURE_UNKNOWN_800 0x0800
+-#define GG_FEATURE_UNKNOWN_1000 0x1000
+-#define GG_FEATURE_TYPING_NOTIFICATION 0x2000
+-#define GG_FEATURE_MULTILOGON 0x4000
+-
+-/* Poniższe makra zostały zachowane dla zgodności API */
+-#define GG_FEATURE_MSG80 0
+-#define GG_FEATURE_STATUS80 0
+-#define GG_FEATURE_STATUS80BETA 0
+-
+-#define GG_FEATURE_ALL (GG_FEATURE_MSG80 | GG_FEATURE_STATUS80 | GG_FEATURE_DND_FFC | GG_FEATURE_IMAGE_DESCR | GG_FEATURE_UNKNOWN_100 | GG_FEATURE_USER_DATA | GG_FEATURE_MSG_ACK | GG_FEATURE_TYPING_NOTIFICATION)
+-
+-#else
+-
+-/**
+- * \ingroup login
+- *
+- * Flagi opcji protokołu.
+- */
+-enum {
+- GG_FEATURE_MSG77, /**< Klient życzy sobie otrzymywać wiadomości zgodnie z protokołem 7.7 */
+- GG_FEATURE_STATUS77, /**< Klient życzy sobie otrzymywać zmiany stanu zgodnie z protokołem 7.7 */
+- GG_FEATURE_DND_FFC, /**< Klient obsługuje statusy "nie przeszkadzać" i "poGGadaj ze mną" */
+- GG_FEATURE_IMAGE_DESCR, /**< Klient obsługuje opisy graficzne oraz flagę \c GG_STATUS80_DESCR_MASK */
+-};
+-
+-
+-#endif
+-
+-#define GG_DEFAULT_DCC_PORT 1550
+-
+-struct gg_header {
+- uint32_t type; /* typ pakietu */
+- uint32_t length; /* długość reszty pakietu */
+-} GG_PACKED;
+-
+-#define GG_WELCOME 0x0001
+-#define GG_NEED_EMAIL 0x0014
+-
+-struct gg_welcome {
+- uint32_t key; /* klucz szyfrowania hasła */
+-} GG_PACKED;
+-
+-#define GG_LOGIN 0x000c
+-
+-struct gg_login {
+- uint32_t uin; /* mój numerek */
+- uint32_t hash; /* hash hasła */
+- uint32_t status; /* status na dzień dobry */
+- uint32_t version; /* moja wersja klienta */
+- uint32_t local_ip; /* mój adres ip */
+- uint16_t local_port; /* port, na którym słucham */
+-} GG_PACKED;
+-
+-#define GG_LOGIN_EXT 0x0013
+-
+-struct gg_login_ext {
+- uint32_t uin; /* mój numerek */
+- uint32_t hash; /* hash hasła */
+- uint32_t status; /* status na dzień dobry */
+- uint32_t version; /* moja wersja klienta */
+- uint32_t local_ip; /* mój adres ip */
+- uint16_t local_port; /* port, na którym słucham */
+- uint32_t external_ip; /* zewnętrzny adres ip */
+- uint16_t external_port; /* zewnętrzny port */
+-} GG_PACKED;
+-
+-#define GG_LOGIN60 0x0015
+-
+-struct gg_login60 {
+- uint32_t uin; /* mój numerek */
+- uint32_t hash; /* hash hasła */
+- uint32_t status; /* status na dzień dobry */
+- uint32_t version; /* moja wersja klienta */
+- uint8_t dunno1; /* 0x00 */
+- uint32_t local_ip; /* mój adres ip */
+- uint16_t local_port; /* port, na którym słucham */
+- uint32_t external_ip; /* zewnętrzny adres ip */
+- uint16_t external_port; /* zewnętrzny port */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno2; /* 0xbe */
+-} GG_PACKED;
+-
+-#define GG_LOGIN70 0x0019
+-
+-struct gg_login70 {
+- uint32_t uin; /* mój numerek */
+- uint8_t hash_type; /* rodzaj hashowania hasła */
+- uint8_t hash[64]; /* hash hasła dopełniony zerami */
+- uint32_t status; /* status na dzień dobry */
+- uint32_t version; /* moja wersja klienta */
+- uint8_t dunno1; /* 0x00 */
+- uint32_t local_ip; /* mój adres ip */
+- uint16_t local_port; /* port, na którym słucham */
+- uint32_t external_ip; /* zewnętrzny adres ip (???) */
+- uint16_t external_port; /* zewnętrzny port (???) */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno2; /* 0xbe */
+-} GG_PACKED;
+-
+-#define GG_LOGIN_OK 0x0003
+-
+-#define GG_LOGIN_FAILED 0x0009
+-
+-#define GG_PUBDIR50_REQUEST 0x0014
+-
+-struct gg_pubdir50_request {
+- uint8_t type; /* GG_PUBDIR50_* */
+- uint32_t seq; /* czas wysłania zapytania */
+-} GG_PACKED;
+-
+-#define GG_PUBDIR50_REPLY 0x000e
+-
+-struct gg_pubdir50_reply {
+- uint8_t type; /* GG_PUBDIR50_* */
+- uint32_t seq; /* czas wysłania zapytania */
+-} GG_PACKED;
+-
+-#define GG_NEW_STATUS 0x0002
+-
+-#ifndef DOXYGEN
+-
+-#define GG_STATUS_NOT_AVAIL 0x0001
+-#define GG_STATUS_NOT_AVAIL_DESCR 0x0015
+-#define GG_STATUS_FFC 0x0017
+-#define GG_STATUS_FFC_DESCR 0x0018
+-#define GG_STATUS_AVAIL 0x0002
+-#define GG_STATUS_AVAIL_DESCR 0x0004
+-#define GG_STATUS_BUSY 0x0003
+-#define GG_STATUS_BUSY_DESCR 0x0005
+-#define GG_STATUS_DND 0x0021
+-#define GG_STATUS_DND_DESCR 0x0022
+-#define GG_STATUS_INVISIBLE 0x0014
+-#define GG_STATUS_INVISIBLE_DESCR 0x0016
+-#define GG_STATUS_BLOCKED 0x0006
+-
+-#define GG_STATUS_IMAGE_MASK 0x0100
+-#define GG_STATUS_DESCR_MASK 0x4000
+-#define GG_STATUS_FRIENDS_MASK 0x8000
+-
+-#define GG_STATUS_FLAG_UNKNOWN 0x00000001
+-#define GG_STATUS_FLAG_VIDEO 0x00000002
+-#define GG_STATUS_FLAG_MOBILE 0x00100000
+-#define GG_STATUS_FLAG_SPAM 0x00800000
+-
+-#else
+-
+-/**
+- * Rodzaje statusów użytkownika.
+- *
+- * \ingroup status
+- */
+-enum {
+- GG_STATUS_NOT_AVAIL, /**< Niedostępny */
+- GG_STATUS_NOT_AVAIL_DESCR, /**< Niedostępny z opisem */
+- GG_STATUS_FFC, /**< PoGGadaj ze mną */
+- GG_STATUS_FFC_DESCR, /**< PoGGadaj ze mną z opisem */
+- GG_STATUS_AVAIL, /**< Dostępny */
+- GG_STATUS_AVAIL_DESCR, /**< Dostępny z opisem */
+- GG_STATUS_BUSY, /**< Zajęty */
+- GG_STATUS_BUSY_DESCR, /**< Zajęty z opisem */
+- GG_STATUS_DND, /**< Nie przeszkadzać */
+- GG_STATUS_DND_DESCR, /**< Nie przeszakdzać z opisem */
+- GG_STATUS_INVISIBLE, /**< Niewidoczny (tylko własny status) */
+- GG_STATUS_INVISIBLE_DESCR, /**< Niewidoczny z opisem (tylko własny status) */
+- GG_STATUS_BLOCKED, /**< Zablokowany (tylko status innych) */
+- GG_STATUS_IMAGE_MASK, /**< Flaga bitowa oznaczająca opis graficzny (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
+- GG_STATUS_DESCR_MASK, /**< Flaga bitowa oznaczająca status z opisem (tylko jeśli wybrano \c GG_FEATURE_IMAGE_DESCR) */
+- GG_STATUS_FRIENDS_MASK, /**< Flaga bitowa dostępności tylko dla znajomych */
+-};
+-
+-/**
+- * Rodzaje statusów użytkownika. Mapa bitowa.
+- *
+- * \ingroup status
+- */
+-enum {
+- GG_STATUS_FLAG_UNKNOWN, /**< Przeznaczenie nieznane, ale występuje zawsze */
+- GG_STATUS_FLAG_VIDEO, /**< Klient obsługuje wideorozmowy */
+- GG_STATUS_FLAG_MOBILE, /**< Klient mobilny (ikona telefonu komórkowego) */
+- GG_STATUS_FLAG_SPAM, /**< Klient chce otrzymywać linki od nieznajomych */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * \ingroup status
+- *
+- * Flaga bitowa dostepnosci informujaca ze mozemy voipowac
+- */
+-
+-#define GG_STATUS_VOICE_MASK 0x20000 /**< czy ma wlaczone audio (7.7) */
+-
+-/**
+- * \ingroup status
+- *
+- * Maksymalna długośc opisu.
+- */
+-#define GG_STATUS_DESCR_MAXSIZE 255
+-#define GG_STATUS_DESCR_MAXSIZE_PRE_8_0 70
+-
+-#define GG_STATUS_MASK 0xff
+-
+-/* GG_S_F() tryb tylko dla znajomych */
+-#define GG_S_F(x) (((x) & GG_STATUS_FRIENDS_MASK) != 0)
+-
+-/* GG_S() stan bez uwzględnienia dodatkowych flag */
+-#define GG_S(x) ((x) & GG_STATUS_MASK)
+-
+-
+-/* GG_S_FF() chętny do rozmowy */
+-#define GG_S_FF(x) (GG_S(x) == GG_STATUS_FFC || GG_S(x) == GG_STATUS_FFC_DESCR)
+-
+-/* GG_S_AV() dostępny */
+-#define GG_S_AV(x) (GG_S(x) == GG_STATUS_AVAIL || GG_S(x) == GG_STATUS_AVAIL_DESCR)
+-
+-/* GG_S_AW() zaraz wracam */
+-#define GG_S_AW(x) (GG_S(x) == GG_STATUS_BUSY || GG_S(x) == GG_STATUS_BUSY_DESCR)
+-
+-/* GG_S_DD() nie przeszkadzać */
+-#define GG_S_DD(x) (GG_S(x) == GG_STATUS_DND || GG_S(x) == GG_STATUS_DND_DESCR)
+-
+-/* GG_S_NA() niedostępny */
+-#define GG_S_NA(x) (GG_S(x) == GG_STATUS_NOT_AVAIL || GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR)
+-
+-/* GG_S_I() niewidoczny */
+-#define GG_S_I(x) (GG_S(x) == GG_STATUS_INVISIBLE || GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
+-
+-
+-/* GG_S_A() dostępny lub chętny do rozmowy */
+-#define GG_S_A(x) (GG_S_FF(x) || GG_S_AV(x))
+-
+-/* GG_S_B() zajęty lub nie przeszkadzać */
+-#define GG_S_B(x) (GG_S_AW(x) || GG_S_DD(x))
+-
+-
+-/* GG_S_D() stan opisowy */
+-#define GG_S_D(x) (GG_S(x) == GG_STATUS_NOT_AVAIL_DESCR || \
+- GG_S(x) == GG_STATUS_FFC_DESCR || \
+- GG_S(x) == GG_STATUS_AVAIL_DESCR || \
+- GG_S(x) == GG_STATUS_BUSY_DESCR || \
+- GG_S(x) == GG_STATUS_DND_DESCR || \
+- GG_S(x) == GG_STATUS_INVISIBLE_DESCR)
+-
+-/* GG_S_BL() blokowany lub blokujący */
+-#define GG_S_BL(x) (GG_S(x) == GG_STATUS_BLOCKED)
+-
+-/**
+- * Zmiana statusu (pakiet \c GG_NEW_STATUS i \c GG_NEW_STATUS80BETA)
+- */
+-struct gg_new_status {
+- uint32_t status; /**< Nowy status */
+-} GG_PACKED;
+-
+-#define GG_NOTIFY_FIRST 0x000f
+-#define GG_NOTIFY_LAST 0x0010
+-
+-#define GG_NOTIFY 0x0010
+-
+-struct gg_notify {
+- uint32_t uin; /* numerek danej osoby */
+- uint8_t dunno1; /* rodzaj wpisu w liście */
+-} GG_PACKED;
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USER_OFFLINE 0x01
+-#define GG_USER_NORMAL 0x03
+-#define GG_USER_BLOCKED 0x04
+-
+-#else
+-
+-/**
+- * \ingroup contacts
+- *
+- * Rodzaj kontaktu.
+- */
+-enum {
+- GG_USER_NORMAL, /**< Zwykły kontakt */
+- GG_USER_BLOCKED, /**< Zablokowany */
+- GG_USER_OFFLINE, /**< Niewidoczny dla kontaktu */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-#define GG_LIST_EMPTY 0x0012
+-
+-#define GG_NOTIFY_REPLY 0x000c /* tak, to samo co GG_LOGIN */
+-
+-struct gg_notify_reply {
+- uint32_t uin; /* numerek */
+- uint32_t status; /* status danej osoby */
+- uint32_t remote_ip; /* adres ip delikwenta */
+- uint16_t remote_port; /* port, na którym słucha klient */
+- uint32_t version; /* wersja klienta */
+- uint16_t dunno2; /* znowu port? */
+-} GG_PACKED;
+-
+-#define GG_NOTIFY_REPLY60 0x0011
+-
+-struct gg_notify_reply60 {
+- uint32_t uin; /* numerek plus flagi w MSB */
+- uint8_t status; /* status danej osoby */
+- uint32_t remote_ip; /* adres ip delikwenta */
+- uint16_t remote_port; /* port, na którym słucha klient */
+- uint8_t version; /* wersja klienta */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno1; /* 0x00 */
+-} GG_PACKED;
+-
+-#define GG_STATUS60 0x000f
+-
+-struct gg_status60 {
+- uint32_t uin; /* numerek plus flagi w MSB */
+- uint8_t status; /* status danej osoby */
+- uint32_t remote_ip; /* adres ip delikwenta */
+- uint16_t remote_port; /* port, na którym słucha klient */
+- uint8_t version; /* wersja klienta */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno1; /* 0x00 */
+-} GG_PACKED;
+-
+-#define GG_NOTIFY_REPLY77 0x0018
+-
+-struct gg_notify_reply77 {
+- uint32_t uin; /* numerek plus flagi w MSB */
+- uint8_t status; /* status danej osoby */
+- uint32_t remote_ip; /* adres ip delikwenta */
+- uint16_t remote_port; /* port, na którym słucha klient */
+- uint8_t version; /* wersja klienta */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno1; /* 0x00 */
+- uint32_t dunno2; /* ? */
+-} GG_PACKED;
+-
+-#define GG_STATUS77 0x0017
+-
+-struct gg_status77 {
+- uint32_t uin; /* numerek plus flagi w MSB */
+- uint8_t status; /* status danej osoby */
+- uint32_t remote_ip; /* adres ip delikwenta */
+- uint16_t remote_port; /* port, na którym słucha klient */
+- uint8_t version; /* wersja klienta */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno1; /* 0x00 */
+- uint32_t dunno2; /* ? */
+-} GG_PACKED;
+-
+-#define GG_ADD_NOTIFY 0x000d
+-#define GG_REMOVE_NOTIFY 0x000e
+-
+-struct gg_add_remove {
+- uint32_t uin; /* numerek */
+- uint8_t dunno1; /* bitmapa */
+-} GG_PACKED;
+-
+-#define GG_STATUS 0x0002
+-
+-struct gg_status {
+- uint32_t uin; /* numerek */
+- uint32_t status; /* nowy stan */
+-} GG_PACKED;
+-
+-#define GG_SEND_MSG 0x000b
+-
+-#ifndef DOXYGEN
+-
+-#define GG_CLASS_QUEUED 0x0001
+-#define GG_CLASS_OFFLINE GG_CLASS_QUEUED
+-#define GG_CLASS_MSG 0x0004
+-#define GG_CLASS_CHAT 0x0008
+-#define GG_CLASS_CTCP 0x0010
+-#define GG_CLASS_ACK 0x0020
+-#define GG_CLASS_EXT GG_CLASS_ACK /**< Dla kompatybilności wstecz */
+-
+-#else
+-
+-/**
+- * Klasy wiadomości. Wartości są maskami bitowymi, które w większości
+- * przypadków można łączyć (połączenie \c GG_CLASS_MSG i \c GG_CLASS_CHAT
+- * nie ma sensu).
+- *
+- * \ingroup messages
+- */
+-enum {
+- GG_CLASS_MSG, /**< Wiadomość ma pojawić się w osobnym oknie */
+- GG_CLASS_CHAT, /**< Wiadomość ma pojawić się w oknie rozmowy */
+- GG_CLASS_CTCP, /**< Wiadomość przeznaczona dla klienta Gadu-Gadu */
+- GG_CLASS_ACK, /**< Klient nie życzy sobie potwierdzenia */
+- GG_CLASS_QUEUED, /**< Wiadomość zakolejkowana na serwerze (tylko przy odbieraniu) */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Maksymalna długość wiadomości.
+- *
+- * \ingroup messages
+- */
+-#define GG_MSG_MAXSIZE 1989
+-
+-struct gg_send_msg {
+- uint32_t recipient;
+- uint32_t seq;
+- uint32_t msgclass;
+-} GG_PACKED;
+-
+-struct gg_msg_richtext {
+- uint8_t flag;
+- uint16_t length;
+-} GG_PACKED;
+-
+-/**
+- * Struktura opisująca formatowanie tekstu. W zależności od wartości pola
+- * \c font, zaraz za tą strukturą może wystąpić \c gg_msg_richtext_color
+- * lub \c gg_msg_richtext_image.
+- *
+- * \ingroup messages
+- */
+-struct gg_msg_richtext_format {
+- uint16_t position; /**< Początkowy znak formatowania (liczony od 0) */
+- uint8_t font; /**< Atrybuty formatowania */
+-} GG_PACKED;
+-
+-#ifndef DOXYGEN
+-
+-#define GG_FONT_BOLD 0x01
+-#define GG_FONT_ITALIC 0x02
+-#define GG_FONT_UNDERLINE 0x04
+-#define GG_FONT_COLOR 0x08
+-#define GG_FONT_IMAGE 0x80
+-
+-#else
+-
+-/**
+- * Atrybuty formatowania wiadomości.
+- *
+- * \ingroup messages
+- */
+-enum {
+- GG_FONT_BOLD,
+- GG_FONT_ITALIC,
+- GG_FONT_UNDERLINE,
+- GG_FONT_COLOR,
+- GG_FONT_IMAGE
+-};
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Struktura opisującą kolor tekstu dla atrybutu \c GG_FONT_COLOR.
+- *
+- * \ingroup messages
+- */
+-struct gg_msg_richtext_color {
+- uint8_t red; /**< Składowa czerwona koloru */
+- uint8_t green; /**< Składowa zielona koloru */
+- uint8_t blue; /**< Składowa niebieska koloru */
+-} GG_PACKED;
+-
+-/**
+- * Strukturya opisująca obrazek wstawiony do wiadomości dla atrubutu
+- * \c GG_FONT_IMAGE.
+- *
+- * \ingroup messages
+- */
+-struct gg_msg_richtext_image {
+- uint16_t unknown1; /**< Nieznane pole o wartości 0x0109 */
+- uint32_t size; /**< Rozmiar obrazka */
+- uint32_t crc32; /**< Suma kontrolna CRC32 obrazka */
+-} GG_PACKED;
+-
+-struct gg_msg_recipients {
+- uint8_t flag;
+- uint32_t count;
+-} GG_PACKED;
+-
+-struct gg_msg_image_request {
+- uint8_t flag;
+- uint32_t size;
+- uint32_t crc32;
+-} GG_PACKED;
+-
+-struct gg_msg_image_reply {
+- uint8_t flag;
+- uint32_t size;
+- uint32_t crc32;
+- /* char filename[]; */
+- /* char image[]; */
+-} GG_PACKED;
+-
+-#define GG_SEND_MSG_ACK 0x0005
+-
+-#ifndef DOXYGEN
+-
+-#define GG_ACK_BLOCKED 0x0001
+-#define GG_ACK_DELIVERED 0x0002
+-#define GG_ACK_QUEUED 0x0003
+-#define GG_ACK_MBOXFULL 0x0004
+-#define GG_ACK_NOT_DELIVERED 0x0006
+-
+-#else
+-
+-/**
+- * Status doręczenia wiadomości.
+- *
+- * \ingroup messages
+- */
+-enum
+-{
+- GG_ACK_DELIVERED, /**< Wiadomość dostarczono. */
+- GG_ACK_QUEUED, /**< Wiadomość zakolejkowano z powodu niedostępności odbiorcy. */
+- GG_ACK_BLOCKED, /**< Wiadomość zablokowana przez serwer (spam, świąteczne ograniczenia itd.) */
+- GG_ACK_MBOXFULL, /**< Wiadomości nie dostarczono z powodu zapełnionej kolejki wiadomości odbiorcy. */
+- GG_ACK_NOT_DELIVERED /**< Wiadomości nie dostarczono (tylko dla \c GG_CLASS_CTCP). */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-struct gg_send_msg_ack {
+- uint32_t status;
+- uint32_t recipient;
+- uint32_t seq;
+-} GG_PACKED;
+-
+-#define GG_RECV_MSG 0x000a
+-
+-struct gg_recv_msg {
+- uint32_t sender;
+- uint32_t seq;
+- uint32_t time;
+- uint32_t msgclass;
+-} GG_PACKED;
+-
+-#define GG_PING 0x0008
+-
+-#define GG_PONG 0x0007
+-
+-#define GG_DISCONNECTING 0x000b
+-
+-#define GG_USERLIST_REQUEST 0x0016
+-
+-#define GG_XML_EVENT 0x0027
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USERLIST_PUT 0x00
+-#define GG_USERLIST_PUT_MORE 0x01
+-#define GG_USERLIST_GET 0x02
+-
+-#else
+-
+-/**
+- * \ingroup importexport
+- *
+- * Rodzaj zapytania.
+- */
+-enum {
+- GG_USERLIST_PUT, /**< Eksport listy kontaktów. */
+- GG_USERLIST_GET, /**< Import listy kontaktów. */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-struct gg_userlist_request {
+- uint8_t type;
+-} GG_PACKED;
+-
+-#define GG_USERLIST_REPLY 0x0010
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USERLIST_PUT_REPLY 0x00
+-#define GG_USERLIST_PUT_MORE_REPLY 0x02
+-#define GG_USERLIST_GET_REPLY 0x06
+-#define GG_USERLIST_GET_MORE_REPLY 0x04
+-
+-#else
+-
+-/**
+- * \ingroup importexport
+- *
+- * Rodzaj odpowiedzi.
+- */
+-enum {
+- GG_USERLIST_PUT_REPLY, /**< Wyeksportowano listy kontaktów. */
+- GG_USERLIST_GET_REPLY, /**< Zaimportowano listę kontaktów. */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-struct gg_userlist_reply {
+- uint8_t type;
+-} GG_PACKED;
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USERLIST100_PUT 0x00
+-#define GG_USERLIST100_GET 0x02
+-
+-#else
+-
+-/**
+- * \ingroup importexport
+- *
+- * Rodzaj zapytania (10.0).
+- */
+-enum {
+- GG_USERLIST100_PUT, /**< Eksport listy kontaktów. */
+- GG_USERLIST100_GET, /**< Import listy kontaktów. */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USERLIST100_FORMAT_TYPE_NONE 0x00
+-#define GG_USERLIST100_FORMAT_TYPE_GG70 0x01
+-#define GG_USERLIST100_FORMAT_TYPE_GG100 0x02
+-
+-#else
+-
+-/**
+- * \ingroup importexport
+- *
+- * Typ formatu listy kontaktów (10.0).
+- */
+-enum {
+- GG_USERLIST100_FORMAT_TYPE_NONE, /**< Brak treści listy kontaktów. */
+- GG_USERLIST100_FORMAT_TYPE_GG70, /**< Format listy kontaktów zgodny z Gadu-Gadu 7.0. */
+- GG_USERLIST100_FORMAT_TYPE_GG100, /**< Format listy kontaktów zgodny z Gadu-Gadu 10.0. */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-#ifndef DOXYGEN
+-
+-#define GG_USERLIST100_REPLY_LIST 0x00
+-#define GG_USERLIST100_REPLY_ACK 0x10
+-#define GG_USERLIST100_REPLY_REJECT 0x12
+-
+-#else
+-
+-/**
+- * \ingroup importexport
+- *
+- * Typ odpowiedzi listy kontaktów (10.0).
+- */
+-enum {
+- GG_USERLIST100_REPLY_LIST, /**< W odpowiedzi znajduje się aktualna lista kontaktów na serwerze. */
+- GG_USERLIST100_REPLY_ACK, /**< Potwierdzenie odebrania nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer nowej wersji listy kontaktów. */
+- GG_USERLIST100_REPLY_REJECT, /**< Odmowa przyjęcia nowej wersji listy kontaktów. W polu \c gg_userlist100_reply.version znajduje się numer wersji listy kontaktów aktualnie przechowywanej przez serwer. */
+-};
+-
+-#endif /* DOXYGEN */
+-
+-struct gg_dcc_tiny_packet {
+- uint8_t type; /* rodzaj pakietu */
+-} GG_PACKED;
+-
+-struct gg_dcc_small_packet {
+- uint32_t type; /* rodzaj pakietu */
+-} GG_PACKED;
+-
+-struct gg_dcc_big_packet {
+- uint32_t type; /* rodzaj pakietu */
+- uint32_t dunno1; /* niewiadoma */
+- uint32_t dunno2; /* niewiadoma */
+-} GG_PACKED;
+-
+-/*
+- * póki co, nie znamy dokładnie protokołu. nie wiemy, co czemu odpowiada.
+- * nazwy są niepoważne i tymczasowe.
+- */
+-#define GG_DCC_WANT_FILE 0x0003 /* peer chce plik */
+-#define GG_DCC_HAVE_FILE 0x0001 /* więc mu damy */
+-#define GG_DCC_HAVE_FILEINFO 0x0003 /* niech ma informacje o pliku */
+-#define GG_DCC_GIMME_FILE 0x0006 /* peer jest pewny */
+-#define GG_DCC_CATCH_FILE 0x0002 /* wysyłamy plik */
+-
+-#define GG_DCC_FILEATTR_READONLY 0x0020
+-
+-#define GG_DCC_TIMEOUT_SEND 1800 /* 30 minut */
+-#define GG_DCC_TIMEOUT_GET 1800 /* 30 minut */
+-#define GG_DCC_TIMEOUT_FILE_ACK 300 /* 5 minut */
+-#define GG_DCC_TIMEOUT_VOICE_ACK 300 /* 5 minut */
+-
+-#define GG_DCC7_INFO 0x1f
+-
+-struct gg_dcc7_info {
+- uint32_t uin; /* numer nadawcy */
+- uint32_t type; /* sposób połączenia */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- char info[GG_DCC7_INFO_LEN]; /* informacje o połączeniu "ip port" */
+- char hash[GG_DCC7_INFO_HASH_LEN];/* skrót "ip" */
+-} GG_PACKED;
+-
+-#define GG_DCC7_NEW 0x20
+-
+-struct gg_dcc7_new {
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint32_t uin_from; /* numer nadawcy */
+- uint32_t uin_to; /* numer odbiorcy */
+- uint32_t type; /* rodzaj transmisji */
+- unsigned char filename[GG_DCC7_FILENAME_LEN]; /* nazwa pliku */
+- uint32_t size; /* rozmiar pliku */
+- uint32_t size_hi; /* rozmiar pliku (starsze bajty) */
+- unsigned char hash[GG_DCC7_HASH_LEN]; /* hash SHA1 */
+-} GG_PACKED;
+-
+-#define GG_DCC7_ACCEPT 0x21
+-
+-struct gg_dcc7_accept {
+- uint32_t uin; /* numer przyjmującego połączenie */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint32_t offset; /* offset przy wznawianiu transmisji */
+- uint32_t dunno1; /* 0x00000000 */
+-} GG_PACKED;
+-
+-// XXX API
+-#define GG_DCC7_TYPE_P2P 0x00000001 /**< Połączenie bezpośrednie */
+-#define GG_DCC7_TYPE_SERVER 0x00000002 /**< Połączenie przez serwer */
+-
+-#define GG_DCC7_REJECT 0x22
+-
+-struct gg_dcc7_reject {
+- uint32_t uin; /**< Numer odrzucającego połączenie */
+- gg_dcc7_id_t id; /**< Identyfikator połączenia */
+- uint32_t reason; /**< Powód rozłączenia */
+-} GG_PACKED;
+-
+-// XXX API
+-#define GG_DCC7_REJECT_BUSY 0x00000001 /**< Połączenie bezpośrednie już trwa, nie umiem obsłużyć więcej */
+-#define GG_DCC7_REJECT_USER 0x00000002 /**< Użytkownik odrzucił połączenie */
+-#define GG_DCC7_REJECT_VERSION 0x00000006 /**< Druga strona ma wersję klienta nieobsługującą połączeń bezpośrednich tego typu */
+-
+-#define GG_DCC7_ID_REQUEST 0x23
+-
+-struct gg_dcc7_id_request {
+- uint32_t type; /**< Rodzaj tranmisji */
+-} GG_PACKED;
+-
+-// XXX API
+-#define GG_DCC7_TYPE_VOICE 0x00000001 /**< Transmisja głosu */
+-#define GG_DCC7_TYPE_FILE 0x00000004 /**< transmisja pliku */
+-
+-#define GG_DCC7_ID_REPLY 0x23
+-
+-struct gg_dcc7_id_reply {
+- uint32_t type; /** Rodzaj transmisji */
+- gg_dcc7_id_t id; /** Przyznany identyfikator */
+-} GG_PACKED;
+-
+-#define GG_DCC7_DUNNO1 0x24
+-
+-struct gg_dcc7_dunno1 {
+- // XXX
+-} GG_PACKED;
+-
+-#define GG_DCC7_TIMEOUT_CONNECT 10 /* 10 sekund */
+-#define GG_DCC7_TIMEOUT_SEND 1800 /* 30 minut */
+-#define GG_DCC7_TIMEOUT_GET 1800 /* 30 minut */
+-#define GG_DCC7_TIMEOUT_FILE_ACK 300 /* 5 minut */
+-#define GG_DCC7_TIMEOUT_VOICE_ACK 300 /* 5 minut */
+-
+-#ifdef _WIN32
+-#pragma pack(pop)
+-#endif
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* __GG_LIBGADU_H */
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-internal.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-internal.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/libgadu-internal.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/libgadu-internal.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,44 +0,0 @@
+-/* $Id$ */
+-
+-/*
+- * (C) Copyright 2009 Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_INTERNAL_H
+-#define LIBGADU_INTERNAL_H
+-
+-#include "libgadu.h"
+-
+-struct gg_dcc7_relay {
+- uint32_t addr;
+- uint16_t port;
+- uint8_t family;
+-};
+-
+-typedef struct gg_dcc7_relay gg_dcc7_relay_t;
+-
+-int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length);
+-
+-int gg_resolve(int *fd, int *pid, const char *hostname);
+-int gg_resolve_pthread(int *fd, void **resolver, const char *hostname);
+-void gg_resolve_pthread_cleanup(void *resolver, int kill);
+-
+-#ifdef HAVE_UINT64_T
+-uint64_t gg_fix64(uint64_t x);
+-#endif
+-
+-#endif /* LIBGADU_INTERNAL_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/message.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/message.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,663 +0,0 @@
+-/*
+- * (C) Copyright 2001-2010 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file message.c
+- *
+- * \brief Obsługa wiadomości
+- *
+- * Plik zawiera funkcje dotyczące obsługi "klasy" gg_message_t, które
+- * w przyszłości zostaną dołączone do API. Obecnie używane są funkcje
+- * konwersji między tekstem z atrybutami i HTML.
+- */
+-
+-#include <stdlib.h>
+-#include <string.h>
+-#include <errno.h>
+-#include <limits.h>
+-#include <ctype.h>
+-
+-#include "message.h"
+-
+-#if 0
+-
+-gg_message_t *gg_message_new(void)
+-{
+- gg_message_t *gm;
+-
+- gm = malloc(sizeof(gg_message_t));
+-
+- if (gm == NULL)
+- return NULL;
+-
+- memset(gm, 0, sizeof(gg_message_t));
+-
+- gm->msgclass = GG_CLASS_CHAT;
+- gm->seq = (uint32_t) -1;
+-
+- return gm;
+-}
+-
+-int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, size_t recipient_count, char *text, char *html, char *attributes, size_t attributes_length, int auto_convert)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- memset(gm, 0, sizeof(gg_message_t));
+- gm->recipients = recipients;
+- gm->recipient_count = recipient_count;
+- gm->text = text;
+- gm->html = html;
+- gm->attributes = attributes;
+- gm->attributes_length = attributes_length;
+- gm->msgclass = msgclass;
+- gm->seq = seq;
+- gm->auto_convert = auto_convert;
+-
+- return 0;
+-}
+-
+-void gg_message_free(gg_message_t *gm)
+-{
+- if (gm == NULL) {
+- errno = EINVAL;
+- return;
+- }
+-
+- free(gm->text);
+- free(gm->text_converted);
+- free(gm->html);
+- free(gm->html_converted);
+- free(gm->recipients);
+- free(gm->attributes);
+-
+- free(gm);
+-}
+-
+-int gg_message_set_auto_convert(gg_message_t *gm, int auto_convert)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- gm->auto_convert = !!auto_convert;
+-
+- if (!gm->auto_convert) {
+- free(gm->text_converted);
+- free(gm->html_converted);
+- gm->text_converted = NULL;
+- gm->html_converted = NULL;
+- }
+-
+- return 0;
+-}
+-
+-int gg_message_get_auto_convert(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- return gm->auto_convert;
+-}
+-
+-int gg_message_set_recipients(gg_message_t *gm, const uin_t *recipients, size_t recipient_count)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (recipient_count >= INT_MAX / sizeof(uin_t)) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if ((recipients == NULL) || (recipient_count == 0)) {
+- free(gm->recipients);
+- gm->recipients = NULL;
+- gm->recipient_count = 0;
+- } else {
+- uin_t *tmp;
+-
+- tmp = realloc(gm->recipients, recipient_count * sizeof(uin_t));
+-
+- if (tmp == NULL)
+- return -1;
+-
+- memcpy(tmp, recipients, recipient_count * sizeof(uin_t));
+-
+- gm->recipients = tmp;
+- gm->recipient_count = recipient_count;
+- }
+-
+- return 0;
+-}
+-
+-int gg_message_set_recipient(gg_message_t *gm, uin_t recipient)
+-{
+- return gg_message_set_recipients(gm, &recipient, 1);
+-}
+-
+-int gg_message_get_recipients(gg_message_t *gm, const uin_t **recipients, size_t *recipient_count)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (recipients != NULL)
+- *recipients = gm->recipients;
+-
+- if (recipient_count != NULL)
+- *recipient_count = gm->recipient_count;
+-
+- return 0;
+-}
+-
+-uin_t gg_message_get_recipient(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, (uin_t) -1);
+-
+- if ((gm->recipients == NULL) || (gm->recipient_count < 1)) {
+- // errno = XXX;
+- return (uin_t) -1;
+- }
+-
+- return gm->recipients[0];
+-}
+-
+-int gg_message_set_class(gg_message_t *gm, uint32_t msgclass)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- gm->msgclass = msgclass;
+-
+- return 0;
+-}
+-
+-uint32_t gg_message_get_class(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
+-
+- return gm->msgclass;
+-}
+-
+-int gg_message_set_seq(gg_message_t *gm, uint32_t seq)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- gm->seq = seq;
+-
+- return 0;
+-}
+-
+-uint32_t gg_message_get_seq(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, (uint32_t) -1);
+-
+- return gm->seq;
+-}
+-
+-int gg_message_set_text(gg_message_t *gm, const char *text)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (text == NULL) {
+- free(gm->text);
+- gm->text = NULL;
+- } else {
+- char *tmp;
+-
+- tmp = strdup(text);
+-
+- if (tmp == NULL)
+- return -1;
+-
+- free(gm->text);
+- gm->text = tmp;
+- }
+-
+- free(gm->html_converted);
+- gm->html_converted = NULL;
+-
+- return 0;
+-}
+-
+-const char *gg_message_get_text(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, NULL);
+-
+- if (gm->text_converted != NULL)
+- return gm->text_converted;
+-
+- if (gm->text == NULL && gm->html != NULL && gm->auto_convert) {
+- size_t len;
+-
+- free(gm->text_converted);
+-
+- len = gg_message_html_to_text(NULL, gm->html);
+-
+- gm->text_converted = malloc(len + 1);
+-
+- if (gm->text_converted == NULL)
+- return NULL;
+-
+- gg_message_html_to_text(gm->text_converted, gm->html);
+-
+- return gm->text_converted;
+- }
+-
+- return gm->text;
+-}
+-
+-int gg_message_set_html(gg_message_t *gm, const char *html)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (html == NULL) {
+- free(gm->html);
+- gm->html = NULL;
+- } else {
+- char *tmp;
+-
+- tmp = strdup(html);
+-
+- if (tmp == NULL)
+- return -1;
+-
+- free(gm->html);
+- gm->html = tmp;
+- }
+-
+- free(gm->text_converted);
+- gm->text_converted = NULL;
+-
+- return 0;
+-}
+-
+-const char *gg_message_get_html(gg_message_t *gm)
+-{
+- GG_MESSAGE_CHECK(gm, NULL);
+-
+- if (gm->html_converted != NULL)
+- return gm->html_converted;
+-
+- if (gm->html == NULL && gm->text != NULL && gm->auto_convert) {
+- size_t len;
+-
+- free(gm->html_converted);
+-
+- len = gg_message_text_to_html(NULL, gm->text, gm->attributes, gm->attributes_length);
+-
+- gm->html_converted = malloc(len + 1);
+-
+- if (gm->html_converted == NULL)
+- return NULL;
+-
+- gg_message_text_to_html(gm->html_converted, gm->text, gm->attributes, gm->attributes_length);
+-
+- return gm->html_converted;
+- }
+-
+- return gm->html;
+-}
+-
+-int gg_message_set_attributes(gg_message_t *gm, const char *attributes, size_t length)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (length > 0xfffd) {
+- // errno = XXX;
+- return -1;
+- }
+-
+- if ((attributes == NULL) || (length == 0)) {
+- free(gm->attributes);
+- gm->attributes = NULL;
+- gm->attributes_length = 0;
+- } else {
+- char *tmp;
+-
+- tmp = realloc(gm->attributes, length);
+-
+- if (tmp == NULL)
+- return -1;
+-
+- gm->attributes = tmp;
+- gm->attributes_length = length;
+- }
+-
+- free(gm->html_converted);
+- gm->html_converted = NULL;
+-
+- return 0;
+-}
+-
+-int gg_message_get_attributes(gg_message_t *gm, const char **attributes, size_t *attributes_length)
+-{
+- GG_MESSAGE_CHECK(gm, -1);
+-
+- if (attributes != NULL)
+- *attributes = gm->attributes;
+-
+- if (attributes_length != NULL)
+- *attributes_length = gm->attributes_length;
+-
+- return 0;
+-}
+-
+-#endif
+-
+-/**
+- * \internal Dodaje tekst na koniec bufora.
+- *
+- * \param dst Wskaźnik na bufor roboczy
+- * \param pos Wskaźnik na aktualne położenie w buforze roboczym
+- * \param src Dodawany tekst
+- * \param len Długość dodawanego tekstu
+- */
+-static void gg_append(char *dst, size_t *pos, const void *src, int len)
+-{
+- if (dst != NULL)
+- memcpy(&dst[*pos], src, len);
+-
+- *pos += len;
+-}
+-
+-/**
+- * \internal Zamienia tekst z formatowaniem Gadu-Gadu na HTML.
+- *
+- * \param dst Bufor wynikowy (może być \c NULL)
+- * \param src Tekst źródłowy w UTF-8
+- * \param format Atrybuty tekstu źródłowego
+- * \param format_len Długość bloku atrybutów tekstu źródłowego
+- *
+- * \note Wynikowy tekst nie jest idealnym kodem HTML, ponieważ ma jak
+- * dokładniej odzwierciedlać to, co wygenerowałby oryginalny klient.
+- *
+- * \note Dokleja \c \\0 na końcu bufora wynikowego.
+- *
+- * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
+- */
+-size_t gg_message_text_to_html(char *dst, const char *src, const char *format, size_t format_len)
+-{
+- const char span_fmt[] = "<span style=\"color:#%02x%02x%02x; font-family:'MS Shell Dlg 2'; font-size:9pt; \">";
+- const int span_len = 75;
+- const char img_fmt[] = "<img name=\"%02x%02x%02x%02x%02x%02x%02x%02x\">";
+- const int img_len = 29;
+- int char_pos = 0;
+- int format_idx = 0;
+- unsigned char old_attr = 0;
+- const unsigned char *color = (const unsigned char*) "\x00\x00\x00";
+- int i;
+- size_t len;
+- const unsigned char *format_ = (const unsigned char*) format;
+-
+- len = 0;
+-
+- /* Nie mamy atrybutów dla pierwsze znaku, a tekst nie jest pusty, więc
+- * tak czy inaczej trzeba otworzyć <span>. */
+-
+- if (src[0] != 0 && (format_idx + 3 > format_len || (format_[format_idx] | (format_[format_idx + 1] << 8)) != 0)) {
+- if (dst != NULL)
+- sprintf(&dst[len], span_fmt, 0, 0, 0);
+-
+- len += span_len;
+- }
+-
+- /* Pętla przechodzi też przez kończące \0, żeby móc dokleić obrazek
+- * na końcu tekstu. */
+-
+- for (i = 0; ; i++) {
+- /* Analizuj atrybuty tak długo jak dotyczą aktualnego znaku. */
+- for (;;) {
+- unsigned char attr;
+- int attr_pos;
+-
+- if (format_idx + 3 > format_len)
+- break;
+-
+- attr_pos = format_[format_idx] | (format_[format_idx + 1] << 8);
+-
+- if (attr_pos != char_pos)
+- break;
+-
+- attr = format_[format_idx + 2];
+-
+- /* Nie doklejaj atrybutów na końcu, co najwyżej obrazki. */
+-
+- if (src[i] == 0)
+- attr &= ~(GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR);
+-
+- format_idx += 3;
+-
+- if ((attr & (GG_FONT_BOLD | GG_FONT_ITALIC | GG_FONT_UNDERLINE | GG_FONT_COLOR)) != 0 || (attr == 0 && old_attr != 0)) {
+- if (char_pos != 0) {
+- if ((old_attr & GG_FONT_UNDERLINE) != 0)
+- gg_append(dst, &len, "</u>", 4);
+-
+- if ((old_attr & GG_FONT_ITALIC) != 0)
+- gg_append(dst, &len, "</i>", 4);
+-
+- if ((old_attr & GG_FONT_BOLD) != 0)
+- gg_append(dst, &len, "</b>", 4);
+-
+- if (src[i] != 0)
+- gg_append(dst, &len, "</span>", 7);
+- }
+-
+- if (((attr & GG_FONT_COLOR) != 0) && (format_idx + 3 <= format_len)) {
+- color = &format_[format_idx];
+- format_idx += 3;
+- } else {
+- color = (unsigned char*) "\x00\x00\x00";
+- }
+-
+- if (src[i] != 0) {
+- if (dst != NULL)
+- sprintf(&dst[len], span_fmt, color[0], color[1], color[2]);
+- len += span_len;
+- }
+- } else if (char_pos == 0 && src[0] != 0) {
+- if (dst != NULL)
+- sprintf(&dst[len], span_fmt, 0, 0, 0);
+- len += span_len;
+- }
+-
+- if ((attr & GG_FONT_BOLD) != 0)
+- gg_append(dst, &len, "<b>", 3);
+-
+- if ((attr & GG_FONT_ITALIC) != 0)
+- gg_append(dst, &len, "<i>", 3);
+-
+- if ((attr & GG_FONT_UNDERLINE) != 0)
+- gg_append(dst, &len, "<u>", 3);
+-
+- if (((attr & GG_FONT_IMAGE) != 0) && (format_idx + 10 <= format_len)) {
+- if (dst != NULL) {
+- sprintf(&dst[len], img_fmt,
+- format_[format_idx + 9],
+- format_[format_idx + 8],
+- format_[format_idx + 7],
+- format_[format_idx + 6],
+- format_[format_idx + 5],
+- format_[format_idx + 4],
+- format_[format_idx + 3],
+- format_[format_idx + 2]);
+- }
+-
+- len += img_len;
+- format_idx += 10;
+- }
+-
+- old_attr = attr;
+- }
+-
+- /* Doklej znak zachowując htmlowe escapowanie. */
+-
+- switch (src[i]) {
+- case '&':
+- gg_append(dst, &len, "&amp;", 5);
+- break;
+- case '<':
+- gg_append(dst, &len, "&lt;", 4);
+- break;
+- case '>':
+- gg_append(dst, &len, "&gt;", 4);
+- break;
+- case '\'':
+- gg_append(dst, &len, "&apos;", 6);
+- break;
+- case '\"':
+- gg_append(dst, &len, "&quot;", 6);
+- break;
+- case '\n':
+- gg_append(dst, &len, "<br>", 4);
+- break;
+- case '\r':
+- case 0:
+- break;
+- default:
+- if (dst != NULL)
+- dst[len] = src[i];
+- len++;
+- }
+-
+- /* Sprawdź, czy bajt nie jest kontynuacją znaku unikodowego. */
+-
+- if ((src[i] & 0xc0) != 0xc0)
+- char_pos++;
+-
+- if (src[i] == 0)
+- break;
+- }
+-
+- /* Zamknij tagi. */
+-
+- if ((old_attr & GG_FONT_UNDERLINE) != 0)
+- gg_append(dst, &len, "</u>", 4);
+-
+- if ((old_attr & GG_FONT_ITALIC) != 0)
+- gg_append(dst, &len, "</i>", 4);
+-
+- if ((old_attr & GG_FONT_BOLD) != 0)
+- gg_append(dst, &len, "</b>", 4);
+-
+- if (src[0] != 0)
+- gg_append(dst, &len, "</span>", 7);
+-
+- if (dst != NULL)
+- dst[len] = 0;
+-
+- return len;
+-}
+-
+-/**
+- * \internal Zamienia tekst w formacie HTML na czysty tekst.
+- *
+- * \param dst Bufor wynikowy (może być \c NULL)
+- * \param html Tekst źródłowy
+- *
+- * \note Dokleja \c \\0 na końcu bufora wynikowego.
+- *
+- * \note Funkcja służy do zachowania kompatybilności przy przesyłaniu
+- * wiadomości HTML do klientów, które tego formatu nie obsługują. Z tego
+- * powodu funkcja nie zachowuje formatowania, a jedynie usuwa tagi i
+- * zamienia podstawowe encje na ich odpowiedniki ASCII.
+- *
+- * \return Długość tekstu wynikowego bez \c \\0 (nawet jeśli \c dst to \c NULL).
+- */
+-size_t gg_message_html_to_text(char *dst, const char *html)
+-{
+- const char *src, *entity, *tag;
+- int in_tag, in_entity;
+- size_t len;
+-
+- len = 0;
+- in_tag = 0;
+- tag = NULL;
+- in_entity = 0;
+- entity = NULL;
+-
+- for (src = html; *src != 0; src++) {
+- if (in_entity && !(isalnum(*src) || *src == '#' || *src == ';')) {
+- in_entity = 0;
+- gg_append(dst, &len, entity, src - entity);
+- }
+-
+- if (*src == '<') {
+- tag = src;
+- in_tag = 1;
+- continue;
+- }
+-
+- if (in_tag && (*src == '>')) {
+- if (strncmp(tag, "<br", 3) == 0) {
+- if (dst != NULL)
+- dst[len] = '\n';
+- len++;
+- }
+- in_tag = 0;
+- continue;
+- }
+-
+- if (in_tag)
+- continue;
+-
+- if (*src == '&') {
+- in_entity = 1;
+- entity = src;
+- continue;
+- }
+-
+- if (in_entity && *src == ';') {
+- in_entity = 0;
+- if (dst != NULL) {
+- if (strncmp(entity, "&lt;", 4) == 0)
+- dst[len++] = '<';
+- else if (strncmp(entity, "&gt;", 4) == 0)
+- dst[len++] = '>';
+- else if (strncmp(entity, "&quot;", 6) == 0)
+- dst[len++] = '"';
+- else if (strncmp(entity, "&apos;", 6) == 0)
+- dst[len++] = '\'';
+- else if (strncmp(entity, "&amp;", 5) == 0)
+- dst[len++] = '&';
+- else if (strncmp(entity, "&nbsp;", 6) == 0) {
+- dst[len++] = 0xc2;
+- dst[len++] = 0xa0;
+- } else
+- dst[len++] = '?';
+- } else {
+- if (strncmp(entity, "&nbsp;", 6) == 0)
+- len += 2;
+- else
+- len++;
+- }
+-
+- continue;
+- }
+-
+- if (in_entity && !(isalnum(*src) || *src == '#'))
+- in_entity = 0;
+-
+- if (in_entity)
+- continue;
+-
+- if (dst != NULL)
+- dst[len] = *src;
+-
+- len++;
+- }
+-
+- if (dst != NULL)
+- dst[len] = 0;
+-
+- return len;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/message.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/message.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/message.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,56 +0,0 @@
+-/*
+- * (C) Copyright 2009 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_MESSAGE_H
+-#define LIBGADU_MESSAGE_H
+-
+-#include <sys/types.h>
+-#include <inttypes.h>
+-#include "libgadu.h"
+-
+-#if 0
+-
+-struct gg_message {
+- uin_t *recipients;
+- size_t recipient_count;
+- char *text;
+- char *html;
+- char *attributes;
+- size_t attributes_length;
+- uint32_t msgclass;
+- uint32_t seq;
+-
+- int auto_convert;
+- char *text_converted;
+- char *html_converted;
+-};
+-
+-#define GG_MESSAGE_CHECK(gm, result) \
+- if ((gm) == NULL) { \
+- errno = EINVAL; \
+- return (result); \
+- }
+-
+-int gg_message_init(gg_message_t *gm, int msgclass, int seq, uin_t *recipients, size_t recipient_count, char *text, char *xhtml, char *attributes, size_t attributes_length, int auto_convert);
+-
+-#endif
+-
+-size_t gg_message_html_to_text(char *dst, const char *html);
+-size_t gg_message_text_to_html(char *dst, const char *utf_msg, const char *format, size_t format_len);
+-
+-#endif /* LIBGADU_MESSAGE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/obsolete.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/obsolete.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/obsolete.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/obsolete.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,237 +0,0 @@
+-/* $Id: obsolete.c 1082 2011-04-08 17:50:14Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2003 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file obsolete.c
+- *
+- * \brief Nieaktualne funkcje
+- *
+- * Plik zawiera definicje funkcji, które są już nieaktualne ze względu
+- * na zmiany w protokole. Programy konsolidowane ze starszych wersjami
+- * bibliotek powinny nadal mieć możliwość działania, mimo ograniczonej
+- * funkcjonalności.
+- */
+-
+-/** \cond obsolete */
+-
+-#include <errno.h>
+-
+-#include "libgadu.h"
+-#include "libgadu-internal.h"
+-
+-struct gg_http *gg_userlist_get(uin_t uin, const char *passwd, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_userlist_get() is obsolete. use gg_userlist_request() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-int gg_userlist_get_watch_fd(struct gg_http *h)
+-{
+- errno = EINVAL;
+- return -1;
+-}
+-
+-void gg_userlist_get_free(struct gg_http *h)
+-{
+-
+-}
+-
+-struct gg_http *gg_userlist_put(uin_t uin, const char *password, const char *contacts, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_userlist_put() is obsolete. use gg_userlist_request() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-int gg_userlist_put_watch_fd(struct gg_http *h)
+-{
+- errno = EINVAL;
+- return -1;
+-}
+-
+-void gg_userlist_put_free(struct gg_http *h)
+-{
+-
+-}
+-
+-struct gg_http *gg_userlist_remove(uin_t uin, const char *passwd, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_userlist_remove() is obsolete. use gg_userlist_request() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-int gg_userlist_remove_watch_fd(struct gg_http *h)
+-{
+- errno = EINVAL;
+- return -1;
+-}
+-
+-void gg_userlist_remove_free(struct gg_http *h)
+-{
+-
+-}
+-
+-struct gg_http *gg_search(const struct gg_search_request *r, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_search() is obsolete. use gg_search50() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-int gg_search_watch_fd(struct gg_http *h)
+-{
+- errno = EINVAL;
+- return -1;
+-}
+-
+-void gg_search_free(struct gg_http *h)
+-{
+-
+-}
+-
+-const struct gg_search_request *gg_search_request_mode_0(char *nickname, char *first_name, char *last_name, char *city, int gender, int min_birth, int max_birth, int active, int start)
+-{
+- return NULL;
+-}
+-
+-const struct gg_search_request *gg_search_request_mode_1(char *email, int active, int start)
+-{
+- return NULL;
+-}
+-
+-const struct gg_search_request *gg_search_request_mode_2(char *phone, int active, int start)
+-{
+- return NULL;
+-}
+-
+-const struct gg_search_request *gg_search_request_mode_3(uin_t uin, int active, int start)
+-{
+- return NULL;
+-}
+-
+-void gg_search_request_free(struct gg_search_request *r)
+-{
+-
+-}
+-
+-struct gg_http *gg_register(const char *email, const char *password, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_register() is obsolete. use gg_register3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_register2(const char *email, const char *password, const char *qa, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_register2() is obsolete. use gg_register3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_unregister(uin_t uin, const char *password, const char *email, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_unregister() is obsolete. use gg_unregister3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_unregister2(uin_t uin, const char *password, const char *qa, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_unregister2() is obsolete. use gg_unregister3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-
+-struct gg_http *gg_change_passwd(uin_t uin, const char *passwd, const char *newpasswd, const char *newemail, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd() is obsolete. use gg_change_passwd4() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_change_passwd2(uin_t uin, const char *passwd, const char *newpasswd, const char *email, const char *newemail, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd2() is obsolete. use gg_change_passwd4() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_change_passwd3(uin_t uin, const char *passwd, const char *newpasswd, const char *qa, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_change_passwd3() is obsolete. use gg_change_passwd4() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_remind_passwd(uin_t uin, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd() is obsolete. use gg_remind_passwd3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_remind_passwd2(uin_t uin, const char *tokenid, const char *tokenval, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_remind_passwd2() is obsolete. use gg_remind_passwd3() instead!\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_http *gg_change_info(uin_t uin, const char *passwd, const struct gg_change_info_request *request, int async)
+-{
+- gg_debug(GG_DEBUG_MISC, "// gg_change_info() is obsolete. use gg_pubdir50() instead\n");
+- errno = EINVAL;
+- return NULL;
+-}
+-
+-struct gg_change_info_request *gg_change_info_request_new(const char *first_name, const char *last_name, const char *nickname, const char *email, int born, int gender, const char *city)
+-{
+- return NULL;
+-}
+-
+-void gg_change_info_request_free(struct gg_change_info_request *r)
+-{
+-
+-}
+-
+-int gg_resolve(int *fd, int *pid, const char *hostname)
+-{
+- return -1;
+-}
+-
+-void gg_resolve_pthread_cleanup(void *arg, int kill)
+-{
+-
+-}
+-
+-int gg_resolve_pthread(int *fd, void **resolver, const char *hostname)
+-{
+- return -1;
+-}
+-
+-int gg_pubdir50_handle_reply(struct gg_event *e, const char *packet, int length)
+-{
+- return -1;
+-}
+-
+-/** \endcond */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/protocol.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/protocol.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/protocol.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/protocol.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,326 +0,0 @@
+-/* $Id$ */
+-
+-/*
+- * (C) Copyright 2009-2010 Jakub Zawadzki <darkjames@darkjames.ath.cx>
+- * Bartłomiej Zimoń <uzi18@o2.pl>
+- * Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_PROTOCOL_H
+-#define LIBGADU_PROTOCOL_H
+-
+-#include "libgadu.h"
+-
+-#ifdef _WIN32
+-#pragma pack(push, 1)
+-#endif
+-
+-#define GG_LOGIN80BETA 0x0029
+-
+-#define GG_LOGIN80 0x0031
+-
+-#undef GG_FEATURE_STATUS80BETA
+-#undef GG_FEATURE_MSG80
+-#undef GG_FEATURE_STATUS80
+-#define GG_FEATURE_STATUS80BETA 0x01
+-#define GG_FEATURE_MSG80 0x02
+-#define GG_FEATURE_STATUS80 0x05
+-
+-#define GG8_LANG "pl"
+-#define GG8_VERSION "Gadu-Gadu Client Build "
+-
+-struct gg_login80 {
+- uint32_t uin; /* mój numerek */
+- uint8_t language[2]; /* język: GG8_LANG */
+- uint8_t hash_type; /* rodzaj hashowania hasła */
+- uint8_t hash[64]; /* hash hasła dopełniony zerami */
+- uint32_t status; /* status na dzień dobry */
+- uint32_t flags; /* flagi (przeznaczenie nieznane) */
+- uint32_t features; /* opcje protokołu (GG8_FEATURES) */
+- uint32_t local_ip; /* mój adres ip */
+- uint16_t local_port; /* port, na którym słucham */
+- uint32_t external_ip; /* zewnętrzny adres ip (???) */
+- uint16_t external_port; /* zewnętrzny port (???) */
+- uint8_t image_size; /* maksymalny rozmiar grafiki w KiB */
+- uint8_t dunno2; /* 0x64 */
+-} GG_PACKED;
+-
+-#define GG_LOGIN_HASH_TYPE_INVALID 0x0016
+-
+-#define GG_LOGIN80_OK 0x0035
+-
+-/**
+- * Logowanie powiodło się (pakiet \c GG_LOGIN80_OK)
+- */
+-struct gg_login80_ok {
+- uint32_t unknown1; /* 0x00000001 */
+-} GG_PACKED;
+-
+-/**
+- * Logowanie nie powiodło się (pakiet \c GG_LOGIN80_FAILED)
+- */
+-#define GG_LOGIN80_FAILED 0x0043
+-
+-struct gg_login80_failed {
+- uint32_t unknown1; /* 0x00000001 */
+-} GG_PACKED;
+-
+-#define GG_NEW_STATUS80BETA 0x0028
+-
+-#define GG_NEW_STATUS80 0x0038
+-
+-/**
+- * Zmiana stanu (pakiet \c GG_NEW_STATUS80)
+- */
+-struct gg_new_status80 {
+- uint32_t status; /**< Nowy status */
+- uint32_t flags; /**< flagi (nieznane przeznaczenie) */
+- uint32_t description_size; /**< rozmiar opisu */
+-} GG_PACKED;
+-
+-#define GG_STATUS80BETA 0x002a
+-#define GG_NOTIFY_REPLY80BETA 0x002b
+-
+-#define GG_STATUS80 0x0036
+-#define GG_NOTIFY_REPLY80 0x0037
+-
+-struct gg_notify_reply80 {
+- uint32_t uin; /* numerek plus flagi w najstarszym bajcie */
+- uint32_t status; /* status danej osoby */
+- uint32_t features; /* opcje protokołu */
+- uint32_t remote_ip; /* adres IP bezpośrednich połączeń */
+- uint16_t remote_port; /* port bezpośrednich połączeń */
+- uint8_t image_size; /* maksymalny rozmiar obrazków w KB */
+- uint8_t unknown1; /* 0x00 */
+- uint32_t flags; /* flagi połączenia */
+- uint32_t descr_len; /* rozmiar opisu */
+-} GG_PACKED;
+-
+-#define GG_SEND_MSG80 0x002d
+-
+-struct gg_send_msg80 {
+- uint32_t recipient;
+- uint32_t seq;
+- uint32_t msgclass;
+- uint32_t offset_plain;
+- uint32_t offset_attr;
+-} GG_PACKED;
+-
+-#define GG_RECV_MSG80 0x002e
+-
+-struct gg_recv_msg80 {
+- uint32_t sender;
+- uint32_t seq;
+- uint32_t time;
+- uint32_t msgclass;
+- uint32_t offset_plain;
+- uint32_t offset_attr;
+-} GG_PACKED;
+-
+-#define GG_DISCONNECT_ACK 0x000d
+-
+-#define GG_RECV_MSG_ACK 0x0046
+-
+-struct gg_recv_msg_ack {
+- uint32_t seq;
+-} GG_PACKED;
+-
+-#define GG_USER_DATA 0x0044
+-
+-struct gg_user_data {
+- uint32_t type;
+- uint32_t user_count;
+-} GG_PACKED;
+-
+-struct gg_user_data_user {
+- uint32_t uin;
+- uint32_t attr_count;
+-} GG_PACKED;
+-
+-#define GG_TYPING_NOTIFICATION 0x0059
+-
+-struct gg_typing_notification {
+- uint16_t length;
+- uint32_t uin;
+-} GG_PACKED;
+-
+-#define GG_XML_ACTION 0x002c
+-
+-#define GG_RECV_OWN_MSG 0x005a
+-
+-#define GG_MULTILOGON_INFO 0x005b
+-
+-struct gg_multilogon_info {
+- uint32_t count;
+-} GG_PACKED;
+-
+-struct gg_multilogon_info_item {
+- uint32_t addr;
+- uint32_t flags;
+- uint32_t features;
+- uint32_t logon_time;
+- gg_multilogon_id_t conn_id;
+- uint32_t unknown1;
+- uint32_t name_size;
+-} GG_PACKED;
+-
+-#define GG_MULTILOGON_DISCONNECT 0x0062
+-
+-struct gg_multilogon_disconnect {
+- gg_multilogon_id_t conn_id;
+-} GG_PACKED;
+-
+-#define GG_MSG_CALLBACK 0x02 /**< Żądanie zwrotnego połączenia bezpośredniego */
+-
+-#define GG_MSG_OPTION_CONFERENCE 0x01
+-#define GG_MSG_OPTION_ATTRIBUTES 0x02
+-#define GG_MSG_OPTION_IMAGE_REQUEST 0x04
+-#define GG_MSG_OPTION_IMAGE_REPLY 0x05
+-#define GG_MSG_OPTION_IMAGE_REPLY_MORE 0x06
+-
+-#define GG_DCC7_ABORT 0x0025
+-
+-struct gg_dcc7_abort {
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint32_t uin_from; /* numer nadawcy */
+- uint32_t uin_to; /* numer odbiorcy */
+-} GG_PACKED;
+-
+-#define GG_DCC7_ABORTED 0x0025
+-
+-struct gg_dcc7_aborted {
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+-} GG_PACKED;
+-
+-#define GG_DCC7_VOICE_RETRIES 0x11 /* 17 powtorzen */
+-
+-#define GG_DCC7_RESERVED1 0xdeadc0de
+-#define GG_DCC7_RESERVED2 0xdeadbeaf
+-
+-struct gg_dcc7_voice_auth {
+- uint8_t type; /* 0x00 -> wysylanie ID
+- 0x01 -> potwierdzenie ID
+- */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
+- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
+-} GG_PACKED;
+-
+-struct gg_dcc7_voice_nodata { /* wyciszony mikrofon, ten pakiet jest wysylany co 1s (jesli chcemy podtrzymac polaczenie) */
+- uint8_t type; /* 0x02 */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint32_t reserved1; /* GG_DCC7_RESERVED1 */
+- uint32_t reserved2; /* GG_DCC7_RESERVED2 */
+-} GG_PACKED;
+-
+-struct gg_dcc7_voice_data {
+- uint8_t type; /* 0x03 */
+- uint32_t did; /* XXX: co ile zwieksza sie u nas id pakietu [uzywac 0x28] */
+- uint32_t len; /* rozmiar strukturki - 1 (sizeof(type)) */
+- uint32_t packet_id; /* numerek pakietu */
+- uint32_t datalen; /* rozmiar danych */
+- /* char data[]; */ /* ramki: albo gsm, albo speex, albo melp, albo inne. */
+-} GG_PACKED;
+-
+-struct gg_dcc7_voice_init {
+- uint8_t type; /* 0x04 */
+- uint32_t id; /* nr kroku [0x1 - 0x5] */
+- uint32_t protocol; /* XXX: wersja protokolu (0x29, 0x2a, 0x2b) */
+- uint32_t len; /* rozmiar sizeof(protocol)+sizeof(len)+sizeof(data) = 0x08 + sizeof(data) */
+- /* char data[]; */ /* reszta danych */
+-} GG_PACKED;
+-
+-struct gg_dcc7_voice_init_confirm {
+- uint8_t type; /* 0x05 */
+- uint32_t id; /* id tego co potwierdzamy [0x1 - 0x5] */
+-} GG_PACKED;
+-
+-#define GG_DCC7_RELAY_TYPE_SERVER 0x01 /* adres serwera, na który spytać o proxy */
+-#define GG_DCC7_RELAY_TYPE_PROXY 0x08 /* adresy proxy, na które sie łączyć */
+-
+-#define GG_DCC7_RELAY_DUNNO1 0x02
+-
+-#define GG_DCC7_RELAY_REQUEST 0x0a
+-
+-struct gg_dcc7_relay_req {
+- uint32_t magic; /* 0x0a */
+- uint32_t len; /* długość całego pakietu */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+- uint16_t type; /* typ zapytania */
+- uint16_t dunno1; /* 0x02 */
+-} GG_PACKED;
+-
+-#define GG_DCC7_RELAY_REPLY_RCOUNT 0x02
+-
+-#define GG_DCC7_RELAY_REPLY 0x0b
+-
+-struct gg_dcc7_relay_reply {
+- uint32_t magic; /* 0x0b */
+- uint32_t len; /* długość całego pakietu */
+- uint32_t rcount; /* ilość serwerów */
+-} GG_PACKED;
+-
+-struct gg_dcc7_relay_reply_server {
+- uint32_t addr; /* adres ip serwera */
+- uint16_t port; /* port serwera */
+- uint8_t family; /* rodzina adresów (na końcu?!) AF_INET=2 */
+-} GG_PACKED;
+-
+-#define GG_DCC7_WELCOME_SERVER 0xc0debabe
+-
+-struct gg_dcc7_welcome_server {
+- uint32_t magic; /* 0xc0debabe */
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+-} GG_PACKED;
+-
+-struct gg_dcc7_welcome_p2p {
+- gg_dcc7_id_t id; /* identyfikator połączenia */
+-} GG_PACKED;
+-
+-#define GG_TIMEOUT_DISCONNECT 5 /**< Maksymalny czas oczekiwania na rozłączenie */
+-
+-#define GG_USERLIST100_VERSION 0x5c
+-
+-struct gg_userlist100_version {
+- uint32_t version; /* numer wersji listy kontaktów */
+-} GG_PACKED;
+-
+-#define GG_USERLIST100_REQUEST 0x0040
+-
+-struct gg_userlist100_request {
+- uint8_t type; /* rodzaj żądania */
+- uint32_t version; /* numer ostatniej znanej wersji listy kontaktów bądź 0 */
+- uint8_t format_type; /* rodzaj żądanego typu formatu listy kontaktów */
+- uint8_t unknown1; /* 0x01 */
+- /* char request[]; */
+-} GG_PACKED;
+-
+-#define GG_USERLIST100_REPLY 0x41
+-
+-struct gg_userlist100_reply {
+- uint8_t type; /* rodzaj odpowiedzi */
+- uint32_t version; /* numer wersji listy kontaktów aktualnie przechowywanej przez serwer */
+- uint8_t format_type; /* rodzaj przesyłanego typu formatu listy kontaktów */
+- uint8_t unknown1; /* 0x01 */
+- /* char reply[]; */
+-} GG_PACKED;
+-
+-#ifdef _WIN32
+-#pragma pack(pop)
+-#endif
+-
+-#endif /* LIBGADU_PROTOCOL_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir50.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir50.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir50.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir50.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,554 +0,0 @@
+-/*
+- * (C) Copyright 2003 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file pubdir50.c
+- *
+- * \brief Obsługa katalogu publicznego od wersji Gadu-Gadu 5.x
+- *
+- * \todo Zoptymalizować konwersję CP1250<->UTF8. Obecnie robiona jest
+- * testowa konwersja, żeby poznać długość tekstu wynikowego.
+- */
+-
+-#include <errno.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <time.h>
+-
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-#include "libgadu-internal.h"
+-#include "encoding.h"
+-
+-/**
+- * Tworzy nowe zapytanie katalogu publicznego.
+- *
+- * \param type Rodzaj zapytania
+- *
+- * \return Zmienna \c gg_pubdir50_t lub \c NULL w przypadku błędu.
+- *
+- * \ingroup pubdir50
+- */
+-gg_pubdir50_t gg_pubdir50_new(int type)
+-{
+- gg_pubdir50_t res = malloc(sizeof(struct gg_pubdir50_s));
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_new(%d);\n", type);
+-
+- if (!res) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_new() out of memory\n");
+- return NULL;
+- }
+-
+- memset(res, 0, sizeof(struct gg_pubdir50_s));
+-
+- res->type = type;
+-
+- return res;
+-}
+-
+-/**
+- * \internal Dodaje lub zastępuje pole zapytania lub odpowiedzi katalogu
+- * publicznego.
+- *
+- * \param req Zapytanie lub odpowiedź
+- * \param num Numer wyniku odpowiedzi (0 dla zapytania)
+- * \param field Nazwa pola
+- * \param value Wartość pola
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_pubdir50_add_n(gg_pubdir50_t req, int num, const char *field, const char *value)
+-{
+- struct gg_pubdir50_entry *tmp = NULL, *entry;
+- char *dupfield, *dupvalue;
+- int i;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_add_n(%p, %d, \"%s\", \"%s\");\n", req, num, field, value);
+-
+- if (!(dupvalue = strdup(value))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
+- return -1;
+- }
+-
+- for (i = 0; i < req->entries_count; i++) {
+- if (req->entries[i].num != num || strcmp(req->entries[i].field, field))
+- continue;
+-
+- free(req->entries[i].value);
+- req->entries[i].value = dupvalue;
+-
+- return 0;
+- }
+-
+- if (!(dupfield = strdup(field))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
+- free(dupvalue);
+- return -1;
+- }
+-
+- if (!(tmp = realloc(req->entries, sizeof(struct gg_pubdir50_entry) * (req->entries_count + 1)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_add_n() out of memory\n");
+- free(dupfield);
+- free(dupvalue);
+- return -1;
+- }
+-
+- req->entries = tmp;
+-
+- entry = &req->entries[req->entries_count];
+- entry->num = num;
+- entry->field = dupfield;
+- entry->value = dupvalue;
+-
+- req->entries_count++;
+-
+- return 0;
+-}
+-
+-/**
+- * Dodaje pole zapytania.
+- *
+- * \param req Zapytanie
+- * \param field Nazwa pola
+- * \param value Wartość pola
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-int gg_pubdir50_add(gg_pubdir50_t req, const char *field, const char *value)
+-{
+- return gg_pubdir50_add_n(req, 0, field, value);
+-}
+-
+-/**
+- * Ustawia numer sekwencyjny zapytania.
+- *
+- * \param req Zapytanie
+- * \param seq Numer sekwencyjny
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-int gg_pubdir50_seq_set(gg_pubdir50_t req, uint32_t seq)
+-{
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_seq_set(%p, %d);\n", req, seq);
+-
+- if (!req) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_seq_set() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- req->seq = seq;
+-
+- return 0;
+-}
+-
+-/**
+- * Zwalnia zasoby po zapytaniu lub odpowiedzi katalogu publicznego.
+- *
+- * \param s Zapytanie lub odpowiedź
+- *
+- * \ingroup pubdir50
+- */
+-void gg_pubdir50_free(gg_pubdir50_t s)
+-{
+- int i;
+-
+- if (!s)
+- return;
+-
+- for (i = 0; i < s->entries_count; i++) {
+- free(s->entries[i].field);
+- free(s->entries[i].value);
+- }
+-
+- free(s->entries);
+- free(s);
+-}
+-
+-/**
+- * Wysyła zapytanie katalogu publicznego do serwera.
+- *
+- * \param sess Struktura sesji
+- * \param req Zapytanie
+- *
+- * \return Numer sekwencyjny zapytania lub 0 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-uint32_t gg_pubdir50(struct gg_session *sess, gg_pubdir50_t req)
+-{
+- int i, size = 5;
+- uint32_t res;
+- char *buf, *p;
+- struct gg_pubdir50_request *r;
+-
+- gg_debug_session(sess, GG_DEBUG_FUNCTION, "** gg_pubdir50(%p, %p);\n", sess, req);
+-
+- if (!sess || !req) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() invalid arguments\n");
+- errno = EFAULT;
+- return 0;
+- }
+-
+- if (sess->state != GG_STATE_CONNECTED) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() not connected\n");
+- errno = ENOTCONN;
+- return 0;
+- }
+-
+- for (i = 0; i < req->entries_count; i++) {
+- /* wyszukiwanie bierze tylko pierwszy wpis */
+- if (req->entries[i].num)
+- continue;
+-
+- if (sess->encoding == GG_ENCODING_CP1250) {
+- size += strlen(req->entries[i].field) + 1;
+- size += strlen(req->entries[i].value) + 1;
+- } else {
+- char *tmp;
+-
+- // XXX \todo zoptymalizować
+- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
+-
+- if (tmp == NULL)
+- return -1;
+-
+- size += strlen(tmp) + 1;
+-
+- free(tmp);
+-
+- // XXX \todo zoptymalizować
+- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
+-
+- if (tmp == NULL)
+- return -1;
+-
+- size += strlen(tmp) + 1;
+-
+- free(tmp);
+- }
+- }
+-
+- if (!(buf = malloc(size))) {
+- gg_debug_session(sess, GG_DEBUG_MISC, "// gg_pubdir50() out of memory (%d bytes)\n", size);
+- return 0;
+- }
+-
+- if (!req->seq)
+- req->seq = time(NULL);
+-
+- res = req->seq;
+-
+- r = (struct gg_pubdir50_request*) buf;
+- r->type = req->type;
+- r->seq = gg_fix32(req->seq);
+-
+- for (i = 0, p = buf + 5; i < req->entries_count; i++) {
+- if (req->entries[i].num)
+- continue;
+-
+- if (sess->encoding == GG_ENCODING_CP1250) {
+- strcpy(p, req->entries[i].field);
+- p += strlen(p) + 1;
+-
+- strcpy(p, req->entries[i].value);
+- p += strlen(p) + 1;
+- } else {
+- char *tmp;
+-
+- // XXX \todo zoptymalizować
+- tmp = gg_encoding_convert(req->entries[i].field, sess->encoding, GG_ENCODING_CP1250, -1, -1);
+-
+- if (tmp == NULL) {
+- free(buf);
+- return -1;
+- }
+-
+- strcpy(p, tmp);
+- p += strlen(tmp) + 1;
+- free(tmp);
+-
+- // XXX \todo zoptymalizować
+- tmp = gg_encoding_convert(req->entries[i].value, sess->encoding, GG_ENCODING_CP1250, -1, -1);
+-
+-
+- if (tmp == NULL) {
+- free(buf);
+- return -1;
+- }
+-
+- strcpy(p, tmp);
+- p += strlen(tmp) + 1;
+- free(tmp);
+- }
+- }
+-
+- if (gg_send_packet(sess, GG_PUBDIR50_REQUEST, buf, size, NULL, 0) == -1)
+- res = 0;
+-
+- free(buf);
+-
+- return res;
+-}
+-
+-/*
+- * \internal Analizuje przychodzący pakiet odpowiedzi i zapisuje wynik
+- * w strukturze \c gg_event.
+- *
+- * \param sess Struktura sesji
+- * \param e Struktura zdarzenia
+- * \param packet Pakiet odpowiedzi
+- * \param length Długość pakietu odpowiedzi
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_pubdir50_handle_reply_sess(struct gg_session *sess, struct gg_event *e, const char *packet, int length)
+-{
+- const char *end = packet + length, *p;
+- struct gg_pubdir50_reply *r = (struct gg_pubdir50_reply*) packet;
+- gg_pubdir50_t res;
+- int num = 0;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_handle_reply_sess(%p, %p, %p, %d);\n", sess, e, packet, length);
+-
+- if (!sess || !e || !packet) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (length < 5) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() packet too short\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (!(res = gg_pubdir50_new(r->type))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() unable to allocate reply\n");
+- return -1;
+- }
+-
+- e->event.pubdir50 = res;
+-
+- res->seq = gg_fix32(r->seq);
+-
+- switch (res->type) {
+- case GG_PUBDIR50_READ:
+- e->type = GG_EVENT_PUBDIR50_READ;
+- break;
+-
+- case GG_PUBDIR50_WRITE:
+- e->type = GG_EVENT_PUBDIR50_WRITE;
+- break;
+-
+- default:
+- e->type = GG_EVENT_PUBDIR50_SEARCH_REPLY;
+- break;
+- }
+-
+- /* brak wyników? */
+- if (length == 5)
+- return 0;
+-
+- /* pomiń początek odpowiedzi */
+- p = packet + 5;
+-
+- while (p < end) {
+- const char *field, *value;
+-
+- field = p;
+-
+- /* sprawdź, czy nie mamy podziału na kolejne pole */
+- if (!*field) {
+- num++;
+- field++;
+- }
+-
+- value = NULL;
+-
+- for (p = field; p < end; p++) {
+- /* jeśli mamy koniec tekstu... */
+- if (!*p) {
+- /* ...i jeszcze nie mieliśmy wartości pola to
+- * wiemy, że po tym zerze jest wartość... */
+- if (!value)
+- value = p + 1;
+- else
+- /* ...w przeciwym wypadku koniec
+- * wartości i możemy wychodzić
+- * grzecznie z pętli */
+- break;
+- }
+- }
+-
+- /* sprawdźmy, czy pole nie wychodzi poza pakiet, żeby nie
+- * mieć segfaultów, jeśli serwer przestanie zakańczać pakietów
+- * przez \0 */
+-
+- if (p == end) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_handle_reply() premature end of packet\n");
+- goto failure;
+- }
+-
+- p++;
+-
+- /* jeśli dostaliśmy namier na następne wyniki, to znaczy że
+- * mamy koniec wyników i nie jest to kolejna osoba. */
+- if (!strcasecmp(field, "nextstart")) {
+- res->next = atoi(value);
+- num--;
+- } else {
+- if (sess->encoding == GG_ENCODING_CP1250) {
+- if (gg_pubdir50_add_n(res, num, field, value) == -1)
+- goto failure;
+- } else {
+- char *tmp;
+-
+- tmp = gg_encoding_convert(value, GG_ENCODING_CP1250, sess->encoding, -1, -1);
+-
+- if (tmp == NULL)
+- goto failure;
+-
+- if (gg_pubdir50_add_n(res, num, field, tmp) == -1) {
+- free(tmp);
+- goto failure;
+- }
+-
+- free(tmp);
+- }
+- }
+- }
+-
+- res->count = num + 1;
+-
+- return 0;
+-
+-failure:
+- gg_pubdir50_free(res);
+- return -1;
+-}
+-
+-/**
+- * Pobiera pole z odpowiedzi katalogu publicznego.
+- *
+- * \param res Odpowiedź
+- * \param num Numer wyniku odpowiedzi
+- * \param field Nazwa pola (wielkość liter nie ma znaczenia)
+- *
+- * \return Wartość pola lub \c NULL jeśli nie znaleziono
+- *
+- * \ingroup pubdir50
+- */
+-const char *gg_pubdir50_get(gg_pubdir50_t res, int num, const char *field)
+-{
+- char *value = NULL;
+- int i;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_pubdir50_get(%p, %d, \"%s\");\n", res, num, field);
+-
+- if (!res || num < 0 || !field) {
+- gg_debug(GG_DEBUG_MISC, "// gg_pubdir50_get() invalid arguments\n");
+- errno = EINVAL;
+- return NULL;
+- }
+-
+- for (i = 0; i < res->entries_count; i++) {
+- if (res->entries[i].num == num && !strcasecmp(res->entries[i].field, field)) {
+- value = res->entries[i].value;
+- break;
+- }
+- }
+-
+- return value;
+-}
+-
+-/**
+- * Zwraca liczbę wyników odpowiedzi.
+- *
+- * \param res Odpowiedź
+- *
+- * \return Liczba wyników lub -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-int gg_pubdir50_count(gg_pubdir50_t res)
+-{
+- return (!res) ? -1 : res->count;
+-}
+-
+-/**
+- * Zwraca rodzaj zapytania lub odpowiedzi.
+- *
+- * \param res Zapytanie lub odpowiedź
+- *
+- * \return Rodzaj lub -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-int gg_pubdir50_type(gg_pubdir50_t res)
+-{
+- return (!res) ? -1 : res->type;
+-}
+-
+-/**
+- * Zwraca numer, od którego należy rozpocząc kolejne wyszukiwanie.
+- *
+- * Dłuższe odpowiedzi katalogu publicznego są wysyłane przez serwer
+- * w mniejszych paczkach. Po otrzymaniu odpowiedzi, jeśli numer kolejnego
+- * wyszukiwania jest większy od zera, dalsze wyniki można otrzymać przez
+- * wywołanie kolejnego zapytania z określonym numerem początkowym.
+- *
+- * \param res Odpowiedź
+- *
+- * \return Numer lub -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-uin_t gg_pubdir50_next(gg_pubdir50_t res)
+-{
+- return (!res) ? (unsigned) -1 : res->next;
+-}
+-
+-/**
+- * Zwraca numer sekwencyjny zapytania lub odpowiedzi.
+- *
+- * \param res Zapytanie lub odpowiedź
+- *
+- * \return Numer sekwencyjny lub -1 w przypadku błędu
+- *
+- * \ingroup pubdir50
+- */
+-uint32_t gg_pubdir50_seq(gg_pubdir50_t res)
+-{
+- return (!res) ? (unsigned) -1 : res->seq;
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/pubdir.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/pubdir.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,857 +0,0 @@
+-/* $Id: pubdir.c 502 2008-01-10 23:25:17Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2001-2006 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Dawid Jarosz <dawjar@poczta.onet.pl>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file pubdir.c
+- *
+- * \brief Obsługa katalogu publicznego
+- */
+-
+-#include <ctype.h>
+-#include <errno.h>
+-#include <stdarg.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-
+-/**
+- * Rejestruje nowego użytkownika.
+- *
+- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
+- *
+- * \param email Adres e-mail
+- * \param password Hasło
+- * \param tokenid Identyfikator tokenu
+- * \param tokenval Zawartość tokenu
+- * \param async Flaga połączenia asynchronicznego
+- *
+- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
+- *
+- * \ingroup register
+- */
+-struct gg_http *gg_register3(const char *email, const char *password, const char *tokenid, const char *tokenval, int async)
+-{
+- struct gg_http *h;
+- char *__pwd, *__email, *__tokenid, *__tokenval, *form, *query;
+-
+- if (!email || !password || !tokenid || !tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> register, NULL parameter\n");
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- __pwd = gg_urlencode(password);
+- __email = gg_urlencode(email);
+- __tokenid = gg_urlencode(tokenid);
+- __tokenval = gg_urlencode(tokenval);
+-
+- if (!__pwd || !__email || !__tokenid || !__tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form fields\n");
+- free(__pwd);
+- free(__email);
+- free(__tokenid);
+- free(__tokenval);
+- return NULL;
+- }
+-
+- form = gg_saprintf("pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u",
+- __pwd, __email, __tokenid, __tokenval,
+- gg_http_hash("ss", email, password));
+-
+- free(__pwd);
+- free(__email);
+- free(__tokenid);
+- free(__tokenval);
+-
+- if (!form) {
+- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for form query\n");
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> register, %s\n", form);
+-
+- query = gg_saprintf(
+- "Host: " GG_REGISTER_HOST "\r\n"
+- "Content-Type: application/x-www-form-urlencoded\r\n"
+- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
+- "Content-Length: %d\r\n"
+- "Pragma: no-cache\r\n"
+- "\r\n"
+- "%s",
+- (int) strlen(form), form);
+-
+- free(form);
+-
+- if (!query) {
+- gg_debug(GG_DEBUG_MISC, "=> register, not enough memory for query\n");
+- return NULL;
+- }
+-
+- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
+- gg_debug(GG_DEBUG_MISC, "=> register, gg_http_connect() failed mysteriously\n");
+- free(query);
+- return NULL;
+- }
+-
+- h->type = GG_SESSION_REGISTER;
+-
+- free(query);
+-
+- h->callback = gg_pubdir_watch_fd;
+- h->destroy = gg_pubdir_free;
+-
+- if (!async)
+- gg_pubdir_watch_fd(h);
+-
+- return h;
+-}
+-
+-#ifdef DOXYGEN
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do
+- * \c gg_pubdir_watch_fd().
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup register
+- */
+-int gg_register_watch_fd(struct gg_httpd *h)
+-{
+- return gg_pubdir_watch_fd(h);
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup register
+- */
+-void gg_register_free(struct gg_http *h)
+-{
+- return gg_pubdir_free(h);
+-}
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Usuwa użytkownika.
+- *
+- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
+- *
+- * \param uin Numer Gadu-Gadu
+- * \param password Hasło
+- * \param tokenid Identyfikator tokenu
+- * \param tokenval Zawartość tokenu
+- * \param async Flaga połączenia asynchronicznego
+- *
+- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
+- *
+- * \ingroup unregister
+- */
+-struct gg_http *gg_unregister3(uin_t uin, const char *password, const char *tokenid, const char *tokenval, int async)
+-{
+- struct gg_http *h;
+- char *__fmpwd, *__pwd, *__tokenid, *__tokenval, *form, *query;
+-
+- if (!password || !tokenid || !tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> unregister, NULL parameter\n");
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- __pwd = gg_saprintf("%ld", random());
+- __fmpwd = gg_urlencode(password);
+- __tokenid = gg_urlencode(tokenid);
+- __tokenval = gg_urlencode(tokenval);
+-
+- if (!__fmpwd || !__pwd || !__tokenid || !__tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form fields\n");
+- free(__pwd);
+- free(__fmpwd);
+- free(__tokenid);
+- free(__tokenval);
+- return NULL;
+- }
+-
+- form = gg_saprintf("fmnumber=%d&fmpwd=%s&delete=1&pwd=%s&email=deletedaccount@gadu-gadu.pl&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __tokenid, __tokenval, gg_http_hash("ss", "deletedaccount@gadu-gadu.pl", __pwd));
+-
+- free(__fmpwd);
+- free(__pwd);
+- free(__tokenid);
+- free(__tokenval);
+-
+- if (!form) {
+- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for form query\n");
+- return NULL;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "=> unregister, %s\n", form);
+-
+- query = gg_saprintf(
+- "Host: " GG_REGISTER_HOST "\r\n"
+- "Content-Type: application/x-www-form-urlencoded\r\n"
+- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
+- "Content-Length: %d\r\n"
+- "Pragma: no-cache\r\n"
+- "\r\n"
+- "%s",
+- (int) strlen(form), form);
+-
+- free(form);
+-
+- if (!query) {
+- gg_debug(GG_DEBUG_MISC, "=> unregister, not enough memory for query\n");
+- return NULL;
+- }
+-
+- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
+- gg_debug(GG_DEBUG_MISC, "=> unregister, gg_http_connect() failed mysteriously\n");
+- free(query);
+- return NULL;
+- }
+-
+- h->type = GG_SESSION_UNREGISTER;
+-
+- free(query);
+-
+- h->callback = gg_pubdir_watch_fd;
+- h->destroy = gg_pubdir_free;
+-
+- if (!async)
+- gg_pubdir_watch_fd(h);
+-
+- return h;
+-}
+-
+-#ifdef DOXYGEN
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do
+- * \c gg_pubdir_watch_fd().
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup unregister
+- */
+-int gg_unregister_watch_fd(struct gg_httpd *h)
+-{
+- return gg_pubdir_watch_fd(h);
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup unregister
+- */
+-void gg_unregister_free(struct gg_http *h)
+-{
+- return gg_pubdir_free(h);
+-}
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Zmienia hasło użytkownika.
+- *
+- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
+- *
+- * \param uin Numer Gadu-Gadu
+- * \param email Adres e-mail
+- * \param passwd Obecne hasło
+- * \param newpasswd Nowe hasło
+- * \param tokenid Identyfikator tokenu
+- * \param tokenval Zawartość tokenu
+- * \param async Flaga połączenia asynchronicznego
+- *
+- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
+- *
+- * \ingroup passwd
+- */
+-struct gg_http *gg_change_passwd4(uin_t uin, const char *email, const char *passwd, const char *newpasswd, const char *tokenid, const char *tokenval, int async)
+-{
+- struct gg_http *h;
+- char *form, *query, *__email, *__fmpwd, *__pwd, *__tokenid, *__tokenval;
+-
+- if (!uin || !email || !passwd || !newpasswd || !tokenid || !tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> change, NULL parameter\n");
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- __fmpwd = gg_urlencode(passwd);
+- __pwd = gg_urlencode(newpasswd);
+- __email = gg_urlencode(email);
+- __tokenid = gg_urlencode(tokenid);
+- __tokenval = gg_urlencode(tokenval);
+-
+- if (!__fmpwd || !__pwd || !__email || !__tokenid || !__tokenval) {
+- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
+- free(__fmpwd);
+- free(__pwd);
+- free(__email);
+- free(__tokenid);
+- free(__tokenval);
+- return NULL;
+- }
+-
+- if (!(form = gg_saprintf("fmnumber=%d&fmpwd=%s&pwd=%s&email=%s&tokenid=%s&tokenval=%s&code=%u", uin, __fmpwd, __pwd, __email, __tokenid, __tokenval, gg_http_hash("ss", email, newpasswd)))) {
+- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for form fields\n");
+- free(__fmpwd);
+- free(__pwd);
+- free(__email);
+- free(__tokenid);
+- free(__tokenval);
+-
+- return NULL;
+- }
+-
+- free(__fmpwd);
+- free(__pwd);
+- free(__email);
+- free(__tokenid);
+- free(__tokenval);
+-
+- gg_debug(GG_DEBUG_MISC, "=> change, %s\n", form);
+-
+- query = gg_saprintf(
+- "Host: " GG_REGISTER_HOST "\r\n"
+- "Content-Type: application/x-www-form-urlencoded\r\n"
+- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
+- "Content-Length: %d\r\n"
+- "Pragma: no-cache\r\n"
+- "\r\n"
+- "%s",
+- (int) strlen(form), form);
+-
+- free(form);
+-
+- if (!query) {
+- gg_debug(GG_DEBUG_MISC, "=> change, not enough memory for query\n");
+- return NULL;
+- }
+-
+- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/fmregister3.asp", query))) {
+- gg_debug(GG_DEBUG_MISC, "=> change, gg_http_connect() failed mysteriously\n");
+- free(query);
+- return NULL;
+- }
+-
+- h->type = GG_SESSION_PASSWD;
+-
+- free(query);
+-
+- h->callback = gg_pubdir_watch_fd;
+- h->destroy = gg_pubdir_free;
+-
+- if (!async)
+- gg_pubdir_watch_fd(h);
+-
+- return h;
+-}
+-
+-#ifdef DOXYGEN
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do
+- * \c gg_pubdir_watch_fd().
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup passwd
+- */
+-int gg_change_passwd_watch_fd(struct gg_httpd *h)
+-{
+- return gg_pubdir_watch_fd(h);
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup passwd
+- */
+-void gg_change_passwd_free(struct gg_http *h)
+-{
+- return gg_pubdir_free(h);
+-}
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Wysyła hasło użytkownika na e-mail.
+- *
+- * Wymaga wcześniejszego pobrania tokenu za pomocą \c gg_token().
+- *
+- * \param uin Numer Gadu-Gadu
+- * \param email Adres e-mail (podany przy rejestracji)
+- * \param tokenid Identyfikator tokenu
+- * \param tokenval Zawartość tokenu
+- * \param async Flaga połączenia asynchronicznego
+- *
+- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
+- *
+- * \ingroup remind
+- */
+-struct gg_http *gg_remind_passwd3(uin_t uin, const char *email, const char *tokenid, const char *tokenval, int async)
+-{
+- struct gg_http *h;
+- char *form, *query, *__tokenid, *__tokenval, *__email;
+-
+- if (!tokenid || !tokenval || !email) {
+- gg_debug(GG_DEBUG_MISC, "=> remind, NULL parameter\n");
+- errno = EFAULT;
+- return NULL;
+- }
+-
+- __tokenid = gg_urlencode(tokenid);
+- __tokenval = gg_urlencode(tokenval);
+- __email = gg_urlencode(email);
+-
+- if (!__tokenid || !__tokenval || !__email) {
+- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
+- free(__tokenid);
+- free(__tokenval);
+- free(__email);
+- return NULL;
+- }
+-
+- if (!(form = gg_saprintf("userid=%d&code=%u&tokenid=%s&tokenval=%s&email=%s", uin, gg_http_hash("u", uin), __tokenid, __tokenval, __email))) {
+- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for form fields\n");
+- free(__tokenid);
+- free(__tokenval);
+- free(__email);
+- return NULL;
+- }
+-
+- free(__tokenid);
+- free(__tokenval);
+- free(__email);
+-
+- gg_debug(GG_DEBUG_MISC, "=> remind, %s\n", form);
+-
+- query = gg_saprintf(
+- "Host: " GG_REMIND_HOST "\r\n"
+- "Content-Type: application/x-www-form-urlencoded\r\n"
+- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
+- "Content-Length: %d\r\n"
+- "Pragma: no-cache\r\n"
+- "\r\n"
+- "%s",
+- (int) strlen(form), form);
+-
+- free(form);
+-
+- if (!query) {
+- gg_debug(GG_DEBUG_MISC, "=> remind, not enough memory for query\n");
+- return NULL;
+- }
+-
+- if (!(h = gg_http_connect(GG_REMIND_HOST, GG_REMIND_PORT, async, "POST", "/appsvc/fmsendpwd3.asp", query))) {
+- gg_debug(GG_DEBUG_MISC, "=> remind, gg_http_connect() failed mysteriously\n");
+- free(query);
+- return NULL;
+- }
+-
+- h->type = GG_SESSION_REMIND;
+-
+- free(query);
+-
+- h->callback = gg_pubdir_watch_fd;
+- h->destroy = gg_pubdir_free;
+-
+- if (!async)
+- gg_pubdir_watch_fd(h);
+-
+- return h;
+-}
+-
+-#ifdef DOXYGEN
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do
+- * \c gg_pubdir_watch_fd().
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup remind
+- */
+-int gg_remind_watch_fd(struct gg_httpd *h)
+-{
+- return gg_pubdir_watch_fd(h);
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji.
+- *
+- * \note W rzeczywistości funkcja jest makrem rozwijanym do \c gg_pubdir_free().
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup remind
+- */
+-void gg_remind_free(struct gg_http *h)
+-{
+- return gg_pubdir_free(h);
+-}
+-
+-#endif /* DOXYGEN */
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_pubdir_watch_fd(struct gg_http *h)
+-{
+- struct gg_pubdir *p;
+- char *tmp;
+-
+- if (!h) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (h->state == GG_STATE_ERROR) {
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, watch_fd issued on failed session\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (h->state != GG_STATE_PARSING) {
+- if (gg_http_watch_fd(h) == -1) {
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, http failure\n");
+- errno = EINVAL;
+- return -1;
+- }
+- }
+-
+- if (h->state != GG_STATE_PARSING)
+- return 0;
+-
+- h->state = GG_STATE_DONE;
+-
+- if (!(h->data = p = malloc(sizeof(struct gg_pubdir)))) {
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, not enough memory for results\n");
+- return -1;
+- }
+-
+- p->success = 0;
+- p->uin = 0;
+-
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, let's parse \"%s\"\n", h->body);
+-
+- if ((tmp = strstr(h->body, "Tokens okregisterreply_packet.reg.dwUserId="))) {
+- p->success = 1;
+- p->uin = strtol(tmp + sizeof("Tokens okregisterreply_packet.reg.dwUserId=") - 1, NULL, 0);
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (okregisterreply, uin=%d)\n", p->uin);
+- } else if ((tmp = strstr(h->body, "success")) || (tmp = strstr(h->body, "results"))) {
+- p->success = 1;
+- if (tmp[7] == ':')
+- p->uin = strtol(tmp + 8, NULL, 0);
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, success (uin=%d)\n", p->uin);
+- } else
+- gg_debug(GG_DEBUG_MISC, "=> pubdir, error.\n");
+-
+- return 0;
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji na katalogu publicznym.
+- *
+- * \param h Struktura połączenia
+- */
+-void gg_pubdir_free(struct gg_http *h)
+-{
+- if (!h)
+- return;
+-
+- free(h->data);
+- gg_http_free(h);
+-}
+-
+-/**
+- * Pobiera token do autoryzacji operacji na katalogu publicznym.
+- *
+- * Token jest niezbędny do tworzenia nowego i usuwania użytkownika,
+- * zmiany hasła itd.
+- *
+- * \param async Flaga połączenia asynchronicznego
+- *
+- * \return Struktura \c gg_http lub \c NULL w przypadku błędu
+- *
+- * \ingroup token
+- */
+-struct gg_http *gg_token(int async)
+-{
+- struct gg_http *h;
+- const char *query;
+-
+- query = "Host: " GG_REGISTER_HOST "\r\n"
+- "Content-Type: application/x-www-form-urlencoded\r\n"
+- "User-Agent: " GG_HTTP_USERAGENT "\r\n"
+- "Content-Length: 0\r\n"
+- "Pragma: no-cache\r\n"
+- "\r\n";
+-
+- if (!(h = gg_http_connect(GG_REGISTER_HOST, GG_REGISTER_PORT, async, "POST", "/appsvc/regtoken.asp", query))) {
+- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
+- return NULL;
+- }
+-
+- h->type = GG_SESSION_TOKEN;
+-
+- h->callback = gg_token_watch_fd;
+- h->destroy = gg_token_free;
+-
+- if (!async)
+- gg_token_watch_fd(h);
+-
+- return h;
+-}
+-
+-/**
+- * Funkcja wywoływana po zaobserwowaniu zmian na deskryptorze połączenia.
+- *
+- * Operacja będzie zakończona, gdy pole \c state będzie równe \c GG_STATE_DONE.
+- * Jeśli wystąpi błąd, \c state będzie równe \c GG_STATE_ERROR, a kod błędu
+- * znajdzie się w polu \c error.
+- *
+- * \param h Struktura połączenia
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- *
+- * \ingroup token
+- */
+-int gg_token_watch_fd(struct gg_http *h)
+-{
+- if (!h) {
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (h->state == GG_STATE_ERROR) {
+- gg_debug(GG_DEBUG_MISC, "=> token, watch_fd issued on failed session\n");
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (h->state != GG_STATE_PARSING) {
+- if (gg_http_watch_fd(h) == -1) {
+- gg_debug(GG_DEBUG_MISC, "=> token, http failure\n");
+- errno = EINVAL;
+- return -1;
+- }
+- }
+-
+- if (h->state != GG_STATE_PARSING)
+- return 0;
+-
+- /* jeśli h->data jest puste, to ściągaliśmy tokenid i url do niego,
+- * ale jeśli coś tam jest, to znaczy, że mamy drugi etap polegający
+- * na pobieraniu tokenu. */
+- if (!h->data) {
+- int width, height, length;
+- char *url = NULL, *tokenid = NULL, *path, *headers;
+- const char *host;
+- struct gg_http *h2;
+- struct gg_token *t;
+-
+- gg_debug(GG_DEBUG_MISC, "=> token body \"%s\"\n", h->body);
+-
+- if (h->body && (!(url = malloc(strlen(h->body))) || !(tokenid = malloc(strlen(h->body))))) {
+- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for results\n");
+- free(url);
+- return -1;
+- }
+-
+- if (!h->body || sscanf(h->body, "%d %d %d\r\n%s\r\n%s", &width, &height, &length, tokenid, url) != 5) {
+- gg_debug(GG_DEBUG_MISC, "=> token, parsing failed\n");
+- free(url);
+- free(tokenid);
+- errno = EINVAL;
+- return -1;
+- }
+-
+- /* dostaliśmy tokenid i wszystkie niezbędne informacje,
+- * więc pobierzmy obrazek z tokenem */
+-
+- if (strncmp(url, "http://", 7)) {
+- path = gg_saprintf("%s?tokenid=%s", url, tokenid);
+- host = GG_REGISTER_HOST;
+- } else {
+- char *slash = strchr(url + 7, '/');
+-
+- if (slash) {
+- path = gg_saprintf("%s?tokenid=%s", slash, tokenid);
+- *slash = 0;
+- host = url + 7;
+- } else {
+- gg_debug(GG_DEBUG_MISC, "=> token, url parsing failed\n");
+- free(url);
+- free(tokenid);
+- errno = EINVAL;
+- return -1;
+- }
+- }
+-
+- if (!path) {
+- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
+- free(url);
+- free(tokenid);
+- return -1;
+- }
+-
+- if (!(headers = gg_saprintf("Host: %s\r\nUser-Agent: " GG_HTTP_USERAGENT "\r\n\r\n", host))) {
+- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token url\n");
+- free(path);
+- free(url);
+- free(tokenid);
+- return -1;
+- }
+-
+- if (!(h2 = gg_http_connect(host, GG_REGISTER_PORT, h->async, "GET", path, headers))) {
+- gg_debug(GG_DEBUG_MISC, "=> token, gg_http_connect() failed mysteriously\n");
+- free(headers);
+- free(url);
+- free(path);
+- free(tokenid);
+- return -1;
+- }
+-
+- free(headers);
+- free(path);
+- free(url);
+-
+- gg_http_free_fields(h);
+-
+- memcpy(h, h2, sizeof(struct gg_http));
+- free(h2);
+-
+- h->type = GG_SESSION_TOKEN;
+-
+- h->callback = gg_token_watch_fd;
+- h->destroy = gg_token_free;
+-
+- if (!h->async)
+- gg_token_watch_fd(h);
+-
+- if (!(h->data = t = malloc(sizeof(struct gg_token)))) {
+- gg_debug(GG_DEBUG_MISC, "=> token, not enough memory for token data\n");
+- free(tokenid);
+- return -1;
+- }
+-
+- t->width = width;
+- t->height = height;
+- t->length = length;
+- t->tokenid = tokenid;
+- } else {
+- /* obrazek mamy w h->body */
+- h->state = GG_STATE_DONE;
+- }
+-
+- return 0;
+-}
+-
+-/**
+- * Zwalnia zasoby po operacji pobierania tokenu.
+- *
+- * \param h Struktura połączenia
+- *
+- * \ingroup token
+- */
+-void gg_token_free(struct gg_http *h)
+-{
+- struct gg_token *t;
+-
+- if (!h)
+- return;
+-
+- if ((t = h->data))
+- free(t->tokenid);
+-
+- free(h->data);
+- gg_http_free(h);
+-}
+-
+-/*
+- * Local variables:
+- * c-indentation-style: k&r
+- * c-basic-offset: 8
+- * indent-tabs-mode: notnil
+- * End:
+- *
+- * vim: shiftwidth=8:
+- */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1149 +0,0 @@
+-/*
+- * (C) Copyright 2001-2009 Wojtek Kaniewski <wojtekka@irc.pl>
+- * Robert J. Woźny <speedy@ziew.org>
+- * Arkadiusz Miśkiewicz <arekm@pld-linux.org>
+- * Tomasz Chiliński <chilek@chilan.com>
+- * Adam Wysocki <gophi@ekg.chmurka.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file resolver.c
+- *
+- * \brief Funkcje rozwiązywania nazw
+- */
+-
+-#ifndef _WIN32
+-# include <sys/wait.h>
+-# include <netdb.h>
+-#endif
+-#include <errno.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <unistd.h>
+-#ifndef _WIN32
+-# include <signal.h>
+-# include <netinet/in.h>
+-# include <arpa/inet.h>
+-#endif
+-
+-#include "libgadu.h"
+-#include "libgadu-config.h"
+-#include "resolver.h"
+-#include "compat.h"
+-#include "session.h"
+-
+-/** Sposób rozwiązywania nazw serwerów */
+-static gg_resolver_t gg_global_resolver_type = GG_RESOLVER_DEFAULT;
+-
+-/** Funkcja rozpoczynająca rozwiązywanie nazwy */
+-static int (*gg_global_resolver_start)(int *fd, void **private_data, const char *hostname);
+-
+-/** Funkcja zwalniająca zasoby po rozwiązaniu nazwy */
+-static void (*gg_global_resolver_cleanup)(void **private_data, int force);
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+-
+-#include <pthread.h>
+-
+-/**
+- * \internal Funkcja pomocnicza zwalniająca zasoby po rozwiązywaniu nazwy
+- * w wątku.
+- *
+- * \param data Wskaźnik na wskaźnik bufora zaalokowanego w wątku
+- */
+-static void gg_gethostbyname_cleaner(void *data)
+-{
+- char **buf_ptr = (char**) data;
+-
+- if (buf_ptr != NULL) {
+- free(*buf_ptr);
+- *buf_ptr = NULL;
+- }
+-}
+-
+-#endif /* GG_CONFIG_HAVE_PTHREAD */
+-
+-/**
+- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
+- *
+- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
+- * nie, to zwykłej \c gethostbyname. Wynikiem jest tablica adresów zakończona
+- * wartością INADDR_NONE, którą należy zwolnić po użyciu.
+- *
+- * \param hostname Nazwa serwera
+- * \param result Wskaźnik na wskaźnik z tablicą adresów zakończoną INADDR_NONE
+- * \param count Wskaźnik na zmienną, do ktorej zapisze się liczbę wyników
+- * \param pthread Flaga blokowania unicestwiania wątku podczas alokacji pamięci
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread)
+-{
+-#ifdef GG_CONFIG_HAVE_GETHOSTBYNAME_R
+- char *buf = NULL;
+- char *new_buf = NULL;
+- struct hostent he;
+- struct hostent *he_ptr = NULL;
+- size_t buf_len = 1024;
+- int res = -1;
+- int h_errnop;
+- int ret = 0;
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- int old_state;
+-#endif
+-
+- if (result == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- pthread_cleanup_push(gg_gethostbyname_cleaner, &buf);
+-
+- if (pthread)
+- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
+-#endif
+-
+- buf = malloc(buf_len);
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(old_state, NULL);
+-#endif
+-
+- if (buf != NULL) {
+-#ifndef sun
+- while ((ret = gethostbyname_r(hostname, &he, buf, buf_len, &he_ptr, &h_errnop)) == ERANGE) {
+-#else
+- while (((he_ptr = gethostbyname_r(hostname, &he, buf, buf_len, &h_errnop)) == NULL) && (errno == ERANGE)) {
+-#endif
+- buf_len *= 2;
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
+-#endif
+-
+- new_buf = realloc(buf, buf_len);
+-
+- if (new_buf != NULL)
+- buf = new_buf;
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(old_state, NULL);
+-#endif
+-
+- if (new_buf == NULL) {
+- ret = ENOMEM;
+- break;
+- }
+- }
+-
+- if (ret == 0 && he_ptr != NULL && he_ptr->h_addr_list[0] != NULL) {
+- int i;
+-
+- /* Policz liczbę adresów */
+-
+- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++)
+- ;
+-
+- /* Zaalokuj */
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
+-#endif
+-
+- *result = malloc((i + 1) * sizeof(struct in_addr));
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(old_state, NULL);
+-#endif
+-
+- if (*result == NULL)
+- return -1;
+-
+- /* Kopiuj */
+-
+- for (i = 0; he_ptr->h_addr_list[i] != NULL; i++)
+- memcpy(&((*result)[i]), he_ptr->h_addr_list[i], sizeof(struct in_addr));
+-
+- (*result)[i].s_addr = INADDR_NONE;
+-
+- *count = i;
+-
+- res = 0;
+- }
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &old_state);
+-#endif
+-
+- free(buf);
+- buf = NULL;
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- if (pthread)
+- pthread_setcancelstate(old_state, NULL);
+-#endif
+- }
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- pthread_cleanup_pop(1);
+-#endif
+-
+- return res;
+-#else /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
+- struct hostent *he;
+- int i;
+-
+- if (result == NULL || count == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- he = gethostbyname(hostname);
+-
+- if (he == NULL || he->h_addr_list[0] == NULL)
+- return -1;
+-
+- /* Policz liczbę adresów */
+-
+- for (i = 0; he->h_addr_list[i] != NULL; i++)
+- ;
+-
+- /* Zaalokuj */
+-
+- *result = malloc((i + 1) * sizeof(struct in_addr));
+-
+- if (*result == NULL)
+- return -1;
+-
+- /* Kopiuj */
+-
+- for (i = 0; he->h_addr_list[i] != NULL; i++)
+- memcpy(&((*result)[i]), he->h_addr_list[0], sizeof(struct in_addr));
+-
+- (*result)[i].s_addr = INADDR_NONE;
+-
+- *count = i;
+-
+- return 0;
+-#endif /* GG_CONFIG_HAVE_GETHOSTBYNAME_R */
+-}
+-
+-#if defined(GG_CONFIG_HAVE_PTHREAD) || !defined(_WIN32)
+-/**
+- * \internal Rozwiązuje nazwę i zapisuje wynik do podanego desktyptora.
+- *
+- * \param fd Deskryptor
+- * \param hostname Nazwa serwera
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_resolver_run(int fd, const char *hostname)
+-{
+- struct in_addr addr_ip[2], *addr_list;
+- int addr_count;
+- int res = 0;
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_run(%d, %s)\n", fd, hostname);
+-
+- if ((addr_ip[0].s_addr = inet_addr(hostname)) == INADDR_NONE) {
+- if (gg_gethostbyname_real(hostname, &addr_list, &addr_count, 1) == -1) {
+- addr_list = addr_ip;
+- /* addr_ip[0] już zawiera INADDR_NONE */
+- }
+- } else {
+- addr_list = addr_ip;
+- addr_ip[1].s_addr = INADDR_NONE;
+- addr_count = 1;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_run() count = %d\n", addr_count);
+-
+- if (write(fd, addr_list, (addr_count + 1) * sizeof(struct in_addr)) != (addr_count + 1) * sizeof(struct in_addr))
+- res = -1;
+-
+- if (addr_list != addr_ip)
+- free(addr_list);
+-
+- return res;
+-}
+-#endif
+-
+-/**
+- * \internal Odpowiednik \c gethostbyname zapewniający współbieżność.
+- *
+- * Jeśli dany system dostarcza \c gethostbyname_r, używa się tej wersji, jeśli
+- * nie, to zwykłej \c gethostbyname. Funkcja służy do zachowania zgodności
+- * ABI i służy do pobierania tylko pierwszego adresu -- pozostałe mogą
+- * zostać zignorowane przez aplikację.
+- *
+- * \param hostname Nazwa serwera
+- *
+- * \return Zaalokowana struktura \c in_addr lub NULL w przypadku błędu.
+- */
+-struct in_addr *gg_gethostbyname(const char *hostname)
+-{
+- struct in_addr *result;
+- int count;
+-
+- if (gg_gethostbyname_real(hostname, &result, &count, 0) == -1)
+- return NULL;
+-
+- return result;
+-}
+-
+-/**
+- * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
+- */
+-struct gg_resolver_fork_data {
+- int pid; /*< Identyfikator procesu */
+-};
+-
+-#ifdef _WIN32
+-/**
+- * Deal with the fact that you can't select() on a win32 file fd.
+- * This makes it practically impossible to tie into purple's event loop.
+- *
+- * -This is thanks to Tor Lillqvist.
+- * XXX - Move this to where the rest of the the win32 compatiblity stuff goes when we push the changes back to libgadu.
+- */
+-static int
+-socket_pipe (int *fds)
+-{
+- SOCKET temp, socket1 = -1, socket2 = -1;
+- struct sockaddr_in saddr;
+- int len;
+- u_long arg;
+- fd_set read_set, write_set;
+- struct timeval tv;
+-
+- temp = socket(AF_INET, SOCK_STREAM, 0);
+-
+- if (temp == INVALID_SOCKET) {
+- goto out0;
+- }
+-
+- arg = 1;
+- if (ioctlsocket(temp, FIONBIO, &arg) == SOCKET_ERROR) {
+- goto out0;
+- }
+-
+- memset(&saddr, 0, sizeof(saddr));
+- saddr.sin_family = AF_INET;
+- saddr.sin_port = 0;
+- saddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
+-
+- if (bind(temp, (struct sockaddr *)&saddr, sizeof (saddr))) {
+- goto out0;
+- }
+-
+- if (listen(temp, 1) == SOCKET_ERROR) {
+- goto out0;
+- }
+-
+- len = sizeof(saddr);
+- if (getsockname(temp, (struct sockaddr *)&saddr, &len)) {
+- goto out0;
+- }
+-
+- socket1 = socket(AF_INET, SOCK_STREAM, 0);
+-
+- if (socket1 == INVALID_SOCKET) {
+- goto out0;
+- }
+-
+- arg = 1;
+- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+- goto out1;
+- }
+-
+- if (connect(socket1, (struct sockaddr *)&saddr, len) != SOCKET_ERROR ||
+- WSAGetLastError() != WSAEWOULDBLOCK) {
+- goto out1;
+- }
+-
+- FD_ZERO(&read_set);
+- FD_SET(temp, &read_set);
+-
+- tv.tv_sec = 0;
+- tv.tv_usec = 0;
+-
+- if (select(0, &read_set, NULL, NULL, NULL) == SOCKET_ERROR) {
+- goto out1;
+- }
+-
+- if (!FD_ISSET(temp, &read_set)) {
+- goto out1;
+- }
+-
+- socket2 = accept(temp, (struct sockaddr *) &saddr, &len);
+- if (socket2 == INVALID_SOCKET) {
+- goto out1;
+- }
+-
+- FD_ZERO(&write_set);
+- FD_SET(socket1, &write_set);
+-
+- tv.tv_sec = 0;
+- tv.tv_usec = 0;
+-
+- if (select(0, NULL, &write_set, NULL, NULL) == SOCKET_ERROR) {
+- goto out2;
+- }
+-
+- if (!FD_ISSET(socket1, &write_set)) {
+- goto out2;
+- }
+-
+- arg = 0;
+- if (ioctlsocket(socket1, FIONBIO, &arg) == SOCKET_ERROR) {
+- goto out2;
+- }
+-
+- arg = 0;
+- if (ioctlsocket(socket2, FIONBIO, &arg) == SOCKET_ERROR) {
+- goto out2;
+- }
+-
+- fds[0] = socket1;
+- fds[1] = socket2;
+-
+- closesocket (temp);
+-
+- return 0;
+-
+-out2:
+- closesocket (socket2);
+-out1:
+- closesocket (socket1);
+-out0:
+- closesocket (temp);
+- errno = EIO; /* XXX */
+-
+- return -1;
+-}
+-#endif
+-
+-
+-
+-#ifdef _WIN32
+-struct gg_resolve_win32thread_data {
+- char *hostname;
+- int fd;
+-};
+-
+-static DWORD WINAPI gg_resolve_win32thread_thread(LPVOID arg)
+-{
+- struct gg_resolve_win32thread_data *d = arg;
+- struct in_addr addr_ip[2], *addr_list;
+- int addr_count;
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() host: %s, fd: %i called\n", d->hostname, d->fd);
+-
+- if ((addr_ip[0].s_addr = inet_addr(d->hostname)) == INADDR_NONE) {
+- /* W przypadku błędu gg_gethostbyname_real() zwróci -1
+- * i nie zmieni &addr. Tam jest już INADDR_NONE,
+- * więc nie musimy robić nic więcej. */
+- if (gg_gethostbyname_real(d->hostname, &addr_list, &addr_count, 0) == -1)
+- {
+- addr_list = addr_ip;
+- }
+- } else {
+- addr_list = addr_ip;
+- addr_ip[1].s_addr = INADDR_NONE;
+- addr_count = 1;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() count = %d\n", addr_count);
+-
+- write(d->fd, addr_list, (addr_count+1) * sizeof(struct in_addr));
+- close(d->fd);
+-
+- free(d->hostname);
+- d->hostname = NULL;
+-
+- free(d);
+-
+- if (addr_list != addr_ip)
+- free(addr_list);
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_thread() done\n");
+-
+- return 0;
+-}
+-
+-
+-static int gg_resolve_win32thread(int *fd, void **resolver, const char *hostname)
+-{
+- struct gg_resolve_win32thread_data *d = NULL;
+- HANDLE h;
+- DWORD dwTId;
+- int pipes[2], new_errno;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolve_win32thread(%p, %p, \"%s\");\n", fd, resolver, hostname);
+-
+- if (!resolver || !fd || !hostname) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- if (socket_pipe(pipes) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
+- return -1;
+- }
+-
+- if (!(d = malloc(sizeof(*d)))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- d->hostname = NULL;
+-
+- if (!(d->hostname = strdup(hostname))) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() out of memory\n");
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- d->fd = pipes[1];
+-
+- h = CreateThread(NULL, 0, gg_resolve_win32thread_thread,
+- d, 0, &dwTId);
+-
+- if (h == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() unable to create thread\n");
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- *resolver = h;
+- *fd = pipes[0];
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread() done\n");
+-
+- return 0;
+-
+-cleanup:
+- if (d) {
+- free(d->hostname);
+- free(d);
+- }
+-
+- close(pipes[0]);
+- close(pipes[1]);
+-
+- errno = new_errno;
+-
+- return -1;
+-
+-}
+-
+-static void gg_resolve_win32thread_cleanup(void **priv_data, int force)
+-{
+- struct gg_resolve_win32thread_data *data;
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force: %i called\n", force);
+-
+- if (priv_data == NULL || *priv_data == NULL)
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() priv_data: NULL\n");
+- return;
+-
+- data = (struct gg_resolve_win32thread_data*) *priv_data;
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() data: %s called\n", data->hostname);
+- *priv_data = NULL;
+-
+- if (force) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() force called\n", force);
+- //pthread_cancel(data->thread);
+- //pthread_join(data->thread, NULL);
+- }
+-
+- free(data->hostname);
+- data->hostname = NULL;
+-
+- if (data->fd != -1) {
+- close(data->fd);
+- data->fd = -1;
+- }
+- gg_debug(GG_DEBUG_MISC, "// gg_resolve_win32thread_cleanup() done\n");
+- free(data);
+-}
+-#endif
+-
+-#ifndef _WIN32
+-/**
+- * \internal Rozwiązuje nazwę serwera w osobnym procesie.
+- *
+- * Połączenia asynchroniczne nie mogą blokować procesu w trakcie rozwiązywania
+- * nazwy serwera. W tym celu tworzony jest potok, nowy proces i dopiero w nim
+- * przeprowadzane jest rozwiązywanie nazwy. Deskryptor strony do odczytu
+- * zapisuje się w strukturze sieci i czeka na dane w postaci struktury
+- * \c in_addr. Jeśli nie znaleziono nazwy, zwracana jest \c INADDR_NONE.
+- *
+- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
+- * potoku
+- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
+- * do numeru procesu potomnego rozwiązującego nazwę
+- * \param hostname Nazwa serwera do rozwiązania
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_resolver_fork_start(int *fd, void **priv_data, const char *hostname)
+-{
+- struct gg_resolver_fork_data *data = NULL;
+- int pipes[2], new_errno;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_fork_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
+-
+- if (fd == NULL || priv_data == NULL || hostname == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- data = malloc(sizeof(struct gg_resolver_fork_data));
+-
+- if (data == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() out of memory for resolver data\n");
+- return -1;
+- }
+-
+- if (pipe(pipes) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
+- free(data);
+- return -1;
+- }
+-
+- data->pid = fork();
+-
+- if (data->pid == -1) {
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- if (data->pid == 0) {
+- close(pipes[0]);
+-
+- if (gg_resolver_run(pipes[1], hostname) == -1)
+- _exit(1);
+- else
+- _exit(0);
+- }
+-
+- close(pipes[1]);
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_fork_start() %p\n", data);
+-
+- *fd = pipes[0];
+- *priv_data = data;
+-
+- return 0;
+-
+-cleanup:
+- free(data);
+- close(pipes[0]);
+- close(pipes[1]);
+-
+- errno = new_errno;
+-
+- return -1;
+-}
+-
+-/**
+- * \internal Usuwanie zasobów po procesie rozwiązywaniu nazwy.
+- *
+- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
+- * zasobów sesji podczas rozwiązywania nazwy.
+- *
+- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
+- * danych
+- * \param force Flaga usuwania zasobów przed zakończeniem działania
+- */
+-static void gg_resolver_fork_cleanup(void **priv_data, int force)
+-{
+- struct gg_resolver_fork_data *data;
+-
+- if (priv_data == NULL || *priv_data == NULL)
+- return;
+-
+- data = (struct gg_resolver_fork_data*) *priv_data;
+- *priv_data = NULL;
+-
+- if (force)
+- kill(data->pid, SIGKILL);
+-
+- waitpid(data->pid, NULL, WNOHANG);
+-
+- free(data);
+-}
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+-
+-/**
+- * \internal Struktura przekazywana do wątku rozwiązującego nazwę.
+- */
+-struct gg_resolver_pthread_data {
+- pthread_t thread; /*< Identyfikator wątku */
+- char *hostname; /*< Nazwa serwera */
+- int rfd; /*< Deskryptor do odczytu */
+- int wfd; /*< Deskryptor do zapisu */
+-};
+-
+-/**
+- * \internal Usuwanie zasobów po wątku rozwiązywaniu nazwy.
+- *
+- * Funkcja wywoływana po zakończeniu rozwiązanywania nazwy lub przy zwalnianiu
+- * zasobów sesji podczas rozwiązywania nazwy.
+- *
+- * \param priv_data Wskaźnik na zmienną przechowującą wskaźnik do prywatnych
+- * danych
+- * \param force Flaga usuwania zasobów przed zakończeniem działania
+- */
+-static void gg_resolver_pthread_cleanup(void **priv_data, int force)
+-{
+- struct gg_resolver_pthread_data *data;
+-
+- if (priv_data == NULL || *priv_data == NULL)
+- return;
+-
+- data = (struct gg_resolver_pthread_data *) *priv_data;
+- *priv_data = NULL;
+-
+- if (force) {
+- pthread_cancel(data->thread);
+- pthread_join(data->thread, NULL);
+- }
+-
+- free(data->hostname);
+- data->hostname = NULL;
+-
+- if (data->wfd != -1) {
+- close(data->wfd);
+- data->wfd = -1;
+- }
+-
+- free(data);
+-}
+-
+-/**
+- * \internal Wątek rozwiązujący nazwę.
+- *
+- * \param arg Wskaźnik na strukturę \c gg_resolver_pthread_data
+- */
+-static void *gg_resolver_pthread_thread(void *arg)
+-{
+- struct gg_resolver_pthread_data *data = arg;
+-
+- pthread_detach(pthread_self());
+-
+- if (gg_resolver_run(data->wfd, data->hostname) == -1)
+- pthread_exit((void*) -1);
+- else
+- pthread_exit(NULL);
+-
+- return NULL; /* żeby kompilator nie marudził */
+-}
+-
+-/**
+- * \internal Rozwiązuje nazwę serwera w osobnym wątku.
+- *
+- * Funkcja działa analogicznie do \c gg_resolver_fork_start(), z tą różnicą,
+- * że działa na wątkach, nie procesach. Jest dostępna wyłącznie gdy podczas
+- * kompilacji włączono odpowiednią opcję.
+- *
+- * \param fd Wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor
+- * potoku
+- * \param priv_data Wskaźnik na zmienną, gdzie zostanie umieszczony wskaźnik
+- * do prywatnych danych wątku rozwiązującego nazwę
+- * \param hostname Nazwa serwera do rozwiązania
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-static int gg_resolver_pthread_start(int *fd, void **priv_data, const char *hostname)
+-{
+- struct gg_resolver_pthread_data *data = NULL;
+- int pipes[2], new_errno;
+-
+- gg_debug(GG_DEBUG_FUNCTION, "** gg_resolver_pthread_start(%p, %p, \"%s\");\n", fd, priv_data, hostname);
+-
+- if (fd == NULL || priv_data == NULL || hostname == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() invalid arguments\n");
+- errno = EFAULT;
+- return -1;
+- }
+-
+- data = malloc(sizeof(struct gg_resolver_pthread_data));
+-
+- if (data == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory for resolver data\n");
+- return -1;
+- }
+-
+- if (pipe(pipes) == -1) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create pipes (errno=%d, %s)\n", errno, strerror(errno));
+- free(data);
+- return -1;
+- }
+-
+- data->hostname = strdup(hostname);
+-
+- if (data->hostname == NULL) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() out of memory\n");
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- data->rfd = pipes[0];
+- data->wfd = pipes[1];
+-
+- if (pthread_create(&data->thread, NULL, gg_resolver_pthread_thread, data)) {
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() unable to create thread\n");
+- new_errno = errno;
+- goto cleanup;
+- }
+-
+- gg_debug(GG_DEBUG_MISC, "// gg_resolver_pthread_start() %p\n", data);
+-
+- *fd = pipes[0];
+- *priv_data = data;
+-
+- return 0;
+-
+-cleanup:
+- if (data != NULL)
+- free(data->hostname);
+-
+- free(data);
+-
+- close(pipes[0]);
+- close(pipes[1]);
+-
+- errno = new_errno;
+-
+- return -1;
+-}
+-
+-#endif /* GG_CONFIG_HAVE_PTHREAD */
+-
+-/**
+- * Ustawia sposób rozwiązywania nazw w sesji.
+- *
+- * \param gs Struktura sesji
+- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_session_set_resolver(struct gg_session *gs, gg_resolver_t type)
+-{
+- GG_SESSION_CHECK(gs, -1);
+-
+- if (type == GG_RESOLVER_DEFAULT) {
+- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
+- gs->resolver_type = gg_global_resolver_type;
+- gs->resolver_start = gg_global_resolver_start;
+- gs->resolver_cleanup = gg_global_resolver_cleanup;
+- return 0;
+- }
+-
+-#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
+-# ifdef _WIN32
+- type = GG_RESOLVER_WIN32;
+-# else
+- type = GG_RESOLVER_FORK;
+-# endif
+-#else
+- type = GG_RESOLVER_PTHREAD;
+-#endif
+- }
+-
+- switch (type) {
+-#ifdef _WIN32
+- case GG_RESOLVER_WIN32:
+- gs->resolver_type = type;
+- gs->resolver_start = gg_resolve_win32thread;
+- gs->resolver_cleanup = gg_resolve_win32thread_cleanup;
+- return 0;
+-#else
+- case GG_RESOLVER_FORK:
+- gs->resolver_type = type;
+- gs->resolver_start = gg_resolver_fork_start;
+- gs->resolver_cleanup = gg_resolver_fork_cleanup;
+- return 0;
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- case GG_RESOLVER_PTHREAD:
+- gs->resolver_type = type;
+- gs->resolver_start = gg_resolver_pthread_start;
+- gs->resolver_cleanup = gg_resolver_pthread_cleanup;
+- return 0;
+-#endif
+-
+- default:
+- errno = EINVAL;
+- return -1;
+- }
+-}
+-
+-/**
+- * Zwraca sposób rozwiązywania nazw w sesji.
+- *
+- * \param gs Struktura sesji
+- *
+- * \return Sposób rozwiązywania nazw
+- */
+-gg_resolver_t gg_session_get_resolver(struct gg_session *gs)
+-{
+- GG_SESSION_CHECK(gs, (gg_resolver_t) -1);
+-
+- return gs->resolver_type;
+-}
+-
+-/**
+- * Ustawia własny sposób rozwiązywania nazw w sesji.
+- *
+- * \param gs Struktura sesji
+- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
+- * \param resolver_cleanup Funkcja zwalniająca zasoby
+- *
+- * Parametry funkcji rozpoczynającej rozwiązywanie nazwy wyglądają następująco:
+- * - \c "int *fd" &mdash; wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor potoku
+- * - \c "void **priv_data" &mdash; wskaźnik na zmienną, gdzie można umieścić wskaźnik do prywatnych danych na potrzeby rozwiązywania nazwy
+- * - \c "const char *name" &mdash; nazwa serwera do rozwiązania
+- *
+- * Parametry funkcji zwalniającej zasoby wyglądają następująco:
+- * - \c "void **priv_data" &mdash; wskaźnik na zmienną przechowującą wskaźnik do prywatnych danych, należy go ustawić na \c NULL po zakończeniu
+- * - \c "int force" &mdash; flaga mówiąca o tym, że zasoby są zwalniane przed zakończeniem rozwiązywania nazwy, np. z powodu zamknięcia sesji.
+- *
+- * Własny kod rozwiązywania nazwy powinien stworzyć potok, parę gniazd lub
+- * inny deskryptor pozwalający na co najmniej jednostronną komunikację i
+- * przekazać go w parametrze \c fd. Po zakończeniu rozwiązywania nazwy,
+- * powinien wysłać otrzymany adres IP w postaci sieciowej (big-endian) do
+- * deskryptora. Jeśli rozwiązywanie nazwy się nie powiedzie, należy wysłać
+- * \c INADDR_NONE. Następnie zostanie wywołana funkcja zwalniająca zasoby
+- * z parametrem \c force równym \c 0. Gdyby sesja została zakończona przed
+- * rozwiązaniem nazwy, np. za pomocą funkcji \c gg_logoff(), funkcja
+- * zwalniająca zasoby zostanie wywołana z parametrem \c force równym \c 1.
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_session_set_custom_resolver(struct gg_session *gs, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
+-{
+- GG_SESSION_CHECK(gs, -1);
+-
+- if (resolver_start == NULL || resolver_cleanup == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- gs->resolver_type = GG_RESOLVER_CUSTOM;
+- gs->resolver_start = resolver_start;
+- gs->resolver_cleanup = resolver_cleanup;
+-
+- return 0;
+-}
+-
+-/**
+- * Ustawia sposób rozwiązywania nazw połączenia HTTP.
+- *
+- * \param gh Struktura połączenia
+- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_http_set_resolver(struct gg_http *gh, gg_resolver_t type)
+-{
+- if (gh == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- if (type == GG_RESOLVER_DEFAULT) {
+- if (gg_global_resolver_type != GG_RESOLVER_DEFAULT) {
+- gh->resolver_type = gg_global_resolver_type;
+- gh->resolver_start = gg_global_resolver_start;
+- gh->resolver_cleanup = gg_global_resolver_cleanup;
+- return 0;
+- }
+-
+-#if !defined(GG_CONFIG_HAVE_PTHREAD) || !defined(GG_CONFIG_PTHREAD_DEFAULT)
+-# ifdef _WIN32
+- type = GG_RESOLVER_WIN32;
+-# else
+- type = GG_RESOLVER_FORK;
+-# endif
+-#else
+- type = GG_RESOLVER_PTHREAD;
+-#endif
+- }
+-
+- switch (type) {
+-#ifdef _WIN32
+- case GG_RESOLVER_WIN32:
+- gh->resolver_type = type;
+- gh->resolver_start = gg_resolve_win32thread;
+- gh->resolver_cleanup = gg_resolve_win32thread_cleanup;
+- return 0;
+-#else
+- case GG_RESOLVER_FORK:
+- gh->resolver_type = type;
+- gh->resolver_start = gg_resolver_fork_start;
+- gh->resolver_cleanup = gg_resolver_fork_cleanup;
+- return 0;
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- case GG_RESOLVER_PTHREAD:
+- gh->resolver_type = type;
+- gh->resolver_start = gg_resolver_pthread_start;
+- gh->resolver_cleanup = gg_resolver_pthread_cleanup;
+- return 0;
+-#endif
+-
+- default:
+- errno = EINVAL;
+- return -1;
+- }
+-}
+-
+-/**
+- * Zwraca sposób rozwiązywania nazw połączenia HTTP.
+- *
+- * \param gh Struktura połączenia
+- *
+- * \return Sposób rozwiązywania nazw
+- */
+-gg_resolver_t gg_http_get_resolver(struct gg_http *gh)
+-{
+- if (gh == NULL) {
+- errno = EINVAL;
+- return GG_RESOLVER_INVALID;
+- }
+-
+- return gh->resolver_type;
+-}
+-
+-/**
+- * Ustawia własny sposób rozwiązywania nazw połączenia HTTP.
+- *
+- * \param gh Struktura sesji
+- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
+- * \param resolver_cleanup Funkcja zwalniająca zasoby
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_http_set_custom_resolver(struct gg_http *gh, int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
+-{
+- if (gh == NULL || resolver_start == NULL || resolver_cleanup == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- gh->resolver_type = GG_RESOLVER_CUSTOM;
+- gh->resolver_start = resolver_start;
+- gh->resolver_cleanup = resolver_cleanup;
+-
+- return 0;
+-}
+-
+-/**
+- * Ustawia sposób rozwiązywania nazw globalnie dla biblioteki.
+- *
+- * \param type Sposób rozwiązywania nazw (patrz \ref build-resolver)
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_global_set_resolver(gg_resolver_t type)
+-{
+- switch (type) {
+- case GG_RESOLVER_DEFAULT:
+- gg_global_resolver_type = type;
+- gg_global_resolver_start = NULL;
+- gg_global_resolver_cleanup = NULL;
+- return 0;
+-
+-#ifdef _WIN32
+- case GG_RESOLVER_WIN32:
+- gg_global_resolver_type = type;
+- gg_global_resolver_start = gg_resolve_win32thread;
+- gg_global_resolver_cleanup = gg_resolve_win32thread_cleanup;
+- return 0;
+-#else
+- case GG_RESOLVER_FORK:
+- gg_global_resolver_type = type;
+- gg_global_resolver_start = gg_resolver_fork_start;
+- gg_global_resolver_cleanup = gg_resolver_fork_cleanup;
+- return 0;
+-#endif
+-
+-#ifdef GG_CONFIG_HAVE_PTHREAD
+- case GG_RESOLVER_PTHREAD:
+- gg_global_resolver_type = type;
+- gg_global_resolver_start = gg_resolver_pthread_start;
+- gg_global_resolver_cleanup = gg_resolver_pthread_cleanup;
+- return 0;
+-#endif
+-
+- default:
+- errno = EINVAL;
+- return -1;
+- }
+-}
+-
+-/**
+- * Zwraca sposób rozwiązywania nazw globalnie dla biblioteki.
+- *
+- * \return Sposób rozwiązywania nazw
+- */
+-gg_resolver_t gg_global_get_resolver(void)
+-{
+- return gg_global_resolver_type;
+-}
+-
+-/**
+- * Ustawia własny sposób rozwiązywania nazw globalnie dla biblioteki.
+- *
+- * \param resolver_start Funkcja rozpoczynająca rozwiązywanie nazwy
+- * \param resolver_cleanup Funkcja zwalniająca zasoby
+- *
+- * Patrz \ref gg_session_set_custom_resolver.
+- *
+- * \return 0 jeśli się powiodło, -1 w przypadku błędu
+- */
+-int gg_global_set_custom_resolver(int (*resolver_start)(int*, void**, const char*), void (*resolver_cleanup)(void**, int))
+-{
+- if (resolver_start == NULL || resolver_cleanup == NULL) {
+- errno = EINVAL;
+- return -1;
+- }
+-
+- gg_global_resolver_type = GG_RESOLVER_CUSTOM;
+- gg_global_resolver_start = resolver_start;
+- gg_global_resolver_cleanup = resolver_cleanup;
+-
+- return 0;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/resolver.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/resolver.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,28 +0,0 @@
+-/*
+- * (C) Copyright 2008 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_RESOLVER_H
+-#define LIBGADU_RESOLVER_H
+-
+-#ifndef _WIN32
+-# include <arpa/inet.h>
+-#endif
+-
+-int gg_gethostbyname_real(const char *hostname, struct in_addr **result, int *count, int pthread);
+-
+-#endif /* LIBGADU_RESOLVER_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/session.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/session.h
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/session.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/session.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,70 +0,0 @@
+-/*
+- * (C) Copyright 2008-2010 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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 LIBGADU_SESSION_H
+-#define LIBGADU_SESSION_H
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+-# include <gnutls/gnutls.h>
+-#endif
+-
+-#define GG_SESSION_CHECK(gs, result) \
+- do { \
+- if ((gs) == NULL) { \
+- errno = EINVAL; \
+- return (result); \
+- } \
+- } while (0)
+-
+-#define GG_SESSION_CHECK_CONNECTED(gs, result) \
+- do { \
+- GG_SESSION_CHECK(gs, result); \
+- \
+- if (!GG_SESSION_IS_CONNECTED(gs)) { \
+- errno = ENOTCONN; \
+- return (result); \
+- } \
+- } while (0)
+-
+-#define GG_SESSION_IS_PROTOCOL_7_7(gs) ((gs)->protocol_version >= 0x2a)
+-#define GG_SESSION_IS_PROTOCOL_8_0(gs) ((gs)->protocol_version >= 0x2d)
+-
+-#define GG_SESSION_IS_IDLE(gs) ((gs)->state == GG_STATE_IDLE)
+-#define GG_SESSION_IS_CONNECTING(gs) ((gs)->state != GG_STATE_IDLE && (gs)->state != GG_STATE_CONNECTED)
+-#define GG_SESSION_IS_CONNECTED(gs) ((gs)->state == GG_STATE_CONNECTED)
+-
+-#ifdef GG_CONFIG_HAVE_GNUTLS
+-
+-typedef struct {
+- gnutls_session_t session;
+- gnutls_certificate_credentials_t xcred;
+-} gg_session_gnutls_t;
+-
+-#define GG_SESSION_GNUTLS(gs) ((gg_session_gnutls_t*) (gs)->ssl)->session
+-
+-#endif /* GG_CONFIG_HAVE_GNUTLS */
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-
+-#define GG_SESSION_OPENSSL(gs) ((SSL*) (gs)->ssl)
+-
+-#endif /* GG_CONFIG_HAVE_OPENSSL */
+-
+-int gg_session_handle_packet(struct gg_session *gs, uint32_t type, const char *ptr, size_t len, struct gg_event *ge);
+-
+-#endif /* LIBGADU_SESSION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/lib/sha1.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/sha1.c
+--- pidgin-2.10.7/libpurple/protocols/gg/lib/sha1.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/lib/sha1.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,303 +0,0 @@
+-/* $Id: sha1.c 1067 2011-03-15 18:57:16Z wojtekka $ */
+-
+-/*
+- * (C) Copyright 2007 Wojtek Kaniewski <wojtekka@irc.pl>
+- *
+- * Public domain SHA-1 implementation by Steve Reid <steve@edmweb.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU Lesser General Public License Version
+- * 2.1 as published by the Free Software Foundation.
+- *
+- * 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 Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser 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.
+- */
+-
+-/**
+- * \file sha1.c
+- *
+- * \brief Funkcje wyznaczania skrótu SHA1
+- */
+-
+-#include <string.h>
+-#include <sys/types.h>
+-#include <unistd.h>
+-
+-#include "libgadu.h"
+-
+-/** \cond ignore */
+-
+-#ifdef GG_CONFIG_HAVE_OPENSSL
+-
+-#include <openssl/sha.h>
+-
+-#else
+-
+-/*
+-SHA-1 in C
+-By Steve Reid <steve@edmweb.com>
+-100% Public Domain
+-
+-Modified by Wojtek Kaniewski <wojtekka@toxygen.net> for compatibility
+-with libgadu and OpenSSL API.
+-
+-Test Vectors (from FIPS PUB 180-1)
+-"abc"
+- A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
+-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
+- 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
+-A million repetitions of "a"
+- 34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
+-*/
+-
+-/* #define LITTLE_ENDIAN * This should be #define'd if true. */
+-/* #define SHA1HANDSOFF * Copies data before messing with it. */
+-
+-#include <string.h>
+-
+-typedef struct {
+- uint32_t state[5];
+- uint32_t count[2];
+- unsigned char buffer[64];
+-} SHA_CTX;
+-
+-static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64]);
+-static void SHA1_Init(SHA_CTX* context);
+-static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len);
+-static void SHA1_Final(unsigned char digest[20], SHA_CTX* context);
+-
+-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
+-
+-/* blk0() and blk() perform the initial expand. */
+-/* I got the idea of expanding during the round function from SSLeay */
+-#ifndef GG_CONFIG_BIGENDIAN
+-#define blk0(i) (block->l[i] = (rol(block->l[i],24)&0xFF00FF00) \
+- |(rol(block->l[i],8)&0x00FF00FF))
+-#else
+-#define blk0(i) block->l[i]
+-#endif
+-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
+- ^block->l[(i+2)&15]^block->l[i&15],1))
+-
+-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
+-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
+-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
+-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
+-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
+-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
+-
+-
+-/* Hash a single 512-bit block. This is the core of the algorithm. */
+-
+-static void SHA1_Transform(uint32_t state[5], const unsigned char buffer[64])
+-{
+-uint32_t a, b, c, d, e;
+-typedef union {
+- unsigned char c[64];
+- uint32_t l[16];
+-} CHAR64LONG16;
+-CHAR64LONG16* block;
+-static unsigned char workspace[64];
+- block = (CHAR64LONG16*)workspace;
+- memcpy(block, buffer, 64);
+- /* Copy context->state[] to working vars */
+- a = state[0];
+- b = state[1];
+- c = state[2];
+- d = state[3];
+- e = state[4];
+- /* 4 rounds of 20 operations each. Loop unrolled. */
+- R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
+- R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
+- R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
+- R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
+- R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
+- R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
+- R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
+- R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
+- R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
+- R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
+- R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
+- R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
+- R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
+- R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
+- R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
+- R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
+- R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
+- R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
+- R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
+- R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
+- /* Add the working vars back into context.state[] */
+- state[0] += a;
+- state[1] += b;
+- state[2] += c;
+- state[3] += d;
+- state[4] += e;
+- /* Wipe variables */
+- a = b = c = d = e = 0;
+-}
+-
+-
+-/* SHA1_Init - Initialize new context */
+-
+-static void SHA1_Init(SHA_CTX* context)
+-{
+- /* SHA1 initialization constants */
+- context->state[0] = 0x67452301;
+- context->state[1] = 0xEFCDAB89;
+- context->state[2] = 0x98BADCFE;
+- context->state[3] = 0x10325476;
+- context->state[4] = 0xC3D2E1F0;
+- context->count[0] = context->count[1] = 0;
+-}
+-
+-
+-/* Run your data through this. */
+-
+-static void SHA1_Update(SHA_CTX* context, const unsigned char* data, unsigned int len)
+-{
+-unsigned int i, j;
+-
+- j = (context->count[0] >> 3) & 63;
+- if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
+- context->count[1] += (len >> 29);
+- if ((j + len) > 63) {
+- memcpy(&context->buffer[j], data, (i = 64-j));
+- SHA1_Transform(context->state, context->buffer);
+- for ( ; i + 63 < len; i += 64) {
+- SHA1_Transform(context->state, &data[i]);
+- }
+- j = 0;
+- }
+- else i = 0;
+- memcpy(&context->buffer[j], &data[i], len - i);
+-}
+-
+-
+-/* Add padding and return the message digest. */
+-
+-static void SHA1_Final(unsigned char digest[20], SHA_CTX* context)
+-{
+-uint32_t i, j;
+-unsigned char finalcount[8];
+-
+- for (i = 0; i < 8; i++) {
+- finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
+- >> ((3-(i & 3)) * 8) ) & 255); /* Endian independent */
+- }
+- SHA1_Update(context, (unsigned char *)"\200", 1);
+- while ((context->count[0] & 504) != 448) {
+- SHA1_Update(context, (unsigned char *)"\0", 1);
+- }
+- SHA1_Update(context, finalcount, 8); /* Should cause a SHA1_Transform() */
+- for (i = 0; i < 20; i++) {
+- digest[i] = (unsigned char)
+- ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
+- }
+- /* Wipe variables */
+- i = j = 0;
+- memset(context->buffer, 0, 64);
+- memset(context->state, 0, 20);
+- memset(context->count, 0, 8);
+- memset(&finalcount, 0, 8);
+-#ifdef SHA1HANDSOFF /* make SHA1_Transform overwrite it's own static vars */
+- SHA1_Transform(context->state, context->buffer);
+-#endif
+-}
+-
+-#endif /* GG_CONFIG_HAVE_OPENSSL */
+-
+-/** \endcond */
+-
+-/** \cond internal */
+-
+-/**
+- * \internal Liczy skrót SHA1 z ziarna i hasła.
+- *
+- * \param password Hasło
+- * \param seed Ziarno
+- * \param result Bufor na wynik funkcji skrĂłtu (20 bajtĂłw)
+- */
+-void gg_login_hash_sha1(const char *password, uint32_t seed, uint8_t *result)
+-{
+- SHA_CTX ctx;
+-
+- SHA1_Init(&ctx);
+- SHA1_Update(&ctx, (const unsigned char*) password, strlen(password));
+- seed = gg_fix32(seed);
+- SHA1_Update(&ctx, (uint8_t*) &seed, 4);
+-
+- SHA1_Final(result, &ctx);
+-}
+-
+-/**
+- * \internal Liczy skrĂłt SHA1 z pliku.
+- *
+- * \param fd Deskryptor pliku
+- * \param result WskaĹşnik na skrĂłt
+- *
+- * \return 0 lub -1
+- */
+-int gg_file_hash_sha1(int fd, uint8_t *result)
+-{
+- unsigned char buf[4096];
+- SHA_CTX ctx;
+- off_t pos, len;
+- int res;
+-
+- if ((pos = lseek(fd, 0, SEEK_CUR)) == (off_t) -1)
+- return -1;
+-
+- if ((len = lseek(fd, 0, SEEK_END)) == (off_t) -1)
+- return -1;
+-
+- if (lseek(fd, 0, SEEK_SET) == (off_t) -1)
+- return -1;
+-
+- SHA1_Init(&ctx);
+-
+- if (len <= 10485760) {
+- while ((res = read(fd, buf, sizeof(buf))) > 0)
+- SHA1_Update(&ctx, buf, res);
+- } else {
+- int i;
+-
+- for (i = 0; i < 9; i++) {
+- int j;
+-
+- if (lseek(fd, (len - 1048576) / 9 * i, SEEK_SET) == (off_t) - 1)
+- return -1;
+-
+- for (j = 0; j < 1048576 / sizeof(buf); j++) {
+- if ((res = read(fd, buf, sizeof(buf))) != sizeof(buf)) {
+- res = -1;
+- break;
+- }
+-
+- SHA1_Update(&ctx, buf, res);
+- }
+-
+- if (res == -1)
+- break;
+- }
+- }
+-
+- if (res == -1)
+- return -1;
+-
+- SHA1_Final(result, &ctx);
+-
+- if (lseek(fd, pos, SEEK_SET) == (off_t) -1)
+- return -1;
+-
+- return 0;
+-}
+-
+-/** \endcond */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/gg/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,111 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw \
+- lib/common.c \
+- lib/compat.h \
+- lib/COPYING \
+- lib/dcc.c \
+- lib/dcc7.c \
+- lib/debug.c \
+- lib/deflate.c \
+- lib/deflate.h \
+- lib/encoding.c \
+- lib/encoding.h \
+- lib/events.c \
+- lib/handlers.c \
+- lib/http.c \
+- lib/libgadu.h \
+- lib/libgadu.c \
+- lib/libgadu-config.h \
+- lib/libgadu-debug.h \
+- lib/libgadu-internal.h \
+- lib/message.c \
+- lib/message.h \
+- lib/obsolete.c \
+- lib/protocol.h \
+- lib/pubdir.c \
+- lib/pubdir50.c \
+- lib/resolver.c \
+- lib/resolver.h \
+- lib/session.h \
+- lib/sha1.c
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-if USE_INTERNAL_LIBGADU
+-INTGGSOURCES = \
+- lib/common.c \
+- lib/compat.h \
+- lib/dcc.c \
+- lib/dcc7.c \
+- lib/debug.c \
+- lib/deflate.c \
+- lib/deflate.h \
+- lib/encoding.c \
+- lib/encoding.h \
+- lib/events.c \
+- lib/handlers.c \
+- lib/http.c \
+- lib/libgadu.h \
+- lib/libgadu.c \
+- lib/libgadu-config.h \
+- lib/libgadu-internal.h \
+- lib/message.c \
+- lib/message.h \
+- lib/obsolete.c \
+- lib/protocol.h \
+- lib/pubdir.c \
+- lib/pubdir50.c \
+- lib/resolver.c \
+- lib/resolver.h \
+- lib/session.h \
+- lib/sha1.c
+-
+-INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
+-endif
+-
+-if USE_GNUTLS
+-GADU_LIBS += $(GNUTLS_LIBS)
+-GADU_CFLAGS += $(GNUTLS_CFLAGS)
+-endif
+-
+-GGSOURCES = \
+- $(INTGGSOURCES) \
+- gg-utils.h \
+- gg-utils.c \
+- confer.h \
+- confer.c \
+- search.h \
+- search.c \
+- buddylist.h \
+- buddylist.c \
+- gg.h \
+- gg.c
+-
+-AM_CFLAGS = $(st)
+-
+-libgg_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_GG
+-
+-st = -DPURPLE_STATIC_PRPL $(GADU_CFLAGS)
+-noinst_LTLIBRARIES = libgg.la
+-libgg_la_SOURCES = $(GGSOURCES)
+-libgg_la_CFLAGS = $(AM_CFLAGS)
+-libgg_la_LIBADD = $(GADU_LIBS)
+-
+-else
+-
+-st = $(GADU_CFLAGS)
+-pkg_LTLIBRARIES = libgg.la
+-libgg_la_SOURCES = $(GGSOURCES)
+-libgg_la_LIBADD = $(GLIB_LIBS) $(GADU_LIBS)
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(INTGG_CFLAGS) \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/gg/Makefile.in 2013-02-11 07:17:20.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1007 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-@USE_GNUTLS_TRUE@am__append_1 = $(GNUTLS_LIBS)
+-@USE_GNUTLS_TRUE@am__append_2 = $(GNUTLS_CFLAGS)
+-subdir = libpurple/protocols/gg
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-@USE_GNUTLS_TRUE@am__DEPENDENCIES_2 = $(am__DEPENDENCIES_1)
+-am__DEPENDENCIES_3 = $(am__DEPENDENCIES_2)
+-@STATIC_GG_FALSE@libgg_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+-@STATIC_GG_FALSE@ $(am__DEPENDENCIES_3)
+-@STATIC_GG_TRUE@libgg_la_DEPENDENCIES = $(am__DEPENDENCIES_3)
+-am__libgg_la_SOURCES_DIST = lib/common.c lib/compat.h lib/dcc.c \
+- lib/dcc7.c lib/debug.c lib/deflate.c lib/deflate.h \
+- lib/encoding.c lib/encoding.h lib/events.c lib/handlers.c \
+- lib/http.c lib/libgadu.h lib/libgadu.c lib/libgadu-config.h \
+- lib/libgadu-internal.h lib/message.c lib/message.h \
+- lib/obsolete.c lib/protocol.h lib/pubdir.c lib/pubdir50.c \
+- lib/resolver.c lib/resolver.h lib/session.h lib/sha1.c \
+- gg-utils.h gg-utils.c confer.h confer.c search.h search.c \
+- buddylist.h buddylist.c gg.h gg.c
+-@USE_INTERNAL_LIBGADU_TRUE@am__objects_1 = libgg_la-common.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-dcc.lo libgg_la-dcc7.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-debug.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-deflate.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-encoding.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-events.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-handlers.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-http.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-libgadu.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-message.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-obsolete.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-pubdir.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-pubdir50.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-resolver.lo \
+-@USE_INTERNAL_LIBGADU_TRUE@ libgg_la-sha1.lo
+-am__objects_2 = $(am__objects_1) libgg_la-gg-utils.lo \
+- libgg_la-confer.lo libgg_la-search.lo libgg_la-buddylist.lo \
+- libgg_la-gg.lo
+-@STATIC_GG_FALSE@am_libgg_la_OBJECTS = $(am__objects_2)
+-@STATIC_GG_TRUE@am_libgg_la_OBJECTS = $(am__objects_2)
+-libgg_la_OBJECTS = $(am_libgg_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libgg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libgg_la_CFLAGS) \
+- $(CFLAGS) $(libgg_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_GG_FALSE@am_libgg_la_rpath = -rpath $(pkgdir)
+-@STATIC_GG_TRUE@am_libgg_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libgg_la_SOURCES)
+-DIST_SOURCES = $(am__libgg_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@ $(am__append_2)
+-GADU_LIBS = @GADU_LIBS@ $(am__append_1)
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw \
+- lib/common.c \
+- lib/compat.h \
+- lib/COPYING \
+- lib/dcc.c \
+- lib/dcc7.c \
+- lib/debug.c \
+- lib/deflate.c \
+- lib/deflate.h \
+- lib/encoding.c \
+- lib/encoding.h \
+- lib/events.c \
+- lib/handlers.c \
+- lib/http.c \
+- lib/libgadu.h \
+- lib/libgadu.c \
+- lib/libgadu-config.h \
+- lib/libgadu-debug.h \
+- lib/libgadu-internal.h \
+- lib/message.c \
+- lib/message.h \
+- lib/obsolete.c \
+- lib/protocol.h \
+- lib/pubdir.c \
+- lib/pubdir50.c \
+- lib/resolver.c \
+- lib/resolver.h \
+- lib/session.h \
+- lib/sha1.c
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-@USE_INTERNAL_LIBGADU_TRUE@INTGGSOURCES = \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/common.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/compat.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/dcc.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/dcc7.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/debug.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/deflate.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/deflate.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/encoding.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/encoding.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/events.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/handlers.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/http.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu-config.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/libgadu-internal.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/message.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/message.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/obsolete.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/protocol.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/pubdir.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/pubdir50.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/resolver.c \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/resolver.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/session.h \
+-@USE_INTERNAL_LIBGADU_TRUE@ lib/sha1.c
+-
+-@USE_INTERNAL_LIBGADU_TRUE@INTGG_CFLAGS = -I$(top_srcdir)/libpurple/protocols/gg/lib -DGG_IGNORE_DEPRECATED -DUSE_INTERNAL_LIBGADU
+-GGSOURCES = \
+- $(INTGGSOURCES) \
+- gg-utils.h \
+- gg-utils.c \
+- confer.h \
+- confer.c \
+- search.h \
+- search.c \
+- buddylist.h \
+- buddylist.c \
+- gg.h \
+- gg.c
+-
+-AM_CFLAGS = $(st)
+-libgg_la_LDFLAGS = -module -avoid-version
+-@STATIC_GG_FALSE@st = $(GADU_CFLAGS)
+-@STATIC_GG_TRUE@st = -DPURPLE_STATIC_PRPL $(GADU_CFLAGS)
+-@STATIC_GG_TRUE@noinst_LTLIBRARIES = libgg.la
+-@STATIC_GG_FALSE@libgg_la_SOURCES = $(GGSOURCES)
+-@STATIC_GG_TRUE@libgg_la_SOURCES = $(GGSOURCES)
+-@STATIC_GG_TRUE@libgg_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_GG_FALSE@libgg_la_LIBADD = $(GLIB_LIBS) $(GADU_LIBS)
+-@STATIC_GG_TRUE@libgg_la_LIBADD = $(GADU_LIBS)
+-@STATIC_GG_FALSE@pkg_LTLIBRARIES = libgg.la
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(INTGG_CFLAGS) \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/gg/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/gg/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libgg.la: $(libgg_la_OBJECTS) $(libgg_la_DEPENDENCIES) $(EXTRA_libgg_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libgg_la_LINK) $(am_libgg_la_rpath) $(libgg_la_OBJECTS) $(libgg_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-buddylist.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-common.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-confer.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-dcc.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-dcc7.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-debug.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-deflate.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-encoding.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-events.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-gg-utils.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-gg.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-handlers.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-http.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-libgadu.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-message.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-obsolete.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-pubdir.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-pubdir50.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-resolver.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-search.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libgg_la-sha1.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libgg_la-common.lo: lib/common.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-common.lo -MD -MP -MF $(DEPDIR)/libgg_la-common.Tpo -c -o libgg_la-common.lo `test -f 'lib/common.c' || echo '$(srcdir)/'`lib/common.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-common.Tpo $(DEPDIR)/libgg_la-common.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/common.c' object='libgg_la-common.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-common.lo `test -f 'lib/common.c' || echo '$(srcdir)/'`lib/common.c
+-
+-libgg_la-dcc.lo: lib/dcc.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-dcc.lo -MD -MP -MF $(DEPDIR)/libgg_la-dcc.Tpo -c -o libgg_la-dcc.lo `test -f 'lib/dcc.c' || echo '$(srcdir)/'`lib/dcc.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-dcc.Tpo $(DEPDIR)/libgg_la-dcc.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/dcc.c' object='libgg_la-dcc.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-dcc.lo `test -f 'lib/dcc.c' || echo '$(srcdir)/'`lib/dcc.c
+-
+-libgg_la-dcc7.lo: lib/dcc7.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-dcc7.lo -MD -MP -MF $(DEPDIR)/libgg_la-dcc7.Tpo -c -o libgg_la-dcc7.lo `test -f 'lib/dcc7.c' || echo '$(srcdir)/'`lib/dcc7.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-dcc7.Tpo $(DEPDIR)/libgg_la-dcc7.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/dcc7.c' object='libgg_la-dcc7.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-dcc7.lo `test -f 'lib/dcc7.c' || echo '$(srcdir)/'`lib/dcc7.c
+-
+-libgg_la-debug.lo: lib/debug.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-debug.lo -MD -MP -MF $(DEPDIR)/libgg_la-debug.Tpo -c -o libgg_la-debug.lo `test -f 'lib/debug.c' || echo '$(srcdir)/'`lib/debug.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-debug.Tpo $(DEPDIR)/libgg_la-debug.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/debug.c' object='libgg_la-debug.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-debug.lo `test -f 'lib/debug.c' || echo '$(srcdir)/'`lib/debug.c
+-
+-libgg_la-deflate.lo: lib/deflate.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-deflate.lo -MD -MP -MF $(DEPDIR)/libgg_la-deflate.Tpo -c -o libgg_la-deflate.lo `test -f 'lib/deflate.c' || echo '$(srcdir)/'`lib/deflate.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-deflate.Tpo $(DEPDIR)/libgg_la-deflate.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/deflate.c' object='libgg_la-deflate.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-deflate.lo `test -f 'lib/deflate.c' || echo '$(srcdir)/'`lib/deflate.c
+-
+-libgg_la-encoding.lo: lib/encoding.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-encoding.lo -MD -MP -MF $(DEPDIR)/libgg_la-encoding.Tpo -c -o libgg_la-encoding.lo `test -f 'lib/encoding.c' || echo '$(srcdir)/'`lib/encoding.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-encoding.Tpo $(DEPDIR)/libgg_la-encoding.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/encoding.c' object='libgg_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-encoding.lo `test -f 'lib/encoding.c' || echo '$(srcdir)/'`lib/encoding.c
+-
+-libgg_la-events.lo: lib/events.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-events.lo -MD -MP -MF $(DEPDIR)/libgg_la-events.Tpo -c -o libgg_la-events.lo `test -f 'lib/events.c' || echo '$(srcdir)/'`lib/events.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-events.Tpo $(DEPDIR)/libgg_la-events.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/events.c' object='libgg_la-events.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-events.lo `test -f 'lib/events.c' || echo '$(srcdir)/'`lib/events.c
+-
+-libgg_la-handlers.lo: lib/handlers.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-handlers.lo -MD -MP -MF $(DEPDIR)/libgg_la-handlers.Tpo -c -o libgg_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-handlers.Tpo $(DEPDIR)/libgg_la-handlers.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/handlers.c' object='libgg_la-handlers.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-handlers.lo `test -f 'lib/handlers.c' || echo '$(srcdir)/'`lib/handlers.c
+-
+-libgg_la-http.lo: lib/http.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-http.lo -MD -MP -MF $(DEPDIR)/libgg_la-http.Tpo -c -o libgg_la-http.lo `test -f 'lib/http.c' || echo '$(srcdir)/'`lib/http.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-http.Tpo $(DEPDIR)/libgg_la-http.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/http.c' object='libgg_la-http.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-http.lo `test -f 'lib/http.c' || echo '$(srcdir)/'`lib/http.c
+-
+-libgg_la-libgadu.lo: lib/libgadu.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-libgadu.lo -MD -MP -MF $(DEPDIR)/libgg_la-libgadu.Tpo -c -o libgg_la-libgadu.lo `test -f 'lib/libgadu.c' || echo '$(srcdir)/'`lib/libgadu.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-libgadu.Tpo $(DEPDIR)/libgg_la-libgadu.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/libgadu.c' object='libgg_la-libgadu.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-libgadu.lo `test -f 'lib/libgadu.c' || echo '$(srcdir)/'`lib/libgadu.c
+-
+-libgg_la-message.lo: lib/message.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-message.lo -MD -MP -MF $(DEPDIR)/libgg_la-message.Tpo -c -o libgg_la-message.lo `test -f 'lib/message.c' || echo '$(srcdir)/'`lib/message.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-message.Tpo $(DEPDIR)/libgg_la-message.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/message.c' object='libgg_la-message.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-message.lo `test -f 'lib/message.c' || echo '$(srcdir)/'`lib/message.c
+-
+-libgg_la-obsolete.lo: lib/obsolete.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-obsolete.lo -MD -MP -MF $(DEPDIR)/libgg_la-obsolete.Tpo -c -o libgg_la-obsolete.lo `test -f 'lib/obsolete.c' || echo '$(srcdir)/'`lib/obsolete.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-obsolete.Tpo $(DEPDIR)/libgg_la-obsolete.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/obsolete.c' object='libgg_la-obsolete.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-obsolete.lo `test -f 'lib/obsolete.c' || echo '$(srcdir)/'`lib/obsolete.c
+-
+-libgg_la-pubdir.lo: lib/pubdir.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-pubdir.lo -MD -MP -MF $(DEPDIR)/libgg_la-pubdir.Tpo -c -o libgg_la-pubdir.lo `test -f 'lib/pubdir.c' || echo '$(srcdir)/'`lib/pubdir.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-pubdir.Tpo $(DEPDIR)/libgg_la-pubdir.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/pubdir.c' object='libgg_la-pubdir.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-pubdir.lo `test -f 'lib/pubdir.c' || echo '$(srcdir)/'`lib/pubdir.c
+-
+-libgg_la-pubdir50.lo: lib/pubdir50.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-pubdir50.lo -MD -MP -MF $(DEPDIR)/libgg_la-pubdir50.Tpo -c -o libgg_la-pubdir50.lo `test -f 'lib/pubdir50.c' || echo '$(srcdir)/'`lib/pubdir50.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-pubdir50.Tpo $(DEPDIR)/libgg_la-pubdir50.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/pubdir50.c' object='libgg_la-pubdir50.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-pubdir50.lo `test -f 'lib/pubdir50.c' || echo '$(srcdir)/'`lib/pubdir50.c
+-
+-libgg_la-resolver.lo: lib/resolver.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-resolver.lo -MD -MP -MF $(DEPDIR)/libgg_la-resolver.Tpo -c -o libgg_la-resolver.lo `test -f 'lib/resolver.c' || echo '$(srcdir)/'`lib/resolver.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-resolver.Tpo $(DEPDIR)/libgg_la-resolver.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/resolver.c' object='libgg_la-resolver.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-resolver.lo `test -f 'lib/resolver.c' || echo '$(srcdir)/'`lib/resolver.c
+-
+-libgg_la-sha1.lo: lib/sha1.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-sha1.lo -MD -MP -MF $(DEPDIR)/libgg_la-sha1.Tpo -c -o libgg_la-sha1.lo `test -f 'lib/sha1.c' || echo '$(srcdir)/'`lib/sha1.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-sha1.Tpo $(DEPDIR)/libgg_la-sha1.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='lib/sha1.c' object='libgg_la-sha1.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-sha1.lo `test -f 'lib/sha1.c' || echo '$(srcdir)/'`lib/sha1.c
+-
+-libgg_la-gg-utils.lo: gg-utils.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-gg-utils.lo -MD -MP -MF $(DEPDIR)/libgg_la-gg-utils.Tpo -c -o libgg_la-gg-utils.lo `test -f 'gg-utils.c' || echo '$(srcdir)/'`gg-utils.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-gg-utils.Tpo $(DEPDIR)/libgg_la-gg-utils.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gg-utils.c' object='libgg_la-gg-utils.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-gg-utils.lo `test -f 'gg-utils.c' || echo '$(srcdir)/'`gg-utils.c
+-
+-libgg_la-confer.lo: confer.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-confer.lo -MD -MP -MF $(DEPDIR)/libgg_la-confer.Tpo -c -o libgg_la-confer.lo `test -f 'confer.c' || echo '$(srcdir)/'`confer.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-confer.Tpo $(DEPDIR)/libgg_la-confer.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='confer.c' object='libgg_la-confer.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-confer.lo `test -f 'confer.c' || echo '$(srcdir)/'`confer.c
+-
+-libgg_la-search.lo: search.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-search.lo -MD -MP -MF $(DEPDIR)/libgg_la-search.Tpo -c -o libgg_la-search.lo `test -f 'search.c' || echo '$(srcdir)/'`search.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-search.Tpo $(DEPDIR)/libgg_la-search.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='search.c' object='libgg_la-search.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-search.lo `test -f 'search.c' || echo '$(srcdir)/'`search.c
+-
+-libgg_la-buddylist.lo: buddylist.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-buddylist.lo -MD -MP -MF $(DEPDIR)/libgg_la-buddylist.Tpo -c -o libgg_la-buddylist.lo `test -f 'buddylist.c' || echo '$(srcdir)/'`buddylist.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-buddylist.Tpo $(DEPDIR)/libgg_la-buddylist.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='buddylist.c' object='libgg_la-buddylist.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-buddylist.lo `test -f 'buddylist.c' || echo '$(srcdir)/'`buddylist.c
+-
+-libgg_la-gg.lo: gg.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -MT libgg_la-gg.lo -MD -MP -MF $(DEPDIR)/libgg_la-gg.Tpo -c -o libgg_la-gg.lo `test -f 'gg.c' || echo '$(srcdir)/'`gg.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libgg_la-gg.Tpo $(DEPDIR)/libgg_la-gg.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='gg.c' object='libgg_la-gg.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libgg_la_CFLAGS) $(CFLAGS) -c -o libgg_la-gg.lo `test -f 'gg.c' || echo '$(srcdir)/'`gg.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/gg/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,100 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libgg
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libgg
+-CFLAGS += -include win32dep.h -DGG_IGNORE_DEPRECATED
+-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./lib \
+- -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 = \
+- lib/common.c \
+- lib/dcc.c \
+- lib/dcc7.c \
+- lib/debug.c \
+- lib/deflate.c \
+- lib/encoding.c \
+- lib/events.c \
+- lib/handlers.c \
+- lib/http.c \
+- lib/libgadu.c \
+- lib/message.c \
+- lib/obsolete.c \
+- lib/pubdir.c \
+- lib/pubdir50.c \
+- lib/resolver.c \
+- lib/sha1.c \
+- buddylist.c \
+- confer.c \
+- gg.c \
+- search.c \
+- gg-utils.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lintl \
+- -lpurple \
+- -lws2_32
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/search.c pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.c
+--- pidgin-2.10.7/libpurple/protocols/gg/search.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,223 +0,0 @@
+-/**
+- * @file search.c
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#include <libgadu.h>
+-
+-#include "gg-utils.h"
+-#include "search.h"
+-
+-
+-/* GGPSearchForm *ggp_search_form_new() {{{ */
+-GGPSearchForm *ggp_search_form_new(GGPSearchType st)
+-{
+- GGPSearchForm *form;
+-
+- form = g_new0(GGPSearchForm, 1);
+-
+- form->search_type = st;
+- form->window = NULL;
+- form->user_data = NULL;
+- form->seq = 0;
+- form->page_number = 0;
+- form->page_size = 0;
+-
+- form->uin = NULL;
+- form->lastname = NULL;
+- form->firstname = NULL;
+- form->nickname = NULL;
+- form->city = NULL;
+- form->birthyear = NULL;
+- form->gender = NULL;
+- form->active = NULL;
+-
+- return form;
+-}
+-/* }}} */
+-
+-/* void ggp_search_form_destroy(GGPSearchForm *form) {{{ */
+-void ggp_search_form_destroy(GGPSearchForm *form)
+-{
+- g_return_if_fail(form != NULL);
+-
+- form->window = NULL;
+- form->user_data = NULL;
+- form->seq = 0;
+- form->page_number = 0;
+- form->page_size = 0;
+-
+- g_free(form->uin);
+- g_free(form->lastname);
+- g_free(form->firstname);
+- g_free(form->nickname);
+- g_free(form->city);
+- g_free(form->birthyear);
+- g_free(form->gender);
+- g_free(form->active);
+- g_free(form);
+-}
+-/* }}} */
+-
+-/* void ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form) {{{ */
+-void ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form)
+-{
+- guint32 *tmp;
+-
+- g_return_if_fail(searches != NULL);
+- g_return_if_fail(form != NULL);
+-
+- tmp = g_new0(guint32, 1);
+- *tmp = seq;
+- form->seq = seq;
+-
+- g_hash_table_insert(searches, tmp, form);
+-}
+-/* }}} */
+-
+-/* void ggp_search_remove(GGPSearches *searches, guint32 seq) {{{ */
+-void ggp_search_remove(GGPSearches *searches, guint32 seq)
+-{
+- g_return_if_fail(searches != NULL);
+-
+- g_hash_table_remove(searches, &seq);
+-}
+-/* }}} */
+-
+-/* GGPSearchForm *ggp_search_get(GGPSearches *searches, seq) {{{ */
+-GGPSearchForm *ggp_search_get(GGPSearches *searches, guint32 seq)
+-{
+- g_return_val_if_fail(searches != NULL, NULL);
+-
+- return g_hash_table_lookup(searches, &seq);
+-}
+-/* }}} */
+-
+-/* GGPSearches *ggp_search_new() {{{ */
+-GGPSearches *ggp_search_new(void)
+-{
+- GGPSearches *searches;
+-
+- searches = g_hash_table_new_full(g_int_hash, g_int_equal,
+- g_free, NULL);
+-
+- return searches;
+-}
+-/* }}} */
+-
+-/* void ggp_search_destroy(GGPSearches *searches) {{{ */
+-void ggp_search_destroy(GGPSearches *searches)
+-{
+- g_return_if_fail(searches != NULL);
+-
+- g_hash_table_destroy(searches);
+-}
+-/* }}} */
+-
+-/* guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form) {{{ */
+-guint32 ggp_search_start(PurpleConnection *gc, GGPSearchForm *form)
+-{
+- GGPInfo *info = gc->proto_data;
+- gg_pubdir50_t req;
+- guint seq, offset;
+- gchar *tmp;
+-
+- purple_debug_info("gg", "It's time to perform a search...\n");
+-
+- if ((req = gg_pubdir50_new(GG_PUBDIR50_SEARCH)) == NULL) {
+- purple_debug_error("gg",
+- "ggp_bmenu_show_details: Unable to create req variable.\n");
+- return 0;
+- }
+-
+- if (form->uin != NULL) {
+- purple_debug_info("gg", " uin: %s\n", form->uin);
+- gg_pubdir50_add(req, GG_PUBDIR50_UIN, form->uin);
+- } else {
+- if (form->lastname != NULL) {
+- purple_debug_info("gg", " lastname: %s\n", form->lastname);
+- gg_pubdir50_add(req, GG_PUBDIR50_LASTNAME, form->lastname);
+- }
+-
+- if (form->firstname != NULL) {
+- purple_debug_info("gg", " firstname: %s\n", form->firstname);
+- gg_pubdir50_add(req, GG_PUBDIR50_FIRSTNAME, form->firstname);
+- }
+-
+- if (form->nickname != NULL) {
+- purple_debug_info("gg", " nickname: %s\n", form->nickname);
+- gg_pubdir50_add(req, GG_PUBDIR50_NICKNAME, form->nickname);
+- }
+-
+- if (form->city != NULL) {
+- purple_debug_info("gg", " city: %s\n", form->city);
+- gg_pubdir50_add(req, GG_PUBDIR50_CITY, form->city);
+- }
+-
+- if (form->birthyear != NULL) {
+- purple_debug_info("gg", " birthyear: %s\n", form->birthyear);
+- gg_pubdir50_add(req, GG_PUBDIR50_BIRTHYEAR, form->birthyear);
+- }
+-
+- if (form->gender != NULL) {
+- purple_debug_info("gg", " gender: %s\n", form->gender);
+- gg_pubdir50_add(req, GG_PUBDIR50_GENDER, form->gender);
+- }
+-
+- if (form->active != NULL) {
+- purple_debug_info("gg", " active: %s\n", form->active);
+- gg_pubdir50_add(req, GG_PUBDIR50_ACTIVE, form->active);
+- }
+- }
+-
+- offset = form->page_size * form->page_number;
+- purple_debug_info("gg", "page number: %u, page size: %u, offset: %u\n",
+- form->page_number, form->page_size, offset);
+- tmp = g_strdup_printf("%u", offset);
+- gg_pubdir50_add(req, GG_PUBDIR50_START, tmp);
+- g_free(tmp);
+-
+- if ((seq = gg_pubdir50(info->session, req)) == 0) {
+- purple_debug_warning("gg", "ggp_bmenu_show_details: Search failed.\n");
+- gg_pubdir50_free(req);
+- return 0;
+- }
+-
+- purple_debug_info("gg", "search sequence number: %d\n", seq);
+- gg_pubdir50_free(req);
+-
+- return seq;
+-}
+-/* }}} */
+-
+-/* char *ggp_search_get_result(gg_pubdir50_t res, int num, const char *field) {{{ */
+-char *ggp_search_get_result(gg_pubdir50_t res, int num, const char *field)
+-{
+- char *tmp;
+-
+- tmp = g_strdup(gg_pubdir50_get(res, num, field));
+-
+- return (tmp == NULL) ? g_strdup("") : tmp;
+-}
+-/* }}} */
+-
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/gg/search.h pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.h
+--- pidgin-2.10.7/libpurple/protocols/gg/search.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/gg/search.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,152 +0,0 @@
+-/**
+- * @file search.h
+- *
+- * purple
+- *
+- * Copyright (C) 2005 Bartosz Oler <bartosz@bzimage.us>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#ifndef _PURPLE_GG_SEARCH_H
+-#define _PURPLE_GG_SEARCH_H
+-
+-#include "connection.h"
+-
+-#include <libgadu.h>
+-#include "gg.h"
+-
+-
+-typedef enum {
+- GGP_SEARCH_TYPE_INFO,
+- GGP_SEARCH_TYPE_FULL
+-
+-} GGPSearchType;
+-
+-typedef struct {
+-
+- char *uin;
+- char *lastname;
+- char *firstname;
+- char *nickname;
+- char *city;
+- char *birthyear;
+- char *gender;
+- char *active;
+-
+- GGPSearchType search_type;
+- guint32 seq;
+- guint16 page_number;
+- guint16 page_size; /* how many contacts fits into one page of results */
+-
+- void *user_data;
+- void *window;
+-} GGPSearchForm;
+-
+-typedef GHashTable GGPSearches;
+-
+-
+-/**
+- * Create a new GGPSearchForm structure, and set the fields
+- * to the sane defaults.
+- *
+- * @return Newly allocated GGPSearchForm.
+- */
+-GGPSearchForm *
+-ggp_search_form_new(GGPSearchType st);
+-
+-/**
+- * Destroy a Search Form.
+- *
+- * @param form Search Form to destroy.
+- */
+-void
+-ggp_search_form_destroy(GGPSearchForm *form);
+-
+-/**
+- * Add a search to the list of searches.
+- *
+- * @param searches The list of searches.
+- * @param seq Search (form) ID number.
+- * @param form The search form to add.
+- */
+-void
+-ggp_search_add(GGPSearches *searches, guint32 seq, GGPSearchForm *form);
+-
+-/**
+- * Remove a search from the list.
+- *
+- * If you want to destory the search completely also call:
+- * ggp_search_form_destroy().
+- *
+- * @param searches The list of searches.
+- * @param seq ID number of the search.
+- */
+-void
+-ggp_search_remove(GGPSearches *searches, guint32 seq);
+-
+-/**
+- * Return the search with the specified ID.
+- *
+- * @param searches The list of searches.
+- * @param seq ID number of the search.
+- */
+-GGPSearchForm *
+-ggp_search_get(GGPSearches *searches, guint32 seq);
+-
+-/**
+- * Create a new GGPSearches structure.
+- *
+- * @return GGPSearches instance.
+- */
+-GGPSearches *
+-ggp_search_new(void);
+-
+-/**
+- * Destroy GGPSearches instance.
+- *
+- * @param searches GGPSearches instance.
+- */
+-void
+-ggp_search_destroy(GGPSearches *searches);
+-
+-/**
+- * Initiate a search in the public directory.
+- *
+- * @param gc PurpleConnection.
+- * @param form Filled in GGPSearchForm.
+- *
+- * @return Sequence number of a search or 0 if an error occurred.
+- */
+-guint32
+-ggp_search_start(PurpleConnection *gc, GGPSearchForm *form);
+-
+-/*
+- * Return converted to the UTF-8 value of the specified field.
+- *
+- * @param res Public directory look-up result.
+- * @param num Id of the record.
+- * @param fileld Name of the field.
+- *
+- * @return UTF-8 encoded value of the field.
+- */
+-char *
+-ggp_search_get_result(gg_pubdir50_t res, int num, const char *field);
+-
+-
+-#endif /* _PURPLE_GG_SEARCH_H */
+-
+-/* vim: set ts=8 sts=0 sw=8 noet: */
+diff -Nur pidgin-2.10.7/libpurple/protocols/irc/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/irc/Makefile.in 2013-02-11 07:17:20.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.in 2013-08-16 23:51:18.822722885 -0300
+@@ -190,8 +190,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -253,8 +251,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/irc/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/irc/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/irc/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,92 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libirc
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libirc
+-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 = cmds.c \
+- dcc_send.c \
+- irc.c \
+- msgs.c \
+- parse.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-
+-ifeq ($(CYRUS_SASL), 1)
+-INCLUDE_PATHS += -I$(CYRUS_SASL_TOP)/include
+-LIB_PATHS += -L$(CYRUS_SASL_TOP)/bin
+-LIBS += -llibsasl
+-endif
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_INSTALL_DIR)
+- cp $(TARGET).dll $(DLL_INSTALL_DIR)
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-##
+-## BUILD DLL
+-##
+-$(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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/auth_cyrus.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_cyrus.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/auth_cyrus.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_cyrus.c 2013-08-17 00:14:13.334946817 -0300
+@@ -320,7 +320,7 @@
+ xmlnode_set_namespace(auth, NS_XMPP_SASL);
+ xmlnode_set_attrib(auth, "mechanism", js->current_mech);
+
+- xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
++ xmlnode_set_attrib(auth, "xmlns:ga", "");
+ xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
+
+ if (clientout) {
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/auth_plain.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_plain.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/auth_plain.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/auth_plain.c 2013-08-17 00:19:44.801822370 -0300
+@@ -40,7 +40,7 @@
+ auth = xmlnode_new("auth");
+ xmlnode_set_namespace(auth, NS_XMPP_SASL);
+
+- xmlnode_set_attrib(auth, "xmlns:ga", "http://www.google.com/talk/protocol/auth");
++ xmlnode_set_attrib(auth, "xmlns:ga", "");
+ xmlnode_set_attrib(auth, "ga:client-uses-full-bind-result", "true");
+
+ response = g_string_new("");
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/buddy.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/buddy.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/buddy.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/buddy.c 2013-08-17 00:22:49.080836449 -0300
+@@ -38,7 +38,6 @@
+ #include "xdata.h"
+ #include "pep.h"
+ #include "adhoccommands.h"
+-#include "google/google.h"
+
+ typedef struct {
+ long idle_seconds;
+@@ -945,17 +944,7 @@
+
+ /* Republish our vcard if the photo is different than the server's */
+ if (js->initial_avatar_hash && !purple_strequal(vcard_hash, js->initial_avatar_hash)) {
+- /*
+- * Google Talk has developed the behavior that it will not accept
+- * a vcard set in the first 10 seconds (or so) of the connection;
+- * it returns an error (namespaces trimmed):
+- * <error code="500" type="wait"><internal-server-error/></error>.
+- */
+- if (js->googletalk)
+- js->vcard_timer = purple_timeout_add_seconds(10, set_own_vcard_cb,
+- js);
+- else
+- jabber_set_info(js->gc, purple_account_get_user_info(account));
++ jabber_set_info(js->gc, purple_account_get_user_info(account));
+ } else if (vcard_hash) {
+ /* A photo is in the vCard. Advertise its hash */
+ js->avatar_hash = vcard_hash;
+@@ -1861,13 +1850,6 @@
+ NULL, NULL);
+ m = g_list_append(m, act);
+ }
+-
+- if (js->googletalk) {
+- act = purple_menu_action_new(_("Initiate _Chat"),
+- PURPLE_CALLBACK(google_buddy_node_chat),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+
+ /*
+ * This if-condition implements parts of XEP-0100: Gateway Interaction
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/disco.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/disco.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/disco.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/disco.c 2013-08-27 22:49:34.275219711 -0300
+@@ -30,9 +30,6 @@
+ #include "adhoccommands.h"
+ #include "buddy.h"
+ #include "disco.h"
+-#include "google/google.h"
+-#include "google/gmail.h"
+-#include "google/jingleinfo.h"
+ #include "iq.h"
+ #include "jabber.h"
+ #include "jingle/jingle.h"
+@@ -142,44 +139,6 @@
+ xmlnode_set_attrib(feature, "var", feat->namespace);
+ }
+ }
+-#ifdef USE_VV
+- } else if (g_str_equal(node, CAPS0115_NODE "#" "voice-v1")) {
+- /*
+- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
+- * where we add <c/> to the <presence/>) for the Google Talk
+- * clients that don't actually check disco#info features.
+- *
+- * This specific feature is redundant but is what
+- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
+- * advertises as 'voice-v1'.
+- */
+- xmlnode *feature = xmlnode_new_child(query, "feature");
+- xmlnode_set_attrib(feature, "var", NS_GOOGLE_VOICE);
+- } else if (g_str_equal(node, CAPS0115_NODE "#" "video-v1")) {
+- /*
+- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
+- * where we add <c/> to the <presence/>) for the Google Talk
+- * clients that don't actually check disco#info features.
+- *
+- * This specific feature is redundant but is what
+- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
+- * advertises as 'video-v1'.
+- */
+- xmlnode *feature = xmlnode_new_child(query, "feature");
+- xmlnode_set_attrib(feature, "var", NS_GOOGLE_VIDEO);
+- } else if (g_str_equal(node, CAPS0115_NODE "#" "camera-v1")) {
+- /*
+- * HUGE HACK! We advertise this ext (see jabber_presence_create_js
+- * where we add <c/> to the <presence/>) for the Google Talk
+- * clients that don't actually check disco#info features.
+- *
+- * This specific feature is redundant but is what
+- * node='http://mail.google.com/xmpp/client/caps', ver='1.1'
+- * advertises as 'camera-v1'.
+- */
+- xmlnode *feature = xmlnode_new_child(query, "feature");
+- xmlnode_set_attrib(feature, "var", NS_GOOGLE_CAMERA);
+-#endif
+ } else {
+ xmlnode *error, *inf;
+
+@@ -419,7 +378,7 @@
+
+ }
+
+-/* should probably share this code with google.c, or maybe from 2.7.0
++/* maybe from 2.7.0
+ introduce an abstracted hostname -> IP function in dns.c */
+ static void
+ jabber_disco_stun_lookup_cb(GSList *hosts, gpointer data,
+@@ -538,16 +497,7 @@
+
+ g_free(js->server_name);
+ js->server_name = g_strdup(name);
+- if (!strcmp(name, "Google Talk")) {
+- purple_debug_info("jabber", "Google Talk!\n");
+- js->googletalk = TRUE;
+-
+- /* autodiscover stun and relays */
+- if (purple_network_get_stun_ip() == NULL ||
+- purple_strequal(purple_network_get_stun_ip(), "")) {
+- jabber_google_send_jingle_info(js);
+- }
+- } else if (purple_network_get_stun_ip() == NULL ||
++ if (purple_network_get_stun_ip() == NULL ||
+ purple_strequal(purple_network_get_stun_ip(), "")) {
+ js->srv_query_data =
+ purple_srv_resolve_account(
+@@ -565,12 +515,7 @@
+ if (!var)
+ continue;
+
+- if (!strcmp(NS_GOOGLE_MAIL_NOTIFY, var)) {
+- js->server_caps |= JABBER_CAP_GMAIL_NOTIFY;
+- jabber_gmail_init(js);
+- } else if (!strcmp(NS_GOOGLE_ROSTER, var)) {
+- js->server_caps |= JABBER_CAP_GOOGLE_ROSTER;
+- } else if (!strcmp("http://jabber.org/protocol/commands", var)) {
++ if (!strcmp("http://jabber.org/protocol/commands", var)) {
+ js->server_caps |= JABBER_CAP_ADHOC;
+ } else if (!strcmp(NS_SIMPLE_BLOCKING, var)) {
+ js->server_caps |= JABBER_CAP_BLOCKING;
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,207 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "jabber.h"
+-#include "gmail.h"
+-
+-static void
+-jabber_gmail_parse(JabberStream *js, const char *from,
+- JabberIqType type, const char *id,
+- xmlnode *packet, gpointer nul)
+-{
+- xmlnode *child;
+- xmlnode *message;
+- const char *to, *url;
+- const char *in_str;
+- char *to_name;
+-
+- int i, count = 1, returned_count;
+-
+- const char **tos, **froms, **urls;
+- char **subjects;
+-
+- if (type == JABBER_IQ_ERROR)
+- return;
+-
+- child = xmlnode_get_child(packet, "mailbox");
+- if (!child)
+- return;
+-
+- in_str = xmlnode_get_attrib(child, "total-matched");
+- if (in_str && *in_str)
+- count = atoi(in_str);
+-
+- /* If Gmail doesn't tell us who the mail is to, let's use our JID */
+- to = xmlnode_get_attrib(packet, "to");
+-
+- message = xmlnode_get_child(child, "mail-thread-info");
+-
+- if (count == 0 || !message) {
+- if (count > 0) {
+- char *bare_jid = jabber_get_bare_jid(to);
+- const char *default_tos[2] = { bare_jid };
+-
+- purple_notify_emails(js->gc, count, FALSE, NULL, NULL, default_tos, NULL, NULL, NULL);
+- g_free(bare_jid);
+- } else {
+- purple_notify_emails(js->gc, count, FALSE, NULL, NULL, NULL, NULL, NULL, NULL);
+- }
+-
+- return;
+- }
+-
+- /* Loop once to see how many messages were returned so we can allocate arrays
+- * accordingly */
+- for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message));
+-
+- froms = g_new0(const char* , returned_count + 1);
+- tos = g_new0(const char* , returned_count + 1);
+- subjects = g_new0(char* , returned_count + 1);
+- urls = g_new0(const char* , returned_count + 1);
+-
+- to = xmlnode_get_attrib(packet, "to");
+- to_name = jabber_get_bare_jid(to);
+- url = xmlnode_get_attrib(child, "url");
+- if (!url || !*url)
+- url = "http://www.gmail.com";
+-
+- message= xmlnode_get_child(child, "mail-thread-info");
+- for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
+- xmlnode *sender_node, *subject_node;
+- const char *from, *tid;
+- char *subject;
+-
+- subject_node = xmlnode_get_child(message, "subject");
+- sender_node = xmlnode_get_child(message, "senders");
+- sender_node = xmlnode_get_child(sender_node, "sender");
+-
+- while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") ||
+- !strcmp(xmlnode_get_attrib(sender_node, "unread"),"0")))
+- sender_node = xmlnode_get_next_twin(sender_node);
+-
+- if (!sender_node) {
+- i--;
+- continue;
+- }
+-
+- from = xmlnode_get_attrib(sender_node, "name");
+- if (!from || !*from)
+- from = xmlnode_get_attrib(sender_node, "address");
+- subject = xmlnode_get_data(subject_node);
+- /*
+- * url = xmlnode_get_attrib(message, "url");
+- */
+- tos[i] = (to_name != NULL ? to_name : "");
+- froms[i] = (from != NULL ? from : "");
+- subjects[i] = (subject != NULL ? subject : g_strdup(""));
+- urls[i] = url;
+-
+- tid = xmlnode_get_attrib(message, "tid");
+- if (tid &&
+- (js->gmail_last_tid == NULL || strcmp(tid, js->gmail_last_tid) > 0)) {
+- g_free(js->gmail_last_tid);
+- js->gmail_last_tid = g_strdup(tid);
+- }
+- }
+-
+- if (i>0)
+- purple_notify_emails(js->gc, count, count == i, (const char**) subjects, froms, tos,
+- urls, NULL, NULL);
+-
+- g_free(to_name);
+- g_free(tos);
+- g_free(froms);
+- for (i = 0; i < returned_count; i++)
+- g_free(subjects[i]);
+- g_free(subjects);
+- g_free(urls);
+-
+- in_str = xmlnode_get_attrib(child, "result-time");
+- if (in_str && *in_str) {
+- g_free(js->gmail_last_time);
+- js->gmail_last_time = g_strdup(in_str);
+- }
+-}
+-
+-void
+-jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
+- const char *id, xmlnode *new_mail)
+-{
+- xmlnode *query;
+- JabberIq *iq;
+-
+- /* bail if the user isn't interested */
+- if (!purple_account_get_check_mail(js->gc->account))
+- return;
+-
+- /* Is this an initial incoming mail notification? If so, send a request for more info */
+- if (type != JABBER_IQ_SET)
+- return;
+-
+- /* Acknowledge the notification */
+- iq = jabber_iq_new(js, JABBER_IQ_RESULT);
+- if (from)
+- xmlnode_set_attrib(iq->node, "to", from);
+- xmlnode_set_attrib(iq->node, "id", id);
+- jabber_iq_send(iq);
+-
+- purple_debug_misc("jabber",
+- "Got new mail notification. Sending request for more info\n");
+-
+- iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
+- jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
+- query = xmlnode_get_child(iq->node, "query");
+-
+- if (js->gmail_last_time)
+- xmlnode_set_attrib(query, "newer-than-time", js->gmail_last_time);
+- if (js->gmail_last_tid)
+- xmlnode_set_attrib(query, "newer-than-tid", js->gmail_last_tid);
+-
+- jabber_iq_send(iq);
+- return;
+-}
+-
+-void jabber_gmail_init(JabberStream *js) {
+- JabberIq *iq;
+- xmlnode *usersetting, *mailnotifications;
+-
+- if (!purple_account_get_check_mail(purple_connection_get_account(js->gc)))
+- return;
+-
+- /*
+- * Quoting http://code.google.com/apis/talk/jep_extensions/usersettings.html:
+- * To ensure better compatibility with other clients, rather than
+- * setting this value to "false" to turn off notifications, it is
+- * recommended that a client set this to "true" and filter incoming
+- * email notifications itself.
+- */
+- iq = jabber_iq_new(js, JABBER_IQ_SET);
+- usersetting = xmlnode_new_child(iq->node, "usersetting");
+- xmlnode_set_namespace(usersetting, "google:setting");
+- mailnotifications = xmlnode_new_child(usersetting, "mailnotifications");
+- xmlnode_set_attrib(mailnotifications, "value", "true");
+- jabber_iq_send(iq);
+-
+- iq = jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_MAIL_NOTIFY);
+- jabber_iq_set_callback(iq, jabber_gmail_parse, NULL);
+- jabber_iq_send(iq);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/gmail.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/gmail.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,30 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_GMAIL_H_
+-#define PURPLE_JABBER_GOOGLE_GMAIL_H_
+-
+-#include "jabber.h"
+-
+-void jabber_gmail_init(JabberStream *js);
+-void jabber_gmail_poke(JabberStream *js, const char *from, JabberIqType type,
+- const char *id, xmlnode *new_mail);
+-
+-#endif /* PURPLE_JABBER_GOOGLE_GMAIL_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,172 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "google.h"
+-#include "jabber.h"
+-#include "chat.h"
+-
+-/* This does two passes on the string. The first pass goes through
+- * and determine if all the structured text is properly balanced, and
+- * how many instances of each there is. The second pass goes and converts
+- * everything to HTML, depending on what's figured out by the first pass.
+- * It will short circuit once it knows it has no more replacements to make
+- */
+-char *jabber_google_format_to_html(const char *text)
+-{
+- const char *p;
+-
+- /* The start of the screen may be consdiered a space for this purpose */
+- gboolean preceding_space = TRUE;
+-
+- gboolean in_bold = FALSE, in_italic = FALSE;
+- gboolean in_tag = FALSE;
+-
+- gint bold_count = 0, italic_count = 0;
+-
+- GString *str;
+-
+- for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
+- gunichar c = g_utf8_get_char(p);
+- if (c == '*' && !in_tag) {
+- if (in_bold && (g_unichar_isspace(*(p+1)) ||
+- *(p+1) == '\0' ||
+- *(p+1) == '<')) {
+- bold_count++;
+- in_bold = FALSE;
+- } else if (preceding_space && !in_bold && !g_unichar_isspace(*(p+1))) {
+- bold_count++;
+- in_bold = TRUE;
+- }
+- preceding_space = TRUE;
+- } else if (c == '_' && !in_tag) {
+- if (in_italic && (g_unichar_isspace(*(p+1)) ||
+- *(p+1) == '\0' ||
+- *(p+1) == '<')) {
+- italic_count++;
+- in_italic = FALSE;
+- } else if (preceding_space && !in_italic && !g_unichar_isspace(*(p+1))) {
+- italic_count++;
+- in_italic = TRUE;
+- }
+- preceding_space = TRUE;
+- } else if (c == '<' && !in_tag) {
+- in_tag = TRUE;
+- } else if (c == '>' && in_tag) {
+- in_tag = FALSE;
+- } else if (!in_tag) {
+- if (g_unichar_isspace(c))
+- preceding_space = TRUE;
+- else
+- preceding_space = FALSE;
+- }
+- }
+-
+- str = g_string_new(NULL);
+- in_bold = in_italic = in_tag = FALSE;
+- preceding_space = TRUE;
+-
+- for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
+- gunichar c = g_utf8_get_char(p);
+-
+- if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) {
+- g_string_append(str, p);
+- return g_string_free(str, FALSE);
+- }
+-
+-
+- if (c == '*' && !in_tag) {
+- if (in_bold &&
+- (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */
+- str = g_string_append(str, "</b>");
+- in_bold = FALSE;
+- bold_count--;
+- } else if (preceding_space && bold_count > 1 && !g_unichar_isspace(*(p+1))) {
+- str = g_string_append(str, "<b>");
+- bold_count--;
+- in_bold = TRUE;
+- } else {
+- str = g_string_append_unichar(str, c);
+- }
+- preceding_space = TRUE;
+- } else if (c == '_' && !in_tag) {
+- if (in_italic &&
+- (g_unichar_isspace(*(p+1))||*(p+1)=='<')) {
+- str = g_string_append(str, "</i>");
+- italic_count--;
+- in_italic = FALSE;
+- } else if (preceding_space && italic_count > 1 && !g_unichar_isspace(*(p+1))) {
+- str = g_string_append(str, "<i>");
+- italic_count--;
+- in_italic = TRUE;
+- } else {
+- str = g_string_append_unichar(str, c);
+- }
+- preceding_space = TRUE;
+- } else if (c == '<' && !in_tag) {
+- str = g_string_append_unichar(str, c);
+- in_tag = TRUE;
+- } else if (c == '>' && in_tag) {
+- str = g_string_append_unichar(str, c);
+- in_tag = FALSE;
+- } else if (!in_tag) {
+- str = g_string_append_unichar(str, c);
+- if (g_unichar_isspace(c))
+- preceding_space = TRUE;
+- else
+- preceding_space = FALSE;
+- } else {
+- str = g_string_append_unichar(str, c);
+- }
+- }
+- return g_string_free(str, FALSE);
+-}
+-
+-
+-
+-void google_buddy_node_chat(PurpleBlistNode *node, gpointer data)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- JabberStream *js;
+- JabberChat *chat;
+- gchar *room;
+- gchar *uuid = purple_uuid_random();
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = PURPLE_BUDDY(node);
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- g_return_if_fail(gc != NULL);
+- js = purple_connection_get_protocol_data(gc);
+-
+- room = g_strdup_printf("private-chat-%s", uuid);
+- chat = jabber_join_chat(js, room, GOOGLE_GROUPCHAT_SERVER, js->user->node,
+- NULL, NULL);
+- if (chat) {
+- chat->muc = TRUE;
+- jabber_chat_invite(gc, chat->id, "", purple_buddy_get_name(buddy));
+- }
+-
+- g_free(room);
+- g_free(uuid);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,35 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_H_
+-#define PURPLE_JABBER_GOOGLE_H_
+-
+-/* This is a place for Google Talk-specific XMPP extensions to live
+- * such that they don't intermingle with code for the XMPP RFCs and XEPs :) */
+-
+-#include "jabber.h"
+-
+-#define GOOGLE_GROUPCHAT_SERVER "groupchat.google.com"
+-
+-char *jabber_google_format_to_html(const char *text);
+-
+-void google_buddy_node_chat(PurpleBlistNode *node, gpointer data);
+-
+-#endif /* PURPLE_JABBER_GOOGLE_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,43 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "google_presence.h"
+-
+-void jabber_google_presence_incoming(JabberStream *js, const char *user, JabberBuddyResource *jbr)
+-{
+- if (!js->googletalk)
+- return;
+- if (jbr->status && purple_str_has_prefix(jbr->status, "♫ ")) {
+- purple_prpl_got_user_status(js->gc->account, user, "tune",
+- PURPLE_TUNE_TITLE, jbr->status + strlen("♫ "), NULL);
+- g_free(jbr->status);
+- jbr->status = NULL;
+- } else {
+- purple_prpl_got_user_status_deactive(js->gc->account, user, "tune");
+- }
+-}
+-
+-char *jabber_google_presence_outgoing(PurpleStatus *tune)
+-{
+- const char *attr = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
+- return attr ? g_strdup_printf("♫ %s", attr) : g_strdup("");
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_presence.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_presence.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,32 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_PRESENCE_H_
+-#define PURPLE_JABBER_GOOGLE_PRESENCE_H_
+-
+-#include "jabber.h"
+-#include "buddy.h"
+-#include "status.h"
+-
+-void jabber_google_presence_incoming(JabberStream *js, const char *who, JabberBuddyResource *jbr);
+-char *jabber_google_presence_outgoing(PurpleStatus *tune);
+-
+-
+-#endif /* PURPLE_JABBER_GOOGLE_PRESENCE_H_ */
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,206 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "google_roster.h"
+-#include "jabber.h"
+-#include "presence.h"
+-#include "debug.h"
+-#include "xmlnode.h"
+-
+-void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item)
+-{
+- PurpleAccount *account = purple_connection_get_account(js->gc);
+- GSList *list = account->deny;
+- const char *jid = xmlnode_get_attrib(item, "jid");
+- char *jid_norm = (char *)jabber_normalize(account, jid);
+-
+- while (list) {
+- if (!strcmp(jid_norm, (char*)list->data)) {
+- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
+- xmlnode_set_attrib(query, "gr:ext", "2");
+- xmlnode_set_attrib(item, "gr:t", "B");
+- return;
+- }
+- list = list->next;
+- }
+-}
+-
+-gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item)
+-{
+- PurpleAccount *account = purple_connection_get_account(js->gc);
+- const char *jid = xmlnode_get_attrib(item, "jid");
+- gboolean on_block_list = FALSE;
+-
+- char *jid_norm;
+-
+- const char *grt = xmlnode_get_attrib_with_namespace(item, "t", NS_GOOGLE_ROSTER);
+- const char *subscription = xmlnode_get_attrib(item, "subscription");
+- const char *ask = xmlnode_get_attrib(item, "ask");
+-
+- if ((!subscription || !strcmp(subscription, "none")) && !ask) {
+- /* The Google Talk servers will automatically add people from your Gmail address book
+- * with subscription=none. If we see someone with subscription=none, ignore them.
+- */
+- return FALSE;
+- }
+-
+- jid_norm = g_strdup(jabber_normalize(account, jid));
+-
+- on_block_list = NULL != g_slist_find_custom(account->deny, jid_norm,
+- (GCompareFunc)strcmp);
+-
+- if (grt && (*grt == 'H' || *grt == 'h')) {
+- /* Hidden; don't show this buddy. */
+- GSList *buddies = purple_find_buddies(account, jid_norm);
+- if (buddies)
+- purple_debug_info("jabber", "Removing %s from local buddy list\n",
+- jid_norm);
+-
+- for ( ; buddies; buddies = g_slist_delete_link(buddies, buddies)) {
+- purple_blist_remove_buddy(buddies->data);
+- }
+-
+- g_free(jid_norm);
+- return FALSE;
+- }
+-
+- if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) {
+- purple_debug_info("jabber", "Blocking %s\n", jid_norm);
+- purple_privacy_deny_add(account, jid_norm, TRUE);
+- } else if (on_block_list && (!grt || (*grt != 'B' && *grt != 'b' ))){
+- purple_debug_info("jabber", "Unblocking %s\n", jid_norm);
+- purple_privacy_deny_remove(account, jid_norm, TRUE);
+- }
+-
+- g_free(jid_norm);
+- return TRUE;
+-}
+-
+-void jabber_google_roster_add_deny(JabberStream *js, const char *who)
+-{
+- PurpleAccount *account;
+- GSList *buddies;
+- JabberIq *iq;
+- xmlnode *query;
+- xmlnode *item;
+- xmlnode *group;
+- PurpleBuddy *b;
+- JabberBuddy *jb;
+- const char *balias;
+-
+- jb = jabber_buddy_find(js, who, TRUE);
+-
+- account = purple_connection_get_account(js->gc);
+- buddies = purple_find_buddies(account, who);
+- if(!buddies)
+- return;
+-
+- b = buddies->data;
+-
+- iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
+-
+- query = xmlnode_get_child(iq->node, "query");
+- item = xmlnode_new_child(query, "item");
+-
+- while(buddies) {
+- PurpleGroup *g;
+-
+- b = buddies->data;
+- g = purple_buddy_get_group(b);
+-
+- group = xmlnode_new_child(item, "group");
+- xmlnode_insert_data(group, purple_group_get_name(g), -1);
+-
+- buddies = buddies->next;
+- }
+-
+- balias = purple_buddy_get_local_buddy_alias(b);
+- xmlnode_set_attrib(item, "jid", who);
+- xmlnode_set_attrib(item, "name", balias ? balias : "");
+- xmlnode_set_attrib(item, "gr:t", "B");
+- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
+- xmlnode_set_attrib(query, "gr:ext", "2");
+-
+- jabber_iq_send(iq);
+-
+- /* Synthesize a sign-off */
+- if (jb) {
+- JabberBuddyResource *jbr;
+- GList *l = jb->resources;
+- while (l) {
+- jbr = l->data;
+- if (jbr && jbr->name)
+- {
+- purple_debug_misc("jabber", "Removing resource %s\n", jbr->name);
+- jabber_buddy_remove_resource(jb, jbr->name);
+- }
+- l = l->next;
+- }
+- }
+-
+- purple_prpl_got_user_status(account, who, "offline", NULL);
+-}
+-
+-void jabber_google_roster_rem_deny(JabberStream *js, const char *who)
+-{
+- GSList *buddies;
+- JabberIq *iq;
+- xmlnode *query;
+- xmlnode *item;
+- xmlnode *group;
+- PurpleBuddy *b;
+- const char *balias;
+-
+- buddies = purple_find_buddies(purple_connection_get_account(js->gc), who);
+- if(!buddies)
+- return;
+-
+- b = buddies->data;
+-
+- iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
+-
+- query = xmlnode_get_child(iq->node, "query");
+- item = xmlnode_new_child(query, "item");
+-
+- while(buddies) {
+- PurpleGroup *g;
+-
+- b = buddies->data;
+- g = purple_buddy_get_group(b);
+-
+- group = xmlnode_new_child(item, "group");
+- xmlnode_insert_data(group, purple_group_get_name(g), -1);
+-
+- buddies = buddies->next;
+- }
+-
+- balias = purple_buddy_get_local_buddy_alias(b);
+- xmlnode_set_attrib(item, "jid", who);
+- xmlnode_set_attrib(item, "name", balias ? balias : "");
+- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
+- xmlnode_set_attrib(query, "gr:ext", "2");
+-
+- jabber_iq_send(iq);
+-
+- /* See if he's online */
+- jabber_presence_subscription_set(js, who, "probe");
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_roster.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_roster.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,37 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_ROSTER_H_
+-#define PURPLE_JABBER_GOOGLE_ROSTER_H_
+-
+-#include "jabber.h"
+-
+-void jabber_google_roster_outgoing(JabberStream *js, xmlnode *query, xmlnode *item);
+-
+-/* Returns FALSE if this should short-circuit processing of this roster item, or TRUE
+- * if this roster item should continue to be processed
+- */
+-gboolean jabber_google_roster_incoming(JabberStream *js, xmlnode *item);
+-
+-void jabber_google_roster_add_deny(JabberStream *js, const char *who);
+-void jabber_google_roster_rem_deny(JabberStream *js, const char *who);
+-
+-
+-#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,866 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "google_session.h"
+-#include "relay.h"
+-
+-#include "jingle/jingle.h"
+-
+-#ifdef USE_VV
+-
+-typedef struct {
+- PurpleMedia *media;
+- gboolean video;
+- GList *remote_audio_candidates; /* list of PurpleMediaCandidate */
+- GList *remote_video_candidates; /* list of PurpleMediaCandidate */
+- gboolean added_streams; /* this indicates if the streams have been
+- to media (ie. after getting relay credentials */
+-} GoogleAVSessionData;
+-
+-static gboolean
+-google_session_id_equal(gconstpointer a, gconstpointer b)
+-{
+- GoogleSessionId *c = (GoogleSessionId*)a;
+- GoogleSessionId *d = (GoogleSessionId*)b;
+-
+- return !strcmp(c->id, d->id) && !strcmp(c->initiator, d->initiator);
+-}
+-
+-static void
+-google_session_destroy(GoogleSession *session)
+-{
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+- g_free(session->id.id);
+- g_free(session->id.initiator);
+- g_free(session->remote_jid);
+-
+- if (session_data->remote_audio_candidates)
+- purple_media_candidate_list_free(session_data->remote_audio_candidates);
+-
+- if (session_data->remote_video_candidates)
+- purple_media_candidate_list_free(session_data->remote_video_candidates);
+-
+- if (session->description)
+- xmlnode_free(session->description);
+-
+- g_free(session->session_data);
+- g_free(session);
+-}
+-
+-static xmlnode *
+-google_session_create_xmlnode(GoogleSession *session, const char *type)
+-{
+- xmlnode *node = xmlnode_new("session");
+- xmlnode_set_namespace(node, NS_GOOGLE_SESSION);
+- xmlnode_set_attrib(node, "id", session->id.id);
+- xmlnode_set_attrib(node, "initiator", session->id.initiator);
+- xmlnode_set_attrib(node, "type", type);
+- return node;
+-}
+-
+-static void
+-google_session_send_candidates(PurpleMedia *media, gchar *session_id,
+- gchar *participant, GoogleSession *session)
+-{
+- PurpleMedia *session_media =
+- ((GoogleAVSessionData *) session->session_data)->media;
+- GList *candidates =
+- purple_media_get_local_candidates(session_media, session_id,
+- session->remote_jid);
+- GList *iter;
+- PurpleMediaCandidate *transport;
+- gboolean video = FALSE;
+-
+- if (!strcmp(session_id, "google-video"))
+- video = TRUE;
+-
+- for (iter = candidates; iter; iter = iter->next) {
+- JabberIq *iq;
+- gchar *ip, *port, *username, *password;
+- gchar pref[16];
+- PurpleMediaCandidateType type;
+- xmlnode *sess;
+- xmlnode *candidate;
+- guint component_id;
+- transport = PURPLE_MEDIA_CANDIDATE(iter->data);
+- component_id = purple_media_candidate_get_component_id(
+- transport);
+-
+- iq = jabber_iq_new(session->js, JABBER_IQ_SET);
+- sess = google_session_create_xmlnode(session, "candidates");
+- xmlnode_insert_child(iq->node, sess);
+- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
+-
+- candidate = xmlnode_new("candidate");
+-
+- ip = purple_media_candidate_get_ip(transport);
+- port = g_strdup_printf("%d",
+- purple_media_candidate_get_port(transport));
+- g_ascii_dtostr(pref, 16,
+- purple_media_candidate_get_priority(transport) / 1000.0);
+- username = purple_media_candidate_get_username(transport);
+- password = purple_media_candidate_get_password(transport);
+- type = purple_media_candidate_get_candidate_type(transport);
+-
+- xmlnode_set_attrib(candidate, "address", ip);
+- xmlnode_set_attrib(candidate, "port", port);
+- xmlnode_set_attrib(candidate, "name",
+- component_id == PURPLE_MEDIA_COMPONENT_RTP ?
+- video ? "video_rtp" : "rtp" :
+- component_id == PURPLE_MEDIA_COMPONENT_RTCP ?
+- video ? "video_rtcp" : "rtcp" : "none");
+- xmlnode_set_attrib(candidate, "username", username);
+- /*
+- * As of this writing, Farsight 2 in Google compatibility
+- * mode doesn't provide a password. The Gmail client
+- * requires this to be set.
+- */
+- xmlnode_set_attrib(candidate, "password",
+- password != NULL ? password : "");
+- xmlnode_set_attrib(candidate, "preference", pref);
+- xmlnode_set_attrib(candidate, "protocol",
+- purple_media_candidate_get_protocol(transport)
+- == PURPLE_MEDIA_NETWORK_PROTOCOL_UDP ?
+- "udp" : "tcp");
+- xmlnode_set_attrib(candidate, "type", type ==
+- PURPLE_MEDIA_CANDIDATE_TYPE_HOST ? "local" :
+- type ==
+- PURPLE_MEDIA_CANDIDATE_TYPE_SRFLX ? "stun" :
+- type ==
+- PURPLE_MEDIA_CANDIDATE_TYPE_RELAY ? "relay" :
+- NULL);
+- xmlnode_set_attrib(candidate, "generation", "0");
+- xmlnode_set_attrib(candidate, "network", "0");
+- xmlnode_insert_child(sess, candidate);
+-
+- g_free(ip);
+- g_free(port);
+- g_free(username);
+- g_free(password);
+-
+- jabber_iq_send(iq);
+- }
+- purple_media_candidate_list_free(candidates);
+-}
+-
+-static void
+-google_session_ready(GoogleSession *session)
+-{
+- PurpleMedia *media =
+- ((GoogleAVSessionData *)session->session_data)->media;
+- gboolean video =
+- ((GoogleAVSessionData *)session->session_data)->video;
+- if (purple_media_codecs_ready(media, NULL) &&
+- purple_media_candidates_prepared(media, NULL, NULL)) {
+- gchar *me = g_strdup_printf("%s@%s/%s",
+- session->js->user->node,
+- session->js->user->domain,
+- session->js->user->resource);
+- JabberIq *iq;
+- xmlnode *sess, *desc, *payload;
+- GList *codecs, *iter;
+- gboolean is_initiator = !strcmp(session->id.initiator, me);
+-
+- if (!is_initiator &&
+- !purple_media_accepted(media, NULL, NULL)) {
+- g_free(me);
+- return;
+- }
+-
+- iq = jabber_iq_new(session->js, JABBER_IQ_SET);
+-
+- if (is_initiator) {
+- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
+- xmlnode_set_attrib(iq->node, "from", session->id.initiator);
+- sess = google_session_create_xmlnode(session, "initiate");
+- } else {
+- google_session_send_candidates(media,
+- "google-voice", session->remote_jid,
+- session);
+- google_session_send_candidates(media,
+- "google-video", session->remote_jid,
+- session);
+- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
+- xmlnode_set_attrib(iq->node, "from", me);
+- sess = google_session_create_xmlnode(session, "accept");
+- }
+- xmlnode_insert_child(iq->node, sess);
+- desc = xmlnode_new_child(sess, "description");
+- if (video)
+- xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_VIDEO);
+- else
+- xmlnode_set_namespace(desc, NS_GOOGLE_SESSION_PHONE);
+-
+- codecs = purple_media_get_codecs(media, "google-video");
+-
+- for (iter = codecs; iter; iter = g_list_next(iter)) {
+- PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
+- gchar *id = g_strdup_printf("%d",
+- purple_media_codec_get_id(codec));
+- gchar *encoding_name =
+- purple_media_codec_get_encoding_name(codec);
+- payload = xmlnode_new_child(desc, "payload-type");
+- xmlnode_set_attrib(payload, "id", id);
+- xmlnode_set_attrib(payload, "name", encoding_name);
+- xmlnode_set_attrib(payload, "width", "320");
+- xmlnode_set_attrib(payload, "height", "200");
+- xmlnode_set_attrib(payload, "framerate", "30");
+- g_free(encoding_name);
+- g_free(id);
+- }
+- purple_media_codec_list_free(codecs);
+-
+- codecs = purple_media_get_codecs(media, "google-voice");
+-
+- for (iter = codecs; iter; iter = g_list_next(iter)) {
+- PurpleMediaCodec *codec = (PurpleMediaCodec*)iter->data;
+- gchar *id = g_strdup_printf("%d",
+- purple_media_codec_get_id(codec));
+- gchar *encoding_name =
+- purple_media_codec_get_encoding_name(codec);
+- gchar *clock_rate = g_strdup_printf("%d",
+- purple_media_codec_get_clock_rate(codec));
+- payload = xmlnode_new_child(desc, "payload-type");
+- if (video)
+- xmlnode_set_namespace(payload, NS_GOOGLE_SESSION_PHONE);
+- xmlnode_set_attrib(payload, "id", id);
+- /*
+- * Hack to make Gmail accept speex as the codec.
+- * It shouldn't have to be case sensitive.
+- */
+- if (purple_strequal(encoding_name, "SPEEX"))
+- xmlnode_set_attrib(payload, "name", "speex");
+- else
+- xmlnode_set_attrib(payload, "name", encoding_name);
+- xmlnode_set_attrib(payload, "clockrate", clock_rate);
+- g_free(clock_rate);
+- g_free(encoding_name);
+- g_free(id);
+- }
+- purple_media_codec_list_free(codecs);
+-
+- jabber_iq_send(iq);
+-
+- if (is_initiator) {
+- google_session_send_candidates(media,
+- "google-voice", session->remote_jid,
+- session);
+- google_session_send_candidates(media,
+- "google-video", session->remote_jid,
+- session);
+- }
+-
+- g_signal_handlers_disconnect_by_func(G_OBJECT(media),
+- G_CALLBACK(google_session_ready), session);
+- }
+-}
+-
+-static void
+-google_session_state_changed_cb(PurpleMedia *media, PurpleMediaState state,
+- gchar *sid, gchar *name, GoogleSession *session)
+-{
+- if (sid == NULL && name == NULL) {
+- if (state == PURPLE_MEDIA_STATE_END) {
+- google_session_destroy(session);
+- }
+- }
+-}
+-
+-static void
+-google_session_stream_info_cb(PurpleMedia *media, PurpleMediaInfoType type,
+- gchar *sid, gchar *name, gboolean local,
+- GoogleSession *session)
+-{
+- if (sid != NULL || name != NULL)
+- return;
+-
+- if (type == PURPLE_MEDIA_INFO_HANGUP) {
+- xmlnode *sess;
+- JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
+-
+- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
+- sess = google_session_create_xmlnode(session, "terminate");
+- xmlnode_insert_child(iq->node, sess);
+-
+- jabber_iq_send(iq);
+- } else if (type == PURPLE_MEDIA_INFO_REJECT) {
+- xmlnode *sess;
+- JabberIq *iq = jabber_iq_new(session->js, JABBER_IQ_SET);
+-
+- xmlnode_set_attrib(iq->node, "to", session->remote_jid);
+- sess = google_session_create_xmlnode(session, "reject");
+- xmlnode_insert_child(iq->node, sess);
+-
+- jabber_iq_send(iq);
+- } else if (type == PURPLE_MEDIA_INFO_ACCEPT && local == TRUE) {
+- google_session_ready(session);
+- }
+-}
+-
+-static GParameter *
+-jabber_google_session_get_params(JabberStream *js, const gchar *relay_ip,
+- guint16 relay_udp, guint16 relay_tcp, guint16 relay_ssltcp,
+- const gchar *relay_username, const gchar *relay_password, guint *num)
+-{
+- guint num_params;
+- GParameter *params =
+- jingle_get_params(js, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
+- relay_username, relay_password, &num_params);
+- GParameter *new_params = g_new0(GParameter, num_params + 1);
+-
+- memcpy(new_params, params, sizeof(GParameter) * num_params);
+-
+- purple_debug_info("jabber", "setting Google jingle compatibility param\n");
+- new_params[num_params].name = "compatibility-mode";
+- g_value_init(&new_params[num_params].value, G_TYPE_UINT);
+- g_value_set_uint(&new_params[num_params].value, 1); /* NICE_COMPATIBILITY_GOOGLE */
+-
+- g_free(params);
+- *num = num_params + 1;
+- return new_params;
+-}
+-
+-
+-static void
+-jabber_google_relay_response_session_initiate_cb(GoogleSession *session,
+- const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
+- const gchar *relay_username, const gchar *relay_password)
+-{
+- GParameter *params;
+- guint num_params;
+- JabberStream *js = session->js;
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+-
+- session_data->media = purple_media_manager_create_media(
+- purple_media_manager_get(),
+- purple_connection_get_account(js->gc),
+- "fsrtpconference", session->remote_jid, TRUE);
+-
+- purple_media_set_prpl_data(session_data->media, session);
+-
+- g_signal_connect_swapped(G_OBJECT(session_data->media),
+- "candidates-prepared",
+- G_CALLBACK(google_session_ready), session);
+- g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
+- G_CALLBACK(google_session_ready), session);
+- g_signal_connect(G_OBJECT(session_data->media), "state-changed",
+- G_CALLBACK(google_session_state_changed_cb), session);
+- g_signal_connect(G_OBJECT(session_data->media), "stream-info",
+- G_CALLBACK(google_session_stream_info_cb), session);
+-
+- params =
+- jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
+- relay_ssltcp, relay_username, relay_password, &num_params);
+-
+- if (purple_media_add_stream(session_data->media, "google-voice",
+- session->remote_jid, PURPLE_MEDIA_AUDIO,
+- TRUE, "nice", num_params, params) == FALSE ||
+- (session_data->video && purple_media_add_stream(
+- session_data->media, "google-video",
+- session->remote_jid, PURPLE_MEDIA_VIDEO,
+- TRUE, "nice", num_params, params) == FALSE)) {
+- purple_media_error(session_data->media, "Error adding stream.");
+- purple_media_end(session_data->media, NULL, NULL);
+- } else {
+- session_data->added_streams = TRUE;
+- }
+-
+- g_free(params);
+-}
+-
+-
+-gboolean
+-jabber_google_session_initiate(JabberStream *js, const gchar *who, PurpleMediaSessionType type)
+-{
+- GoogleSession *session;
+- JabberBuddy *jb;
+- JabberBuddyResource *jbr;
+- gchar *jid;
+- GoogleAVSessionData *session_data = NULL;
+-
+- /* construct JID to send to */
+- jb = jabber_buddy_find(js, who, FALSE);
+- if (!jb) {
+- purple_debug_error("jingle-rtp",
+- "Could not find Jabber buddy\n");
+- return FALSE;
+- }
+- jbr = jabber_buddy_find_resource(jb, NULL);
+- if (!jbr) {
+- purple_debug_error("jingle-rtp",
+- "Could not find buddy's resource\n");
+- }
+-
+- if ((strchr(who, '/') == NULL) && jbr && (jbr->name != NULL)) {
+- jid = g_strdup_printf("%s/%s", who, jbr->name);
+- } else {
+- jid = g_strdup(who);
+- }
+-
+- session = g_new0(GoogleSession, 1);
+- session->id.id = jabber_get_next_id(js);
+- session->id.initiator = g_strdup_printf("%s@%s/%s", js->user->node,
+- js->user->domain, js->user->resource);
+- session->state = SENT_INITIATE;
+- session->js = js;
+- session->remote_jid = jid;
+- session_data = g_new0(GoogleAVSessionData, 1);
+- session->session_data = session_data;
+-
+- if (type & PURPLE_MEDIA_VIDEO)
+- session_data->video = TRUE;
+-
+- /* if we got a relay token and relay host in google:jingleinfo, issue an
+- HTTP request to get that data */
+- if (js->google_relay_host && js->google_relay_token) {
+- jabber_google_do_relay_request(js, session,
+- jabber_google_relay_response_session_initiate_cb);
+- } else {
+- jabber_google_relay_response_session_initiate_cb(session, NULL, 0, 0, 0,
+- NULL, NULL);
+- }
+-
+- /* we don't actually know yet wether it succeeded... maybe this is very
+- wrong... */
+- return TRUE;
+-}
+-
+-static void
+-jabber_google_relay_response_session_handle_initiate_cb(GoogleSession *session,
+- const gchar *relay_ip, guint relay_udp, guint relay_tcp, guint relay_ssltcp,
+- const gchar *relay_username, const gchar *relay_password)
+-{
+- GParameter *params;
+- guint num_params;
+- JabberStream *js = session->js;
+- xmlnode *codec_element;
+- const gchar *xmlns;
+- PurpleMediaCodec *codec;
+- GList *video_codecs = NULL;
+- GList *codecs = NULL;
+- JabberIq *result;
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+-
+- params =
+- jabber_google_session_get_params(js, relay_ip, relay_udp, relay_tcp,
+- relay_ssltcp, relay_username, relay_password, &num_params);
+-
+- if (purple_media_add_stream(session_data->media, "google-voice",
+- session->remote_jid, PURPLE_MEDIA_AUDIO, FALSE,
+- "nice", num_params, params) == FALSE ||
+- (session_data->video && purple_media_add_stream(
+- session_data->media, "google-video",
+- session->remote_jid, PURPLE_MEDIA_VIDEO,
+- FALSE, "nice", num_params, params) == FALSE)) {
+- purple_media_error(session_data->media, "Error adding stream.");
+- purple_media_stream_info(session_data->media,
+- PURPLE_MEDIA_INFO_REJECT, NULL, NULL, TRUE);
+- } else {
+- /* successfully added stream(s) */
+- session_data->added_streams = TRUE;
+-
+- if (session_data->remote_audio_candidates) {
+- purple_media_add_remote_candidates(session_data->media,
+- "google-voice", session->remote_jid,
+- session_data->remote_audio_candidates);
+- purple_media_candidate_list_free(session_data->remote_audio_candidates);
+- session_data->remote_audio_candidates = NULL;
+- }
+- if (session_data->remote_video_candidates) {
+- purple_media_add_remote_candidates(session_data->media,
+- "google-video", session->remote_jid,
+- session_data->remote_video_candidates);
+- purple_media_candidate_list_free(session_data->remote_video_candidates);
+- session_data->remote_video_candidates = NULL;
+- }
+- }
+-
+- g_free(params);
+-
+- for (codec_element = xmlnode_get_child(session->description, "payload-type");
+- codec_element; codec_element = codec_element->next) {
+- const char *id, *encoding_name, *clock_rate,
+- *width, *height, *framerate;
+- gboolean video;
+- if (codec_element->name &&
+- strcmp(codec_element->name, "payload-type"))
+- continue;
+-
+- xmlns = xmlnode_get_namespace(codec_element);
+- encoding_name = xmlnode_get_attrib(codec_element, "name");
+- id = xmlnode_get_attrib(codec_element, "id");
+-
+- if (!session_data->video ||
+- (xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_PHONE))) {
+- clock_rate = xmlnode_get_attrib(
+- codec_element, "clockrate");
+- video = FALSE;
+- } else {
+- width = xmlnode_get_attrib(codec_element, "width");
+- height = xmlnode_get_attrib(codec_element, "height");
+- framerate = xmlnode_get_attrib(
+- codec_element, "framerate");
+- clock_rate = "90000";
+- video = TRUE;
+- }
+-
+- if (id) {
+- codec = purple_media_codec_new(atoi(id), encoding_name,
+- video ? PURPLE_MEDIA_VIDEO :
+- PURPLE_MEDIA_AUDIO,
+- clock_rate ? atoi(clock_rate) : 0);
+- if (video)
+- video_codecs = g_list_append(
+- video_codecs, codec);
+- else
+- codecs = g_list_append(codecs, codec);
+- }
+- }
+-
+- if (codecs)
+- purple_media_set_remote_codecs(session_data->media, "google-voice",
+- session->remote_jid, codecs);
+- if (video_codecs)
+- purple_media_set_remote_codecs(session_data->media, "google-video",
+- session->remote_jid, video_codecs);
+-
+- purple_media_codec_list_free(codecs);
+- purple_media_codec_list_free(video_codecs);
+-
+- result = jabber_iq_new(js, JABBER_IQ_RESULT);
+- jabber_iq_set_id(result, session->iq_id);
+- xmlnode_set_attrib(result->node, "to", session->remote_jid);
+- jabber_iq_send(result);
+-}
+-
+-static gboolean
+-google_session_handle_initiate(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
+-{
+- const gchar *xmlns;
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+-
+- if (session->state != UNINIT) {
+- purple_debug_error("jabber", "Received initiate for active session.\n");
+- return FALSE;
+- }
+-
+- session->description = xmlnode_copy(xmlnode_get_child(sess, "description"));
+- xmlns = xmlnode_get_namespace(session->description);
+-
+- if (purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
+- session_data->video = FALSE;
+- else if (purple_strequal(xmlns, NS_GOOGLE_SESSION_VIDEO))
+- session_data->video = TRUE;
+- else {
+- purple_debug_error("jabber", "Received initiate with "
+- "invalid namespace %s.\n", xmlns);
+- return FALSE;
+- }
+-
+- session_data->media = purple_media_manager_create_media(
+- purple_media_manager_get(),
+- purple_connection_get_account(js->gc),
+- "fsrtpconference", session->remote_jid, FALSE);
+-
+- purple_media_set_prpl_data(session_data->media, session);
+-
+- g_signal_connect_swapped(G_OBJECT(session_data->media),
+- "candidates-prepared",
+- G_CALLBACK(google_session_ready), session);
+- g_signal_connect_swapped(G_OBJECT(session_data->media), "codecs-changed",
+- G_CALLBACK(google_session_ready), session);
+- g_signal_connect(G_OBJECT(session_data->media), "state-changed",
+- G_CALLBACK(google_session_state_changed_cb), session);
+- g_signal_connect(G_OBJECT(session_data->media), "stream-info",
+- G_CALLBACK(google_session_stream_info_cb), session);
+-
+- session->iq_id = g_strdup(iq_id);
+-
+- if (js->google_relay_host && js->google_relay_token) {
+- jabber_google_do_relay_request(js, session,
+- jabber_google_relay_response_session_handle_initiate_cb);
+- } else {
+- jabber_google_relay_response_session_handle_initiate_cb(session, NULL,
+- 0, 0, 0, NULL, NULL);
+- }
+-
+- return TRUE;
+-}
+-
+-
+-static void
+-google_session_handle_candidates(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
+-{
+- JabberIq *result;
+- GList *list = NULL, *video_list = NULL;
+- xmlnode *cand;
+- static int name = 0;
+- char n[4];
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+-
+- for (cand = xmlnode_get_child(sess, "candidate"); cand;
+- cand = xmlnode_get_next_twin(cand)) {
+- PurpleMediaCandidate *info;
+- const gchar *cname = xmlnode_get_attrib(cand, "name");
+- const gchar *type = xmlnode_get_attrib(cand, "type");
+- const gchar *protocol = xmlnode_get_attrib(cand, "protocol");
+- const gchar *address = xmlnode_get_attrib(cand, "address");
+- const gchar *port = xmlnode_get_attrib(cand, "port");
+- const gchar *preference = xmlnode_get_attrib(cand, "preference");
+- guint component_id;
+-
+- if (cname && type && address && port) {
+- PurpleMediaCandidateType candidate_type;
+- guint prio = preference ? g_ascii_strtod(preference, NULL) * 1000 : 0;
+-
+- g_snprintf(n, sizeof(n), "S%d", name++);
+-
+- if (g_str_equal(type, "local"))
+- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
+- else if (g_str_equal(type, "stun"))
+- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_PRFLX;
+- else if (g_str_equal(type, "relay"))
+- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_RELAY;
+- else
+- candidate_type = PURPLE_MEDIA_CANDIDATE_TYPE_HOST;
+-
+- if (purple_strequal(cname, "rtcp") ||
+- purple_strequal(cname, "video_rtcp"))
+- component_id = PURPLE_MEDIA_COMPONENT_RTCP;
+- else
+- component_id = PURPLE_MEDIA_COMPONENT_RTP;
+-
+- info = purple_media_candidate_new(n, component_id,
+- candidate_type,
+- purple_strequal(protocol, "udp") ?
+- PURPLE_MEDIA_NETWORK_PROTOCOL_UDP :
+- PURPLE_MEDIA_NETWORK_PROTOCOL_TCP,
+- address,
+- atoi(port));
+- g_object_set(info, "username", xmlnode_get_attrib(cand, "username"),
+- "password", xmlnode_get_attrib(cand, "password"),
+- "priority", prio, NULL);
+- if (!strncmp(cname, "video_", 6)) {
+- if (session_data->added_streams) {
+- video_list = g_list_append(video_list, info);
+- } else {
+- session_data->remote_video_candidates =
+- g_list_append(session_data->remote_video_candidates,
+- info);
+- }
+- } else {
+- if (session_data->added_streams) {
+- list = g_list_append(list, info);
+- } else {
+- session_data->remote_audio_candidates =
+- g_list_append(session_data->remote_audio_candidates,
+- info);
+- }
+- }
+- }
+- }
+-
+- if (list) {
+- purple_media_add_remote_candidates(session_data->media, "google-voice",
+- session->remote_jid, list);
+- purple_media_candidate_list_free(list);
+- }
+- if (video_list) {
+- purple_media_add_remote_candidates(session_data->media, "google-video",
+- session->remote_jid, video_list);
+- purple_media_candidate_list_free(video_list);
+- }
+-
+- result = jabber_iq_new(js, JABBER_IQ_RESULT);
+- jabber_iq_set_id(result, iq_id);
+- xmlnode_set_attrib(result->node, "to", session->remote_jid);
+- jabber_iq_send(result);
+-}
+-
+-static void
+-google_session_handle_accept(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
+-{
+- xmlnode *desc_element = xmlnode_get_child(sess, "description");
+- xmlnode *codec_element = xmlnode_get_child(
+- desc_element, "payload-type");
+- GList *codecs = NULL, *video_codecs = NULL;
+- JabberIq *result = NULL;
+- const gchar *xmlns = xmlnode_get_namespace(desc_element);
+- gboolean video = (xmlns && !strcmp(xmlns, NS_GOOGLE_SESSION_VIDEO));
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+-
+- for (; codec_element; codec_element = codec_element->next) {
+- const gchar *xmlns, *encoding_name, *id,
+- *clock_rate, *width, *height, *framerate;
+- gboolean video_codec = FALSE;
+-
+- if (!purple_strequal(codec_element->name, "payload-type"))
+- continue;
+-
+- xmlns = xmlnode_get_namespace(codec_element);
+- encoding_name = xmlnode_get_attrib(codec_element, "name");
+- id = xmlnode_get_attrib(codec_element, "id");
+-
+- if (!video || purple_strequal(xmlns, NS_GOOGLE_SESSION_PHONE))
+- clock_rate = xmlnode_get_attrib(
+- codec_element, "clockrate");
+- else {
+- clock_rate = "90000";
+- width = xmlnode_get_attrib(codec_element, "width");
+- height = xmlnode_get_attrib(codec_element, "height");
+- framerate = xmlnode_get_attrib(
+- codec_element, "framerate");
+- video_codec = TRUE;
+- }
+-
+- if (id && encoding_name) {
+- PurpleMediaCodec *codec = purple_media_codec_new(
+- atoi(id), encoding_name,
+- video_codec ? PURPLE_MEDIA_VIDEO :
+- PURPLE_MEDIA_AUDIO,
+- clock_rate ? atoi(clock_rate) : 0);
+- if (video_codec)
+- video_codecs = g_list_append(
+- video_codecs, codec);
+- else
+- codecs = g_list_append(codecs, codec);
+- }
+- }
+-
+- if (codecs)
+- purple_media_set_remote_codecs(session_data->media, "google-voice",
+- session->remote_jid, codecs);
+- if (video_codecs)
+- purple_media_set_remote_codecs(session_data->media, "google-video",
+- session->remote_jid, video_codecs);
+-
+- purple_media_stream_info(session_data->media, PURPLE_MEDIA_INFO_ACCEPT,
+- NULL, NULL, FALSE);
+-
+- result = jabber_iq_new(js, JABBER_IQ_RESULT);
+- jabber_iq_set_id(result, iq_id);
+- xmlnode_set_attrib(result->node, "to", session->remote_jid);
+- jabber_iq_send(result);
+-}
+-
+-static void
+-google_session_handle_reject(JabberStream *js, GoogleSession *session, xmlnode *sess)
+-{
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+- purple_media_end(session_data->media, NULL, NULL);
+-}
+-
+-static void
+-google_session_handle_terminate(JabberStream *js, GoogleSession *session, xmlnode *sess)
+-{
+- GoogleAVSessionData *session_data =
+- (GoogleAVSessionData *) session->session_data;
+- purple_media_end(session_data->media, NULL, NULL);
+-}
+-
+-static void
+-google_session_parse_iq(JabberStream *js, GoogleSession *session, xmlnode *sess, const char *iq_id)
+-{
+- const char *type = xmlnode_get_attrib(sess, "type");
+-
+- if (!strcmp(type, "initiate")) {
+- google_session_handle_initiate(js, session, sess, iq_id);
+- } else if (!strcmp(type, "accept")) {
+- google_session_handle_accept(js, session, sess, iq_id);
+- } else if (!strcmp(type, "reject")) {
+- google_session_handle_reject(js, session, sess);
+- } else if (!strcmp(type, "terminate")) {
+- google_session_handle_terminate(js, session, sess);
+- } else if (!strcmp(type, "candidates")) {
+- google_session_handle_candidates(js, session, sess, iq_id);
+- }
+-}
+-
+-void
+-jabber_google_session_parse(JabberStream *js, const char *from,
+- JabberIqType type, const char *iq_id,
+- xmlnode *session_node)
+-{
+- GoogleSession *session = NULL;
+- GoogleSessionId id;
+-
+- xmlnode *desc_node;
+-
+- GList *iter = NULL;
+-
+- if (type != JABBER_IQ_SET)
+- return;
+-
+- id.id = (gchar*)xmlnode_get_attrib(session_node, "id");
+- if (!id.id)
+- return;
+-
+- id.initiator = (gchar*)xmlnode_get_attrib(session_node, "initiator");
+- if (!id.initiator)
+- return;
+-
+- iter = purple_media_manager_get_media_by_account(
+- purple_media_manager_get(),
+- purple_connection_get_account(js->gc));
+- for (; iter; iter = g_list_delete_link(iter, iter)) {
+- GoogleSession *gsession =
+- purple_media_get_prpl_data(iter->data);
+- if (google_session_id_equal(&(gsession->id), &id)) {
+- session = gsession;
+- break;
+- }
+- }
+- if (iter != NULL) {
+- g_list_free(iter);
+- }
+-
+- if (session) {
+- google_session_parse_iq(js, session, session_node, iq_id);
+- return;
+- }
+-
+- /* If the session doesn't exist, this has to be an initiate message */
+- if (strcmp(xmlnode_get_attrib(session_node, "type"), "initiate"))
+- return;
+- desc_node = xmlnode_get_child(session_node, "description");
+- if (!desc_node)
+- return;
+- session = g_new0(GoogleSession, 1);
+- session->id.id = g_strdup(id.id);
+- session->id.initiator = g_strdup(id.initiator);
+- session->state = UNINIT;
+- session->js = js;
+- session->remote_jid = g_strdup(session->id.initiator);
+- session->session_data = g_new0(GoogleAVSessionData, 1);
+-
+- google_session_handle_initiate(js, session, session_node, iq_id);
+-}
+-#endif /* USE_VV */
+-
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/google_session.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/google_session.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,56 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_SESSION_H_
+-#define PURPLE_JABBER_GOOGLE_SESSION_H_
+-
+-#include "jabber.h"
+-
+-typedef struct {
+- char *id;
+- char *initiator;
+-} GoogleSessionId;
+-
+-typedef enum {
+- UNINIT,
+- SENT_INITIATE,
+- RECEIVED_INITIATE,
+- IN_PRORESS,
+- TERMINATED
+-} GoogleSessionState;
+-
+-typedef struct {
+- GoogleSessionId id;
+- GoogleSessionState state;
+- JabberStream *js;
+- char *remote_jid;
+- char *iq_id;
+- xmlnode *description; /* store incoming description through
+- relay credential fetching */
+- gpointer session_data;
+-} GoogleSession;
+-
+-gboolean jabber_google_session_initiate(JabberStream *js, const gchar *who,
+- PurpleMediaSessionType type);
+-
+-void jabber_google_session_parse(JabberStream *js, const char *from,
+- JabberIqType type, const char *iq, xmlnode *session);
+-
+-#endif /* PURPLE_JABBER_GOOGLE_SESSION_H_ */
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,176 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "jingleinfo.h"
+-
+-static void
+-jabber_google_stun_lookup_cb(GSList *hosts, gpointer data,
+- const char *error_message)
+-{
+- JabberStream *js = (JabberStream *) data;
+-
+- if (error_message) {
+- purple_debug_error("jabber", "Google STUN lookup failed: %s\n",
+- error_message);
+- g_slist_free(hosts);
+- js->stun_query = NULL;
+- return;
+- }
+-
+- if (hosts && g_slist_next(hosts)) {
+- struct sockaddr *addr = g_slist_next(hosts)->data;
+- char dst[INET6_ADDRSTRLEN];
+- int port;
+-
+- if (addr->sa_family == AF_INET6) {
+- inet_ntop(addr->sa_family, &((struct sockaddr_in6 *) addr)->sin6_addr,
+- dst, sizeof(dst));
+- port = ntohs(((struct sockaddr_in6 *) addr)->sin6_port);
+- } else {
+- inet_ntop(addr->sa_family, &((struct sockaddr_in *) addr)->sin_addr,
+- dst, sizeof(dst));
+- port = ntohs(((struct sockaddr_in *) addr)->sin_port);
+- }
+-
+- if (js->stun_ip)
+- g_free(js->stun_ip);
+- js->stun_ip = g_strdup(dst);
+- js->stun_port = port;
+-
+- purple_debug_info("jabber", "set Google STUN IP/port address: "
+- "%s:%d\n", dst, port);
+-
+- /* unmark ongoing query */
+- js->stun_query = NULL;
+- }
+-
+- while (hosts != NULL) {
+- hosts = g_slist_delete_link(hosts, hosts);
+- /* Free the address */
+- g_free(hosts->data);
+- hosts = g_slist_delete_link(hosts, hosts);
+- }
+-}
+-
+-static void
+-jabber_google_jingle_info_common(JabberStream *js, const char *from,
+- JabberIqType type, xmlnode *query)
+-{
+- const xmlnode *stun = xmlnode_get_child(query, "stun");
+- const xmlnode *relay = xmlnode_get_child(query, "relay");
+- gchar *my_bare_jid;
+-
+- /*
+- * Make sure that random people aren't sending us STUN servers. Per
+- * http://code.google.com/apis/talk/jep_extensions/jingleinfo.html, these
+- * stanzas are stamped from our bare JID.
+- */
+- if (from) {
+- my_bare_jid = g_strdup_printf("%s@%s", js->user->node, js->user->domain);
+- if (!purple_strequal(from, my_bare_jid)) {
+- purple_debug_warning("jabber", "got google:jingleinfo with invalid from (%s)\n",
+- from);
+- g_free(my_bare_jid);
+- return;
+- }
+-
+- g_free(my_bare_jid);
+- }
+-
+- if (type == JABBER_IQ_ERROR || type == JABBER_IQ_GET)
+- return;
+-
+- purple_debug_info("jabber", "got google:jingleinfo\n");
+-
+- if (stun) {
+- xmlnode *server = xmlnode_get_child(stun, "server");
+-
+- if (server) {
+- const gchar *host = xmlnode_get_attrib(server, "host");
+- const gchar *udp = xmlnode_get_attrib(server, "udp");
+-
+- if (host && udp) {
+- PurpleAccount *account;
+- int port = atoi(udp);
+- /* if there, would already be an ongoing query,
+- cancel it */
+- if (js->stun_query)
+- purple_dnsquery_destroy(js->stun_query);
+-
+- account = purple_connection_get_account(js->gc);
+- js->stun_query = purple_dnsquery_a_account(account, host, port,
+- jabber_google_stun_lookup_cb, js);
+- }
+- }
+- }
+-
+- if (relay) {
+- xmlnode *token = xmlnode_get_child(relay, "token");
+- xmlnode *server = xmlnode_get_child(relay, "server");
+-
+- if (token) {
+- gchar *relay_token = xmlnode_get_data(token);
+-
+- /* we let js own the string returned from xmlnode_get_data */
+- js->google_relay_token = relay_token;
+- }
+-
+- if (server) {
+- js->google_relay_host =
+- g_strdup(xmlnode_get_attrib(server, "host"));
+- }
+- }
+-}
+-
+-static void
+-jabber_google_jingle_info_cb(JabberStream *js, const char *from,
+- JabberIqType type, const char *id,
+- xmlnode *packet, gpointer data)
+-{
+- xmlnode *query = xmlnode_get_child_with_namespace(packet, "query",
+- NS_GOOGLE_JINGLE_INFO);
+-
+- if (query)
+- jabber_google_jingle_info_common(js, from, type, query);
+- else
+- purple_debug_warning("jabber", "Got invalid google:jingleinfo\n");
+-}
+-
+-void
+-jabber_google_handle_jingle_info(JabberStream *js, const char *from,
+- JabberIqType type, const char *id,
+- xmlnode *child)
+-{
+- jabber_google_jingle_info_common(js, from, type, child);
+-}
+-
+-void
+-jabber_google_send_jingle_info(JabberStream *js)
+-{
+- JabberIq *jingle_info =
+- jabber_iq_new_query(js, JABBER_IQ_GET, NS_GOOGLE_JINGLE_INFO);
+-
+- jabber_iq_set_callback(jingle_info, jabber_google_jingle_info_cb,
+- NULL);
+- purple_debug_info("jabber", "sending google:jingleinfo query\n");
+- jabber_iq_send(jingle_info);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/jingleinfo.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/jingleinfo.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,32 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef PURPLE_JABBER_GOOGLE_ROSTER_H_
+-#define PURPLE_JABBER_GOOGLE_ROSTER_H_
+-
+-#include "jabber.h"
+-
+-void jabber_google_handle_jingle_info(JabberStream *js, const char *from,
+- JabberIqType type, const char *id,
+- xmlnode *child);
+-void jabber_google_send_jingle_info(JabberStream *js);
+-
+-
+-#endif /* PURPLE_JABBER_GOOGLE_ROSTER_H_ */
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/relay.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/relay.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,151 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "relay.h"
+-
+-typedef struct {
+- GoogleSession *session;
+- JabberGoogleRelayCallback *cb;
+-} JabberGoogleRelayCallbackData;
+-
+-static void
+-jabber_google_relay_parse_response(const gchar *response, gchar **ip,
+- guint *udp, guint *tcp, guint *ssltcp, gchar **username, gchar **password)
+-{
+- gchar **lines = g_strsplit(response, "\n", -1);
+- int i = 0;
+-
+- for (; lines[i] ; i++) {
+- gchar *line = lines[i];
+- gchar **parts = g_strsplit(line, "=", 2);
+-
+- if (parts[0] && parts[1]) {
+- if (purple_strequal(parts[0], "relay.ip")) {
+- *ip = g_strdup(parts[1]);
+- } else if (purple_strequal(parts[0], "relay.udp_port")) {
+- *udp = atoi(parts[1]);
+- } else if (purple_strequal(parts[0], "relay.tcp_port")) {
+- *tcp = atoi(parts[1]);
+- } else if (purple_strequal(parts[0], "relay.ssltcp_port")) {
+- *ssltcp = atoi(parts[1]);
+- } else if (purple_strequal(parts[0], "username")) {
+- *username = g_strdup(parts[1]);
+- } else if (purple_strequal(parts[0], "password")) {
+- *password = g_strdup(parts[1]);
+- }
+- }
+- g_strfreev(parts);
+- }
+-
+- g_strfreev(lines);
+-}
+-
+-static void
+-jabber_google_relay_remove_url_data(JabberStream *js,
+- PurpleUtilFetchUrlData *url_data)
+-{
+- GList *iter = js->google_relay_requests;
+-
+- while (iter) {
+- if (iter->data == url_data) {
+- js->google_relay_requests =
+- g_list_delete_link(js->google_relay_requests, iter);
+- break;
+- }
+- }
+-}
+-
+-static void
+-jabber_google_relay_fetch_cb(PurpleUtilFetchUrlData *url_data,
+- gpointer user_data, const gchar *url_text, gsize len,
+- const gchar *error_message)
+-{
+- JabberGoogleRelayCallbackData *data =
+- (JabberGoogleRelayCallbackData *) user_data;
+- GoogleSession *session = data->session;
+- JabberStream *js = session->js;
+- JabberGoogleRelayCallback *cb = data->cb;
+- gchar *relay_ip = NULL;
+- guint relay_udp = 0;
+- guint relay_tcp = 0;
+- guint relay_ssltcp = 0;
+- gchar *relay_username = NULL;
+- gchar *relay_password = NULL;
+-
+- g_free(data);
+-
+- if (url_data) {
+- jabber_google_relay_remove_url_data(js, url_data);
+- }
+-
+- purple_debug_info("jabber", "got response on HTTP request to relay server\n");
+-
+- if (url_text && len > 0) {
+- purple_debug_info("jabber", "got Google relay request response:\n%s\n",
+- url_text);
+- jabber_google_relay_parse_response(url_text, &relay_ip, &relay_udp,
+- &relay_tcp, &relay_ssltcp, &relay_username, &relay_password);
+- }
+-
+- if (cb)
+- cb(session, relay_ip, relay_udp, relay_tcp, relay_ssltcp,
+- relay_username, relay_password);
+-
+- g_free(relay_ip);
+- g_free(relay_username);
+- g_free(relay_password);
+-}
+-
+-void
+-jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
+- JabberGoogleRelayCallback cb)
+-{
+- PurpleUtilFetchUrlData *url_data = NULL;
+- gchar *url = g_strdup_printf("http://%s", js->google_relay_host);
+- /* yes, the relay token is included twice as different request headers,
+- this is apparently needed to make Google's relay servers work... */
+- gchar *request =
+- g_strdup_printf("GET /create_session HTTP/1.0\r\n"
+- "Host: %s\r\n"
+- "X-Talk-Google-Relay-Auth: %s\r\n"
+- "X-Google-Relay-Auth: %s\r\n\r\n",
+- js->google_relay_host, js->google_relay_token, js->google_relay_token);
+- JabberGoogleRelayCallbackData *data = g_new0(JabberGoogleRelayCallbackData, 1);
+-
+- data->session = session;
+- data->cb = cb;
+- purple_debug_info("jabber",
+- "sending Google relay request %s to %s\n", request, url);
+- url_data =
+- purple_util_fetch_url_request(url, FALSE, NULL, FALSE, request, FALSE,
+- jabber_google_relay_fetch_cb, data);
+- if (url_data) {
+- js->google_relay_requests =
+- g_list_prepend(js->google_relay_requests, url_data);
+- } else {
+- purple_debug_error("jabber", "unable to create Google relay request\n");
+- jabber_google_relay_fetch_cb(NULL, data, NULL, 0, NULL);
+- }
+- g_free(url);
+- g_free(request);
+-}
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/google/relay.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/google/relay.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/google/relay.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,33 +0,0 @@
+-/**
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef JABBER_GOOGLE_RELAY
+-#define JABBER_GOOGLE_RELAY
+-
+-#include "google_session.h"
+-
+-typedef void (JabberGoogleRelayCallback)(GoogleSession *session, const gchar *ip,
+- guint udp_port, guint tcp_port, guint tls_port,
+- const gchar *username, const gchar *password);
+-
+-void jabber_google_do_relay_request(JabberStream *js, GoogleSession *session,
+- JabberGoogleRelayCallback cb);
+-
+-#endif /* JABBER_GOOGLE_RELAY */
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/iq.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/iq.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/iq.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/iq.c 2013-08-17 00:19:05.943958296 -0300
+@@ -28,10 +28,6 @@
+
+ #include "buddy.h"
+ #include "disco.h"
+-#include "google/gmail.h"
+-#include "google/google.h"
+-#include "google/jingleinfo.h"
+-#include "google/google_session.h"
+ #include "iq.h"
+ #include "jingle/jingle.h"
+ #include "oob.h"
+@@ -461,13 +457,7 @@
+ signal_iq_handlers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+
+ jabber_iq_register_handler("jingle", JINGLE, jingle_parse);
+- jabber_iq_register_handler("mailbox", NS_GOOGLE_MAIL_NOTIFY,
+- jabber_gmail_poke);
+- jabber_iq_register_handler("new-mail", NS_GOOGLE_MAIL_NOTIFY,
+- jabber_gmail_poke);
+ jabber_iq_register_handler("ping", NS_PING, jabber_ping_parse);
+- jabber_iq_register_handler("query", NS_GOOGLE_JINGLE_INFO,
+- jabber_google_handle_jingle_info);
+ jabber_iq_register_handler("query", NS_BYTESTREAMS,
+ jabber_bytestreams_parse);
+ jabber_iq_register_handler("query", NS_DISCO_INFO, jabber_disco_info_parse);
+@@ -481,8 +471,6 @@
+ jabber_iq_register_handler("query", "jabber:iq:version",
+ jabber_iq_version_parse);
+ #ifdef USE_VV
+- jabber_iq_register_handler("session", NS_GOOGLE_SESSION,
+- jabber_google_session_parse);
+ #endif
+ jabber_iq_register_handler("block", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
+ jabber_iq_register_handler("unblock", NS_SIMPLE_BLOCKING, jabber_blocklist_parse_push);
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jabber.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/jabber.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.c 2013-08-27 23:23:55.191865468 -0300
+@@ -51,9 +51,6 @@
+ #include "chat.h"
+ #include "data.h"
+ #include "disco.h"
+-#include "google/google.h"
+-#include "google/google_roster.h"
+-#include "google/google_session.h"
+ #include "ibb.h"
+ #include "iq.h"
+ #include "jutil.h"
+@@ -1003,9 +1000,6 @@
+ js->stun_ip = NULL;
+ js->stun_port = 0;
+ js->stun_query = NULL;
+- js->google_relay_token = NULL;
+- js->google_relay_host = NULL;
+- js->google_relay_requests = NULL;
+
+ /* if we are idle, set idle-ness on the stream (this could happen if we get
+ disconnected and the reconnects while being idle. I don't think it makes
+@@ -1679,8 +1673,6 @@
+ }
+ g_free(js->server_name);
+ g_free(js->certificate_CN);
+- g_free(js->gmail_last_time);
+- g_free(js->gmail_last_tid);
+ g_free(js->old_msg);
+ g_free(js->old_avatarhash);
+ g_free(js->old_artist);
+@@ -1709,21 +1701,6 @@
+ js->stun_query = NULL;
+ }
+
+- /* remove Google relay-related stuff */
+- g_free(js->google_relay_token);
+- g_free(js->google_relay_host);
+- if (js->google_relay_requests) {
+- while (js->google_relay_requests) {
+- PurpleUtilFetchUrlData *url_data =
+- (PurpleUtilFetchUrlData *) js->google_relay_requests->data;
+- purple_util_fetch_url_cancel(url_data);
+- g_free(url_data);
+- js->google_relay_requests =
+- g_list_delete_link(js->google_relay_requests,
+- js->google_relay_requests);
+- }
+- }
+-
+ g_free(js);
+
+ gc->proto_data = NULL;
+@@ -1916,12 +1893,6 @@
+ if (js == NULL)
+ return;
+
+- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
+- {
+- jabber_google_roster_add_deny(js, who);
+- return;
+- }
+-
+ if (!(js->server_caps & JABBER_CAP_BLOCKING))
+ {
+ purple_notify_error(NULL, _("Server doesn't support blocking"),
+@@ -1952,12 +1923,6 @@
+ if (js == NULL)
+ return;
+
+- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
+- {
+- jabber_google_roster_rem_deny(js, who);
+- return;
+- }
+-
+ if (!(js->server_caps & JABBER_CAP_BLOCKING))
+ return;
+
+@@ -3310,13 +3275,7 @@
+ jbr = jabber_buddy_find_resource(jb, resource);
+ g_free(resource);
+
+- if (type & PURPLE_MEDIA_AUDIO &&
+- !jabber_resource_has_capability(jbr,
+- JINGLE_APP_RTP_SUPPORT_AUDIO) &&
+- jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE))
+- return jabber_google_session_initiate(js, who, type);
+- else
+- return jingle_rtp_initiate_media(js, who, type);
++ return jingle_rtp_initiate_media(js, who, type);
+ }
+
+ jb = jabber_buddy_find(js, who, FALSE);
+@@ -3500,11 +3459,6 @@
+ caps |= PURPLE_MEDIA_CAPS_MODIFY_SESSION |
+ PURPLE_MEDIA_CAPS_CHANGE_DIRECTION;
+ }
+- if (jabber_resource_has_capability(jbr, NS_GOOGLE_VOICE)) {
+- caps |= PURPLE_MEDIA_CAPS_AUDIO;
+- if (jabber_resource_has_capability(jbr, NS_GOOGLE_VIDEO))
+- caps |= PURPLE_MEDIA_CAPS_AUDIO_VIDEO;
+- }
+
+ total |= caps;
+ }
+@@ -3869,10 +3823,6 @@
+ jabber_add_feature(JINGLE, 0);
+
+ #ifdef USE_VV
+- jabber_add_feature(NS_GOOGLE_PROTOCOL_SESSION, jabber_audio_enabled);
+- jabber_add_feature(NS_GOOGLE_VOICE, jabber_audio_enabled);
+- jabber_add_feature(NS_GOOGLE_VIDEO, jabber_video_enabled);
+- jabber_add_feature(NS_GOOGLE_CAMERA, jabber_video_enabled);
+ jabber_add_feature(JINGLE_APP_RTP, 0);
+ jabber_add_feature(JINGLE_APP_RTP_SUPPORT_AUDIO, jabber_audio_enabled);
+ jabber_add_feature(JINGLE_APP_RTP_SUPPORT_VIDEO, jabber_video_enabled);
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jabber.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/jabber.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jabber.h 2013-08-17 00:10:38.778345348 -0300
+@@ -36,12 +36,6 @@
+ JABBER_CAP_IQ_SEARCH = 1 << 7,
+ JABBER_CAP_IQ_REGISTER = 1 << 8,
+
+- /* Google Talk extensions:
+- * http://code.google.com/apis/talk/jep_extensions/extensions.html
+- */
+- JABBER_CAP_GMAIL_NOTIFY = 1 << 9,
+- JABBER_CAP_GOOGLE_ROSTER = 1 << 10,
+-
+ JABBER_CAP_PING = 1 << 11,
+ JABBER_CAP_ADHOC = 1 << 12,
+ JABBER_CAP_BLOCKING = 1 << 13,
+@@ -195,12 +189,8 @@
+ gboolean reinit;
+
+ JabberCapabilities server_caps;
+- gboolean googletalk;
+ char *server_name;
+
+- char *gmail_last_time;
+- char *gmail_last_tid;
+-
+ char *serverFQDN;
+
+ #ifdef HAVE_CYRUS_SASL
+@@ -276,12 +266,6 @@
+ gchar *stun_ip;
+ int stun_port;
+ PurpleDnsQueryData *stun_query;
+-
+- /* stuff for Google's relay handling */
+- gchar *google_relay_token;
+- gchar *google_relay_host;
+- GList *google_relay_requests; /* the HTTP requests to get */
+- /* relay info */
+ };
+
+ typedef gboolean (JabberFeatureEnabled)(JabberStream *js, const gchar *namespace);
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.c 2013-08-17 00:17:51.991679891 -0300
+@@ -486,13 +486,11 @@
+
+ if (has_account_stun) {
+ purple_debug_info("jabber",
+- "setting param stun-ip for stream using Google auto-config: %s\n",
+ js->stun_ip);
+ params[next_index].name = "stun-ip";
+ g_value_init(&params[next_index].value, G_TYPE_STRING);
+ g_value_set_string(&params[next_index].value, js->stun_ip);
+ purple_debug_info("jabber",
+- "setting param stun-port for stream using Google auto-config: %d\n",
+ js->stun_port);
+ next_index++;
+ params[next_index].name = "stun-port";
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/jingle/jingle.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/jingle/jingle.h 2013-08-27 23:02:43.456476444 -0300
+@@ -79,8 +79,7 @@
+ void jingle_terminate_sessions(JabberStream *js);
+
+ #ifdef USE_VV
+-/* create a GParam array given autoconfigured STUN (and later perhaps TURN).
+- if google_talk is TRUE, set compatability mode to GOOGLE_TALK */
++/* create a GParam array given autoconfigured STUN (and later perhaps TURN).*/
+ GParameter *jingle_get_params(JabberStream *js, const gchar *relay_ip,
+ guint relay_udp, guint relay_tcp, guint relay_ssltcp,
+ const gchar *relay_username, const gchar *relay_password, guint *num_params);
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/libxmpp.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/libxmpp.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/libxmpp.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/libxmpp.c 2013-08-17 00:13:06.222881329 -0300
+@@ -41,7 +41,6 @@
+ #include "si.h"
+ #include "message.h"
+ #include "presence.h"
+-#include "google/google.h"
+ #include "pep.h"
+ #include "usermood.h"
+ #include "usertune.h"
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.am 2013-08-17 00:18:17.592468560 -0300
+@@ -27,20 +27,6 @@
+ data.h \
+ disco.c \
+ disco.h \
+- google/gmail.c \
+- google/gmail.h \
+- google/google.c \
+- google/google.h \
+- google/google_presence.c \
+- google/google_presence.h \
+- google/google_roster.c \
+- google/google_roster.h \
+- google/google_session.c \
+- google/google_session.h \
+- google/jingleinfo.c \
+- google/jingleinfo.h \
+- google/relay.c \
+- google/relay.h \
+ ibb.c \
+ ibb.h \
+ iq.c \
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.in 2013-02-11 07:17:20.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.in 2013-08-17 00:12:44.605549467 -0300
+@@ -104,12 +104,7 @@
+ auth.h auth_digest_md5.c auth_digest_md5.h auth_plain.c \
+ auth_scram.c auth_scram.h buddy.c buddy.h bosh.c bosh.h caps.c \
+ caps.h chat.c chat.h data.c data.h disco.c disco.h \
+- google/gmail.c google/gmail.h google/google.c google/google.h \
+- google/google_presence.c google/google_presence.h \
+- google/google_roster.c google/google_roster.h \
+- google/google_session.c google/google_session.h \
+- google/jingleinfo.c google/jingleinfo.h google/relay.c \
+- google/relay.h ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
++ ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
+ jingle/jingle.c jingle/jingle.h jingle/content.c \
+ jingle/content.h jingle/iceudp.c jingle/iceudp.h \
+ jingle/rawudp.c jingle/rawudp.h jingle/rtp.c jingle/rtp.h \
+@@ -126,9 +121,7 @@
+ libjabber_la-auth_scram.lo libjabber_la-buddy.lo \
+ libjabber_la-bosh.lo libjabber_la-caps.lo libjabber_la-chat.lo \
+ libjabber_la-data.lo libjabber_la-disco.lo \
+- libjabber_la-gmail.lo libjabber_la-google.lo \
+- libjabber_la-google_presence.lo libjabber_la-google_roster.lo \
+- libjabber_la-google_session.lo libjabber_la-jingleinfo.lo \
++ libjabber_la-jingleinfo.lo \
+ libjabber_la-relay.lo libjabber_la-ibb.lo libjabber_la-iq.lo \
+ libjabber_la-jabber.lo libjabber_la-jingle.lo \
+ libjabber_la-content.lo libjabber_la-iceudp.lo \
+@@ -244,8 +237,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -307,8 +298,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+@@ -457,13 +446,8 @@
+ JABBERSOURCES = adhoccommands.c adhoccommands.h auth.c auth.h \
+ auth_digest_md5.c auth_digest_md5.h auth_plain.c auth_scram.c \
+ auth_scram.h buddy.c buddy.h bosh.c bosh.h caps.c caps.h \
+- chat.c chat.h data.c data.h disco.c disco.h google/gmail.c \
+- google/gmail.h google/google.c google/google.h \
+- google/google_presence.c google/google_presence.h \
+- google/google_roster.c google/google_roster.h \
+- google/google_session.c google/google_session.h \
+- google/jingleinfo.c google/jingleinfo.h google/relay.c \
+- google/relay.h ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
++ chat.c chat.h data.c data.h disco.c disco.h \
++ ibb.c ibb.h iq.c iq.h jabber.c jabber.h \
+ jingle/jingle.c jingle/jingle.h jingle/content.c \
+ jingle/content.h jingle/iceudp.c jingle/iceudp.h \
+ jingle/rawudp.c jingle/rawudp.h jingle/rtp.c jingle/rtp.h \
+@@ -600,11 +584,6 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-content.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-data.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-disco.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-gmail.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_presence.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_roster.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-google_session.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-ibb.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-iceudp.Plo@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libjabber_la-iq.Plo@am__quote@
+@@ -731,55 +710,6 @@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-disco.lo `test -f 'disco.c' || echo '$(srcdir)/'`disco.c
+
+-libjabber_la-gmail.lo: google/gmail.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-gmail.lo -MD -MP -MF $(DEPDIR)/libjabber_la-gmail.Tpo -c -o libjabber_la-gmail.lo `test -f 'google/gmail.c' || echo '$(srcdir)/'`google/gmail.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-gmail.Tpo $(DEPDIR)/libjabber_la-gmail.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/gmail.c' object='libjabber_la-gmail.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-gmail.lo `test -f 'google/gmail.c' || echo '$(srcdir)/'`google/gmail.c
+-
+-libjabber_la-google.lo: google/google.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google.Tpo -c -o libjabber_la-google.lo `test -f 'google/google.c' || echo '$(srcdir)/'`google/google.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google.Tpo $(DEPDIR)/libjabber_la-google.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google.c' object='libjabber_la-google.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google.lo `test -f 'google/google.c' || echo '$(srcdir)/'`google/google.c
+-
+-libjabber_la-google_presence.lo: google/google_presence.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_presence.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_presence.Tpo -c -o libjabber_la-google_presence.lo `test -f 'google/google_presence.c' || echo '$(srcdir)/'`google/google_presence.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_presence.Tpo $(DEPDIR)/libjabber_la-google_presence.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_presence.c' object='libjabber_la-google_presence.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_presence.lo `test -f 'google/google_presence.c' || echo '$(srcdir)/'`google/google_presence.c
+-
+-libjabber_la-google_roster.lo: google/google_roster.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_roster.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_roster.Tpo -c -o libjabber_la-google_roster.lo `test -f 'google/google_roster.c' || echo '$(srcdir)/'`google/google_roster.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_roster.Tpo $(DEPDIR)/libjabber_la-google_roster.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_roster.c' object='libjabber_la-google_roster.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_roster.lo `test -f 'google/google_roster.c' || echo '$(srcdir)/'`google/google_roster.c
+-
+-libjabber_la-google_session.lo: google/google_session.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-google_session.lo -MD -MP -MF $(DEPDIR)/libjabber_la-google_session.Tpo -c -o libjabber_la-google_session.lo `test -f 'google/google_session.c' || echo '$(srcdir)/'`google/google_session.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-google_session.Tpo $(DEPDIR)/libjabber_la-google_session.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/google_session.c' object='libjabber_la-google_session.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-google_session.lo `test -f 'google/google_session.c' || echo '$(srcdir)/'`google/google_session.c
+-
+-libjabber_la-jingleinfo.lo: google/jingleinfo.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-jingleinfo.lo -MD -MP -MF $(DEPDIR)/libjabber_la-jingleinfo.Tpo -c -o libjabber_la-jingleinfo.lo `test -f 'google/jingleinfo.c' || echo '$(srcdir)/'`google/jingleinfo.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-jingleinfo.Tpo $(DEPDIR)/libjabber_la-jingleinfo.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/jingleinfo.c' object='libjabber_la-jingleinfo.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-jingleinfo.lo `test -f 'google/jingleinfo.c' || echo '$(srcdir)/'`google/jingleinfo.c
+-
+-libjabber_la-relay.lo: google/relay.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-relay.lo -MD -MP -MF $(DEPDIR)/libjabber_la-relay.Tpo -c -o libjabber_la-relay.lo `test -f 'google/relay.c' || echo '$(srcdir)/'`google/relay.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-relay.Tpo $(DEPDIR)/libjabber_la-relay.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='google/relay.c' object='libjabber_la-relay.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -c -o libjabber_la-relay.lo `test -f 'google/relay.c' || echo '$(srcdir)/'`google/relay.c
+-
+ libjabber_la-ibb.lo: ibb.c
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libjabber_la_CFLAGS) $(CFLAGS) -MT libjabber_la-ibb.lo -MD -MP -MF $(DEPDIR)/libjabber_la-ibb.Tpo -c -o libjabber_la-ibb.lo `test -f 'ibb.c' || echo '$(srcdir)/'`ibb.c
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libjabber_la-ibb.Tpo $(DEPDIR)/libjabber_la-ibb.Plo
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/jabber/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,141 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libjabber
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libjabber
+-XMPP_TARGET = libxmpp
+-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./win32 \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(LIBXML2_TOP)/include/libxml2 \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(LIBXML2_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L.
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = \
+- adhoccommands.c \
+- auth.c \
+- auth_cyrus.c \
+- auth_digest_md5.c \
+- auth_plain.c \
+- auth_scram.c \
+- buddy.c \
+- bosh.c \
+- caps.c \
+- chat.c \
+- data.c \
+- disco.c \
+- google/gmail.c \
+- google/google.c \
+- google/google_presence.c \
+- google/google_roster.c \
+- google/google_session.c \
+- google/jingleinfo.c \
+- google/relay.c \
+- ibb.c \
+- iq.c \
+- jabber.c \
+- jingle/jingle.c \
+- jingle/content.c \
+- jingle/iceudp.c \
+- jingle/rawudp.c \
+- jingle/rtp.c \
+- jingle/session.c \
+- jingle/transport.c \
+- jutil.c \
+- message.c \
+- oob.c \
+- parser.c \
+- pep.c \
+- ping.c \
+- presence.c \
+- roster.c \
+- si.c \
+- useravatar.c \
+- usermood.c \
+- usernick.c \
+- usertune.c \
+- xdata.c \
+- win32/posix.uname.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-XMPP_C_SRC = libxmpp.c
+-XMPP_OBJECTS = $(XMPP_C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lgobject-2.0 \
+- -lxml2 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-ifeq ($(CYRUS_SASL), 1)
+-INCLUDE_PATHS += -I$(CYRUS_SASL_TOP)/include
+-LIB_PATHS += -L$(CYRUS_SASL_TOP)/bin
+-LIBS += -llibsasl
+-endif
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll $(XMPP_TARGET).dll
+-
+-install: all $(DLL_INSTALL_DIR)
+- cp $(XMPP_TARGET).dll $(DLL_INSTALL_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-$(TARGET).dll $(TARGET).dll.a: $(PURPLE_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+-
+-$(XMPP_TARGET).dll: $(TARGET).dll.a $(XMPP_OBJECTS)
+- $(CC) -shared $(XMPP_OBJECTS) $(LIB_PATHS) $(LIBS) -ljabber $(DLL_LD_FLAGS) -o $(XMPP_TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
+- rm -f $(XMPP_OBJECTS) $(XMPP_TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/message.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/message.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/message.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/message.c 2013-08-17 00:20:08.115874207 -0300
+@@ -30,7 +30,6 @@
+ #include "buddy.h"
+ #include "chat.h"
+ #include "data.h"
+-#include "google/google.h"
+ #include "message.h"
+ #include "xmlnode.h"
+ #include "pep.h"
+@@ -151,11 +150,6 @@
+ jbr->thread_id = g_strdup(jbr->thread_id);
+ }
+
+- if (jm->js->googletalk && jm->xhtml == NULL) {
+- char *tmp = jm->body;
+- jm->body = jabber_google_format_to_html(jm->body);
+- g_free(tmp);
+- }
+ serv_got_im(gc, jm->from, jm->xhtml ? jm->xhtml : jm->body, 0, jm->sent);
+ }
+
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/namespaces.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/namespaces.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/namespaces.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/namespaces.h 2013-08-17 00:11:17.449534779 -0300
+@@ -95,18 +95,4 @@
+ /* XEP-0264 File Transfer Thumbnails (Thumbs) */
+ #define NS_THUMBS "urn:xmpp:thumbs:0"
+
+-/* Google extensions */
+-#define NS_GOOGLE_CAMERA "http://www.google.com/xmpp/protocol/camera/v1"
+-#define NS_GOOGLE_VIDEO "http://www.google.com/xmpp/protocol/video/v1"
+-#define NS_GOOGLE_VOICE "http://www.google.com/xmpp/protocol/voice/v1"
+-#define NS_GOOGLE_JINGLE_INFO "google:jingleinfo"
+-
+-#define NS_GOOGLE_MAIL_NOTIFY "google:mail:notify"
+-#define NS_GOOGLE_ROSTER "google:roster"
+-
+-#define NS_GOOGLE_PROTOCOL_SESSION "http://www.google.com/xmpp/protocol/session"
+-#define NS_GOOGLE_SESSION "http://www.google.com/session"
+-#define NS_GOOGLE_SESSION_PHONE "http://www.google.com/session/phone"
+-#define NS_GOOGLE_SESSION_VIDEO "http://www.google.com/session/video"
+-
+ #endif /* PURPLE_JABBER_NAMESPACES_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/presence.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/presence.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/presence.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/presence.c 2013-08-17 00:16:58.436696950 -0300
+@@ -34,8 +34,6 @@
+
+ #include "buddy.h"
+ #include "chat.h"
+-#include "google/google.h"
+-#include "google/google_presence.h"
+ #include "presence.h"
+ #include "iq.h"
+ #include "jutil.h"
+@@ -208,9 +206,6 @@
+ /* changing the buzz state has to trigger a re-broadcasting of the presence for caps */
+
+ tune = purple_presence_get_status(p, "tune");
+- if (js->googletalk && !stripped && purple_status_is_active(tune)) {
+- stripped = jabber_google_presence_outgoing(tune);
+- }
+
+ #define CHANGED(a,b) ((!a && b) || (a && a[0] == '\0' && b && b[0] != '\0') || \
+ (a && !b) || (a && a[0] != '\0' && b && b[0] == '\0') || (a && b && strcmp(a,b)))
+@@ -361,11 +356,6 @@
+ #ifdef USE_VV
+ /*
+ * MASSIVE HUGE DISGUSTING HACK
+- * This is a huge hack. As far as I can tell, Google Talk's gmail client
+- * doesn't bother to check the actual features we advertise; they
+- * just assume that if we specify a 'voice-v1' ext (ignoring that
+- * these are to be assigned no semantic value), we support receiving voice
+- * calls.
+ *
+ * Ditto for 'video-v1'.
+ */
+@@ -883,7 +873,6 @@
+
+ jbr = jabber_buddy_find_resource(presence->jb, NULL);
+ if (jbr) {
+- jabber_google_presence_incoming(js, buddy_name, jbr);
+ purple_prpl_got_user_status(account, buddy_name,
+ jabber_buddy_state_get_status_id(jbr->state),
+ "priority", jbr->priority,
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/roster.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/roster.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/roster.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/roster.c 2013-08-17 00:09:16.245807467 -0300
+@@ -27,8 +27,6 @@
+
+ #include "buddy.h"
+ #include "chat.h"
+-#include "google/google.h"
+-#include "google/google_roster.h"
+ #include "presence.h"
+ #include "roster.h"
+ #include "iq.h"
+@@ -83,11 +81,6 @@
+ iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
+ query = xmlnode_get_child(iq->node, "query");
+
+- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
+- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
+- xmlnode_set_attrib(query, "gr:ext", "2");
+- }
+-
+ jabber_iq_set_callback(iq, roster_request_cb, NULL);
+ jabber_iq_send(iq);
+ }
+@@ -244,10 +237,6 @@
+ } else {
+ GSList *groups = NULL;
+
+- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
+- if (!jabber_google_roster_incoming(js, item))
+- continue;
+-
+ for(group = xmlnode_get_child(item, "group"); group; group = xmlnode_get_next_twin(group)) {
+ char *group_name = xmlnode_get_data(group);
+
+@@ -349,11 +338,6 @@
+
+ g_slist_free(groups);
+
+- if (js->server_caps & JABBER_CAP_GOOGLE_ROSTER) {
+- jabber_google_roster_outgoing(js, query, item);
+- xmlnode_set_attrib(query, "xmlns:gr", NS_GOOGLE_ROSTER);
+- xmlnode_set_attrib(query, "gr:ext", "2");
+- }
+ jabber_iq_send(iq);
+ }
+
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/win32/posix.uname.c pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/posix.uname.c
+--- pidgin-2.10.7/libpurple/protocols/jabber/win32/posix.uname.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/posix.uname.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,141 +0,0 @@
+-/*
+- posix.uname.c - version 1.1
+- Copyright (C) 1999, 2000
+- Earnie Boyd and assigns
+-
+- Fills the utsname structure with the appropriate values.
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU Lesser General Public License as published
+- by the Free Software Foundation; either version 2.1, 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 PARTICUALR PURPOSE. See the
+- GNU Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software Foundation,
+- Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301, USA.
+- */
+-
+-/*
+- Send bug reports to Earnie Boyd <earnie_boyd@yahoo.com>
+- */
+-
+-#include "utsname.h"
+-#include <string.h>
+-#include <stdio.h>
+-
+-#include <glib.h>
+-
+-/* ANONYMOUS unions and structs are used from the windows header definitions.
+- These need to be defined for them to work correctly with gcc2.95.2-mingw. */
+-/*#define _ANONYMOUS_STRUCT*/
+-/*#define _ANONYMOUS_UNION*/
+-#include <windows.h>
+-#ifdef __MINGW32__
+-#include <_mingw.h>
+-#endif
+-
+-int
+-jabber_win32_uname( struct utsname *uts )
+-{
+- DWORD sLength;
+- OSVERSIONINFO OS_version;
+- SYSTEM_INFO System_Info;
+-
+-/* XXX Should these be in the global runtime */
+- enum WinOS {Win95, Win98, WinNT, unknown};
+- int MingwOS;
+-
+- memset( uts, 0, sizeof ( *uts ) );
+- OS_version.dwOSVersionInfoSize = sizeof( OSVERSIONINFO );
+-
+- GetVersionEx ( &OS_version );
+- GetSystemInfo ( &System_Info );
+-
+- g_strlcpy( uts->sysname, "WIN32_" , sizeof(uts->sysname));
+- switch( OS_version.dwPlatformId )
+- {
+- case VER_PLATFORM_WIN32_NT:
+- g_strlcat( uts->sysname, "WinNT", sizeof(uts->sysname) );
+- MingwOS = WinNT;
+- break;
+- case VER_PLATFORM_WIN32_WINDOWS:
+- switch ( OS_version.dwMinorVersion )
+- {
+- case 0:
+- g_strlcat( uts->sysname, "Win95", sizeof(uts->sysname) );
+- MingwOS = Win95;
+- break;
+- case 10:
+- g_strlcat( uts->sysname, "Win98", sizeof(uts->sysname) );
+- MingwOS = Win98;
+- break;
+- default:
+- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
+- MingwOS = unknown;
+- break;
+- }
+- break;
+- default:
+- g_strlcat( uts->sysname, "Win??", sizeof(uts->sysname) );
+- MingwOS = unknown;
+- break;
+- }
+-
+-#ifdef __MINGW32__
+- sprintf( uts->version, "%i", __MINGW32_MAJOR_VERSION );
+- sprintf( uts->release, "%i", __MINGW32_MINOR_VERSION );
+-#endif
+-
+- switch( System_Info.wProcessorArchitecture )
+- {
+- case PROCESSOR_ARCHITECTURE_PPC:
+- g_strlcpy( uts->machine, "ppc" , sizeof( uts->machine ) );
+- break;
+- case PROCESSOR_ARCHITECTURE_ALPHA:
+- g_strlcpy( uts->machine, "alpha" , sizeof( uts->machine ) );
+- break;
+- case PROCESSOR_ARCHITECTURE_MIPS:
+- g_strlcpy( uts->machine, "mips" , sizeof( uts->machine ) );
+- break;
+- case PROCESSOR_ARCHITECTURE_INTEL:
+- /* dwProcessorType is only valid in Win95 and Win98
+- wProcessorLevel is only valid in WinNT */
+- switch( MingwOS )
+- {
+- case Win95:
+- case Win98:
+- switch( System_Info.dwProcessorType )
+- {
+- case PROCESSOR_INTEL_386:
+- case PROCESSOR_INTEL_486:
+- case PROCESSOR_INTEL_PENTIUM:
+- sprintf( uts->machine, "i%ld", System_Info.dwProcessorType );
+- break;
+- default:
+- g_strlcpy( uts->machine, "i386" , sizeof( uts->machine ) );
+- break;
+- }
+- break;
+- case WinNT:
+- sprintf( uts->machine, "i%d86", System_Info.wProcessorLevel );
+- break;
+- default:
+- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
+- break;
+- }
+- break;
+- default:
+- g_strlcpy( uts->machine, "unknown" , sizeof( uts->machine ) );
+- break;
+- }
+-
+- sLength = sizeof ( uts->nodename ) - 1;
+- GetComputerNameA( uts->nodename, &sLength );
+- return 1;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/jabber/win32/utsname.h pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/utsname.h
+--- pidgin-2.10.7/libpurple/protocols/jabber/win32/utsname.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/jabber/win32/utsname.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,24 +0,0 @@
+-#ifndef _SYS_UTSNAME_H
+-#define _SYS_UTSNAME_H
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-struct utsname
+-{
+- char sysname[20];
+- char nodename[20];
+- char release[20];
+- char version[20];
+- char machine[20];
+-};
+-
+-int jabber_win32_uname (struct utsname *);
+-#define uname(utsname) jabber_win32_uname(utsname)
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/Makefile.am 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.am 2013-08-16 22:37:55.011207011 -0300
+@@ -1,5 +1,5 @@
+ EXTRA_DIST = Makefile.mingw
+
+-DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr
++DIST_SUBDIRS = bonjour irc jabber null silc silc10 simple zephyr
+
+ SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/Makefile.in 2013-02-11 07:17:19.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.in 2013-08-16 23:50:36.651423353 -0300
+@@ -160,8 +160,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -223,8 +221,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+@@ -365,7 +361,7 @@
+ top_builddir = @top_builddir@
+ top_srcdir = @top_srcdir@
+ EXTRA_DIST = Makefile.mingw
+-DIST_SUBDIRS = bonjour gg irc jabber msn myspace mxit novell null oscar sametime silc silc10 simple yahoo zephyr
++DIST_SUBDIRS = bonjour irc jabber null silc silc10 simple zephyr
+ SUBDIRS = $(DYNAMIC_PRPLS) $(STATIC_PRPLS)
+ all: all-recursive
+
+diff -Nur pidgin-2.10.7/libpurple/protocols/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/Makefile.mingw 2013-02-11 07:16:51.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,29 +0,0 @@
+-# Makefile.mingw
+-#
+-# Author: hermanator12002@yahoo.com
+-# Date 9/11/02
+-# Description: Protocols Makefile for win32 (mingw) port of libpurple
+-#
+-
+-PIDGIN_TREE_TOP := ../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-SUBDIRS = gg irc jabber msn mxit novell null oscar sametime silc simple yahoo bonjour myspace
+-
+-.PHONY: all install clean
+-
+-all:
+- for subdir in $(SUBDIRS); do \
+- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) || exit 1; \
+- done;
+-
+-install: all
+- for subdir in $(SUBDIRS); do \
+- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) install || exit 1; \
+- done;
+-
+-clean:
+- for subdir in $(SUBDIRS); do \
+- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) clean || exit 1; \
+- done;
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/cmdproc.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.c
+--- pidgin-2.10.7/libpurple/protocols/msn/cmdproc.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,339 +0,0 @@
+-/**
+- * @file cmdproc.c MSN command processor functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "cmdproc.h"
+-#include "error.h"
+-
+-MsnCmdProc *
+-msn_cmdproc_new(MsnSession *session)
+-{
+- MsnCmdProc *cmdproc;
+-
+- cmdproc = g_new0(MsnCmdProc, 1);
+-
+- cmdproc->session = session;
+- cmdproc->txqueue = g_queue_new();
+- cmdproc->history = msn_history_new();
+-
+- cmdproc->multiparts = g_hash_table_new_full(g_str_hash, g_str_equal,
+- NULL, (GDestroyNotify)msn_message_unref);
+-
+- return cmdproc;
+-}
+-
+-void
+-msn_cmdproc_destroy(MsnCmdProc *cmdproc)
+-{
+- MsnTransaction *trans;
+-
+- while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
+- msn_transaction_destroy(trans);
+-
+- g_queue_free(cmdproc->txqueue);
+-
+- msn_history_destroy(cmdproc->history);
+-
+- if (cmdproc->last_cmd != NULL)
+- msn_command_unref(cmdproc->last_cmd);
+-
+- g_hash_table_destroy(cmdproc->multiparts);
+-
+- g_free(cmdproc);
+-}
+-
+-void
+-msn_cmdproc_process_queue(MsnCmdProc *cmdproc)
+-{
+- MsnTransaction *trans;
+-
+- while ((trans = g_queue_pop_head(cmdproc->txqueue)) != NULL)
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-void
+-msn_cmdproc_queue_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
+-{
+- g_return_if_fail(cmdproc != NULL);
+- g_return_if_fail(trans != NULL);
+-
+- g_queue_push_tail(cmdproc->txqueue, trans);
+-}
+-
+-static void
+-show_debug_cmd(MsnCmdProc *cmdproc, gboolean incoming, const char *command)
+-{
+- MsnServConn *servconn;
+- const char *names[] = { "NS", "SB" };
+- char *show;
+- char tmp;
+- size_t len;
+-
+- servconn = cmdproc->servconn;
+- len = strlen(command);
+- show = g_strdup(command);
+-
+- tmp = (incoming) ? 'S' : 'C';
+-
+- if ((show[len - 1] == '\n') && (show[len - 2] == '\r'))
+- {
+- show[len - 2] = '\0';
+- }
+-
+- purple_debug_misc("msn", "%c: %s %03d: %s\n", tmp,
+- names[servconn->type], servconn->num, show);
+-
+- g_free(show);
+-}
+-
+-gboolean
+-msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans)
+-{
+- MsnServConn *servconn;
+- char *data;
+- size_t len;
+- gboolean ret;
+-
+- g_return_val_if_fail(cmdproc != NULL, TRUE);
+- g_return_val_if_fail(trans != NULL, TRUE);
+-
+- servconn = cmdproc->servconn;
+-
+- if (!servconn->connected) {
+- msn_transaction_destroy(trans);
+- return FALSE;
+- }
+-
+- if (trans->saveable)
+- msn_history_add(cmdproc->history, trans);
+-
+- data = msn_transaction_to_string(trans);
+-
+- len = strlen(data);
+-
+- show_debug_cmd(cmdproc, FALSE, data);
+-
+- if (trans->callbacks == NULL)
+- trans->callbacks = g_hash_table_lookup(cmdproc->cbs_table->cmds,
+- trans->command);
+-
+- if (trans->payload != NULL)
+- {
+- data = g_realloc(data, len + trans->payload_len);
+- memcpy(data + len, trans->payload, trans->payload_len);
+- len += trans->payload_len;
+-
+- /*
+- * We're done with trans->payload. Free it so that the memory
+- * doesn't sit around in cmdproc->history.
+- */
+- g_free(trans->payload);
+- trans->payload = NULL;
+- trans->payload_len = 0;
+- }
+-
+- ret = msn_servconn_write(servconn, data, len) != -1;
+-
+- if (!trans->saveable)
+- msn_transaction_destroy(trans);
+- g_free(data);
+- return ret;
+-}
+-
+-void
+-msn_cmdproc_process_payload(MsnCmdProc *cmdproc, char *payload,
+- int payload_len)
+-{
+- MsnCommand *last;
+-
+- g_return_if_fail(cmdproc != NULL);
+-
+- last = cmdproc->last_cmd;
+- last->payload = g_memdup(payload, payload_len);
+- last->payload_len = payload_len;
+-
+- if (last->payload_cb != NULL)
+- last->payload_cb(cmdproc, last, payload, payload_len);
+-}
+-
+-void
+-msn_cmdproc_process_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnMsgTypeCb cb;
+- const char *message_id = NULL;
+-
+- /* Multi-part messages */
+- message_id = msn_message_get_header_value(msg, "Message-ID");
+- if (message_id != NULL) {
+- /* This is the first in a series of chunks */
+-
+- const char *chunk_text = msn_message_get_header_value(msg, "Chunks");
+- guint chunk;
+- if (chunk_text != NULL) {
+- chunk = strtol(chunk_text, NULL, 10);
+- /* 1024 chunks of ~1300 bytes is ~1MB, which seems OK to prevent
+- some random client causing pidgin to hog a ton of memory.
+- Probably should figure out the maximum that the official client
+- actually supports, though. */
+- if (chunk > 0 && chunk < 1024) {
+- msg->total_chunks = chunk;
+- msg->received_chunks = 1;
+- g_hash_table_insert(cmdproc->multiparts, (gpointer)message_id, msn_message_ref(msg));
+- purple_debug_info("msn", "Received chunked message, message_id: '%s', total chunks: %d\n",
+- message_id, chunk);
+- } else {
+- purple_debug_error("msn", "MessageId '%s' has too many chunks: %d\n", message_id, chunk);
+- }
+- return;
+- } else {
+- chunk_text = msn_message_get_header_value(msg, "Chunk");
+- if (chunk_text != NULL) {
+- /* This is one chunk in a series of chunks */
+-
+- MsnMessage *first = g_hash_table_lookup(cmdproc->multiparts, message_id);
+- chunk = strtol(chunk_text, NULL, 10);
+- if (first != NULL) {
+- if (first->received_chunks != chunk) {
+- /*
+- * We received an out of order chunk number (i.e. not the
+- * next one in the sequence). Not sure if this can happen
+- * legitimately, but we definitely don't handle it right
+- * now.
+- */
+- g_hash_table_remove(cmdproc->multiparts, message_id);
+- return;
+- }
+-
+- /* Chunk is from 1 to total-1 (doesn't count first one) */
+- purple_debug_info("msn", "Received chunk %d of %d, message_id: '%s'\n",
+- chunk + 1, first->total_chunks, message_id);
+- first->body = g_realloc(first->body, first->body_len + msg->body_len);
+- memcpy(first->body + first->body_len, msg->body, msg->body_len);
+- first->body_len += msg->body_len;
+- first->received_chunks++;
+- if (first->received_chunks != first->total_chunks)
+- /* We're waiting for more chunks */
+- return;
+-
+- /*
+- * We have all the chunks for this message, great! Send
+- * it along... The caller takes care of freeing the old one.
+- */
+- msg = first;
+- } else {
+- purple_debug_error("msn",
+- "Unable to find first chunk of message_id '%s' to correspond with chunk %d.\n",
+- message_id, chunk + 1);
+- }
+- } else {
+- purple_debug_error("msn", "Received MessageId '%s' with no chunk number!\n", message_id);
+- }
+- }
+- }
+-
+- if (msn_message_get_content_type(msg) == NULL)
+- {
+- purple_debug_misc("msn", "failed to find message content\n");
+- return;
+- }
+-
+- cb = g_hash_table_lookup(cmdproc->cbs_table->msgs,
+- msn_message_get_content_type(msg));
+-
+- if (cb != NULL)
+- cb(cmdproc, msg);
+- else
+- purple_debug_warning("msn", "Unhandled content-type '%s'\n",
+- msn_message_get_content_type(msg));
+-
+- if (message_id != NULL)
+- g_hash_table_remove(cmdproc->multiparts, message_id);
+-}
+-
+-void
+-msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnTransCb cb = NULL;
+- MsnTransaction *trans = NULL;
+-
+- if (cmd->trId)
+- cmd->trans = trans = msn_history_find(cmdproc->history, cmd->trId);
+-
+- if (trans != NULL)
+- if (trans->timer) {
+- purple_timeout_remove(trans->timer);
+- trans->timer = 0;
+- }
+-
+- if (g_ascii_isdigit(cmd->command[0]) && trans != NULL)
+- {
+- MsnErrorCb error_cb;
+- int error;
+-
+- error = atoi(cmd->command);
+-
+- error_cb = trans->error_cb;
+- if (error_cb == NULL)
+- error_cb = g_hash_table_lookup(cmdproc->cbs_table->errors, trans->command);
+-
+- if (error_cb != NULL)
+- error_cb(cmdproc, trans, error);
+- else
+- msn_error_handle(cmdproc->session, error);
+-
+- return;
+- }
+-
+- cb = g_hash_table_lookup(cmdproc->cbs_table->async, cmd->command);
+-
+- if (cb == NULL && trans != NULL && trans->callbacks != NULL)
+- cb = g_hash_table_lookup(trans->callbacks, cmd->command);
+-
+- if (cb == NULL)
+- cb = g_hash_table_lookup(cmdproc->cbs_table->fallback, cmd->command);
+-
+- if (cb != NULL)
+- cb(cmdproc, cmd);
+- else
+- purple_debug_warning("msn", "Unhandled command '%s'\n",
+- cmd->command);
+-
+- if (trans != NULL && trans->pendent_cmd != NULL)
+- msn_transaction_unqueue_cmd(trans, cmdproc);
+-}
+-
+-void
+-msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command)
+-{
+- show_debug_cmd(cmdproc, TRUE, command);
+-
+- if (cmdproc->last_cmd != NULL)
+- msn_command_unref(cmdproc->last_cmd);
+-
+- cmdproc->last_cmd = msn_command_from_string(command);
+-
+- msn_cmdproc_process_cmd(cmdproc, cmdproc->last_cmd);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/cmdproc.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.h
+--- pidgin-2.10.7/libpurple/protocols/msn/cmdproc.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/cmdproc.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,100 +0,0 @@
+-/**
+- * @file cmdproc.h MSN command processor functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_CMDPROC_H
+-#define MSN_CMDPROC_H
+-
+-typedef struct _MsnCmdProc MsnCmdProc;
+-
+-#include "command.h"
+-#include "history.h"
+-#include "servconn.h"
+-#include "session.h"
+-#include "table.h"
+-
+-struct _MsnCmdProc
+-{
+- MsnSession *session;
+- MsnServConn *servconn;
+-
+- GQueue *txqueue;
+-
+- MsnCommand *last_cmd;
+-
+- MsnTable *cbs_table;
+-
+- MsnHistory *history;
+-
+- GHashTable *multiparts; /**< Multi-part message ID's */
+-
+- void *data; /**< Extra data, like the switchboard. */
+-};
+-
+-/**
+- * Creates a MsnCmdProc structure.
+- *
+- * @param session The session to associate with.
+- *
+- * @return A new MsnCmdProc structure.
+- */
+-MsnCmdProc *msn_cmdproc_new(MsnSession *session);
+-
+-/**
+- * Destroys an MsnCmdProc.
+- *
+- * @param cmdproc The object structure.
+- */
+-void msn_cmdproc_destroy(MsnCmdProc *cmdproc);
+-
+-/**
+- * Process the queued transactions.
+- *
+- * @param cmdproc The MsnCmdProc.
+- */
+-void msn_cmdproc_process_queue(MsnCmdProc *cmdproc);
+-
+-/**
+- * Sends transaction using this servconn.
+- *
+- * @param cmdproc The MsnCmdProc to be used.
+- * @param trans The MsnTransaction to be sent.
+- */
+-gboolean msn_cmdproc_send_trans(MsnCmdProc *cmdproc, MsnTransaction *trans);
+-
+-/**
+- * Add a transaction to the queue to be processed latter.
+- *
+- * @param cmdproc The MsnCmdProc in which the transaction will be queued.
+- * @param trans The MsnTransaction to be queued.
+- */
+-void msn_cmdproc_queue_trans(MsnCmdProc *cmdproc,
+- MsnTransaction *trans);
+-
+-void msn_cmdproc_process_msg(MsnCmdProc *cmdproc,
+- MsnMessage *msg);
+-void msn_cmdproc_process_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd);
+-void msn_cmdproc_process_cmd_text(MsnCmdProc *cmdproc, const char *command);
+-void msn_cmdproc_process_payload(MsnCmdProc *cmdproc,
+- char *payload, int payload_len);
+-
+-#endif /* MSN_CMDPROC_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/command.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.c
+--- pidgin-2.10.7/libpurple/protocols/msn/command.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,113 +0,0 @@
+-/**
+- * @file command.c MSN command functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "internal.h"
+-
+-#include "command.h"
+-
+-static gboolean
+-is_num(const char *str)
+-{
+- const char *c;
+- for (c = str; *c; c++) {
+- if (!(g_ascii_isdigit(*c)))
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-MsnCommand *
+-msn_command_from_string(const char *string)
+-{
+- MsnCommand *cmd;
+- char *param_start;
+-
+- g_return_val_if_fail(string != NULL, NULL);
+-
+- cmd = g_new0(MsnCommand, 1);
+- cmd->command = g_strdup(string);
+- param_start = strchr(cmd->command, ' ');
+-
+- if (param_start)
+- {
+- *param_start++ = '\0';
+- cmd->params = g_strsplit_set(param_start, " ", 0);
+- }
+-
+- if (cmd->params != NULL)
+- {
+- int c;
+-
+- for (c = 0; cmd->params[c] && cmd->params[c][0]; c++);
+- cmd->param_count = c;
+-
+- if (cmd->param_count) {
+- char *param = cmd->params[0];
+- cmd->trId = is_num(param) ? atoi(param) : 0;
+- } else {
+- cmd->trId = 0;
+- }
+- }
+- else
+- {
+- cmd->trId = 0;
+- }
+-
+- msn_command_ref(cmd);
+-
+- return cmd;
+-}
+-
+-static void
+-msn_command_destroy(MsnCommand *cmd)
+-{
+- g_free(cmd->payload);
+- g_free(cmd->command);
+- g_strfreev(cmd->params);
+- g_free(cmd);
+-}
+-
+-MsnCommand *
+-msn_command_ref(MsnCommand *cmd)
+-{
+- g_return_val_if_fail(cmd != NULL, NULL);
+-
+- cmd->ref_count++;
+- return cmd;
+-}
+-
+-void
+-msn_command_unref(MsnCommand *cmd)
+-{
+- g_return_if_fail(cmd != NULL);
+- g_return_if_fail(cmd->ref_count > 0);
+-
+- cmd->ref_count--;
+-
+- if (cmd->ref_count == 0)
+- {
+- msn_command_destroy(cmd);
+- }
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/command.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.h
+--- pidgin-2.10.7/libpurple/protocols/msn/command.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/command.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,84 +0,0 @@
+-/**
+- * @file command.h MSN command functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_COMMAND_H
+-#define MSN_COMMAND_H
+-
+-typedef struct _MsnCommand MsnCommand;
+-
+-#include "cmdproc.h"
+-#include "transaction.h"
+-
+-typedef void (*MsnPayloadCb)(MsnCmdProc *cmdproc, MsnCommand *cmd,
+- char *payload, size_t len);
+-
+-/**
+- * A received command.
+- */
+-struct _MsnCommand
+-{
+- unsigned int trId;
+-
+- char *command;
+- char **params;
+- int param_count;
+-
+- guint ref_count;
+-
+- MsnTransaction *trans;
+-
+- char *payload;
+- size_t payload_len;
+-
+- MsnPayloadCb payload_cb;
+- void *payload_cbdata;
+-};
+-
+-/**
+- * Create a command object from the incoming string and ref it.
+- *
+- * @param string The incoming string.
+- *
+- * @return A MsnCommand object.
+- */
+-MsnCommand *msn_command_from_string(const char *string);
+-
+-/**
+- * Increment the ref count.
+- *
+- * @param cmd The MsnCommand to be ref.
+- *
+- * @return The ref command.
+- */
+-MsnCommand *msn_command_ref(MsnCommand *cmd);
+-
+-/**
+- * Decrement the ref count. If the count goes to 0, destroy it.
+- *
+- * @param cmd The MsnCommand to be unref.
+- *
+- */
+-void msn_command_unref(MsnCommand *cmd);
+-
+-#endif /* MSN_COMMAND_H */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/contact.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.c
+--- pidgin-2.10.7/libpurple/protocols/msn/contact.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2044 +0,0 @@
+-/**
+- * @file contact.c
+- * get MSN contacts via SOAP request
+- * created by MaYuan<mayuan2006@gmail.com>
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "contact.h"
+-#include "xmlnode.h"
+-#include "group.h"
+-#include "msnutils.h"
+-#include "soap.h"
+-#include "nexus.h"
+-#include "user.h"
+-
+-const char *MsnSoapPartnerScenarioText[] =
+-{
+- "Initial",
+- "ContactSave",
+- "MessengerPendingList",
+- "ContactMsgrAPI",
+- "BlockUnblock",
+- "Timer"
+-};
+-
+-const char *MsnMemberRole[] =
+-{
+- "Forward",
+- "Allow",
+- "Block",
+- "Reverse",
+- "Pending"
+-};
+-
+-typedef struct {
+- MsnSession *session;
+- MsnSoapPartnerScenario which;
+-} GetContactListCbData;
+-
+-MsnCallbackState *
+-msn_callback_state_new(MsnSession *session)
+-{
+- MsnCallbackState *state = g_new0(MsnCallbackState, 1);
+-
+- state->session = session;
+-
+- return state;
+-}
+-
+-MsnCallbackState *
+-msn_callback_state_dup(MsnCallbackState *state)
+-{
+- MsnCallbackState *new_state = g_new0(MsnCallbackState, 1);
+-
+- new_state->session = state->session;
+- new_state->who = g_strdup(state->who);
+- new_state->uid = g_strdup(state->uid);
+- new_state->old_group_name = g_strdup(state->old_group_name);
+- new_state->new_group_name = g_strdup(state->new_group_name);
+- new_state->guid = g_strdup(state->guid);
+- /* The rest should be made new */
+-
+- return new_state;
+-}
+-
+-void
+-msn_callback_state_free(MsnCallbackState *state)
+-{
+- if (state == NULL)
+- return;
+-
+- g_free(state->who);
+- g_free(state->uid);
+- g_free(state->old_group_name);
+- g_free(state->new_group_name);
+- g_free(state->guid);
+- xmlnode_free(state->body);
+-
+- g_free(state);
+-}
+-
+-void
+-msn_callback_state_set_who(MsnCallbackState *state, const gchar *who)
+-{
+- g_return_if_fail(state != NULL);
+-
+- g_free(state->who);
+- state->who = g_strdup(who);
+-}
+-
+-void
+-msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid)
+-{
+- g_return_if_fail(state != NULL);
+-
+- g_free(state->uid);
+- state->uid = g_strdup(uid);
+-}
+-
+-void
+-msn_callback_state_set_old_group_name(MsnCallbackState *state, const gchar *old_group_name)
+-{
+- g_return_if_fail(state != NULL);
+-
+- g_free(state->old_group_name);
+- state->old_group_name = g_strdup(old_group_name);
+-}
+-
+-void
+-msn_callback_state_set_new_group_name(MsnCallbackState *state, const gchar *new_group_name)
+-{
+- g_return_if_fail(state != NULL);
+-
+- g_free(state->new_group_name);
+- state->new_group_name = g_strdup(new_group_name);
+-}
+-
+-void
+-msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid)
+-{
+- g_return_if_fail(state != NULL);
+-
+- g_free(state->guid);
+- state->guid = g_strdup(guid);
+-}
+-
+-
+-void
+-msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id)
+-{
+- g_return_if_fail(state != NULL);
+-
+- state->list_id = list_id;
+-}
+-
+-void
+-msn_callback_state_set_action(MsnCallbackState *state, MsnCallbackAction action)
+-{
+- g_return_if_fail(state != NULL);
+-
+- state->action |= action;
+-}
+-
+-/***************************************************************
+- * General SOAP handling
+- ***************************************************************/
+-
+-static const char *
+-msn_contact_operation_str(MsnCallbackAction action)
+-{
+- /* Make sure this is large enough when adding more */
+- static char buf[BUF_LEN];
+- buf[0] = '\0';
+-
+- if (action & MSN_ADD_BUDDY)
+- strcat(buf, "Adding Buddy,");
+- if (action & MSN_MOVE_BUDDY)
+- strcat(buf, "Moving Buddy,");
+- if (action & MSN_ACCEPTED_BUDDY)
+- strcat(buf, "Accepted Buddy,");
+- if (action & MSN_DENIED_BUDDY)
+- strcat(buf, "Denied Buddy,");
+- if (action & MSN_ADD_GROUP)
+- strcat(buf, "Adding Group,");
+- if (action & MSN_DEL_GROUP)
+- strcat(buf, "Deleting Group,");
+- if (action & MSN_RENAME_GROUP)
+- strcat(buf, "Renaming Group,");
+- if (action & MSN_UPDATE_INFO)
+- strcat(buf, "Updating Contact Info,");
+- if (action & MSN_ANNOTATE_USER)
+- strcat(buf, "Annotating Contact,");
+-
+- return buf;
+-}
+-
+-static gboolean msn_contact_request(MsnCallbackState *state);
+-
+-static void
+-msn_contact_request_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- xmlnode *fault;
+- char *faultcode_str;
+- xmlnode *cachekey;
+- char *changed;
+-
+- if (resp == NULL) {
+- purple_debug_error("msn",
+- "Operation {%s} failed. No response received from server.\n",
+- msn_contact_operation_str(state->action));
+- msn_session_set_error(state->session, MSN_ERROR_BAD_BLIST, NULL);
+- msn_callback_state_free(state);
+- return;
+- }
+-
+- /* Update CacheKey if necessary */
+- cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKeyChanged");
+- if (cachekey != NULL) {
+- changed = xmlnode_get_data(cachekey);
+- if (changed && !strcmp(changed, "true")) {
+- cachekey = xmlnode_get_child(resp->xml, "Header/ServiceHeader/CacheKey");
+- g_free(state->session->abch_cachekey);
+- state->session->abch_cachekey = xmlnode_get_data(cachekey);
+- purple_debug_info("msn", "Updated CacheKey for %s to '%s'.\n",
+- purple_account_get_username(state->session->account),
+- state->session->abch_cachekey);
+- }
+- g_free(changed);
+- }
+-
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+-
+- if (fault == NULL) {
+- /* No errors */
+- if (state->cb)
+- state->cb(req, resp, data);
+- msn_callback_state_free(state);
+- return;
+- }
+-
+- faultcode_str = xmlnode_get_data(xmlnode_get_child(fault, "faultcode"));
+-
+- if (faultcode_str && g_str_equal(faultcode_str, "q0:BadContextToken")) {
+- purple_debug_info("msn",
+- "Contact Operation {%s} failed because of bad token."
+- " Updating token now and retrying operation.\n",
+- msn_contact_operation_str(state->action));
+- /* Token has expired, so renew it, and try again later */
+- msn_nexus_update_token(state->session->nexus, MSN_AUTH_CONTACTS,
+- (GSourceFunc)msn_contact_request, data);
+- }
+- else
+- {
+- if (state->cb) {
+- state->cb(req, resp, data);
+- } else {
+- /* We don't know how to respond to this faultcode, so log it */
+- char *str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), str);
+- g_free(str);
+- }
+- msn_callback_state_free(state);
+- }
+-
+- g_free(faultcode_str);
+-}
+-
+-static gboolean
+-msn_contact_request(MsnCallbackState *state)
+-{
+- xmlnode *cachekey = xmlnode_get_child(state->body,
+- "Header/ABApplicationHeader/CacheKey");
+- if (cachekey != NULL)
+- xmlnode_free(cachekey);
+- if (state->session->abch_cachekey != NULL) {
+- cachekey = xmlnode_new_child(xmlnode_get_child(state->body, "Header/ABApplicationHeader"), "CacheKey");
+- xmlnode_insert_data(cachekey, state->session->abch_cachekey, -1);
+- }
+- if (state->token == NULL)
+- state->token = xmlnode_get_child(state->body,
+- "Header/ABAuthHeader/TicketToken");
+- /* delete old & replace with new token */
+- xmlnode_free(state->token->child);
+- xmlnode_insert_data(state->token,
+- msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
+- msn_soap_message_send(state->session,
+- msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
+- MSN_CONTACT_SERVER, state->post_url, FALSE,
+- msn_contact_request_cb, state);
+- return FALSE;
+-}
+-
+-/***************************************************************
+- * Address Book and Membership List Operations
+- ***************************************************************/
+-
+-/*get MSN member role utility*/
+-static MsnListId
+-msn_get_memberrole(const char *role)
+-{
+- g_return_val_if_fail(role != NULL, 0);
+-
+- if (!strcmp(role,"Allow")) {
+- return MSN_LIST_AL;
+- } else if (!strcmp(role,"Block")) {
+- return MSN_LIST_BL;
+- } else if (!strcmp(role,"Reverse")) {
+- return MSN_LIST_RL;
+- } else if (!strcmp(role,"Pending")) {
+- return MSN_LIST_PL;
+- }
+- return 0;
+-}
+-
+-/* Create the AddressBook in the server, if we don't have one */
+-static void
+-msn_create_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- MsnCallbackState *state = data;
+- if (resp && xmlnode_get_child(resp->xml, "Body/Fault") == NULL) {
+- purple_debug_info("msn", "Address Book successfully created!\n");
+- msn_get_address_book(state->session, MSN_PS_INITIAL, NULL, NULL);
+- } else {
+- purple_debug_info("msn", "Address Book creation failed!\n");
+- }
+-}
+-
+-static void
+-msn_create_address_book(MsnSession *session)
+-{
+- gchar *body;
+- MsnCallbackState *state;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->user != NULL);
+- g_return_if_fail(session->user->passport != NULL);
+-
+- purple_debug_info("msn", "Creating an Address Book.\n");
+-
+- body = g_strdup_printf(MSN_ADD_ADDRESSBOOK_TEMPLATE,
+- session->user->passport);
+-
+- state = msn_callback_state_new(session);
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_ADD_ADDRESSBOOK_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_create_address_cb;
+- msn_contact_request(state);
+-
+- g_free(body);
+-}
+-
+-static void
+-msn_parse_each_member(MsnSession *session, xmlnode *member, const char *node,
+- MsnListId list)
+-{
+- char *passport;
+- char *type;
+- char *member_id;
+- MsnUser *user;
+- xmlnode *annotation;
+- guint nid = MSN_NETWORK_UNKNOWN;
+- char *invite = NULL;
+-
+- passport = xmlnode_get_data(xmlnode_get_child(member, node));
+- if (!msn_email_is_valid(passport)) {
+- g_free(passport);
+- return;
+- }
+-
+- type = xmlnode_get_data(xmlnode_get_child(member, "Type"));
+- member_id = xmlnode_get_data(xmlnode_get_child(member, "MembershipId"));
+-
+- user = msn_userlist_find_add_user(session->userlist, passport, NULL);
+-
+- for (annotation = xmlnode_get_child(member, "Annotations/Annotation");
+- annotation;
+- annotation = xmlnode_get_next_twin(annotation)) {
+- char *name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
+- char *value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
+- if (name && value) {
+- if (!strcmp(name, "MSN.IM.BuddyType")) {
+- nid = strtoul(value, NULL, 10);
+- }
+- else if (!strcmp(name, "MSN.IM.InviteMessage")) {
+- invite = value;
+- value = NULL;
+- }
+- }
+- g_free(name);
+- g_free(value);
+- }
+-
+- /* For EmailMembers, the network must be found in the annotations, above.
+- Otherwise, PassportMembers are on the Passport network. */
+- if (!strcmp(node, "PassportName"))
+- nid = MSN_NETWORK_PASSPORT;
+-
+- purple_debug_info("msn", "CL: %s name: %s, Type: %s, MembershipID: %s, NetworkID: %u\n",
+- node, passport, type, member_id == NULL ? "(null)" : member_id, nid);
+-
+- msn_user_set_network(user, nid);
+- msn_user_set_invite_message(user, invite);
+-
+- if (list == MSN_LIST_PL && member_id) {
+- user->member_id_on_pending_list = atoi(member_id);
+- }
+-
+- msn_got_lst_user(session, user, 1 << list, NULL);
+-
+- g_free(passport);
+- g_free(type);
+- g_free(member_id);
+- g_free(invite);
+-}
+-
+-static void
+-msn_parse_each_service(MsnSession *session, xmlnode *service)
+-{
+- xmlnode *type;
+-
+- if ((type = xmlnode_get_child(service, "Info/Handle/Type"))) {
+- char *type_str = xmlnode_get_data(type);
+-
+- if (g_str_equal(type_str, "Profile")) {
+- /* Process Windows Live 'Messenger Roaming Identity' */
+- } else if (g_str_equal(type_str, "Messenger")) {
+- xmlnode *lastchange = xmlnode_get_child(service, "LastChange");
+- char *lastchange_str = xmlnode_get_data(lastchange);
+- xmlnode *membership;
+-
+- purple_debug_info("msn", "CL last change: %s\n", lastchange_str);
+- purple_account_set_string(session->account, "CLLastChange",
+- lastchange_str);
+-
+- for (membership = xmlnode_get_child(service,
+- "Memberships/Membership");
+- membership; membership = xmlnode_get_next_twin(membership)) {
+-
+- xmlnode *role = xmlnode_get_child(membership, "MemberRole");
+- char *role_str = xmlnode_get_data(role);
+- MsnListId list = msn_get_memberrole(role_str);
+- xmlnode *member;
+-
+- purple_debug_info("msn", "CL MemberRole role: %s, list: %d\n",
+- role_str, list);
+-
+- for (member = xmlnode_get_child(membership, "Members/Member");
+- member; member = xmlnode_get_next_twin(member)) {
+- const char *member_type = xmlnode_get_attrib(member, "type");
+- if (g_str_equal(member_type, "PassportMember")) {
+- msn_parse_each_member(session, member, "PassportName",
+- list);
+- } else if (g_str_equal(member_type, "PhoneMember")) {
+-
+- } else if (g_str_equal(member_type, "EmailMember")) {
+- msn_parse_each_member(session, member, "Email", list);
+- }
+- }
+-
+- g_free(role_str);
+- }
+-
+- g_free(lastchange_str);
+- }
+-
+- g_free(type_str);
+- }
+-}
+-
+-/*parse contact list*/
+-static gboolean
+-msn_parse_contact_list(MsnSession *session, xmlnode *node)
+-{
+- xmlnode *fault, *faultnode;
+-
+- /* we may get a response if our cache data is too old:
+- *
+- * <faultstring>Need to do full sync. Can't sync deltas Client
+- * has too old a copy for us to do a delta sync</faultstring>
+- *
+- * this is not handled yet
+- */
+- if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
+- if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
+- char *faultstring = xmlnode_get_data(faultnode);
+- purple_debug_info("msn", "Retrieving contact list failed: %s\n",
+- faultstring);
+- g_free(faultstring);
+- }
+- if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
+- char *errorcode = xmlnode_get_data(faultnode);
+-
+- if (g_str_equal(errorcode, "ABDoesNotExist")) {
+- msn_create_address_book(session);
+- g_free(errorcode);
+- return FALSE;
+- }
+-
+- g_free(errorcode);
+- }
+-
+- msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
+- return FALSE;
+- } else {
+- xmlnode *service;
+-
+- for (service = xmlnode_get_child(node, "Body/FindMembershipResponse/"
+- "FindMembershipResult/Services/Service");
+- service; service = xmlnode_get_next_twin(service)) {
+- msn_parse_each_service(session, service);
+- }
+- return TRUE;
+- }
+-}
+-
+-static void
+-msn_get_contact_list_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session = state->session;
+-
+- g_return_if_fail(session != NULL);
+-
+- if (resp != NULL) {
+-#ifdef MSN_PARTIAL_LISTS
+- const char *abLastChange;
+- const char *dynamicItemLastChange;
+-#endif
+-
+- purple_debug_misc("msn", "Got the contact list!\n");
+-
+- if (msn_parse_contact_list(session, resp->xml)) {
+-#ifdef MSN_PARTIAL_LISTS
+- abLastChange = purple_account_get_string(session->account,
+- "ablastChange", NULL);
+- dynamicItemLastChange = purple_account_get_string(session->account,
+- "DynamicItemLastChanged", NULL);
+-#endif
+-
+- if (state->partner_scenario == MSN_PS_INITIAL) {
+-#ifdef MSN_PARTIAL_LISTS
+- /* XXX: this should be enabled when we can correctly do partial
+- syncs with the server. Currently we need to retrieve the whole
+- list to detect sync issues */
+- msn_get_address_book(session, MSN_PS_INITIAL, abLastChange, dynamicItemLastChange);
+-#else
+- msn_get_address_book(session, MSN_PS_INITIAL, NULL, NULL);
+-#endif
+- }
+- }
+- }
+-}
+-
+-/*SOAP get contact list*/
+-void
+-msn_get_contact_list(MsnSession *session,
+- const MsnSoapPartnerScenario partner_scenario, const char *update_time)
+-{
+- gchar *body = NULL;
+- gchar *update_str = NULL;
+- MsnCallbackState *state;
+- const gchar *partner_scenario_str = MsnSoapPartnerScenarioText[partner_scenario];
+-
+- purple_debug_misc("msn", "Getting Contact List.\n");
+-
+- if (update_time != NULL) {
+- purple_debug_info("msn", "CL Last update time: %s\n", update_time);
+- update_str = g_strdup_printf(MSN_GET_CONTACT_UPDATE_XML, update_time);
+- }
+-
+- body = g_strdup_printf(MSN_GET_CONTACT_TEMPLATE, partner_scenario_str,
+- update_str ? update_str : "");
+-
+- state = msn_callback_state_new(session);
+- state->partner_scenario = partner_scenario;
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_GET_CONTACT_SOAP_ACTION;
+- state->post_url = MSN_GET_CONTACT_POST_URL;
+- state->cb = msn_get_contact_list_cb;
+- msn_contact_request(state);
+-
+- g_free(update_str);
+- g_free(body);
+-}
+-
+-static void
+-msn_parse_addressbook_groups(MsnSession *session, xmlnode *node)
+-{
+- xmlnode *group;
+-
+- purple_debug_info("msn", "msn_parse_addressbook_groups()\n");
+-
+- for(group = xmlnode_get_child(node, "Group"); group;
+- group = xmlnode_get_next_twin(group)){
+- xmlnode *groupId, *groupInfo, *groupname;
+- char *group_id = NULL, *group_name = NULL;
+-
+- if ((groupId = xmlnode_get_child(group, "groupId")))
+- group_id = xmlnode_get_data(groupId);
+- if ((groupInfo = xmlnode_get_child(group, "groupInfo")) && (groupname = xmlnode_get_child(groupInfo, "name")))
+- group_name = xmlnode_get_data(groupname);
+-
+- if (group_id == NULL) {
+- /* Group of ungroupped buddies */
+- g_free(group_name);
+- continue;
+- }
+-
+- msn_group_new(session->userlist, group_id, group_name);
+-
+- purple_debug_info("msn", "AB group_id: %s, name: %s\n", group_id, group_name ? group_name : "(null)");
+- if ((purple_find_group(group_name)) == NULL) {
+- PurpleGroup *g = purple_group_new(group_name);
+- purple_blist_add_group(g, NULL);
+- }
+- g_free(group_id);
+- g_free(group_name);
+- }
+-}
+-
+-static gboolean
+-msn_parse_addressbook_mobile(xmlnode *contactInfo, char **inout_mobile_number)
+-{
+- xmlnode *phones;
+- char *mobile_number = NULL;
+- gboolean mobile = FALSE;
+-
+- *inout_mobile_number = NULL;
+-
+- if ((phones = xmlnode_get_child(contactInfo, "phones"))) {
+- xmlnode *contact_phone;
+- char *phone_type = NULL;
+-
+- for (contact_phone = xmlnode_get_child(phones, "ContactPhone");
+- contact_phone;
+- contact_phone = xmlnode_get_next_twin(contact_phone)) {
+- xmlnode *contact_phone_type;
+-
+- if (!(contact_phone_type =
+- xmlnode_get_child(contact_phone, "contactPhoneType")))
+- continue;
+-
+- phone_type = xmlnode_get_data(contact_phone_type);
+-
+- if (phone_type && !strcmp(phone_type, "ContactPhoneMobile")) {
+- xmlnode *number;
+-
+- if ((number = xmlnode_get_child(contact_phone, "number"))) {
+- xmlnode *messenger_enabled;
+- char *is_messenger_enabled = NULL;
+-
+- g_free(mobile_number);
+- mobile_number = xmlnode_get_data(number);
+-
+- if (mobile_number &&
+- (messenger_enabled = xmlnode_get_child(contact_phone, "isMessengerEnabled"))
+- && (is_messenger_enabled = xmlnode_get_data(messenger_enabled))
+- && !strcmp(is_messenger_enabled, "true"))
+- mobile = TRUE;
+-
+- g_free(is_messenger_enabled);
+- }
+- }
+-
+- g_free(phone_type);
+- }
+- }
+-
+- *inout_mobile_number = mobile_number;
+- return mobile;
+-}
+-
+-static void
+-msn_parse_addressbook_contacts(MsnSession *session, xmlnode *node)
+-{
+- xmlnode *contactNode;
+- char *passport = NULL, *Name = NULL, *uid = NULL, *type = NULL, *mobile_number = NULL, *alias = NULL;
+- gboolean mobile = FALSE;
+- PurpleConnection *pc = purple_account_get_connection(session->account);
+-
+- for(contactNode = xmlnode_get_child(node, "Contact"); contactNode;
+- contactNode = xmlnode_get_next_twin(contactNode)) {
+- xmlnode *contactId, *contactInfo, *contactType, *passportName, *displayName, *guid, *groupIds;
+- xmlnode *annotation;
+- MsnUser *user;
+-
+- g_free(passport);
+- g_free(Name);
+- g_free(uid);
+- g_free(type);
+- g_free(mobile_number);
+- g_free(alias);
+- passport = Name = uid = type = mobile_number = alias = NULL;
+- mobile = FALSE;
+-
+- if (!(contactId = xmlnode_get_child(contactNode,"contactId"))
+- || !(contactInfo = xmlnode_get_child(contactNode, "contactInfo"))
+- || !(contactType = xmlnode_get_child(contactInfo, "contactType")))
+- continue;
+-
+- uid = xmlnode_get_data(contactId);
+- type = xmlnode_get_data(contactType);
+-
+- /* Find out our settings */
+- if (type && !strcmp(type, "Me")) {
+- /* setup the Display Name */
+- if (purple_connection_get_display_name(pc) == NULL) {
+- char *friendly = NULL;
+- if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
+- friendly = xmlnode_get_data(displayName);
+- purple_connection_set_display_name(pc,
+- friendly ? purple_url_decode(friendly) : NULL);
+- g_free(friendly);
+- }
+-
+- for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
+- annotation;
+- annotation = xmlnode_get_next_twin(annotation)) {
+- char *name, *value;
+- name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
+- value = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
+- if (name && g_str_equal(name, "MSN.IM.MPOP")) {
+- if (!value || atoi(value) != 0)
+- session->enable_mpop = TRUE;
+- else
+- session->enable_mpop = FALSE;
+- }
+- g_free(name);
+- g_free(value);
+- }
+-
+- continue; /* Not adding own account as buddy to buddylist */
+- }
+-
+- passportName = xmlnode_get_child(contactInfo, "passportName");
+- if (passportName == NULL) {
+- xmlnode *emailsNode, *contactEmailNode, *emailNode;
+- xmlnode *messengerEnabledNode;
+- char *msnEnabled;
+-
+- /*TODO: add it to the non-instant Messenger group and recognize as email Membership*/
+- /* Yahoo/Federated User? */
+- emailsNode = xmlnode_get_child(contactInfo, "emails");
+- if (emailsNode == NULL) {
+- /*TODO: need to support the Mobile type*/
+- continue;
+- }
+- for (contactEmailNode = xmlnode_get_child(emailsNode, "ContactEmail");
+- contactEmailNode;
+- contactEmailNode = xmlnode_get_next_twin(contactEmailNode)) {
+- if ((messengerEnabledNode = xmlnode_get_child(contactEmailNode, "isMessengerEnabled"))) {
+-
+- msnEnabled = xmlnode_get_data(messengerEnabledNode);
+-
+- if (msnEnabled && !strcmp(msnEnabled, "true")) {
+- if ((emailNode = xmlnode_get_child(contactEmailNode, "email")))
+- passport = xmlnode_get_data(emailNode);
+-
+- /* Messenger enabled, Get the Passport*/
+- purple_debug_info("msn", "AB Yahoo/Federated User %s\n", passport ? passport : "(null)");
+- g_free(msnEnabled);
+- break;
+- }
+-
+- g_free(msnEnabled);
+- }
+- }
+- } else {
+- xmlnode *messenger_user;
+- /* ignore non-messenger contacts */
+- if ((messenger_user = xmlnode_get_child(contactInfo, "isMessengerUser"))) {
+- char *is_messenger_user = xmlnode_get_data(messenger_user);
+-
+- if (is_messenger_user && !strcmp(is_messenger_user, "false")) {
+- g_free(is_messenger_user);
+- continue;
+- }
+-
+- g_free(is_messenger_user);
+- }
+-
+- passport = xmlnode_get_data(passportName);
+- }
+-
+- /* Couldn't find anything */
+- if (passport == NULL)
+- continue;
+-
+- if (!msn_email_is_valid(passport))
+- continue;
+-
+- if ((displayName = xmlnode_get_child(contactInfo, "displayName")))
+- Name = xmlnode_get_data(displayName);
+- else
+- Name = g_strdup(passport);
+-
+- for (annotation = xmlnode_get_child(contactInfo, "annotations/Annotation");
+- annotation;
+- annotation = xmlnode_get_next_twin(annotation)) {
+- char *name;
+- name = xmlnode_get_data(xmlnode_get_child(annotation, "Name"));
+- if (!name)
+- continue;
+- if (!strcmp(name, "AB.NickName"))
+- alias = xmlnode_get_data(xmlnode_get_child(annotation, "Value"));
+- else if (!strcmp(name, "MSN.IM.HasSharedFolder"))
+- ; /* Do nothing yet... */
+- else if (!strcmp(name, "AB.Spouse"))
+- ; /* Do nothing yet... */
+- else if (!strcmp(name, "MSN.Mobile.ContactId"))
+- ; /* Do nothing yet... */
+- else
+- purple_debug_info("msn",
+- "Unknown AB contact annotation: %s\n", name);
+- g_free(name);
+- }
+-
+- mobile = msn_parse_addressbook_mobile(contactInfo, &mobile_number);
+-
+- purple_debug_misc("msn", "AB passport:{%s} uid:{%s} display:{%s} alias: {%s} mobile:{%s} mobile number:{%s}\n",
+- passport, uid ? uid : "(null)", Name ? Name : "(null)", alias ? alias : "(null)",
+- mobile ? "true" : "false", mobile_number ? mobile_number : "(null)");
+-
+- user = msn_userlist_find_add_user(session->userlist, passport, Name);
+- msn_user_set_uid(user, uid);
+- msn_user_set_mobile_phone(user, mobile_number);
+-
+- groupIds = xmlnode_get_child(contactInfo, "groupIds");
+- if (groupIds) {
+- for (guid = xmlnode_get_child(groupIds, "guid"); guid;
+- guid = xmlnode_get_next_twin(guid)) {
+- char *group_id = xmlnode_get_data(guid);
+- msn_user_add_group_id(user, group_id);
+- purple_debug_misc("msn", "AB guid:%s\n", group_id ? group_id : "(null)");
+- g_free(group_id);
+- }
+- } else {
+- purple_debug_info("msn", "User not in any groups, adding to default group.\n");
+- /*not in any group,Then set default group*/
+- msn_user_add_group_id(user, MSN_INDIVIDUALS_GROUP_ID);
+- }
+-
+- msn_got_lst_user(session, user, MSN_LIST_FL_OP, NULL);
+-
+- if (mobile && user)
+- {
+- user->mobile = TRUE;
+- purple_prpl_got_user_status(session->account, user->passport, "mobile", NULL);
+- purple_prpl_got_user_status(session->account, user->passport, "available", NULL);
+- }
+- if (alias)
+- purple_serv_got_private_alias(pc, passport, alias);
+- }
+-
+- g_free(passport);
+- g_free(Name);
+- g_free(uid);
+- g_free(type);
+- g_free(mobile_number);
+- g_free(alias);
+-}
+-
+-static void
+-msn_parse_addressbook_circles(MsnSession *session, xmlnode *node)
+-{
+- xmlnode *ticket;
+-
+- /* TODO: Parse groups */
+-
+- ticket = xmlnode_get_child(node, "CircleTicket");
+- if (ticket) {
+- char *data = xmlnode_get_data(ticket);
+- msn_notification_send_circle_auth(session, data);
+- g_free(data);
+- }
+-}
+-
+-static gboolean
+-msn_parse_addressbook(MsnSession *session, xmlnode *node)
+-{
+- xmlnode *result;
+- xmlnode *groups;
+- xmlnode *contacts;
+- xmlnode *abNode;
+- xmlnode *circleNode;
+- xmlnode *fault;
+-
+- if ((fault = xmlnode_get_child(node, "Body/Fault"))) {
+- xmlnode *faultnode;
+-
+- if ((faultnode = xmlnode_get_child(fault, "faultstring"))) {
+- gchar *faultstring = xmlnode_get_data(faultnode);
+- purple_debug_info("msn", "AB Faultstring: %s\n", faultstring);
+- g_free(faultstring);
+- }
+-
+- if ((faultnode = xmlnode_get_child(fault, "detail/errorcode"))) {
+- gchar *errorcode = xmlnode_get_data(faultnode);
+-
+- purple_debug_info("msn", "AB Error Code: %s\n", errorcode);
+-
+- if (g_str_equal(errorcode, "ABDoesNotExist")) {
+- g_free(errorcode);
+- return TRUE;
+- }
+- g_free(errorcode);
+- }
+-
+- return FALSE;
+- }
+-
+- result = xmlnode_get_child(node, "Body/ABFindContactsPagedResponse/ABFindContactsPagedResult");
+- if (result == NULL) {
+- purple_debug_misc("msn", "Received no address book update\n");
+- return TRUE;
+- }
+-
+- /* I don't see this "groups" tag documented on msnpiki, need to find out
+- if they are really there, and update msnpiki */
+- /*Process Group List*/
+- groups = xmlnode_get_child(result, "Groups");
+- if (groups != NULL) {
+- msn_parse_addressbook_groups(session, groups);
+- }
+-
+- /* Add an "Other Contacts" group for buddies who aren't in a group */
+- msn_group_new(session->userlist, MSN_INDIVIDUALS_GROUP_ID,
+- MSN_INDIVIDUALS_GROUP_NAME);
+- purple_debug_misc("msn", "AB group_id:%s name:%s\n",
+- MSN_INDIVIDUALS_GROUP_ID, MSN_INDIVIDUALS_GROUP_NAME);
+- if ((purple_find_group(MSN_INDIVIDUALS_GROUP_NAME)) == NULL){
+- PurpleGroup *g = purple_group_new(MSN_INDIVIDUALS_GROUP_NAME);
+- purple_blist_add_group(g, NULL);
+- }
+-
+- /* Add a "Non-IM Contacts" group */
+- msn_group_new(session->userlist, MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
+- purple_debug_misc("msn", "AB group_id:%s name:%s\n", MSN_NON_IM_GROUP_ID, MSN_NON_IM_GROUP_NAME);
+- if ((purple_find_group(MSN_NON_IM_GROUP_NAME)) == NULL) {
+- PurpleGroup *g = purple_group_new(MSN_NON_IM_GROUP_NAME);
+- purple_blist_add_group(g, NULL);
+- }
+-
+- /*Process contact List*/
+- purple_debug_info("msn", "Process contact list...\n");
+- contacts = xmlnode_get_child(result, "Contacts");
+- if (contacts != NULL) {
+- msn_parse_addressbook_contacts(session, contacts);
+- }
+-
+- abNode = xmlnode_get_child(result, "Ab");
+- if (abNode != NULL) {
+- xmlnode *node2;
+- char *tmp = NULL;
+-
+- if ((node2 = xmlnode_get_child(abNode, "lastChange")))
+- tmp = xmlnode_get_data(node2);
+- purple_debug_info("msn", "AB lastchanged Time:{%s}\n", tmp ? tmp : "(null)");
+- purple_account_set_string(session->account, "ablastChange", tmp);
+-
+- g_free(tmp); tmp = NULL;
+- if ((node2 = xmlnode_get_child(abNode, "DynamicItemLastChanged")))
+- tmp = xmlnode_get_data(node2);
+- purple_debug_info("msn", "AB DynamicItemLastChanged :{%s}\n", tmp ? tmp : "(null)");
+- purple_account_set_string(session->account, "DynamicItemLastChanged", tmp);
+- g_free(tmp);
+- }
+-
+- circleNode = xmlnode_get_child(result, "CircleResult");
+- if (circleNode != NULL) {
+- msn_parse_addressbook_circles(session, circleNode);
+- }
+-
+- return TRUE;
+-}
+-
+-static void
+-msn_get_address_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session = state->session;
+-
+- g_return_if_fail(session != NULL);
+-
+- purple_debug_misc("msn", "Got the Address Book!\n");
+-
+- if (msn_parse_addressbook(session, resp->xml)) {
+- msn_send_privacy(session->account->gc);
+- msn_notification_dump_contact(session);
+- } else {
+- /* This is making us loop infinitely when we fail to parse the
+- address book, disable for now (we should re-enable when we
+- send timestamps)
+- */
+- /*
+- msn_get_address_book(session, NULL, NULL);
+- */
+- msn_session_set_error(session, MSN_ERROR_BAD_BLIST, NULL);
+- }
+-}
+-
+-/*get the address book*/
+-void
+-msn_get_address_book(MsnSession *session,
+- MsnSoapPartnerScenario partner_scenario, const char *LastChanged,
+- const char *dynamicItemLastChange)
+-{
+- char *body, *update_str = NULL;
+- MsnCallbackState *state;
+-
+- purple_debug_misc("msn", "Getting Address Book\n");
+-
+- /*build SOAP and POST it*/
+- if (dynamicItemLastChange != NULL)
+- update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, dynamicItemLastChange);
+- else if (LastChanged != NULL)
+- update_str = g_strdup_printf(MSN_GET_ADDRESS_UPDATE_XML, LastChanged);
+-
+- body = g_strdup_printf(MSN_GET_ADDRESS_TEMPLATE,
+- MsnSoapPartnerScenarioText[partner_scenario],
+- update_str ? update_str : "");
+-
+- state = msn_callback_state_new(session);
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_GET_ADDRESS_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_get_address_cb;
+- msn_contact_request(state);
+-
+- g_free(update_str);
+- g_free(body);
+-}
+-
+-/***************************************************************
+- * Contact Operations
+- ***************************************************************/
+-
+-static void
+-msn_add_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session = state->session;
+-
+- MsnUserList *userlist;
+- MsnUser *user;
+- xmlnode *guid;
+-
+- xmlnode *fault;
+-
+- g_return_if_fail(session != NULL);
+- userlist = session->userlist;
+-
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
+- if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
+- /* Do something special! */
+- purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
+-
+- } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
+- PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
+- char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
+- purple_notify_error(state->session, _("Buddy Add error"), str,
+- _("The username specified does not exist."));
+- g_free(str);
+- msn_userlist_rem_buddy(userlist, state->who);
+- if (buddy != NULL)
+- purple_blist_remove_buddy(buddy);
+-
+- } else {
+- /* We don't know how to respond to this faultcode, so log it */
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- if (fault_str != NULL) {
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- }
+- }
+- return;
+- }
+-
+- purple_debug_info("msn", "Contact added successfully\n");
+-
+- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
+- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
+-
+- user = msn_userlist_find_add_user(userlist, state->who, state->who);
+- msn_user_add_group_id(user, state->guid);
+-
+- guid = xmlnode_get_child(resp->xml,
+- "Body/ABContactAddResponse/ABContactAddResult/guid");
+- if (guid != NULL) {
+- char *uid = xmlnode_get_data(guid);
+- msn_user_set_uid(user, uid);
+- purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
+- g_free(uid);
+- }
+-}
+-
+-/* add a Contact in MSN_INDIVIDUALS_GROUP */
+-void
+-msn_add_contact(MsnSession *session, MsnCallbackState *state, const char *passport)
+-{
+- MsnUser *user;
+- gchar *body = NULL;
+- gchar *contact_xml = NULL;
+-
+- purple_debug_info("msn", "Adding contact %s to contact list\n", passport);
+-
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (user == NULL) {
+- purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
+- return; /* guess this never happened! */
+- }
+-
+- if (user->networkid != MSN_NETWORK_PASSPORT) {
+- contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
+- user->networkid == MSN_NETWORK_YAHOO ?
+- "Messenger2" :
+- "Messenger3",
+- passport, 0);
+- } else {
+- contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
+- }
+- body = g_strdup_printf(MSN_ADD_CONTACT_TEMPLATE, contact_xml);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_CONTACT_ADD_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_add_contact_read_cb;
+- msn_contact_request(state);
+-
+- g_free(contact_xml);
+- g_free(body);
+-}
+-
+-static void
+-msn_add_contact_to_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session = state->session;
+- MsnUserList *userlist;
+- xmlnode *fault;
+-
+- g_return_if_fail(session != NULL);
+- userlist = session->userlist;
+-
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *errorcode = xmlnode_get_data(xmlnode_get_child(fault, "detail/errorcode"));
+- if (errorcode && !strcmp(errorcode, "EmailDomainIsFederated")) {
+- /* Do something special! */
+- purple_debug_error("msn", "Contact is from a federated domain, but don't know what to do yet!\n");
+-
+- } else if (errorcode && !strcmp(errorcode, "InvalidPassportUser")) {
+- PurpleBuddy *buddy = purple_find_buddy(session->account, state->who);
+- char *str = g_strdup_printf(_("Unable to add \"%s\"."), state->who);
+- purple_notify_error(session, _("Buddy Add error"), str,
+- _("The username specified does not exist."));
+- g_free(str);
+- msn_userlist_rem_buddy(userlist, state->who);
+- if (buddy != NULL)
+- purple_blist_remove_buddy(buddy);
+-
+- } else {
+- /* We don't know how to respond to this faultcode, so log it */
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- if (fault_str != NULL) {
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- }
+- }
+- return;
+- }
+-
+- if (msn_userlist_add_buddy_to_group(userlist, state->who,
+- state->new_group_name)) {
+- purple_debug_info("msn", "Contact %s added to group %s successfully!\n", state->who, state->new_group_name);
+- } else {
+- purple_debug_info("msn", "Contact %s added to group %s successfully on server, but failed in the local list\n", state->who, state->new_group_name);
+- }
+-
+- if (state->action & MSN_ADD_BUDDY) {
+- MsnUser *user = msn_userlist_find_user(userlist, state->who);
+- xmlnode *guid = xmlnode_get_child(resp->xml,
+- "Body/ABGroupContactAddResponse/ABGroupContactAddResult/guid");
+-
+- if (guid != NULL) {
+- char *uid = xmlnode_get_data(guid);
+- msn_user_set_uid(user, uid);
+- purple_debug_info("msn", "Set %s guid to %s.\n", state->who, uid);
+- g_free(uid);
+- }
+-
+- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_AL);
+- msn_userlist_add_buddy_to_list(userlist, state->who, MSN_LIST_FL);
+-
+- if (msn_user_is_in_list(user, MSN_LIST_PL)) {
+- msn_del_contact_from_list(state->session, NULL, state->who, MSN_LIST_PL);
+- return;
+- }
+- }
+-
+- if (state->action & MSN_MOVE_BUDDY) {
+- msn_del_contact_from_group(state->session, state->who, state->old_group_name);
+- }
+-}
+-
+-void
+-msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
+- const char *passport, const char *groupId)
+-{
+- MsnUserList *userlist;
+- MsnUser *user;
+- gchar *body = NULL, *contact_xml, *invite;
+-
+- g_return_if_fail(passport != NULL);
+- g_return_if_fail(groupId != NULL);
+-
+- g_return_if_fail(session != NULL);
+-
+- userlist = session->userlist;
+-
+- if (!strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
+-
+- user = msn_userlist_find_add_user(userlist, passport, passport);
+-
+- if (state->action & MSN_ADD_BUDDY) {
+- msn_add_contact(session, state, passport);
+- return;
+- }
+-
+- if (state->action & MSN_MOVE_BUDDY) {
+- msn_user_add_group_id(user, groupId);
+- msn_del_contact_from_group(session, passport, state->old_group_name);
+- }
+-
+- return;
+- }
+-
+- purple_debug_info("msn", "Adding user %s to group %s\n", passport,
+- msn_userlist_find_group_name(userlist, groupId));
+-
+- user = msn_userlist_find_user(userlist, passport);
+- if (user == NULL) {
+- purple_debug_warning("msn", "Unable to retrieve user %s from the userlist!\n", passport);
+- msn_callback_state_free(state);
+- return; /* guess this never happened! */
+- }
+-
+- if (user->uid != NULL) {
+- contact_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
+- } else if (user->networkid != MSN_NETWORK_PASSPORT) {
+- contact_xml = g_strdup_printf(MSN_CONTACT_EMAIL_XML,
+- user->networkid == MSN_NETWORK_YAHOO ?
+- "Messenger2" :
+- "Messenger3",
+- passport, 0);
+- } else {
+- contact_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
+- }
+-
+- if (user->invite_message) {
+- char *tmp;
+- body = g_markup_escape_text(user->invite_message, -1);
+-
+- /* Ignore the cast, we treat it as const anyway. */
+- tmp = (char *)purple_connection_get_display_name(session->account->gc);
+- tmp = tmp ? g_markup_escape_text(tmp, -1) : g_strdup("");
+-
+- invite = g_strdup_printf(MSN_CONTACT_INVITE_MESSAGE_XML, body, tmp);
+-
+- g_free(body);
+- g_free(tmp);
+-
+- /* We can free this now */
+- g_free(user->invite_message);
+- user->invite_message = NULL;
+-
+- } else {
+- invite = g_strdup("");
+- }
+-
+- body = g_strdup_printf(MSN_ADD_CONTACT_GROUP_TEMPLATE, groupId, contact_xml, invite);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_ADD_CONTACT_GROUP_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_add_contact_to_group_read_cb;
+- msn_contact_request(state);
+-
+- g_free(invite);
+- g_free(contact_xml);
+- g_free(body);
+-}
+-
+-static void
+-msn_delete_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnUserList *userlist = state->session->userlist;
+- MsnUser *user = msn_userlist_find_user_with_id(userlist, state->uid);
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- purple_debug_info("msn", "Delete contact successful\n");
+-
+- if (user != NULL) {
+- msn_userlist_remove_user(userlist, user);
+- }
+-}
+-
+-/*delete a Contact*/
+-void
+-msn_delete_contact(MsnSession *session, MsnUser *user)
+-{
+- gchar *body = NULL;
+- gchar *contact_id_xml = NULL ;
+- MsnCallbackState *state;
+-
+- if (user->uid != NULL) {
+- contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
+- purple_debug_info("msn", "Deleting contact with contactId: %s\n", user->uid);
+- } else {
+- purple_debug_info("msn", "Unable to delete contact %s without a ContactId\n", user->passport);
+- return;
+- }
+-
+- state = msn_callback_state_new(session);
+- msn_callback_state_set_uid(state, user->uid);
+-
+- /* build SOAP request */
+- body = g_strdup_printf(MSN_DEL_CONTACT_TEMPLATE, contact_id_xml);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_CONTACT_DEL_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_delete_contact_read_cb;
+- msn_contact_request(state);
+-
+- g_free(contact_id_xml);
+- g_free(body);
+-}
+-
+-static void
+-msn_del_contact_from_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- if (msn_userlist_rem_buddy_from_group(state->session->userlist,
+- state->who, state->old_group_name)) {
+- purple_debug_info("msn", "Contact %s deleted successfully from group %s\n", state->who, state->old_group_name);
+- } else {
+- purple_debug_info("msn", "Contact %s deleted successfully from group %s in the server, but failed in the local list\n", state->who, state->old_group_name);
+- }
+-}
+-
+-void
+-msn_del_contact_from_group(MsnSession *session, const char *passport, const char *group_name)
+-{
+- MsnUserList * userlist;
+- MsnUser *user;
+- MsnCallbackState *state;
+- gchar *body, *contact_id_xml;
+- const gchar *groupId;
+-
+- g_return_if_fail(passport != NULL);
+- g_return_if_fail(group_name != NULL);
+- g_return_if_fail(session != NULL);
+-
+- userlist = session->userlist;
+-
+- groupId = msn_userlist_find_group_id(userlist, group_name);
+- if (groupId != NULL) {
+- purple_debug_info("msn", "Deleting user %s from group %s\n", passport, group_name);
+- } else {
+- purple_debug_warning("msn", "Unable to retrieve group id from group %s !\n", group_name);
+- return;
+- }
+-
+- user = msn_userlist_find_user(userlist, passport);
+-
+- if (user == NULL) {
+- purple_debug_warning("msn", "Unable to retrieve user from passport %s!\n", passport);
+- return;
+- }
+-
+- if ( !strcmp(groupId, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(groupId, MSN_NON_IM_GROUP_ID)) {
+- msn_user_remove_group_id(user, groupId);
+- return;
+- }
+-
+- state = msn_callback_state_new(session);
+- msn_callback_state_set_who(state, passport);
+- msn_callback_state_set_guid(state, groupId);
+- msn_callback_state_set_old_group_name(state, group_name);
+-
+- if (user->uid != NULL)
+- contact_id_xml = g_strdup_printf(MSN_CONTACT_ID_XML, user->uid);
+- else
+- contact_id_xml = g_strdup_printf(MSN_CONTACT_XML, passport);
+- body = g_strdup_printf(MSN_CONTACT_DEL_GROUP_TEMPLATE, contact_id_xml, groupId);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_CONTACT_DEL_GROUP_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_del_contact_from_group_read_cb;
+- msn_contact_request(state);
+-
+- g_free(contact_id_xml);
+- g_free(body);
+-}
+-
+-
+-static void
+-msn_update_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = (MsnCallbackState *)data;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- purple_debug_info("msn", "Contact updated successfully\n");
+-}
+-
+-/* Update a contact's info */
+-void
+-msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value)
+-{
+- MsnCallbackState *state;
+- xmlnode *contact;
+- xmlnode *contact_info;
+- xmlnode *changes;
+- MsnUser *user = NULL;
+-
+- purple_debug_info("msn", "Update contact information for %s with new %s: %s\n",
+- passport ? passport : "(null)",
+- type == MSN_UPDATE_DISPLAY ? "display name" : "alias",
+- value ? value : "(null)");
+- g_return_if_fail(passport != NULL);
+-
+- if (strcmp(passport, "Me") != 0) {
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (!user)
+- return;
+- }
+-
+- contact_info = xmlnode_new("contactInfo");
+- changes = xmlnode_new("propertiesChanged");
+-
+- switch (type) {
+- xmlnode *annotations;
+- xmlnode *display;
+- xmlnode *a, *n, *v;
+- case MSN_UPDATE_DISPLAY:
+- display = xmlnode_new_child(contact_info, "displayName");
+- xmlnode_insert_data(display, value, -1);
+- xmlnode_insert_data(changes, "DisplayName", -1);
+- break;
+-
+- case MSN_UPDATE_ALIAS:
+- annotations = xmlnode_new_child(contact_info, "annotations");
+- xmlnode_insert_data(changes, "Annotation ", -1);
+-
+- a = xmlnode_new_child(annotations, "Annotation");
+- n = xmlnode_new_child(a, "Name");
+- xmlnode_insert_data(n, "AB.NickName", -1);
+- v = xmlnode_new_child(a, "Value");
+- xmlnode_insert_data(v, value, -1);
+- break;
+-
+- default:
+- g_return_if_reached();
+- }
+-
+- state = msn_callback_state_new(session);
+-
+- state->body = xmlnode_from_str(MSN_CONTACT_UPDATE_TEMPLATE, -1);
+- state->action = MSN_UPDATE_INFO;
+- state->post_action = MSN_CONTACT_UPDATE_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_update_contact_read_cb;
+-
+- contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
+- xmlnode_insert_child(contact, contact_info);
+- xmlnode_insert_child(contact, changes);
+-
+- xmlnode_insert_data(xmlnode_get_child(state->body,
+- "Header/ABApplicationHeader/PartnerScenario"),
+- MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
+-
+- if (user) {
+- xmlnode *contactId = xmlnode_new_child(contact, "contactId");
+- msn_callback_state_set_uid(state, user->uid);
+- xmlnode_insert_data(contactId, state->uid, -1);
+- } else {
+- xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
+- xmlnode_insert_data(contactType, "Me", -1);
+- }
+-
+- msn_contact_request(state);
+-}
+-
+-static void
+-msn_annotate_contact_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = (MsnCallbackState *)data;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- purple_debug_info("msn", "Contact annotated successfully\n");
+-}
+-
+-/* Update a contact's annotations */
+-void
+-msn_annotate_contact(MsnSession *session, const char *passport, ...)
+-{
+- va_list params;
+- MsnCallbackState *state;
+- xmlnode *contact;
+- xmlnode *contact_info;
+- xmlnode *annotations;
+- MsnUser *user = NULL;
+-
+- g_return_if_fail(passport != NULL);
+-
+- if (strcmp(passport, "Me") != 0) {
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (!user)
+- return;
+- }
+-
+- contact_info = xmlnode_new("contactInfo");
+- annotations = xmlnode_new_child(contact_info, "annotations");
+-
+- va_start(params, passport);
+- while (TRUE) {
+- const char *name;
+- const char *value;
+- xmlnode *a, *n, *v;
+-
+- name = va_arg(params, const char *);
+- if (!name)
+- break;
+-
+- value = va_arg(params, const char *);
+- if (!value)
+- break;
+-
+- a = xmlnode_new_child(annotations, "Annotation");
+- n = xmlnode_new_child(a, "Name");
+- xmlnode_insert_data(n, name, -1);
+- v = xmlnode_new_child(a, "Value");
+- xmlnode_insert_data(v, value, -1);
+- }
+- va_end(params);
+-
+- state = msn_callback_state_new(session);
+-
+- state->body = xmlnode_from_str(MSN_CONTACT_ANNOTATE_TEMPLATE, -1);
+- state->action = MSN_ANNOTATE_USER;
+- state->post_action = MSN_CONTACT_ANNOTATE_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_annotate_contact_read_cb;
+-
+- xmlnode_insert_data(xmlnode_get_child(state->body,
+- "Header/ABApplicationHeader/PartnerScenario"),
+- MsnSoapPartnerScenarioText[MSN_PS_SAVE_CONTACT], -1);
+-
+- contact = xmlnode_get_child(state->body, "Body/ABContactUpdate/contacts/Contact");
+- xmlnode_insert_child(contact, contact_info);
+-
+- if (user) {
+- xmlnode *contactId = xmlnode_new_child(contact, "contactId");
+- msn_callback_state_set_uid(state, user->uid);
+- xmlnode_insert_data(contactId, state->uid, -1);
+- } else {
+- xmlnode *contactType = xmlnode_new_child(contact_info, "contactType");
+- xmlnode_insert_data(contactType, "Me", -1);
+- }
+-
+- msn_contact_request(state);
+-}
+-
+-static void
+-msn_del_contact_from_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session = state->session;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- purple_debug_info("msn", "Contact %s deleted successfully from %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
+-
+- if (state->list_id == MSN_LIST_PL) {
+- MsnUser *user = msn_userlist_find_user(session->userlist, state->who);
+- MsnCallbackState *new_state = msn_callback_state_dup(state);
+-
+- if (user != NULL)
+- msn_user_unset_op(user, MSN_LIST_PL_OP);
+-
+- msn_add_contact_to_list(session, new_state, state->who, MSN_LIST_RL);
+- return;
+- } else if (state->list_id == MSN_LIST_AL) {
+- purple_privacy_permit_remove(session->account, state->who, TRUE);
+- msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_BL);
+- } else if (state->list_id == MSN_LIST_BL) {
+- purple_privacy_deny_remove(session->account, state->who, TRUE);
+- msn_add_contact_to_list(session, NULL, state->who, MSN_LIST_AL);
+- }
+-
+-}
+-
+-void
+-msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
+- const gchar *passport, const MsnListId list)
+-{
+- gchar *body = NULL, *member = NULL;
+- MsnSoapPartnerScenario partner_scenario;
+- MsnUser *user;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->userlist != NULL);
+- g_return_if_fail(passport != NULL);
+- g_return_if_fail(list < 5);
+-
+- purple_debug_info("msn", "Deleting contact %s from %s list\n", passport, MsnMemberRole[list]);
+-
+- if (state == NULL) {
+- state = msn_callback_state_new(session);
+- }
+- msn_callback_state_set_list_id(state, list);
+- msn_callback_state_set_who(state, passport);
+-
+- user = msn_userlist_find_user(session->userlist, passport);
+-
+- if (list == MSN_LIST_PL) {
+- partner_scenario = MSN_PS_CONTACT_API;
+- if (user->networkid != MSN_NETWORK_PASSPORT)
+- member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+- "EmailMember", "Email",
+- user->member_id_on_pending_list);
+- else
+- member = g_strdup_printf(MSN_MEMBER_MEMBERSHIPID_XML,
+- "PassportMember", "Passport",
+- user->member_id_on_pending_list);
+- } else {
+- /* list == MSN_LIST_AL || list == MSN_LIST_BL */
+- partner_scenario = MSN_PS_BLOCK_UNBLOCK;
+- if (user && user->networkid != MSN_NETWORK_PASSPORT)
+- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+- "EmailMember", "Email",
+- "Email", passport, "Email");
+- else
+- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+- "PassportMember", "Passport",
+- "PassportName", passport, "PassportName");
+- }
+-
+- body = g_strdup_printf(MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE,
+- MsnSoapPartnerScenarioText[partner_scenario],
+- MsnMemberRole[list], member);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION;
+- state->post_url = MSN_SHARE_POST_URL;
+- state->cb = msn_del_contact_from_list_read_cb;
+- msn_contact_request(state);
+-
+- g_free(member);
+- g_free(body);
+-}
+-
+-static void
+-msn_add_contact_to_list_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp,
+- gpointer data)
+-{
+- MsnCallbackState *state = data;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- g_return_if_fail(state->session != NULL);
+-
+- purple_debug_info("msn", "Contact %s added successfully to %s list on server!\n", state->who, MsnMemberRole[state->list_id]);
+-
+- if (state->list_id == MSN_LIST_RL) {
+- MsnUser *user = msn_userlist_find_user(state->session->userlist, state->who);
+-
+- if (user != NULL) {
+- msn_user_set_op(user, MSN_LIST_RL_OP);
+- }
+-
+- if (state->action & MSN_DENIED_BUDDY) {
+- msn_add_contact_to_list(state->session, NULL, state->who, MSN_LIST_BL);
+- } else if (state->list_id == MSN_LIST_AL) {
+- purple_privacy_permit_add(state->session->account, state->who, TRUE);
+- } else if (state->list_id == MSN_LIST_BL) {
+- purple_privacy_deny_add(state->session->account, state->who, TRUE);
+- }
+- }
+-}
+-
+-void
+-msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
+- const gchar *passport, const MsnListId list)
+-{
+- gchar *body = NULL, *member = NULL;
+- MsnSoapPartnerScenario partner_scenario;
+- MsnUser *user;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(passport != NULL);
+- g_return_if_fail(list < 5);
+-
+- purple_debug_info("msn", "Adding contact %s to %s list\n", passport, MsnMemberRole[list]);
+-
+- if (state == NULL) {
+- state = msn_callback_state_new(session);
+- }
+- msn_callback_state_set_list_id(state, list);
+- msn_callback_state_set_who(state, passport);
+-
+- user = msn_userlist_find_user(session->userlist, passport);
+-
+- partner_scenario = (list == MSN_LIST_RL) ? MSN_PS_CONTACT_API : MSN_PS_BLOCK_UNBLOCK;
+- if (user && user->networkid != MSN_NETWORK_PASSPORT)
+- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+- "EmailMember", "Email",
+- "Email", state->who, "Email");
+- else
+- member = g_strdup_printf(MSN_MEMBER_PASSPORT_XML,
+- "PassportMember", "Passport",
+- "PassportName", state->who, "PassportName");
+-
+- body = g_strdup_printf(MSN_CONTACT_ADD_TO_LIST_TEMPLATE,
+- MsnSoapPartnerScenarioText[partner_scenario],
+- MsnMemberRole[list], member);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION;
+- state->post_url = MSN_SHARE_POST_URL;
+- state->cb = msn_add_contact_to_list_read_cb;
+- msn_contact_request(state);
+-
+- g_free(member);
+- g_free(body);
+-}
+-
+-#if 0
+-static void
+-msn_gleams_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- purple_debug_info("msn", "Gleams read done\n");
+-}
+-
+-/*get the gleams info*/
+-void
+-msn_get_gleams(MsnSession *session)
+-{
+- MsnSoapReq *soap_request;
+-
+- purple_debug_info("msn", "msn get gleams info...\n");
+-
+- state = msn_callback_state_new(session);
+- state->body = xmlnode_from_str(MSN_GLEAMS_TEMPLATE, -1);
+- state->post_action = MSN_GET_GLEAMS_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_gleams_read_cb;
+- msn_contact_request(state);
+-}
+-#endif
+-
+-
+-/***************************************************************
+- * Group Operations
+- ***************************************************************/
+-
+-static void
+-msn_group_read_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- MsnCallbackState *state = data;
+- MsnSession *session;
+- MsnUserList *userlist;
+- xmlnode *fault;
+-
+- /* We don't know how to respond to this faultcode, so log it */
+- fault = xmlnode_get_child(resp->xml, "Body/Fault");
+- if (fault != NULL) {
+- char *fault_str = xmlnode_to_str(fault, NULL);
+- purple_debug_error("msn", "Operation {%s} Failed, SOAP Fault was: %s\n",
+- msn_contact_operation_str(state->action), fault_str);
+- g_free(fault_str);
+- return;
+- }
+-
+- purple_debug_info("msn", "Group request successful.\n");
+-
+- g_return_if_fail(state->session != NULL);
+- g_return_if_fail(state->session->userlist != NULL);
+-
+- session = state->session;
+- userlist = session->userlist;
+-
+- if (state->action & MSN_RENAME_GROUP) {
+- msn_userlist_rename_group_id(session->userlist,
+- state->guid,
+- state->new_group_name);
+- }
+-
+- if (state->action & MSN_ADD_GROUP) {
+- /* the response is taken from
+- http://telepathy.freedesktop.org/wiki/Pymsn/MSNP/ContactListActions
+- should copy it to msnpiki some day */
+- xmlnode *guid_node = xmlnode_get_child(resp->xml,
+- "Body/ABGroupAddResponse/ABGroupAddResult/guid");
+-
+- if (guid_node) {
+- char *guid = xmlnode_get_data(guid_node);
+-
+- /* create and add the new group to the userlist */
+- purple_debug_info("msn", "Adding group %s with guid = %s to the userlist\n", state->new_group_name, guid);
+- msn_group_new(session->userlist, guid, state->new_group_name);
+-
+- if (state->action & MSN_ADD_BUDDY) {
+- msn_userlist_add_buddy(session->userlist,
+- state->who,
+- state->new_group_name);
+- } else if (state->action & MSN_MOVE_BUDDY) {
+- /* This will be freed when the add contact callback fires */
+- MsnCallbackState *new_state = msn_callback_state_dup(state);
+- msn_add_contact_to_group(session, new_state, state->who, guid);
+- g_free(guid);
+- return;
+- }
+- g_free(guid);
+- } else {
+- purple_debug_info("msn", "Adding group %s failed\n",
+- state->new_group_name);
+- }
+- }
+-
+- if (state->action & MSN_DEL_GROUP) {
+- GList *l;
+-
+- msn_userlist_remove_group_id(session->userlist, state->guid);
+- for (l = userlist->users; l != NULL; l = l->next) {
+- msn_user_remove_group_id( (MsnUser *)l->data, state->guid);
+- }
+- }
+-}
+-
+-/* add group */
+-void
+-msn_add_group(MsnSession *session, MsnCallbackState *state, const char* group_name)
+-{
+- char *body = NULL;
+- char *escaped_group_name = NULL;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(group_name != NULL);
+-
+- purple_debug_info("msn", "Adding group %s to contact list.\n", group_name);
+-
+- if (state == NULL) {
+- state = msn_callback_state_new(session);
+- }
+-
+- msn_callback_state_set_action(state, MSN_ADD_GROUP);
+- msn_callback_state_set_new_group_name(state, group_name);
+-
+- /* escape group name's html special chars so it can safely be sent
+- * in a XML SOAP request
+- */
+- escaped_group_name = g_markup_escape_text(group_name, -1);
+- body = g_strdup_printf(MSN_GROUP_ADD_TEMPLATE, escaped_group_name);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_GROUP_ADD_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_group_read_cb;
+- msn_contact_request(state);
+-
+- g_free(escaped_group_name);
+- g_free(body);
+-}
+-
+-/* delete group */
+-void
+-msn_del_group(MsnSession *session, const gchar *group_name)
+-{
+- MsnCallbackState *state;
+- char *body = NULL;
+- const gchar *guid;
+-
+- g_return_if_fail(session != NULL);
+-
+- g_return_if_fail(group_name != NULL);
+- purple_debug_info("msn", "Deleting group %s from contact list\n", group_name);
+-
+- guid = msn_userlist_find_group_id(session->userlist, group_name);
+-
+- /* if group uid we need to del is NULL,
+- * we need to delete nothing
+- */
+- if (guid == NULL) {
+- purple_debug_info("msn", "Group %s guid not found, returning.\n", group_name);
+- return;
+- }
+-
+- if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
+- /* XXX add back PurpleGroup since it isn't really removed in the server? */
+- return;
+- }
+-
+- state = msn_callback_state_new(session);
+- msn_callback_state_set_action(state, MSN_DEL_GROUP);
+- msn_callback_state_set_guid(state, guid);
+-
+- body = g_strdup_printf(MSN_GROUP_DEL_TEMPLATE, guid);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_GROUP_DEL_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_group_read_cb;
+- msn_contact_request(state);
+-
+- g_free(body);
+-}
+-
+-/* rename group */
+-void
+-msn_contact_rename_group(MsnSession *session, const char *old_group_name, const char *new_group_name)
+-{
+- gchar *body = NULL;
+- const gchar * guid;
+- MsnCallbackState *state;
+- char *escaped_group_name;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->userlist != NULL);
+- g_return_if_fail(old_group_name != NULL);
+- g_return_if_fail(new_group_name != NULL);
+-
+- purple_debug_info("msn", "Renaming group %s to %s.\n", old_group_name, new_group_name);
+-
+- guid = msn_userlist_find_group_id(session->userlist, old_group_name);
+- if (guid == NULL)
+- return;
+-
+- state = msn_callback_state_new(session);
+- msn_callback_state_set_guid(state, guid);
+- msn_callback_state_set_new_group_name(state, new_group_name);
+-
+- if ( !strcmp(guid, MSN_INDIVIDUALS_GROUP_ID) || !strcmp(guid, MSN_NON_IM_GROUP_ID) ) {
+- MsnCallbackState *new_state = msn_callback_state_dup(state);
+- msn_add_group(session, new_state, new_group_name);
+- /* XXX move every buddy there (we probably need to fix concurrent SOAP reqs first) */
+- }
+-
+- msn_callback_state_set_action(state, MSN_RENAME_GROUP);
+-
+- escaped_group_name = g_markup_escape_text(new_group_name, -1);
+- body = g_strdup_printf(MSN_GROUP_RENAME_TEMPLATE, guid, escaped_group_name);
+-
+- state->body = xmlnode_from_str(body, -1);
+- state->post_action = MSN_GROUP_RENAME_SOAP_ACTION;
+- state->post_url = MSN_ADDRESS_BOOK_POST_URL;
+- state->cb = msn_group_read_cb;
+- msn_contact_request(state);
+-
+- g_free(escaped_group_name);
+- g_free(body);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/contact.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.h
+--- pidgin-2.10.7/libpurple/protocols/msn/contact.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/contact.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,746 +0,0 @@
+-/**
+- * @file contact.h Header file for contact.c
+- * Author
+- * MaYuan<mayuan2006@gmail.com>
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-#ifndef MSN_CONTACT_H
+-#define MSN_CONTACT_H
+-
+-typedef struct _MsnCallbackState MsnCallbackState;
+-
+-typedef enum
+-{
+- MSN_ADD_BUDDY = 0x01,
+- MSN_MOVE_BUDDY = 0x02,
+- MSN_ACCEPTED_BUDDY = 0x04,
+- MSN_DENIED_BUDDY = 0x08,
+- MSN_ADD_GROUP = 0x10,
+- MSN_DEL_GROUP = 0x20,
+- MSN_RENAME_GROUP = 0x40,
+- MSN_UPDATE_INFO = 0x80,
+- MSN_ANNOTATE_USER = 0x100
+-} MsnCallbackAction;
+-
+-typedef enum
+-{
+- MSN_UPDATE_DISPLAY, /* Real display name */
+- MSN_UPDATE_ALIAS, /* Aliased display name */
+- MSN_UPDATE_COMMENT
+-} MsnContactUpdateType;
+-
+-typedef enum
+-{
+- MSN_PS_INITIAL,
+- MSN_PS_SAVE_CONTACT,
+- MSN_PS_PENDING_LIST,
+- MSN_PS_CONTACT_API,
+- MSN_PS_BLOCK_UNBLOCK,
+- MSN_PS_TIMER
+-} MsnSoapPartnerScenario;
+-
+-#include "session.h"
+-#include "soap.h"
+-
+-#define MSN_APPLICATION_ID "CFE80F9D-180F-4399-82AB-413F33A1FA11"
+-
+-#define MSN_CONTACT_SERVER "local-bay.contacts.msn.com"
+-
+-/* Get Contact List */
+-
+-#define MSN_GET_CONTACT_POST_URL "/abservice/SharingService.asmx"
+-#define MSN_GET_CONTACT_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/FindMembership"
+-
+-#define MSN_GET_CONTACT_UPDATE_XML \
+- "<View>Full</View>"\
+- "<deltasOnly>true</deltasOnly>"\
+- "<lastChange>%s</lastChange>"
+-
+-#define MSN_GET_CONTACT_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
+-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<soap:Header xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId xmlns=\"http://www.msn.com/webservices/AddressBook\">" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration xmlns=\"http://www.msn.com/webservices/AddressBook\">false</IsMigration>"\
+- "<PartnerScenario xmlns=\"http://www.msn.com/webservices/AddressBook\">%s</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest xmlns=\"http://www.msn.com/webservices/AddressBook\">false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<FindMembership xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<serviceFilter xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<Types xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Messenger</ServiceType>"\
+- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Invitation</ServiceType>"\
+- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">SocialNetwork</ServiceType>"\
+- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Space</ServiceType>"\
+- "<ServiceType xmlns=\"http://www.msn.com/webservices/AddressBook\">Profile</ServiceType>"\
+- "</Types>"\
+- "</serviceFilter>"\
+- "%s"\
+- "</FindMembership>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/************************************************
+- * Address Book SOAP
+- * *********************************************/
+-
+-#define MSN_ADDRESS_BOOK_POST_URL "/abservice/abservice.asmx"
+-
+-/* Create AddressBook template */
+-#define MSN_ADD_ADDRESSBOOK_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABAdd"
+-
+-#define MSN_ADD_ADDRESSBOOK_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Initial</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abInfo>"\
+- "<name/>"\
+- "<ownerPuid>0</ownerPuid>"\
+- "<ownerEmail>%s</ownerEmail>"\
+- "<fDefault>true</fDefault>"\
+- "</abInfo>"\
+- "</ABAdd>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* Get AddressBook */
+-#define MSN_GET_ADDRESS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindContactsPaged"
+-#define MSN_GET_ADDRESS_FULL_TIME "0001-01-01T00:00:00.0000000-08:00"
+-#define MSN_GET_ADDRESS_UPDATE_XML \
+- "<filterOptions>"\
+- "<deltasOnly>true</deltasOnly>"\
+- "<lastChange>%s</lastChange>"\
+- "</filterOptions>"
+-
+-#define MSN_GET_GLEAM_UPDATE_XML \
+- "%s"\
+- "<dynamicItemView>Gleam</dynamicItemView>"\
+- "<dynamicItemLastChange>%s</dynamicItemLastChange>"
+-
+-#define MSN_GET_ADDRESS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>%s</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABFindContactsPaged xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abView>Full</abView>"\
+- "<extendedContent>AB AllGroups CircleResult</extendedContent>"\
+- "%s"\
+- "</ABFindContactsPaged>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-
+-/*Gleams SOAP request template*/
+-#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll"
+-#define MSN_GLEAMS_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Initial</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABFindAll xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<abView>Full</abView>"\
+- "<dynamicItemView>Gleam</dynamicItemView>"\
+- "<dynamicItemLastChange>0001-01-01T00:00:00.0000000-08:00</dynamicItemLastChange>"\
+- "</ABFindAll>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-
+-/*******************************************************
+- * Contact Management SOAP actions
+- *******************************************************/
+-
+-/* Add a new contact */
+-#define MSN_CONTACT_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactAdd"
+-#define MSN_CONTACT_LIVE_PENDING_XML \
+- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<contactInfo>"\
+- "<contactType>LivePending</contactType>"\
+- "<passportName>%s</passportName>"\
+- "<isMessengerUser>true</isMessengerUser>"\
+- "</contactInfo>"\
+- "</Contact>"
+-
+-#define MSN_CONTACT_XML \
+- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<contactInfo>"\
+- "<passportName>%s</passportName>"\
+- "<isSmtp>false</isSmtp>"\
+- "<isMessengerUser>true</isMessengerUser>"\
+- "</contactInfo>"\
+- "</Contact>"
+-
+-#define MSN_CONTACT_DISPLAYNAME_XML \
+- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<contactInfo>"\
+- "<displayName>%s</displayName>"\
+- "<passportName>%s</passportName>"\
+- "<isMessengerUser>true</isMessengerUser>"\
+- "</contactInfo>"\
+- "</Contact>"
+-
+-#define MSN_CONTACT_ID_XML \
+- "<Contact>"\
+- "<contactId>%s</contactId>"\
+- "</Contact>"
+-
+-#define MSN_CONTACT_EMAIL_XML \
+- "<Contact>"\
+- "<contactInfo>"\
+- "<emails>"\
+- "<ContactEmail>"\
+- "<contactEmailType>%s</contactEmailType>"\
+- "<email>%s</email>"\
+- "<isMessengerEnabled>true</isMessengerEnabled>"\
+- "<Capability>%d</Capability>"\
+- "<MessengerEnabledExternally>false</MessengerEnabledExternally>"\
+- "<propertiesChanged/>"\
+- "</ContactEmail>"\
+- "</emails>"\
+- "</contactInfo>"\
+- "</Contact>"
+-
+-#define MSN_CONTACT_INVITE_MESSAGE_XML \
+- "<MessengerMemberInfo>"\
+- "<PendingAnnotations>"\
+- "<Annotation>"\
+- "<Name>MSN.IM.InviteMessage</Name>"\
+- "<Value>%s</Value>"\
+- "</Annotation>"\
+- "</PendingAnnotations>"\
+- "<DisplayName>%s</DisplayName>"\
+- "</MessengerMemberInfo>"
+-
+-#define MSN_ADD_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>ContactSave</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<contacts>%s</contacts>"\
+- "<options>"\
+- "<EnableAllowListManagement>true</EnableAllowListManagement>"\
+- "</options>"\
+- "</ABContactAdd>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* Add a contact to a group */
+-#define MSN_ADD_CONTACT_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactAdd"
+-#define MSN_ADD_CONTACT_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>ContactSave</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABGroupContactAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<groupFilter>"\
+- "<groupIds>"\
+- "<guid>%s</guid>"\
+- "</groupIds>"\
+- "</groupFilter>"\
+- "<contacts>%s</contacts>"\
+- "<groupContactAddOptions>"\
+- "<fGenerateMissingQuickName>true</fGenerateMissingQuickName>"\
+- "<EnableAllowListManagement>true</EnableAllowListManagement>"\
+- "</groupContactAddOptions>"\
+- "%s"\
+- "</ABGroupContactAdd>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* Delete a contact from the Contact List */
+-#define MSN_CONTACT_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactDelete"
+-#define MSN_DEL_CONTACT_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Timer</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<contacts>%s</contacts>"\
+- "</ABContactDelete>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* Remove a contact from a group */
+-#define MSN_CONTACT_DEL_GROUP_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupContactDelete"
+-#define MSN_CONTACT_DEL_GROUP_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Timer</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABGroupContactDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<contacts>%s</contacts>"\
+- "<groupFilter>"\
+- "<groupIds>"\
+- "<guid>%s</guid>"\
+- "</groupIds>"\
+- "</groupFilter>"\
+- "</ABGroupContactDelete>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-
+-/* Update Contact Information */
+-#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate"
+-#define MSN_CONTACT_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario></PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<contacts>"\
+- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- ""\
+- "</Contact>"\
+- "</contacts>"\
+- "</ABContactUpdate>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* Update Contact Annotations */
+-#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate"
+-#define MSN_CONTACT_ANNOTATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario></PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABContactUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<contacts>"\
+- "<Contact xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<propertiesChanged>Annotation</propertiesChanged>"\
+- "</Contact>"\
+- "</contacts>"\
+- "</ABContactUpdate>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/*******************************************************
+- * Add/Delete contact from lists SOAP actions
+- *******************************************************/
+-
+-/* block means delete from allow list and add contact to block list */
+-#define MSN_SHARE_POST_URL "/abservice/SharingService.asmx"
+-
+-#define MSN_ADD_MEMBER_TO_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/AddMember"
+-#define MSN_DELETE_MEMBER_FROM_LIST_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/DeleteMember"
+-
+-#define MSN_MEMBER_PASSPORT_XML \
+- "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
+- "<Type>%s</Type>"\
+- "<State>Accepted</State>"\
+- "<%s>%s</%s>"\
+- "</Member>"
+-
+-#define MSN_MEMBER_MEMBERSHIPID_XML \
+- "<Member xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xsi:type=\"%s\">"\
+- "<Type>%s</Type>"\
+- "<MembershipId>%u</MembershipId>"\
+- "<State>Accepted</State>"\
+- "</Member>"
+-
+-/* first delete contact from allow list */
+-
+-#define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>%s</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<DeleteMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<serviceHandle>"\
+- "<Id>0</Id>"\
+- "<Type>Messenger</Type>"\
+- "<ForeignId></ForeignId>"\
+- "</serviceHandle>"\
+- "<memberships>"\
+- "<Membership>"\
+- "<MemberRole>%s</MemberRole>"\
+- "<Members>"\
+- "%s"\
+- "</Members>"\
+- "</Membership>"\
+- "</memberships>"\
+- "</DeleteMember>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-#define MSN_CONTACT_ADD_TO_LIST_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>%s</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<AddMember xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<serviceHandle>"\
+- "<Id>0</Id>"\
+- "<Type>Messenger</Type>"\
+- "<ForeignId></ForeignId>"\
+- "</serviceHandle>"\
+- "<memberships>"\
+- "<Membership>"\
+- "<MemberRole>%s</MemberRole>"\
+- "<Members>"\
+- "%s"\
+- "</Members>"\
+- "</Membership>"\
+- "</memberships>"\
+- "</AddMember>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-
+-
+-/*******************************************************
+- * Group management SOAP actions
+- *******************************************************/
+-
+-/* add a group */
+-#define MSN_GROUP_ADD_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupAdd"
+-#define MSN_GROUP_ADD_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>GroupSave</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABGroupAdd xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<groupAddOptions>"\
+- "<fRenameOnMsgrConflict>false</fRenameOnMsgrConflict>"\
+- "</groupAddOptions>"\
+- "<groupInfo>"\
+- "<GroupInfo>"\
+- "<name>%s</name>"\
+- "<groupType>C8529CE2-6EAD-434d-881F-341E17DB3FF8</groupType>"\
+- "<fMessenger>false</fMessenger>"\
+- "<annotations>"\
+- "<Annotation>"\
+- "<Name>MSN.IM.Display</Name>"\
+- "<Value>1</Value>"\
+- "</Annotation>"\
+- "</annotations>"\
+- "</GroupInfo>"\
+- "</groupInfo>"\
+- "</ABGroupAdd>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* delete a group */
+-#define MSN_GROUP_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupDelete"
+-#define MSN_GROUP_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Timer</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABGroupDelete xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<groupFilter>"\
+- "<groupIds>"\
+- "<guid>%s</guid>"\
+- "</groupIds>"\
+- "</groupFilter>"\
+- "</ABGroupDelete>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/* change a group's name */
+-#define MSN_GROUP_RENAME_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupUpdate"
+-#define MSN_GROUP_RENAME_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soapenc=\"http://schemas.xmlsoap.org/soap/encoding/\">"\
+- "<soap:Header>"\
+- "<ABApplicationHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ApplicationId>" MSN_APPLICATION_ID "</ApplicationId>"\
+- "<IsMigration>false</IsMigration>"\
+- "<PartnerScenario>Timer</PartnerScenario>"\
+- "</ABApplicationHeader>"\
+- "<ABAuthHeader xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<ManagedGroupRequest>false</ManagedGroupRequest>"\
+- "<TicketToken>EMPTY</TicketToken>"\
+- "</ABAuthHeader>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<ABGroupUpdate xmlns=\"http://www.msn.com/webservices/AddressBook\">"\
+- "<abId>00000000-0000-0000-0000-000000000000</abId>"\
+- "<groups>"\
+- "<Group>"\
+- "<groupId>%s</groupId>"\
+- "<groupInfo>"\
+- "<name>%s</name>"\
+- "</groupInfo>"\
+- "<propertiesChanged>GroupName </propertiesChanged>"\
+- "</Group>"\
+- "</groups>"\
+- "</ABGroupUpdate>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-struct _MsnCallbackState
+-{
+- gchar * who;
+- gchar * uid;
+- gchar * old_group_name;
+- gchar * new_group_name;
+- gchar * guid;
+- MsnListId list_id;
+- MsnCallbackAction action;
+- MsnSession *session;
+- xmlnode *body;
+- xmlnode *token;
+- const gchar *post_action;
+- const gchar *post_url;
+- MsnSoapCallback cb;
+- /* For msn_get_contact_list only */
+- MsnSoapPartnerScenario partner_scenario;
+-};
+-
+-/************************************************
+- * function prototype
+- ************************************************/
+-MsnCallbackState * msn_callback_state_new(MsnSession *session);
+-MsnCallbackState * msn_callback_state_dup(MsnCallbackState *state);
+-void msn_callback_state_free(MsnCallbackState *state);
+-void msn_callback_state_set_who(MsnCallbackState *state, const gchar *who);
+-void msn_callback_state_set_uid(MsnCallbackState *state, const gchar *uid);
+-void msn_callback_state_set_old_group_name(MsnCallbackState *state,
+- const gchar *old_group_name);
+-void msn_callback_state_set_new_group_name(MsnCallbackState *state,
+- const gchar *new_group_name);
+-void msn_callback_state_set_guid(MsnCallbackState *state, const gchar *guid);
+-void msn_callback_state_set_list_id(MsnCallbackState *state, MsnListId list_id);
+-void msn_callback_state_set_action(MsnCallbackState *state,
+- MsnCallbackAction action);
+-
+-void msn_get_contact_list(MsnSession *session,
+- const MsnSoapPartnerScenario partner_scenario,
+- const char *update);
+-void msn_get_address_book(MsnSession *session,
+- const MsnSoapPartnerScenario partner_scenario,
+- const char * update, const char * gupdate);
+-
+-/* contact SOAP operations */
+-void msn_update_contact(MsnSession *session, const char *passport, MsnContactUpdateType type, const char* value);
+-
+-void msn_annotate_contact(MsnSession *session, const char *passport, ...) G_GNUC_NULL_TERMINATED;
+-
+-void msn_add_contact(MsnSession *session, MsnCallbackState *state,
+- const char *passport);
+-void msn_delete_contact(MsnSession *session, MsnUser *user);
+-
+-void msn_add_contact_to_group(MsnSession *session, MsnCallbackState *state,
+- const char *passport, const char *groupId);
+-void msn_del_contact_from_group(MsnSession *session, const char *passport,
+- const char *group_name);
+-/* group operations */
+-void msn_add_group(MsnSession *session, MsnCallbackState *state,
+- const char* group_name);
+-void msn_del_group(MsnSession *session, const gchar *group_name);
+-void msn_contact_rename_group(MsnSession *session, const char *old_group_name,
+- const char *new_group_name);
+-
+-/* lists operations */
+-void msn_add_contact_to_list(MsnSession *session, MsnCallbackState *state,
+- const gchar *passport, const MsnListId list);
+-void msn_del_contact_from_list(MsnSession *session, MsnCallbackState *state,
+- const gchar *passport, const MsnListId list);
+-
+-#endif /* MSN_CONTACT_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/directconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.c
+--- pidgin-2.10.7/libpurple/protocols/msn/directconn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,958 +0,0 @@
+-/**
+- * @file directconn.c MSN direct connection functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "cipher.h"
+-#include "debug.h"
+-
+-#include "msn.h"
+-#include "msnutils.h"
+-#include "directconn.h"
+-
+-#include "slp.h"
+-#include "slpmsg.h"
+-#include "p2p.h"
+-
+-#define DC_MAX_BODY_SIZE 8*1024
+-#define DC_MAX_PACKET_SIZE (P2P_PACKET_HEADER_SIZE + DC_MAX_BODY_SIZE)
+-
+-static void
+-msn_dc_calculate_nonce_hash(MsnDirectConnNonceType type,
+- const guchar nonce[16], gchar nonce_hash[37])
+-{
+- guchar digest[20];
+-
+- if (type == DC_NONCE_SHA1) {
+- PurpleCipher *cipher = purple_ciphers_find_cipher("sha1");
+- PurpleCipherContext *context = purple_cipher_context_new(cipher, NULL);
+- purple_cipher_context_append(context, nonce, sizeof(nonce));
+- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+- purple_cipher_context_destroy(context);
+- } else if (type == DC_NONCE_PLAIN) {
+- memcpy(digest, nonce, 16);
+- } else {
+- nonce_hash[0] = '\0';
+- g_return_if_reached();
+- }
+-
+- g_sprintf(nonce_hash,
+- "%02X%02X%02X%02X-%02X%02X-%02X%02X-%02X%02X-%02X%02X%02X%02X%02X%02X",
+-
+- digest[3],
+- digest[2],
+- digest[1],
+- digest[0],
+-
+- digest[5],
+- digest[4],
+-
+- digest[7],
+- digest[6],
+-
+- digest[8],
+- digest[9],
+-
+- digest[10],
+- digest[11],
+- digest[12],
+- digest[13],
+- digest[14],
+- digest[15]
+- );
+-}
+-
+-static void
+-msn_dc_generate_nonce(MsnDirectConn *dc)
+-{
+- guint32 *nonce;
+- int i;
+-
+- nonce = (guint32 *)&dc->nonce;
+- for (i = 0; i < 4; i++)
+- nonce[i] = rand();
+-
+- msn_dc_calculate_nonce_hash(dc->nonce_type, dc->nonce, dc->nonce_hash);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "DC %p generated nonce %s\n", dc, dc->nonce_hash);
+-}
+-
+-static MsnDirectConnPacket *
+-msn_dc_new_packet(guint32 length)
+-{
+- MsnDirectConnPacket *p;
+-
+- p = g_new0(MsnDirectConnPacket, 1);
+- p->length = length;
+- p->data = g_malloc(length);
+-
+- return p;
+-}
+-
+-static void
+-msn_dc_destroy_packet(MsnDirectConnPacket *p)
+-{
+- g_free(p->data);
+-
+- if (p->part)
+- msn_slpmsgpart_unref(p->part);
+-
+- g_free(p);
+-}
+-
+-MsnDirectConn *
+-msn_dc_new(MsnSlpCall *slpcall)
+-{
+- MsnDirectConn *dc;
+-
+- g_return_val_if_fail(slpcall != NULL, NULL);
+-
+- dc = g_new0(MsnDirectConn, 1);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_new %p\n", dc);
+-
+- dc->slplink = slpcall->slplink;
+- dc->slpcall = slpcall;
+-
+- if (dc->slplink->dc != NULL)
+- purple_debug_warning("msn", "msn_dc_new: slplink already has an allocated DC!\n");
+-
+- dc->slplink->dc = dc;
+-
+- dc->msg_body = NULL;
+- dc->prev_ack = NULL;
+- dc->listen_data = NULL;
+- dc->connect_data = NULL;
+- dc->listenfd = -1;
+- dc->listenfd_handle = 0;
+- dc->connect_timeout_handle = 0;
+- dc->fd = -1;
+- dc->recv_handle = 0;
+- dc->send_handle = 0;
+- dc->state = DC_STATE_CLOSED;
+- dc->in_buffer = NULL;
+- dc->out_queue = g_queue_new();
+- dc->msg_pos = -1;
+- dc->send_connection_info_msg_cb = NULL;
+- dc->ext_ip = NULL;
+- dc->timeout_handle = 0;
+- dc->progress = FALSE;
+- /*dc->num_calls = 1;*/
+-
+- /* TODO: Probably should set this based on buddy caps */
+- dc->nonce_type = DC_NONCE_PLAIN;
+- msn_dc_generate_nonce(dc);
+-
+- return dc;
+-}
+-
+-void
+-msn_dc_destroy(MsnDirectConn *dc)
+-{
+- MsnSlpLink *slplink;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_destroy %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- if (dc->slpcall != NULL)
+- dc->slpcall->wait_for_socket = FALSE;
+-
+- slplink = dc->slplink;
+- if (slplink) {
+- slplink->dc = NULL;
+- if (slplink->swboard == NULL)
+- msn_slplink_unref(slplink);
+- }
+-
+- g_free(dc->msg_body);
+-
+- if (dc->prev_ack) {
+- msn_slpmsg_destroy(dc->prev_ack);
+- }
+-
+- if (dc->listen_data != NULL) {
+- purple_network_listen_cancel(dc->listen_data);
+- }
+-
+- if (dc->connect_data != NULL) {
+- purple_proxy_connect_cancel(dc->connect_data);
+- }
+-
+- if (dc->listenfd != -1) {
+- purple_network_remove_port_mapping(dc->listenfd);
+- close(dc->listenfd);
+- }
+-
+- if (dc->listenfd_handle != 0) {
+- purple_input_remove(dc->listenfd_handle);
+- }
+-
+- if (dc->connect_timeout_handle != 0) {
+- purple_timeout_remove(dc->connect_timeout_handle);
+- }
+-
+- if (dc->fd != -1) {
+- close(dc->fd);
+- }
+-
+- if (dc->send_handle != 0) {
+- purple_input_remove(dc->send_handle);
+- }
+-
+- if (dc->recv_handle != 0) {
+- purple_input_remove(dc->recv_handle);
+- }
+-
+- g_free(dc->in_buffer);
+-
+- if (dc->out_queue != NULL) {
+- while (!g_queue_is_empty(dc->out_queue))
+- msn_dc_destroy_packet( g_queue_pop_head(dc->out_queue) );
+-
+- g_queue_free(dc->out_queue);
+- }
+-
+- g_free(dc->ext_ip);
+-
+- if (dc->timeout_handle != 0) {
+- purple_timeout_remove(dc->timeout_handle);
+- }
+-
+- g_free(dc);
+-}
+-
+-/*
+-void
+-msn_dc_ref(MsnDirectConn *dc)
+-{
+- g_return_if_fail(dc != NULL);
+-
+- dc->num_calls++;
+-}
+-
+-void
+-msn_dc_unref(MsnDirectConn *dc)
+-{
+- g_return_if_fail(dc != NULL);
+-
+-
+- if (dc->num_calls > 0) {
+- dc->num_calls--;
+- }
+-}
+-*/
+-
+-void
+-msn_dc_send_invite(MsnDirectConn *dc)
+-{
+- MsnSlpCall *slpcall;
+- MsnSlpMessage *msg;
+- gchar *header;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_send_invite %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- slpcall = dc->slpcall;
+- g_return_if_fail(slpcall != NULL);
+-
+- header = g_strdup_printf(
+- "INVITE MSNMSGR:%s MSNSLP/1.0",
+- slpcall->slplink->remote_user
+- );
+-
+- msg = msn_slpmsg_sip_new(
+- slpcall,
+- 0,
+- header,
+- slpcall->branch,
+- "application/x-msnmsgr-transrespbody",
+- dc->msg_body
+- );
+- msg->info = "DC INVITE";
+- msg->text_body = TRUE;
+- g_free(header);
+- g_free(dc->msg_body);
+- dc->msg_body = NULL;
+-
+- msn_slplink_queue_slpmsg(slpcall->slplink, msg);
+-}
+-
+-void
+-msn_dc_send_ok(MsnDirectConn *dc)
+-{
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_send_ok %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- msn_slp_send_ok(dc->slpcall, dc->slpcall->branch,
+- "application/x-msnmsgr-transrespbody", dc->msg_body);
+- g_free(dc->msg_body);
+- dc->msg_body = NULL;
+-
+- msn_slplink_send_slpmsg(dc->slpcall->slplink, dc->prev_ack);
+- msn_slpmsg_destroy(dc->prev_ack);
+- dc->prev_ack = NULL;
+- msn_slplink_send_queued_slpmsgs(dc->slpcall->slplink);
+-}
+-
+-void
+-msn_dc_fallback_to_sb(MsnDirectConn *dc)
+-{
+- MsnSlpLink *slplink;
+- MsnSlpCall *slpcall;
+- GQueue *queue = NULL;
+-
+- purple_debug_info("msn", "msn_dc_fallback_to_sb %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- slpcall = dc->slpcall;
+- slplink = msn_slplink_ref(dc->slplink);
+- if (slpcall && !g_queue_is_empty(dc->out_queue)) {
+- queue = dc->out_queue;
+- dc->out_queue = NULL;
+- }
+-
+- msn_dc_destroy(dc);
+-
+- if (slpcall) {
+- msn_slpcall_session_init(slpcall);
+- if (queue) {
+- while (!g_queue_is_empty(queue)) {
+- MsnDirectConnPacket *p = g_queue_pop_head(queue);
+- msn_slplink_send_msgpart(slplink, (MsnSlpMessage*)p->part->ack_data);
+- msn_dc_destroy_packet(p);
+- }
+- g_queue_free(queue);
+- }
+- }
+- msn_slplink_unref(slplink);
+-}
+-
+-static void
+-msn_dc_send_cb(gpointer data, gint fd, PurpleInputCondition cond)
+-{
+- MsnDirectConn *dc = data;
+- MsnDirectConnPacket *p;
+- int bytes_to_send;
+- int bytes_sent;
+-
+- g_return_if_fail(dc != NULL);
+- g_return_if_fail(fd != -1);
+-
+- if (g_queue_is_empty(dc->out_queue)) {
+- if (dc->send_handle != 0) {
+- purple_input_remove(dc->send_handle);
+- dc->send_handle = 0;
+- }
+- return;
+- }
+-
+- p = g_queue_peek_head(dc->out_queue);
+-
+- if (dc->msg_pos < 0) {
+- /* First we send the length of the packet */
+- guint32 len = GUINT32_TO_LE(p->length);
+- bytes_sent = send(fd, &len, 4, 0);
+- if (bytes_sent < 0) {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- return;
+-
+- purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
+- msn_dc_destroy(dc);
+- return;
+- }
+- dc->msg_pos = 0;
+- }
+-
+- bytes_to_send = p->length - dc->msg_pos;
+- bytes_sent = send(fd, p->data + dc->msg_pos, bytes_to_send, 0);
+- if (bytes_sent < 0) {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- return;
+-
+- purple_debug_warning("msn", "msn_dc_send_cb: send error\n");
+- msn_dc_destroy(dc);
+- return;
+- }
+-
+- dc->progress = TRUE;
+-
+- dc->msg_pos += bytes_sent;
+- if (dc->msg_pos == p->length) {
+- if (p->sent_cb != NULL)
+- p->sent_cb(p);
+-
+- g_queue_pop_head(dc->out_queue);
+- msn_dc_destroy_packet(p);
+-
+- dc->msg_pos = -1;
+- }
+-}
+-
+-static void
+-msn_dc_enqueue_packet(MsnDirectConn *dc, MsnDirectConnPacket *p)
+-{
+- gboolean was_empty;
+-
+- was_empty = g_queue_is_empty(dc->out_queue);
+- g_queue_push_tail(dc->out_queue, p);
+-
+- if (was_empty && dc->send_handle == 0) {
+- dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
+- msn_dc_send_cb(dc, dc->fd, PURPLE_INPUT_WRITE);
+- }
+-}
+-
+-static void
+-msn_dc_send_foo(MsnDirectConn *dc)
+-{
+- MsnDirectConnPacket *p;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_send_foo %p\n", dc);
+-
+- p = msn_dc_new_packet(4);
+-
+- memcpy(p->data, "foo\0", 4);
+-
+- msn_dc_enqueue_packet(dc, p);
+-}
+-
+-#if 0 /* We don't actually need this */
+-typedef struct {
+- guint32 null;
+- guint32 id;
+- guint32 null[5];
+- guint32 flags;
+- guint8 nonce[16];
+-} MsnDirectConnNoncePacket;
+-#endif
+-#define DC_NONCE_PACKET_SIZE (8 * 4 + 16)
+-#define DC_NONCE_PACKET_NONCE (8 * 4)
+-
+-static void
+-msn_dc_send_handshake(MsnDirectConn *dc)
+-{
+- MsnDirectConnPacket *p;
+- gchar *h;
+-
+- p = msn_dc_new_packet(DC_NONCE_PACKET_SIZE);
+- h = (gchar *)p->data;
+-
+- msn_push32le(h, 0); /* NUL */
+-
+- msn_push32le(h, dc->slpcall->slplink->slp_seq_id++);
+-
+- /* More NUL stuff */
+- msn_push64le(h, 0);
+- msn_push64le(h, 0);
+- msn_push32le(h, 0);
+-
+- /* Flags */
+- msn_push32le(h, P2P_DC_HANDSHAKE);
+-
+- /* The real Nonce, yay! */
+- memcpy(h, dc->nonce, 16);
+-
+- msn_dc_enqueue_packet(dc, p);
+-}
+-
+-static gboolean
+-msn_dc_verify_handshake(MsnDirectConn *dc, guint32 packet_length)
+-{
+- guchar nonce[16];
+- gchar nonce_hash[37];
+-
+- if (packet_length != DC_NONCE_PACKET_SIZE)
+- return FALSE;
+-
+- memcpy(nonce, dc->in_buffer + 4 + DC_NONCE_PACKET_NONCE, 16);
+-
+- if (dc->nonce_type == DC_NONCE_PLAIN) {
+- if (memcmp(dc->nonce, nonce, 16) == 0) {
+- purple_debug_info("msn",
+- "Nonce from buddy request and nonce from DC attempt match, "
+- "allowing direct connection\n");
+- return TRUE;
+- } else {
+- purple_debug_warning("msn",
+- "Nonce from buddy request and nonce from DC attempt "
+- "don't match, ignoring direct connection\n");
+- return FALSE;
+- }
+-
+- } else if (dc->nonce_type == DC_NONCE_SHA1) {
+- msn_dc_calculate_nonce_hash(dc->nonce_type, nonce, nonce_hash);
+-
+- if (g_str_equal(dc->remote_nonce, nonce_hash)) {
+- purple_debug_info("msn",
+- "Received nonce %s from buddy request "
+- "and calculated nonce %s from DC attempt. "
+- "Nonces match, allowing direct connection\n",
+- dc->remote_nonce, nonce_hash);
+- return TRUE;
+- } else {
+- purple_debug_warning("msn",
+- "Received nonce %s from buddy request "
+- "and calculated nonce %s from DC attempt. "
+- "Nonces don't match, ignoring direct connection\n",
+- dc->remote_nonce, nonce_hash);
+- return FALSE;
+- }
+- } else
+- return FALSE;
+-}
+-
+-static void
+-msn_dc_send_packet_cb(MsnDirectConnPacket *p)
+-{
+- if (p->part != NULL && p->part->ack_cb != NULL)
+- p->part->ack_cb(p->part, p->part->ack_data);
+-}
+-
+-void
+-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part)
+-{
+- MsnDirectConnPacket *p;
+- size_t length;
+-
+- p = msn_dc_new_packet(0);
+- p->data = (guchar *)msn_slpmsgpart_serialize(part, &length);
+- p->length = length - P2P_PACKET_FOOTER_SIZE; /* DC doesn't need footer? */
+-
+- p->sent_cb = msn_dc_send_packet_cb;
+- p->part = msn_slpmsgpart_ref(part);
+-
+- msn_dc_enqueue_packet(dc, p);
+-}
+-
+-static int
+-msn_dc_process_packet(MsnDirectConn *dc, guint32 packet_length)
+-{
+- MsnSlpMessagePart *part;
+-
+- g_return_val_if_fail(dc != NULL, DC_PROCESS_ERROR);
+-
+- switch (dc->state) {
+- case DC_STATE_CLOSED:
+- break;
+-
+- case DC_STATE_FOO:
+- /* FOO message is always 4 bytes long */
+- if (packet_length != 4 || memcmp(dc->in_buffer, "\4\0\0\0foo", 8) != 0)
+- return DC_PROCESS_FALLBACK;
+-
+- dc->state = DC_STATE_HANDSHAKE;
+- break;
+-
+- case DC_STATE_HANDSHAKE:
+- if (!msn_dc_verify_handshake(dc, packet_length))
+- return DC_PROCESS_FALLBACK;
+-
+- msn_dc_send_handshake(dc);
+- dc->state = DC_STATE_ESTABLISHED;
+-
+- msn_slpcall_session_init(dc->slpcall);
+- dc->slpcall = NULL;
+- break;
+-
+- case DC_STATE_HANDSHAKE_REPLY:
+- if (!msn_dc_verify_handshake(dc, packet_length))
+- return DC_PROCESS_FALLBACK;
+-
+- dc->state = DC_STATE_ESTABLISHED;
+-
+- msn_slpcall_session_init(dc->slpcall);
+- dc->slpcall = NULL;
+- break;
+-
+- case DC_STATE_ESTABLISHED:
+- if (packet_length) {
+- MsnP2PVersion p2p;
+- p2p = msn_slplink_get_p2p_version(dc->slplink);
+- part = msn_slpmsgpart_new_from_data(p2p, dc->in_buffer + 4, packet_length);
+- if (part) {
+- msn_slplink_process_msg(dc->slplink, part);
+- msn_slpmsgpart_unref(part);
+- }
+- }
+-
+- /*
+- if (dc->num_calls == 0) {
+- msn_dc_destroy(dc);
+-
+- return DC_PROCESS_CLOSE;
+- }
+- */
+- break;
+- }
+-
+- return DC_PROCESS_OK;
+-}
+-
+-static void
+-msn_dc_recv_cb(gpointer data, gint fd, PurpleInputCondition cond)
+-{
+- MsnDirectConn *dc;
+- int free_buf_space;
+- int bytes_received;
+- guint32 packet_length;
+-
+- g_return_if_fail(data != NULL);
+- g_return_if_fail(fd != -1);
+-
+- dc = data;
+- free_buf_space = dc->in_size - dc->in_pos;
+-
+- bytes_received = recv(fd, dc->in_buffer + dc->in_pos, free_buf_space, 0);
+- if (bytes_received < 0) {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- return;
+-
+- purple_debug_warning("msn", "msn_dc_recv_cb: recv error\n");
+-
+- if(dc->state != DC_STATE_ESTABLISHED)
+- msn_dc_fallback_to_sb(dc);
+- else
+- msn_dc_destroy(dc);
+- return;
+-
+- } else if (bytes_received == 0) {
+- /* EOF. Remote side closed connection. */
+- purple_debug_info("msn", "msn_dc_recv_cb: recv EOF\n");
+-
+- if(dc->state != DC_STATE_ESTABLISHED)
+- msn_dc_fallback_to_sb(dc);
+- else
+- msn_dc_destroy(dc);
+- return;
+- }
+-
+- dc->progress = TRUE;
+-
+- dc->in_pos += bytes_received;
+-
+- /* Wait for packet length */
+- while (dc->in_pos >= 4) {
+- packet_length = GUINT32_FROM_LE(*((guint32*)dc->in_buffer));
+-
+- if (packet_length > DC_MAX_PACKET_SIZE) {
+- /* Oversized packet */
+- purple_debug_warning("msn", "msn_dc_recv_cb: oversized packet received\n");
+- return;
+- }
+-
+- /* Wait for the whole packet to arrive */
+- if (dc->in_pos < 4 + packet_length)
+- return;
+-
+- switch (msn_dc_process_packet(dc, packet_length)) {
+- case DC_PROCESS_CLOSE:
+- return;
+-
+- case DC_PROCESS_FALLBACK:
+- purple_debug_warning("msn", "msn_dc_recv_cb: packet processing error, fall back to SB\n");
+- msn_dc_fallback_to_sb(dc);
+- return;
+-
+- }
+-
+- if (dc->in_pos > packet_length + 4) {
+- g_memmove(dc->in_buffer, dc->in_buffer + 4 + packet_length, dc->in_pos - packet_length - 4);
+- }
+-
+- dc->in_pos -= packet_length + 4;
+- }
+-}
+-
+-static gboolean
+-msn_dc_timeout(gpointer data)
+-{
+- MsnDirectConn *dc = data;
+-
+- g_return_val_if_fail(dc != NULL, FALSE);
+-
+- if (dc->progress) {
+- dc->progress = FALSE;
+- return TRUE;
+- } else {
+- dc->timeout_handle = 0;
+- msn_dc_destroy(dc);
+- return FALSE;
+- }
+-}
+-
+-static void
+-msn_dc_init(MsnDirectConn *dc)
+-{
+- g_return_if_fail(dc != NULL);
+-
+- dc->in_size = DC_MAX_PACKET_SIZE + 4;
+- dc->in_pos = 0;
+- dc->in_buffer = g_malloc(dc->in_size);
+-
+- dc->recv_handle = purple_input_add(dc->fd, PURPLE_INPUT_READ, msn_dc_recv_cb, dc);
+- dc->send_handle = purple_input_add(dc->fd, PURPLE_INPUT_WRITE, msn_dc_send_cb, dc);
+-
+- dc->timeout_handle = purple_timeout_add_seconds(DC_TIMEOUT, msn_dc_timeout, dc);
+-}
+-
+-void
+-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg)
+-{
+- MsnDirectConn *dc = data;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_connected_to_peer_cb %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- dc->connect_data = NULL;
+- purple_timeout_remove(dc->connect_timeout_handle);
+- dc->connect_timeout_handle = 0;
+-
+- dc->fd = fd;
+- if (dc->fd != -1) {
+- msn_dc_init(dc);
+- msn_dc_send_foo(dc);
+- msn_dc_send_handshake(dc);
+- dc->state = DC_STATE_HANDSHAKE_REPLY;
+- }
+-}
+-
+-/*
+- * This callback will be called when we're the server
+- * and nobody has connected us in DC_INCOMING_TIMEOUT seconds
+- */
+-static gboolean
+-msn_dc_incoming_connection_timeout_cb(gpointer data) {
+- MsnDirectConn *dc = data;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_incoming_connection_timeout_cb %p\n", dc);
+-
+- g_return_val_if_fail(dc != NULL, FALSE);
+-
+- if (dc->listen_data != NULL) {
+- purple_network_listen_cancel(dc->listen_data);
+- dc->listen_data = NULL;
+- }
+-
+- if (dc->listenfd_handle != 0) {
+- purple_input_remove(dc->listenfd_handle);
+- dc->listenfd_handle = 0;
+- }
+-
+- if (dc->listenfd != -1) {
+- purple_network_remove_port_mapping(dc->listenfd);
+- close(dc->listenfd);
+- dc->listenfd = -1;
+- }
+-
+- dc->connect_timeout_handle = 0;
+- msn_dc_fallback_to_sb(dc);
+-
+- return FALSE;
+-}
+-
+-/*
+- * This callback will be called when we're unable to connect to
+- * the remote host in DC_OUTGOING_TIMEOUT seconds.
+- */
+-gboolean
+-msn_dc_outgoing_connection_timeout_cb(gpointer data)
+-{
+- MsnDirectConn *dc = data;
+-
+- purple_debug_info("msn", "msn_dc_outgoing_connection_timeout_cb %p\n", dc);
+-
+- g_return_val_if_fail(dc != NULL, FALSE);
+-
+- dc->connect_timeout_handle = 0;
+-
+- if (dc->connect_data != NULL) {
+- purple_proxy_connect_cancel(dc->connect_data);
+- dc->connect_data = NULL;
+- }
+-
+- if (dc->ext_ip && dc->ext_port) {
+- /* Try external IP/port if available. */
+- dc->connect_data = purple_proxy_connect(
+- NULL,
+- dc->slpcall->slplink->session->account,
+- dc->ext_ip,
+- dc->ext_port,
+- msn_dc_connected_to_peer_cb,
+- dc
+- );
+-
+- g_free(dc->ext_ip);
+- dc->ext_ip = NULL;
+-
+- if (dc->connect_data) {
+- dc->connect_timeout_handle = purple_timeout_add_seconds(
+- DC_OUTGOING_TIMEOUT,
+- msn_dc_outgoing_connection_timeout_cb,
+- dc
+- );
+- } else {
+- /*
+- * Connection failed
+- * Fall back to SB transfer
+- */
+- msn_dc_outgoing_connection_timeout_cb(dc);
+- }
+-
+- } else {
+- /*
+- * Both internal and external connection attempts failed.
+- * Fall back to SB transfer.
+- */
+- msn_dc_fallback_to_sb(dc);
+- }
+-
+- return FALSE;
+-}
+-
+-/*
+- * This callback will be called when we're the server
+- * and somebody has connected to us in DC_INCOMING_TIMEOUT seconds.
+- */
+-static void
+-msn_dc_incoming_connection_cb(gpointer data, gint listenfd, PurpleInputCondition cond)
+-{
+- MsnDirectConn *dc = data;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_incoming_connection_cb %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- if (dc->connect_timeout_handle != 0) {
+- purple_timeout_remove(dc->connect_timeout_handle);
+- dc->connect_timeout_handle = 0;
+- }
+-
+- if (dc->listenfd_handle != 0) {
+- purple_input_remove(dc->listenfd_handle);
+- dc->listenfd_handle = 0;
+- }
+-
+- dc->fd = accept(listenfd, NULL, 0);
+-
+- purple_network_remove_port_mapping(dc->listenfd);
+- close(dc->listenfd);
+- dc->listenfd = -1;
+-
+- if (dc->fd != -1) {
+- msn_dc_init(dc);
+- dc->state = DC_STATE_FOO;
+- }
+-}
+-
+-void
+-msn_dc_listen_socket_created_cb(int listenfd, gpointer data)
+-{
+- MsnDirectConn *dc = data;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_dc_listen_socket_created_cb %p\n", dc);
+-
+- g_return_if_fail(dc != NULL);
+-
+- dc->listen_data = NULL;
+-
+- if (listenfd != -1) {
+- const char *ext_ip;
+- const char *int_ip;
+- int port;
+-
+- ext_ip = purple_network_get_my_ip(listenfd);
+- int_ip = purple_network_get_local_system_ip(listenfd);
+- port = purple_network_get_port_from_fd(listenfd);
+-
+- dc->listenfd = listenfd;
+- dc->listenfd_handle = purple_input_add(
+- listenfd,
+- PURPLE_INPUT_READ,
+- msn_dc_incoming_connection_cb,
+- dc
+- );
+- dc->connect_timeout_handle = purple_timeout_add_seconds(
+- DC_INCOMING_TIMEOUT,
+- msn_dc_incoming_connection_timeout_cb,
+- dc
+- );
+-
+- if (strcmp(int_ip, ext_ip) != 0) {
+- dc->msg_body = g_strdup_printf(
+- "Bridge: TCPv1\r\n"
+- "Listening: true\r\n"
+- "%sNonce: {%s}\r\n"
+- "IPv4External-Addrs: %s\r\n"
+- "IPv4External-Port: %d\r\n"
+- "IPv4Internal-Addrs: %s\r\n"
+- "IPv4Internal-Port: %d\r\n"
+- "\r\n",
+-
+- dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
+- dc->nonce_hash,
+- ext_ip,
+- port,
+- int_ip,
+- port
+- );
+-
+- } else {
+- dc->msg_body = g_strdup_printf(
+- "Bridge: TCPv1\r\n"
+- "Listening: true\r\n"
+- "%sNonce: {%s}\r\n"
+- "IPv4External-Addrs: %s\r\n"
+- "IPv4External-Port: %d\r\n"
+- "\r\n",
+-
+- dc->nonce_type != DC_NONCE_PLAIN ? "Hashed-" : "",
+- dc->nonce_hash,
+- ext_ip,
+- port
+- );
+- }
+-
+- if (dc->slpcall->wait_for_socket) {
+- if (dc->send_connection_info_msg_cb != NULL)
+- dc->send_connection_info_msg_cb(dc);
+-
+- dc->slpcall->wait_for_socket = FALSE;
+- }
+- }
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/directconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.h
+--- pidgin-2.10.7/libpurple/protocols/msn/directconn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/directconn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,200 +0,0 @@
+-/**
+- * @file directconn.h MSN direct connection functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_DIRECTCONN_H
+-#define MSN_DIRECTCONN_H
+-
+-typedef struct _MsnDirectConn MsnDirectConn;
+-
+-#include "network.h"
+-#include "proxy.h"
+-#include "circbuffer.h"
+-
+-#include "slp.h"
+-#include "slplink.h"
+-#include "slpmsg.h"
+-#include "slpmsg_part.h"
+-#include "p2p.h"
+-
+-#define MSN_DCCONN_MAX_SIZE 1352
+-
+-typedef enum
+-{
+- DC_STATE_CLOSED, /*< No socket opened yet */
+- DC_STATE_FOO, /*< Waiting for FOO message */
+- DC_STATE_HANDSHAKE, /*< Waiting for handshake message */
+- DC_STATE_HANDSHAKE_REPLY, /*< Waiting for handshake reply message */
+- DC_STATE_ESTABLISHED /*< Handshake complete */
+-} MsnDirectConnState;
+-
+-typedef enum
+-{
+- DC_PROCESS_OK = 0,
+- DC_PROCESS_ERROR,
+- DC_PROCESS_FALLBACK,
+- DC_PROCESS_CLOSE
+-
+-} MsnDirectConnProcessResult;
+-
+-typedef enum
+-{
+- DC_NONCE_UNKNOWN, /**< Invalid scheme */
+- DC_NONCE_PLAIN, /**< No hashing */
+- DC_NONCE_SHA1 /**< First 16 bytes of SHA1 of nonce */
+-
+-} MsnDirectConnNonceType;
+-
+-typedef struct _MsnDirectConnPacket MsnDirectConnPacket;
+-
+-struct _MsnDirectConnPacket {
+- guint32 length;
+- guchar *data;
+-
+- void (*sent_cb)(struct _MsnDirectConnPacket*);
+- MsnSlpMessagePart *part;
+-};
+-
+-struct _MsnDirectConn
+-{
+- MsnDirectConnState state; /**< Direct connection status */
+- MsnSlpLink *slplink; /**< The slplink using this direct connection */
+- MsnSlpCall *slpcall; /**< The slpcall which initiated the direct connection */
+- char *msg_body; /**< The body of message sent by send_connection_info_msg_cb */
+- MsnSlpMessage *prev_ack; /**< The saved SLP ACK message */
+-
+- MsnDirectConnNonceType nonce_type; /**< The type of nonce hashing */
+- guchar nonce[16]; /**< The nonce used for handshake */
+- gchar nonce_hash[37]; /**< The hash of nonce */
+- gchar remote_nonce[37]; /**< The remote side's nonce */
+-
+- PurpleNetworkListenData *listen_data; /**< The pending socket creation request */
+- PurpleProxyConnectData *connect_data; /**< The pending connection attempt */
+- int listenfd; /**< The socket we're listening for incoming connections */
+- guint listenfd_handle; /**< The timeout handle for incoming connection */
+- guint connect_timeout_handle; /**< The timeout handle for outgoing connection */
+-
+- int fd; /**< The direct connection socket */
+- guint recv_handle; /**< The incoming data callback handle */
+- guint send_handle; /**< The outgoing data callback handle */
+-
+- gchar *in_buffer; /**< The receive buffer */
+- int in_size; /**< The receive buffer size */
+- int in_pos; /**< The first free position in receive buffer */
+- GQueue *out_queue; /**< The outgoing packet queue */
+- int msg_pos; /**< The position of next byte to be sent in the actual packet */
+-
+- /** The callback used for sending information to the peer about the opened socket */
+- void (*send_connection_info_msg_cb)(MsnDirectConn *);
+-
+- gchar *ext_ip; /**< Our external IP address */
+- int ext_port; /**< Our external port */
+-
+- guint timeout_handle;
+- gboolean progress;
+-
+- /*int num_calls;*/ /**< The number of slpcalls using this direct connection */
+-};
+-
+-/* Outgoing attempt */
+-#define DC_OUTGOING_TIMEOUT (5)
+-/* Time for internal + external connection attempts */
+-#define DC_INCOMING_TIMEOUT (DC_OUTGOING_TIMEOUT * 3)
+-/* Timeout for lack of activity */
+-#define DC_TIMEOUT (60)
+-
+-/*
+- * Queues an MSN message to be sent via direct connection.
+- */
+-void
+-msn_dc_enqueue_part(MsnDirectConn *dc, MsnSlpMessagePart *part);
+-
+-/*
+- * Creates, initializes, and returns a new MsnDirectConn structure.
+- */
+-MsnDirectConn *
+-msn_dc_new(MsnSlpCall *slpcall);
+-
+-/*
+- * Destroys an MsnDirectConn structure. Frees every buffer allocated earlier
+- * restores saved callbacks, etc.
+- */
+-void
+-msn_dc_destroy(MsnDirectConn *dc);
+-
+-/*
+- * Fallback to switchboard connection. Used when neither side is able to
+- * create a listening socket.
+- */
+-void
+-msn_dc_fallback_to_sb(MsnDirectConn *dc);
+-
+-/*
+- * Increases the slpcall counter in DC. The direct connection remains open
+- * until all slpcalls using it are destroyed.
+- */
+-void
+-msn_dc_ref(MsnDirectConn *dc);
+-
+-/*
+- * Decrease the slpcall counter in DC. The direct connection remains open
+- * until all slpcalls using it are destroyed.
+- */
+-void
+-msn_dc_unref(MsnDirectConn *dc);
+-
+-/*
+- * Sends a direct connect INVITE message on the associated slplink
+- * with the corresponding connection type and information.
+- */
+-void
+-msn_dc_send_invite(MsnDirectConn *dc);
+-
+-/*
+- * Sends a direct connect OK message as a response to an INVITE received earliaer
+- * on the corresponding slplink.
+- */
+-void
+-msn_dc_send_ok(MsnDirectConn *dc);
+-
+-/*
+- * This callback will be called when we're successfully connected to
+- * the remote host.
+- */
+-void
+-msn_dc_connected_to_peer_cb(gpointer data, gint fd, const gchar *error_msg);
+-
+-/*
+- * This callback will be called when we're unable to connect to
+- * the remote host in DC_CONNECT_TIMEOUT seconds.
+- */
+-gboolean
+-msn_dc_outgoing_connection_timeout_cb(gpointer data);
+-
+-/*
+- * This callback will be called when the listening socket is successfully
+- * created and its parameters (IP/port) are available.
+- */
+-void
+-msn_dc_listen_socket_created_cb(int listenfd, gpointer data);
+-
+-#endif /* MSN_DIRECTCONN_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/error.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.c
+--- pidgin-2.10.7/libpurple/protocols/msn/error.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,384 +0,0 @@
+-/**
+- * @file error.c Error functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-/* Masca: can we get rid of the sync issue dialog? */
+-#include "request.h"
+-
+-#include "error.h"
+-
+-typedef struct
+-{
+- MsnSession *session;
+- char *who;
+- char *group;
+- gboolean add;
+-
+-} MsnAddRemData;
+-
+-const char *
+-msn_error_get_text(unsigned int type, gboolean *debug)
+-{
+- static char msg[256];
+- const char *result;
+- *debug = FALSE;
+-
+- switch (type) {
+- case 0:
+- result = _("Unable to parse message");
+- *debug = TRUE;
+- break;
+- case 200:
+- result = _("Syntax Error (probably a client bug)");
+- *debug = TRUE;
+- break;
+- case 201:
+- result = _("Invalid email address");
+- break;
+- case 205:
+- result = _("User does not exist");
+- break;
+- case 206:
+- result = _("Fully qualified domain name missing");
+- break;
+- case 207:
+- result = _("Already logged in");
+- break;
+- case 208:
+- result = _("Invalid username");
+- break;
+- case 209:
+- result = _("Invalid friendly name");
+- break;
+- case 210:
+- result = _("List full");
+- break;
+- case 215:
+- result = _("Already there");
+- *debug = TRUE;
+- break;
+- case 216:
+- result = _("Not on list");
+- break;
+- case 217:
+- result = _("User is offline");
+- break;
+- case 218:
+- result = _("Already in the mode");
+- *debug = TRUE;
+- break;
+- case 219:
+- result = _("Already in opposite list");
+- *debug = TRUE;
+- break;
+- case 223:
+- result = _("Too many groups");
+- break;
+- case 224:
+- result = _("Invalid group");
+- break;
+- case 225:
+- result = _("User not in group");
+- break;
+- case 229:
+- result = _("Group name too long");
+- break;
+- case 230:
+- result = _("Cannot remove group zero");
+- *debug = TRUE;
+- break;
+- case 231:
+- result = _("Tried to add a user to a group that doesn't exist");
+- break;
+- case 280:
+- result = _("Switchboard failed");
+- *debug = TRUE;
+- break;
+- case 281:
+- result = _("Notify transfer failed");
+- *debug = TRUE;
+- break;
+-
+- case 300:
+- result = _("Required fields missing");
+- *debug = TRUE;
+- break;
+- case 301:
+- result = _("Too many hits to a FND");
+- *debug = TRUE;
+- break;
+- case 302:
+- result = _("Not logged in");
+- break;
+-
+- case 500:
+- result = _("Service temporarily unavailable");
+- break;
+- case 501:
+- result = _("Database server error");
+- *debug = TRUE;
+- break;
+- case 502:
+- result = _("Command disabled");
+- *debug = TRUE;
+- break;
+- case 510:
+- result = _("File operation error");
+- *debug = TRUE;
+- break;
+- case 520:
+- result = _("Memory allocation error");
+- *debug = TRUE;
+- break;
+- case 540:
+- result = _("Wrong CHL value sent to server");
+- *debug = TRUE;
+- break;
+-
+- case 600:
+- result = _("Server busy");
+- break;
+- case 601:
+- result = _("Server unavailable");
+- break;
+- case 602:
+- result = _("Peer notification server down");
+- *debug = TRUE;
+- break;
+- case 603:
+- result = _("Database connect error");
+- *debug = TRUE;
+- break;
+- case 604:
+- result = _("Server is going down (abandon ship)");
+- break;
+- case 605:
+- result = _("Server unavailable");
+- break;
+-
+- case 707:
+- result = _("Error creating connection");
+- *debug = TRUE;
+- break;
+- case 710:
+- result = _("CVR parameters are either unknown or not allowed");
+- *debug = TRUE;
+- break;
+- case 711:
+- result = _("Unable to write");
+- break;
+- case 712:
+- result = _("Session overload");
+- *debug = TRUE;
+- break;
+- case 713:
+- result = _("User is too active");
+- break;
+- case 714:
+- result = _("Too many sessions");
+- break;
+- case 715:
+- result = _("Passport not verified");
+- break;
+- case 717:
+- result = _("Bad friend file");
+- *debug = TRUE;
+- break;
+- case 731:
+- result = _("Not expected");
+- *debug = TRUE;
+- break;
+-
+- case 800:
+- result = _("Friendly name is changing too rapidly");
+- break;
+-
+- case 910:
+- case 912:
+- case 918:
+- case 919:
+- case 921:
+- case 922:
+- result = _("Server too busy");
+- break;
+- case 911:
+- case 917:
+- result = _("Authentication failed");
+- break;
+- case 913:
+- result = _("Not allowed when offline");
+- break;
+- case 914:
+- case 915:
+- case 916:
+- result = _("Server unavailable");
+- break;
+- case 920:
+- result = _("Not accepting new users");
+- break;
+- case 923:
+- result = _("Kids Passport without parental consent");
+- break;
+- case 924:
+- result = _("Passport account not yet verified");
+- break;
+- case 927:
+- result = _("Passport account suspended");
+- break;
+- case 928:
+- result = _("Bad ticket");
+- *debug = TRUE;
+- break;
+-
+- default:
+- g_snprintf(msg, sizeof(msg),
+- _("Unknown Error Code %d"), type);
+- *debug = TRUE;
+- result = msg;
+- break;
+- }
+-
+- return result;
+-}
+-
+-void
+-msn_error_handle(MsnSession *session, unsigned int type)
+-{
+- char *buf;
+- gboolean debug;
+-
+- buf = g_strdup_printf(_("MSN Error: %s\n"),
+- msn_error_get_text(type, &debug));
+- if (debug)
+- purple_debug_warning("msn", "error %d: %s\n", type, buf);
+- else
+- purple_notify_error(session->account->gc, NULL, buf, NULL);
+- g_free(buf);
+-}
+-
+-/* Remove the buddy referenced by the MsnAddRemData before the serverside list
+- * is changed. If the buddy will be added, he'll be added back; if he will be
+- * removed, he won't be. */
+-/* Actually with our MSNP14 code that isn't true yet, he won't be added back :(
+- * */
+-static void
+-msn_complete_sync_issue(MsnAddRemData *data)
+-{
+- PurpleBuddy *buddy;
+- PurpleGroup *group = NULL;
+-
+- if (data->group != NULL)
+- group = purple_find_group(data->group);
+-
+- if (group != NULL)
+- buddy = purple_find_buddy_in_group(data->session->account, data->who, group);
+- else
+- buddy = purple_find_buddy(data->session->account, data->who);
+-
+- if (buddy != NULL)
+- purple_blist_remove_buddy(buddy);
+-}
+-
+-
+-static void
+-msn_add_cb(MsnAddRemData *data)
+-{
+-#if 0
+- /* this *should* be necessary !! */
+- msn_complete_sync_issue(data);
+-#endif
+- MsnUserList *userlist = data->session->userlist;
+-
+- msn_userlist_add_buddy(userlist, data->who, data->group);
+-
+- g_free(data->group);
+- g_free(data->who);
+- g_free(data);
+-}
+-
+-static void
+-msn_rem_cb(MsnAddRemData *data)
+-{
+- MsnUserList *userlist = data->session->userlist;
+- msn_complete_sync_issue(data);
+-
+-
+- if (data->group == NULL) {
+- msn_userlist_rem_buddy_from_list(userlist, data->who, MSN_LIST_FL);
+- } else {
+- g_free(data->group);
+- }
+-
+- g_free(data->who);
+- g_free(data);
+-}
+-
+-void
+-msn_error_sync_issue(MsnSession *session, const char *passport,
+- const char *group_name)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- MsnAddRemData *data;
+- char *msg, *reason;
+-
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- data = g_new0(MsnAddRemData, 1);
+- data->who = g_strdup(passport);
+- data->group = g_strdup(group_name);
+- data->session = session;
+-
+- msg = g_strdup_printf(_("Buddy list synchronization issue in %s (%s)"),
+- purple_account_get_username(account),
+- purple_account_get_protocol_name(account));
+-
+- if (group_name != NULL)
+- {
+- reason = g_strdup_printf(_("%s on the local list is "
+- "inside the group \"%s\" but not on "
+- "the server list. "
+- "Do you want this buddy to be added?"),
+- passport, group_name);
+- }
+- else
+- {
+- reason = g_strdup_printf(_("%s is on the local list but "
+- "not on the server list. "
+- "Do you want this buddy to be added?"),
+- passport);
+- }
+-
+- purple_request_action(gc, NULL, msg, reason, PURPLE_DEFAULT_ACTION_NONE,
+- account, data->who, NULL,
+- data, 2,
+- _("Yes"), G_CALLBACK(msn_add_cb),
+- _("No"), G_CALLBACK(msn_rem_cb));
+-
+- g_free(reason);
+- g_free(msg);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/error.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.h
+--- pidgin-2.10.7/libpurple/protocols/msn/error.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/error.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,57 +0,0 @@
+-/**
+- * @file error.h Error functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_ERROR_H
+-#define MSN_ERROR_H
+-
+-#include "session.h"
+-
+-/**
+- * Returns the string representation of an error type.
+- *
+- * @param type The error type.
+- * @param debug Whether this should be treated as a debug log message or a user-visible error
+- *
+- * @return The string representation of the error type.
+- */
+-const char *msn_error_get_text(unsigned int type, gboolean *debug);
+-
+-/**
+- * Handles an error.
+- *
+- * @param session The current session.
+- * @param type The error type.
+- */
+-void msn_error_handle(MsnSession *session, unsigned int type);
+-
+-/**
+- * Show the sync issue in a dialog using request api
+- *
+- * @param sesion MsnSession associated to this error.
+- * @param passport The passport associated with the error.
+- * @param group_name The group in the buddy is suppoused to be
+- */
+-void msn_error_sync_issue(MsnSession *session, const char *passport,
+- const char *group_name);
+-
+-#endif /* MSN_ERROR_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/group.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.c
+--- pidgin-2.10.7/libpurple/protocols/msn/group.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,89 +0,0 @@
+-/**
+- * @file group.c Group functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "msn.h"
+-#include "group.h"
+-
+-MsnGroup *
+-msn_group_new(MsnUserList *userlist, const char *id, const char *name)
+-{
+- MsnGroup *group;
+-
+- g_return_val_if_fail(id != NULL, NULL);
+- g_return_val_if_fail(name != NULL, NULL);
+-
+- group = g_new0(MsnGroup, 1);
+-
+- msn_userlist_add_group(userlist, group);
+-
+- group->id = g_strdup(id);
+- group->name = g_strdup(name);
+-
+- return group;
+-}
+-
+-void
+-msn_group_destroy(MsnGroup *group)
+-{
+- g_return_if_fail(group != NULL);
+-
+- g_free(group->id);
+- g_free(group->name);
+- g_free(group);
+-}
+-
+-void
+-msn_group_set_id(MsnGroup *group, const char *id)
+-{
+- g_return_if_fail(group != NULL);
+- g_return_if_fail(id != NULL);
+-
+- g_free(group->id);
+- group->id = g_strdup(id);
+-}
+-
+-void
+-msn_group_set_name(MsnGroup *group, const char *name)
+-{
+- g_return_if_fail(group != NULL);
+- g_return_if_fail(name != NULL);
+-
+- g_free(group->name);
+- group->name = g_strdup(name);
+-}
+-
+-char*
+-msn_group_get_id(const MsnGroup *group)
+-{
+- g_return_val_if_fail(group != NULL, NULL);
+-
+- return group->id;
+-}
+-
+-const char *
+-msn_group_get_name(const MsnGroup *group)
+-{
+- g_return_val_if_fail(group != NULL, NULL);
+-
+- return group->name;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/group.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.h
+--- pidgin-2.10.7/libpurple/protocols/msn/group.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/group.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,109 +0,0 @@
+-/**
+- * @file group.h Group functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_GROUP_H
+-#define MSN_GROUP_H
+-
+-typedef struct _MsnGroup MsnGroup;
+-
+-#include "internal.h"
+-
+-#include "session.h"
+-#include "user.h"
+-#include "userlist.h"
+-
+-#define MSN_INDIVIDUALS_GROUP_ID "1983"
+-#define MSN_INDIVIDUALS_GROUP_NAME _("Other Contacts")
+-
+-#define MSN_NON_IM_GROUP_ID "email"
+-#define MSN_NON_IM_GROUP_NAME _("Non-IM Contacts")
+-
+-/**
+- * A group.
+- */
+-struct _MsnGroup
+-{
+- MsnSession *session; /**< The MSN session. */
+-
+- char *id; /**< The group ID. */
+- char *name; /**< The name of the group. */
+-};
+-
+-/**************************************************************************
+- ** @name Group API *
+- **************************************************************************/
+-/*@{*/
+-
+-/**
+- * Creates a new group structure.
+- *
+- * @param session The MSN session.
+- * @param id The group ID.
+- * @param name The name of the group.
+- *
+- * @return A new group structure.
+- */
+-MsnGroup *msn_group_new(MsnUserList *userlist, const char *id, const char *name);
+-
+-/**
+- * Destroys a group structure.
+- *
+- * @param group The group to destroy.
+- */
+-void msn_group_destroy(MsnGroup *group);
+-
+-/**
+- * Sets the ID for a group.
+- *
+- * @param group The group.
+- * @param id The ID.
+- */
+-void msn_group_set_id(MsnGroup *group, const char *id);
+-
+-/**
+- * Sets the name for a group.
+- *
+- * @param group The group.
+- * @param name The name.
+- */
+-void msn_group_set_name(MsnGroup *group, const char *name);
+-
+-/**
+- * Returns the ID for a group.
+- *
+- * @param group The group.
+- *
+- * @return The ID.
+- */
+-char* msn_group_get_id(const MsnGroup *group);
+-
+-/**
+- * Returns the name for a group.
+- *
+- * @param group The group.
+- *
+- * @return The name.
+- */
+-const char *msn_group_get_name(const MsnGroup *group);
+-
+-#endif /* MSN_GROUP_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/history.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.c
+--- pidgin-2.10.7/libpurple/protocols/msn/history.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-/**
+- * @file history.c MSN history functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "msn.h"
+-#include "history.h"
+-
+-MsnHistory *
+-msn_history_new(void)
+-{
+- MsnHistory *history = g_new0(MsnHistory, 1);
+-
+- history->trId = 1;
+-
+- history->queue = g_queue_new();
+-
+- return history;
+-}
+-
+-void
+-msn_history_destroy(MsnHistory *history)
+-{
+- MsnTransaction *trans;
+-
+- while ((trans = g_queue_pop_head(history->queue)) != NULL)
+- msn_transaction_destroy(trans);
+-
+- g_queue_free(history->queue);
+- g_free(history);
+-}
+-
+-MsnTransaction *
+-msn_history_find(MsnHistory *history, unsigned int trId)
+-{
+- MsnTransaction *trans;
+- GList *list;
+-
+- for (list = history->queue->head; list != NULL; list = list->next)
+- {
+- trans = list->data;
+- if (trans->trId == trId)
+- return trans;
+- }
+-
+- return NULL;
+-}
+-
+-void
+-msn_history_add(MsnHistory *history, MsnTransaction *trans)
+-{
+- GQueue *queue;
+- int max_elems;
+-
+- g_return_if_fail(history != NULL);
+- g_return_if_fail(trans != NULL);
+-
+- queue = history->queue;
+-
+- trans->trId = history->trId++;
+-
+- g_queue_push_tail(queue, trans);
+-
+- if (trans->cmdproc->servconn->type == MSN_SERVCONN_NS)
+- max_elems = MSN_NS_HIST_ELEMS;
+- else
+- max_elems = MSN_SB_HIST_ELEMS;
+-
+- if (queue->length > max_elems)
+- {
+- trans = g_queue_pop_head(queue);
+- msn_transaction_destroy(trans);
+- }
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/history.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.h
+--- pidgin-2.10.7/libpurple/protocols/msn/history.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/history.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,50 +0,0 @@
+-/**
+- * @file history.h MSN history functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_HISTORY_H
+-#define MSN_HISTORY_H
+-
+-#include "internal.h"
+-
+-typedef struct _MsnHistory MsnHistory;
+-
+-#include "transaction.h"
+-
+-#define MSN_NS_HIST_ELEMS 0x300
+-#define MSN_SB_HIST_ELEMS 0x30
+-
+-/**
+- * The history.
+- */
+-struct _MsnHistory
+-{
+- GQueue *queue;
+- unsigned int trId;
+-};
+-
+-MsnHistory *msn_history_new(void);
+-void msn_history_destroy(MsnHistory *history);
+-MsnTransaction *msn_history_find(MsnHistory *history, unsigned int triId);
+-void msn_history_add(MsnHistory *history, MsnTransaction *trans);
+-
+-#endif /* MSN_HISTORY_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/httpconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.c
+--- pidgin-2.10.7/libpurple/protocols/msn/httpconn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,739 +0,0 @@
+-/**
+- * @file httpconn.c HTTP connection method
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "msn.h"
+-#include "debug.h"
+-#include "httpconn.h"
+-
+-typedef struct
+-{
+- MsnHttpConn *httpconn;
+- char *body;
+- size_t body_len;
+-} MsnHttpQueueData;
+-
+-static void
+-msn_httpconn_process_queue(MsnHttpConn *httpconn)
+-{
+- httpconn->waiting_response = FALSE;
+-
+- if (httpconn->queue != NULL)
+- {
+- MsnHttpQueueData *queue_data;
+-
+- queue_data = (MsnHttpQueueData *)httpconn->queue->data;
+-
+- httpconn->queue = g_list_remove(httpconn->queue, queue_data);
+-
+- msn_httpconn_write(queue_data->httpconn,
+- queue_data->body,
+- queue_data->body_len);
+-
+- g_free(queue_data->body);
+- g_free(queue_data);
+- }
+-}
+-
+-static gboolean
+-msn_httpconn_parse_data(MsnHttpConn *httpconn, const char *buf,
+- size_t size, char **ret_buf, size_t *ret_size,
+- gboolean *error)
+-{
+- const char *s, *c;
+- char *header, *body;
+- const char *body_start;
+- char *tmp;
+- size_t body_len = 0;
+-
+- g_return_val_if_fail(httpconn != NULL, FALSE);
+- g_return_val_if_fail(buf != NULL, FALSE);
+- g_return_val_if_fail(size > 0, FALSE);
+- g_return_val_if_fail(ret_buf != NULL, FALSE);
+- g_return_val_if_fail(ret_size != NULL, FALSE);
+- g_return_val_if_fail(error != NULL, FALSE);
+-
+-#if 0
+- purple_debug_info("msn", "HTTP: parsing data {%s}\n", buf);
+-#endif
+-
+- /* Healthy defaults. */
+- body = NULL;
+-
+- *ret_buf = NULL;
+- *ret_size = 0;
+- *error = FALSE;
+-
+- /* First, some tests to see if we have a full block of stuff. */
+- if (((strncmp(buf, "HTTP/1.1 200 OK\r\n", 17) != 0) &&
+- (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) != 0)) &&
+- ((strncmp(buf, "HTTP/1.0 200 OK\r\n", 17) != 0) &&
+- (strncmp(buf, "HTTP/1.0 100 Continue\r\n", 23) != 0)))
+- {
+- *error = TRUE;
+-
+- return FALSE;
+- }
+-
+- if (strncmp(buf, "HTTP/1.1 100 Continue\r\n", 23) == 0)
+- {
+- if ((s = strstr(buf, "\r\n\r\n")) == NULL)
+- return FALSE;
+-
+- s += 4;
+-
+- if (*s == '\0')
+- {
+- *ret_buf = g_strdup("");
+- *ret_size = 0;
+-
+- msn_httpconn_process_queue(httpconn);
+-
+- return TRUE;
+- }
+-
+- size -= (s - buf);
+- buf = s;
+- }
+-
+- if ((s = strstr(buf, "\r\n\r\n")) == NULL)
+- /* Need to wait for the full HTTP header to arrive */
+- return FALSE;
+-
+- s += 4; /* Skip \r\n\r\n */
+- header = g_strndup(buf, s - buf);
+- body_start = s;
+- body_len = size - (body_start - buf);
+-
+- if ((s = purple_strcasestr(header, "Content-Length: ")) != NULL)
+- {
+- int tmp_len;
+-
+- s += strlen("Content-Length: ");
+-
+- if ((c = strchr(s, '\r')) == NULL)
+- {
+- g_free(header);
+-
+- return FALSE;
+- }
+-
+- tmp = g_strndup(s, c - s);
+- tmp_len = atoi(tmp);
+- g_free(tmp);
+-
+- if (body_len != tmp_len)
+- {
+- /* Need to wait for the full packet to arrive */
+-
+- g_free(header);
+-
+-#if 0
+- purple_debug_warning("msn",
+- "body length (%d) != content length (%d)\n",
+- body_len, tmp_len);
+-#endif
+-
+- return FALSE;
+- }
+- }
+-
+- body = g_malloc(body_len + 1);
+- memcpy(body, body_start, body_len);
+- body[body_len] = '\0';
+-
+- if (purple_debug_is_verbose())
+- purple_debug_misc("msn", "Incoming HTTP buffer (header): {%s}\n",
+- header);
+-
+- /* Now we should be able to process the data. */
+- if ((s = purple_strcasestr(header, "X-MSN-Messenger: ")) != NULL)
+- {
+- gchar *full_session_id = NULL, *gw_ip = NULL, *session_action = NULL;
+- char *t, *session_id;
+- char **elems, **cur, **tokens;
+-
+- full_session_id = gw_ip = session_action = NULL;
+-
+- s += strlen("X-MSN-Messenger: ");
+-
+- if ((c = strchr(s, '\r')) == NULL)
+- {
+- msn_session_set_error(httpconn->session,
+- MSN_ERROR_HTTP_MALFORMED, NULL);
+- purple_debug_error("msn", "Malformed X-MSN-Messenger field.\n{%s}\n",
+- buf);
+-
+- g_free(header);
+- g_free(body);
+- return FALSE;
+- }
+-
+- tmp = g_strndup(s, c - s);
+-
+- elems = g_strsplit(tmp, "; ", 0);
+-
+- for (cur = elems; *cur != NULL; cur++)
+- {
+- tokens = g_strsplit(*cur, "=", 2);
+-
+- if (strcmp(tokens[0], "SessionID") == 0) {
+- g_free(full_session_id);
+- full_session_id = tokens[1];
+- } else if (strcmp(tokens[0], "GW-IP") == 0) {
+- g_free(gw_ip);
+- gw_ip = tokens[1];
+- } else if (strcmp(tokens[0], "Session") == 0) {
+- g_free(session_action);
+- session_action = tokens[1];
+- } else
+- g_free(tokens[1]);
+-
+- g_free(tokens[0]);
+- /* Don't free each of the tokens, only the array. */
+- g_free(tokens);
+- }
+-
+- g_strfreev(elems);
+-
+- g_free(tmp);
+-
+- t = full_session_id ? strchr(full_session_id, '.') : NULL;
+- if (t != NULL)
+- session_id = g_strndup(full_session_id, t - full_session_id);
+- else {
+- purple_debug_error("msn", "Malformed full_session_id[%s]\n",
+- full_session_id ? full_session_id : NULL);
+- session_id = g_strdup(full_session_id);
+- }
+-
+- if (session_action == NULL || strcmp(session_action, "close") != 0)
+- {
+- g_free(httpconn->full_session_id);
+- httpconn->full_session_id = full_session_id;
+-
+- g_free(httpconn->session_id);
+- httpconn->session_id = session_id;
+-
+- g_free(httpconn->host);
+- httpconn->host = gw_ip;
+- }
+- else
+- {
+- /* I'll be honest, I don't fully understand all this, but this
+- * causes crashes, Stu. */
+-#if 0
+- MsnServConn *servconn;
+-
+- /* It's going to die. */
+- /* poor thing */
+-
+- servconn = httpconn->servconn;
+-
+- if (servconn != NULL)
+- servconn->wasted = TRUE;
+-#endif
+-
+- g_free(full_session_id);
+- g_free(session_id);
+- g_free(gw_ip);
+- }
+-
+- g_free(session_action);
+- }
+-
+- g_free(header);
+-
+- *ret_buf = body;
+- *ret_size = body_len;
+-
+- msn_httpconn_process_queue(httpconn);
+-
+- return TRUE;
+-}
+-
+-static void
+-read_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- MsnHttpConn *httpconn;
+- MsnServConn *servconn;
+- char buf[MSN_BUF_LEN];
+- gssize len;
+- char *result_msg = NULL;
+- size_t result_len = 0;
+- gboolean error = FALSE;
+-
+- httpconn = data;
+- servconn = httpconn->servconn;
+-
+- if (servconn->type == MSN_SERVCONN_NS)
+- servconn->session->account->gc->last_received = time(NULL);
+-
+- len = read(httpconn->fd, buf, sizeof(buf) - 1);
+- if (len < 0 && errno == EAGAIN)
+- return;
+- if (len <= 0) {
+- purple_debug_error("msn", "HTTP: servconn %03d read error, "
+- "len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
+- servconn->num, len, error, g_strerror(errno));
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
+-
+- return;
+- }
+-
+- buf[len] = '\0';
+-
+- httpconn->rx_buf = g_realloc(httpconn->rx_buf, len + httpconn->rx_len + 1);
+- memcpy(httpconn->rx_buf + httpconn->rx_len, buf, len + 1);
+- httpconn->rx_len += len;
+-
+- if (!msn_httpconn_parse_data(httpconn, httpconn->rx_buf, httpconn->rx_len,
+- &result_msg, &result_len, &error))
+- {
+- /* Either we must wait for more input, or something went wrong */
+- if (error)
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
+-
+- return;
+- }
+-
+- if (error)
+- {
+- purple_debug_error("msn", "HTTP: Special error\n");
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
+-
+- return;
+- }
+-
+- g_free(httpconn->rx_buf);
+- httpconn->rx_buf = NULL;
+- httpconn->rx_len = 0;
+-
+- if (result_len == 0)
+- {
+- /* Nothing to do here */
+-#if 0
+- purple_debug_info("msn", "HTTP: nothing to do here\n");
+-#endif
+- g_free(result_msg);
+- return;
+- }
+-
+- g_free(servconn->rx_buf);
+- servconn->rx_buf = result_msg;
+- servconn->rx_len = result_len;
+-
+- msn_servconn_process_data(servconn);
+-}
+-
+-static void
+-httpconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- MsnHttpConn *httpconn;
+- gssize ret;
+- int writelen;
+-
+- httpconn = data;
+- writelen = purple_circ_buffer_get_max_read(httpconn->tx_buf);
+-
+- if (writelen == 0)
+- {
+- purple_input_remove(httpconn->tx_handler);
+- httpconn->tx_handler = 0;
+- return;
+- }
+-
+- ret = write(httpconn->fd, httpconn->tx_buf->outptr, writelen);
+- if (ret <= 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- /* Error! */
+- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(httpconn->tx_buf, ret);
+-
+- /* TODO: I don't think these 2 lines are needed. Remove them? */
+- if (ret == writelen)
+- httpconn_write_cb(data, source, cond);
+-}
+-
+-static gboolean
+-write_raw(MsnHttpConn *httpconn, const char *data, size_t data_len)
+-{
+- gssize res; /* result of the write operation */
+-
+- if (httpconn->tx_handler == 0)
+- res = write(httpconn->fd, data, data_len);
+- else
+- {
+- res = -1;
+- errno = EAGAIN;
+- }
+-
+- if ((res <= 0) && ((errno != EAGAIN) && (errno != EWOULDBLOCK)))
+- {
+- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
+- return FALSE;
+- }
+-
+- if (res < 0 || res < data_len)
+- {
+- if (res < 0)
+- res = 0;
+- if (httpconn->tx_handler == 0 && httpconn->fd)
+- httpconn->tx_handler = purple_input_add(httpconn->fd,
+- PURPLE_INPUT_WRITE, httpconn_write_cb, httpconn);
+- purple_circ_buffer_append(httpconn->tx_buf, data + res,
+- data_len - res);
+- }
+-
+- return TRUE;
+-}
+-
+-static char *
+-msn_httpconn_proxy_auth(MsnHttpConn *httpconn)
+-{
+- PurpleAccount *account;
+- PurpleProxyInfo *gpi;
+- const char *username, *password;
+- char *auth = NULL;
+-
+- account = httpconn->session->account;
+-
+- gpi = purple_proxy_get_setup(account);
+-
+- if (gpi == NULL || !(purple_proxy_info_get_type(gpi) == PURPLE_PROXY_HTTP ||
+- purple_proxy_info_get_type(gpi) == PURPLE_PROXY_USE_ENVVAR))
+- return NULL;
+-
+- username = purple_proxy_info_get_username(gpi);
+- password = purple_proxy_info_get_password(gpi);
+-
+- if (username != NULL) {
+- char *tmp;
+- auth = g_strdup_printf("%s:%s", username, password ? password : "");
+- tmp = purple_base64_encode((const guchar *)auth, strlen(auth));
+- g_free(auth);
+- auth = g_strdup_printf("Proxy-Authorization: Basic %s\r\n", tmp);
+- g_free(tmp);
+- }
+-
+- return auth;
+-}
+-
+-static gboolean
+-msn_httpconn_poll(gpointer data)
+-{
+- MsnHttpConn *httpconn;
+- char *header;
+- char *auth;
+-
+- httpconn = data;
+-
+- g_return_val_if_fail(httpconn != NULL, FALSE);
+-
+- if ((httpconn->host == NULL) || (httpconn->full_session_id == NULL))
+- {
+- /* There's no need to poll if the session is not fully established */
+- return TRUE;
+- }
+-
+- if (httpconn->waiting_response)
+- {
+- /* There's no need to poll if we're already waiting for a response */
+- return TRUE;
+- }
+-
+- auth = msn_httpconn_proxy_auth(httpconn);
+-
+- header = g_strdup_printf(
+- "POST http://%s/gateway/gateway.dll?Action=poll&SessionID=%s HTTP/1.1\r\n"
+- "Accept: */*\r\n"
+- "Accept-Language: en-us\r\n"
+- "User-Agent: MSMSGS\r\n"
+- "Host: %s\r\n"
+- "Proxy-Connection: Keep-Alive\r\n"
+- "%s" /* Proxy auth */
+- "Connection: Keep-Alive\r\n"
+- "Pragma: no-cache\r\n"
+- "Content-Type: application/x-msn-messenger\r\n"
+- "Content-Length: 0\r\n\r\n",
+- httpconn->host,
+- httpconn->full_session_id,
+- httpconn->host,
+- auth ? auth : "");
+-
+- g_free(auth);
+-
+- if (write_raw(httpconn, header, strlen(header)))
+- httpconn->waiting_response = TRUE;
+-
+- g_free(header);
+-
+- return TRUE;
+-}
+-
+-gssize
+-msn_httpconn_write(MsnHttpConn *httpconn, const char *body, size_t body_len)
+-{
+- char *params;
+- char *data;
+- int header_len;
+- char *auth;
+- const char *server_types[] = { "NS", "SB" };
+- const char *server_type;
+- char *host;
+- MsnServConn *servconn;
+-
+- /* TODO: remove http data from servconn */
+-
+- g_return_val_if_fail(httpconn != NULL, 0);
+- g_return_val_if_fail(body != NULL, 0);
+- g_return_val_if_fail(body_len > 0, 0);
+-
+- servconn = httpconn->servconn;
+-
+- if (httpconn->waiting_response)
+- {
+- MsnHttpQueueData *queue_data = g_new0(MsnHttpQueueData, 1);
+-
+- queue_data->httpconn = httpconn;
+- queue_data->body = g_memdup(body, body_len);
+- queue_data->body_len = body_len;
+-
+- httpconn->queue = g_list_append(httpconn->queue, queue_data);
+-
+- return body_len;
+- }
+-
+- server_type = server_types[servconn->type];
+-
+- if (httpconn->virgin)
+- {
+- /* QuLogic: This doesn't look right to me, but it still seems to work */
+- host = MSN_HTTPCONN_SERVER;
+-
+- /* The first time servconn->host is the host we should connect to. */
+- params = g_strdup_printf("Action=open&Server=%s&IP=%s",
+- server_type,
+- servconn->host);
+- httpconn->virgin = FALSE;
+- }
+- else
+- {
+- /* The rest of the times servconn->host is the gateway host. */
+- host = httpconn->host;
+-
+- if (host == NULL || httpconn->full_session_id == NULL)
+- {
+- purple_debug_warning("msn", "Attempted HTTP write before session is established\n");
+- return -1;
+- }
+-
+- params = g_strdup_printf("SessionID=%s",
+- httpconn->full_session_id);
+- }
+-
+- auth = msn_httpconn_proxy_auth(httpconn);
+-
+- data = g_strdup_printf(
+- "POST http://%s/gateway/gateway.dll?%s HTTP/1.1\r\n"
+- "Accept: */*\r\n"
+- "Accept-Language: en-us\r\n"
+- "User-Agent: MSMSGS\r\n"
+- "Host: %s\r\n"
+- "Proxy-Connection: Keep-Alive\r\n"
+- "%s" /* Proxy auth */
+- "Connection: Keep-Alive\r\n"
+- "Pragma: no-cache\r\n"
+- "Content-Type: application/x-msn-messenger\r\n"
+- "Content-Length: %d\r\n\r\n",
+- host,
+- params,
+- host,
+- auth ? auth : "",
+- (int) body_len);
+-
+- g_free(params);
+-
+- g_free(auth);
+-
+- header_len = strlen(data);
+- data = g_realloc(data, header_len + body_len);
+- memcpy(data + header_len, body, body_len);
+-
+- if (write_raw(httpconn, data, header_len + body_len))
+- httpconn->waiting_response = TRUE;
+-
+- g_free(data);
+-
+- return body_len;
+-}
+-
+-MsnHttpConn *
+-msn_httpconn_new(MsnServConn *servconn)
+-{
+- MsnHttpConn *httpconn;
+-
+- g_return_val_if_fail(servconn != NULL, NULL);
+-
+- httpconn = g_new0(MsnHttpConn, 1);
+-
+- purple_debug_info("msn", "new httpconn (%p)\n", httpconn);
+-
+- /* TODO: Remove this */
+- httpconn->session = servconn->session;
+-
+- httpconn->servconn = servconn;
+-
+- httpconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
+- httpconn->tx_handler = 0;
+-
+- httpconn->fd = -1;
+-
+- return httpconn;
+-}
+-
+-void
+-msn_httpconn_destroy(MsnHttpConn *httpconn)
+-{
+- g_return_if_fail(httpconn != NULL);
+-
+- purple_debug_info("msn", "destroy httpconn (%p)\n", httpconn);
+-
+- if (httpconn->connected)
+- msn_httpconn_disconnect(httpconn);
+-
+- g_free(httpconn->full_session_id);
+-
+- g_free(httpconn->session_id);
+-
+- g_free(httpconn->host);
+-
+- while (httpconn->queue != NULL) {
+- MsnHttpQueueData *queue_data;
+-
+- queue_data = (MsnHttpQueueData *) httpconn->queue->data;
+-
+- httpconn->queue = g_list_delete_link(httpconn->queue, httpconn->queue);
+-
+- g_free(queue_data->body);
+- g_free(queue_data);
+- }
+-
+- purple_circ_buffer_destroy(httpconn->tx_buf);
+- if (httpconn->tx_handler > 0)
+- purple_input_remove(httpconn->tx_handler);
+-
+- g_free(httpconn);
+-}
+-
+-static void
+-connect_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- MsnHttpConn *httpconn;
+-
+- httpconn = data;
+- httpconn->connect_data = NULL;
+- httpconn->fd = source;
+-
+- if (source >= 0)
+- {
+- httpconn->inpa = purple_input_add(httpconn->fd, PURPLE_INPUT_READ,
+- read_cb, data);
+-
+- httpconn->timer = purple_timeout_add_seconds(2, msn_httpconn_poll, httpconn);
+-
+- msn_httpconn_process_queue(httpconn);
+- }
+- else
+- {
+- purple_debug_error("msn", "HTTP: Connection error: %s\n",
+- error_message ? error_message : "(null)");
+- msn_servconn_got_error(httpconn->servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
+- }
+-}
+-
+-gboolean
+-msn_httpconn_connect(MsnHttpConn *httpconn, const char *host, int port)
+-{
+- g_return_val_if_fail(httpconn != NULL, FALSE);
+- g_return_val_if_fail(host != NULL, FALSE);
+- g_return_val_if_fail(port > 0, FALSE);
+-
+- if (httpconn->connected)
+- msn_httpconn_disconnect(httpconn);
+-
+- httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account,
+- host, 80, connect_cb, httpconn);
+-
+- if (httpconn->connect_data != NULL)
+- {
+- httpconn->waiting_response = TRUE;
+- httpconn->connected = TRUE;
+- }
+-
+- return httpconn->connected;
+-}
+-
+-void
+-msn_httpconn_disconnect(MsnHttpConn *httpconn)
+-{
+- g_return_if_fail(httpconn != NULL);
+-
+- if (!httpconn->connected)
+- return;
+-
+- if (httpconn->connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(httpconn->connect_data);
+- httpconn->connect_data = NULL;
+- }
+-
+- if (httpconn->timer)
+- {
+- purple_timeout_remove(httpconn->timer);
+- httpconn->timer = 0;
+- }
+-
+- if (httpconn->inpa > 0)
+- {
+- purple_input_remove(httpconn->inpa);
+- httpconn->inpa = 0;
+- }
+-
+- close(httpconn->fd);
+- httpconn->fd = -1;
+-
+- g_free(httpconn->rx_buf);
+- httpconn->rx_buf = NULL;
+- httpconn->rx_len = 0;
+-
+- httpconn->connected = FALSE;
+-
+- /* msn_servconn_disconnect(httpconn->servconn); */
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/httpconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.h
+--- pidgin-2.10.7/libpurple/protocols/msn/httpconn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/httpconn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,112 +0,0 @@
+-/**
+- * @file httpconn.h HTTP connection
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_HTTPCONN_H
+-#define MSN_HTTPCONN_H
+-
+-typedef struct _MsnHttpConn MsnHttpConn;
+-
+-#include "circbuffer.h"
+-#include "servconn.h"
+-#include "session.h"
+-
+-/**
+- * An HTTP Connection.
+- */
+-struct _MsnHttpConn
+-{
+- MsnSession *session; /**< The MSN Session. */
+- MsnServConn *servconn; /**< The connection object. */
+-
+- PurpleProxyConnectData *connect_data;
+-
+- char *full_session_id; /**< The full session id. */
+- char *session_id; /**< The trimmed session id. */
+-
+- int timer; /**< The timer for polling. */
+-
+- gboolean waiting_response; /**< The flag that states if we are waiting
+- a response from the server. */
+- gboolean connected; /**< The flag that states if the connection is on. */
+- gboolean virgin; /**< The flag that states if this connection
+- should specify the host (not gateway) to
+- connect to. */
+-
+- char *host; /**< The HTTP gateway host. */
+- GList *queue; /**< The queue of data chunks to write. */
+-
+- int fd; /**< The connection's file descriptor. */
+- guint inpa; /**< The connection's input handler. */
+-
+- char *rx_buf; /**< The receive buffer. */
+- int rx_len; /**< The receive buffer length. */
+-
+- PurpleCircBuffer *tx_buf;
+- guint tx_handler;
+-};
+-
+-/**
+- * Creates a new HTTP connection object.
+- *
+- * @param servconn The connection object.
+- *
+- * @return The new object.
+- */
+-MsnHttpConn *msn_httpconn_new(MsnServConn *servconn);
+-
+-/**
+- * Destroys an HTTP connection object.
+- *
+- * @param httpconn The HTTP connection object.
+- */
+-void msn_httpconn_destroy(MsnHttpConn *httpconn);
+-
+-/**
+- * Writes a chunk of data to the HTTP connection.
+- *
+- * @param servconn The server connection.
+- * @param data The data to write.
+- * @param data_len The size of the data to write.
+- *
+- * @return The number of bytes written.
+- */
+-gssize msn_httpconn_write(MsnHttpConn *httpconn, const char *data, size_t data_len);
+-
+-/**
+- * Connects the HTTP connection object to a host.
+- *
+- * @param httpconn The HTTP connection object.
+- * @param host The host to connect to.
+- * @param port The port to connect to.
+- */
+-gboolean msn_httpconn_connect(MsnHttpConn *httpconn,
+- const char *host, int port);
+-
+-/**
+- * Disconnects the HTTP connection object.
+- *
+- * @param httpconn The HTTP connection object.
+- */
+-void msn_httpconn_disconnect(MsnHttpConn *httpconn);
+-
+-#endif /* MSN_HTTPCONN_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/msn/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,102 +0,0 @@
+-EXTRA_DIST = \
+- directconn.c \
+- directconn.h \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-MSNSOURCES = \
+- cmdproc.c \
+- cmdproc.h \
+- command.c \
+- command.h \
+- contact.c\
+- contact.h\
+- directconn.c \
+- directconn.h \
+- error.c \
+- error.h \
+- group.c \
+- group.h \
+- history.c \
+- history.h \
+- httpconn.c \
+- httpconn.h \
+- msg.c \
+- msg.h \
+- msn.c \
+- msn.h \
+- nexus.c \
+- nexus.h \
+- notification.c \
+- notification.h \
+- object.c \
+- object.h \
+- oim.c\
+- oim.h\
+- p2p.c \
+- p2p.h \
+- page.c \
+- page.h \
+- servconn.c \
+- servconn.h \
+- session.c \
+- session.h \
+- slp.c \
+- slp.h \
+- slpcall.c \
+- slpcall.h \
+- slplink.c \
+- slplink.h \
+- slpmsg.c \
+- slpmsg.h \
+- slpmsg_part.c \
+- slpmsg_part.h \
+- soap.c \
+- soap.h \
+- state.c \
+- state.h \
+- sbconn.c \
+- sbconn.h \
+- switchboard.c \
+- switchboard.h \
+- table.c \
+- table.h \
+- tlv.c \
+- tlv.h \
+- transaction.c \
+- transaction.h \
+- user.c \
+- user.h \
+- userlist.c \
+- userlist.h \
+- xfer.c \
+- xfer.h \
+- msnutils.c \
+- msnutils.h
+-
+-AM_CFLAGS = $(st)
+-
+-libmsn_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_MSN
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libmsn.la
+-libmsn_la_SOURCES = $(MSNSOURCES)
+-libmsn_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libmsn.la
+-libmsn_la_SOURCES = $(MSNSOURCES)
+-libmsn_la_LIBADD = $(GLIB_LIBS)
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/msn/Makefile.in 2013-02-11 07:17:20.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1102 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/msn
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-@STATIC_MSN_FALSE@libmsn_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+-am__libmsn_la_SOURCES_DIST = cmdproc.c cmdproc.h command.c command.h \
+- contact.c contact.h directconn.c directconn.h error.c error.h \
+- group.c group.h history.c history.h httpconn.c httpconn.h \
+- msg.c msg.h msn.c msn.h nexus.c nexus.h notification.c \
+- notification.h object.c object.h oim.c oim.h p2p.c p2p.h \
+- page.c page.h servconn.c servconn.h session.c session.h slp.c \
+- slp.h slpcall.c slpcall.h slplink.c slplink.h slpmsg.c \
+- slpmsg.h slpmsg_part.c slpmsg_part.h soap.c soap.h state.c \
+- state.h sbconn.c sbconn.h switchboard.c switchboard.h table.c \
+- table.h tlv.c tlv.h transaction.c transaction.h user.c user.h \
+- userlist.c userlist.h xfer.c xfer.h msnutils.c msnutils.h
+-am__objects_1 = libmsn_la-cmdproc.lo libmsn_la-command.lo \
+- libmsn_la-contact.lo libmsn_la-directconn.lo \
+- libmsn_la-error.lo libmsn_la-group.lo libmsn_la-history.lo \
+- libmsn_la-httpconn.lo libmsn_la-msg.lo libmsn_la-msn.lo \
+- libmsn_la-nexus.lo libmsn_la-notification.lo \
+- libmsn_la-object.lo libmsn_la-oim.lo libmsn_la-p2p.lo \
+- libmsn_la-page.lo libmsn_la-servconn.lo libmsn_la-session.lo \
+- libmsn_la-slp.lo libmsn_la-slpcall.lo libmsn_la-slplink.lo \
+- libmsn_la-slpmsg.lo libmsn_la-slpmsg_part.lo libmsn_la-soap.lo \
+- libmsn_la-state.lo libmsn_la-sbconn.lo \
+- libmsn_la-switchboard.lo libmsn_la-table.lo libmsn_la-tlv.lo \
+- libmsn_la-transaction.lo libmsn_la-user.lo \
+- libmsn_la-userlist.lo libmsn_la-xfer.lo libmsn_la-msnutils.lo
+-@STATIC_MSN_FALSE@am_libmsn_la_OBJECTS = $(am__objects_1)
+-@STATIC_MSN_TRUE@am_libmsn_la_OBJECTS = $(am__objects_1)
+-libmsn_la_OBJECTS = $(am_libmsn_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libmsn_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmsn_la_CFLAGS) \
+- $(CFLAGS) $(libmsn_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_MSN_FALSE@am_libmsn_la_rpath = -rpath $(pkgdir)
+-@STATIC_MSN_TRUE@am_libmsn_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libmsn_la_SOURCES)
+-DIST_SOURCES = $(am__libmsn_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- directconn.c \
+- directconn.h \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-MSNSOURCES = \
+- cmdproc.c \
+- cmdproc.h \
+- command.c \
+- command.h \
+- contact.c\
+- contact.h\
+- directconn.c \
+- directconn.h \
+- error.c \
+- error.h \
+- group.c \
+- group.h \
+- history.c \
+- history.h \
+- httpconn.c \
+- httpconn.h \
+- msg.c \
+- msg.h \
+- msn.c \
+- msn.h \
+- nexus.c \
+- nexus.h \
+- notification.c \
+- notification.h \
+- object.c \
+- object.h \
+- oim.c\
+- oim.h\
+- p2p.c \
+- p2p.h \
+- page.c \
+- page.h \
+- servconn.c \
+- servconn.h \
+- session.c \
+- session.h \
+- slp.c \
+- slp.h \
+- slpcall.c \
+- slpcall.h \
+- slplink.c \
+- slplink.h \
+- slpmsg.c \
+- slpmsg.h \
+- slpmsg_part.c \
+- slpmsg_part.h \
+- soap.c \
+- soap.h \
+- state.c \
+- state.h \
+- sbconn.c \
+- sbconn.h \
+- switchboard.c \
+- switchboard.h \
+- table.c \
+- table.h \
+- tlv.c \
+- tlv.h \
+- transaction.c \
+- transaction.h \
+- user.c \
+- user.h \
+- userlist.c \
+- userlist.h \
+- xfer.c \
+- xfer.h \
+- msnutils.c \
+- msnutils.h
+-
+-AM_CFLAGS = $(st)
+-libmsn_la_LDFLAGS = -module -avoid-version
+-@STATIC_MSN_FALSE@st =
+-@STATIC_MSN_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_MSN_TRUE@noinst_LTLIBRARIES = libmsn.la
+-@STATIC_MSN_FALSE@libmsn_la_SOURCES = $(MSNSOURCES)
+-@STATIC_MSN_TRUE@libmsn_la_SOURCES = $(MSNSOURCES)
+-@STATIC_MSN_TRUE@libmsn_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_MSN_FALSE@pkg_LTLIBRARIES = libmsn.la
+-@STATIC_MSN_FALSE@libmsn_la_LIBADD = $(GLIB_LIBS)
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/msn/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/msn/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libmsn.la: $(libmsn_la_OBJECTS) $(libmsn_la_DEPENDENCIES) $(EXTRA_libmsn_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libmsn_la_LINK) $(am_libmsn_la_rpath) $(libmsn_la_OBJECTS) $(libmsn_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-cmdproc.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-command.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-contact.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-directconn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-error.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-group.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-history.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-httpconn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msg.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-msnutils.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-nexus.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-notification.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-object.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-oim.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-p2p.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-page.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-sbconn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-servconn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-session.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slp.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpcall.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slplink.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpmsg.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-slpmsg_part.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-soap.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-state.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-switchboard.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-table.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-tlv.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-transaction.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-user.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-userlist.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmsn_la-xfer.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libmsn_la-cmdproc.lo: cmdproc.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-cmdproc.lo -MD -MP -MF $(DEPDIR)/libmsn_la-cmdproc.Tpo -c -o libmsn_la-cmdproc.lo `test -f 'cmdproc.c' || echo '$(srcdir)/'`cmdproc.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-cmdproc.Tpo $(DEPDIR)/libmsn_la-cmdproc.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cmdproc.c' object='libmsn_la-cmdproc.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-cmdproc.lo `test -f 'cmdproc.c' || echo '$(srcdir)/'`cmdproc.c
+-
+-libmsn_la-command.lo: command.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-command.lo -MD -MP -MF $(DEPDIR)/libmsn_la-command.Tpo -c -o libmsn_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-command.Tpo $(DEPDIR)/libmsn_la-command.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='command.c' object='libmsn_la-command.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-command.lo `test -f 'command.c' || echo '$(srcdir)/'`command.c
+-
+-libmsn_la-contact.lo: contact.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-contact.lo -MD -MP -MF $(DEPDIR)/libmsn_la-contact.Tpo -c -o libmsn_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-contact.Tpo $(DEPDIR)/libmsn_la-contact.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='contact.c' object='libmsn_la-contact.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-contact.lo `test -f 'contact.c' || echo '$(srcdir)/'`contact.c
+-
+-libmsn_la-directconn.lo: directconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-directconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-directconn.Tpo -c -o libmsn_la-directconn.lo `test -f 'directconn.c' || echo '$(srcdir)/'`directconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-directconn.Tpo $(DEPDIR)/libmsn_la-directconn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='directconn.c' object='libmsn_la-directconn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-directconn.lo `test -f 'directconn.c' || echo '$(srcdir)/'`directconn.c
+-
+-libmsn_la-error.lo: error.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-error.lo -MD -MP -MF $(DEPDIR)/libmsn_la-error.Tpo -c -o libmsn_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-error.Tpo $(DEPDIR)/libmsn_la-error.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='error.c' object='libmsn_la-error.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-error.lo `test -f 'error.c' || echo '$(srcdir)/'`error.c
+-
+-libmsn_la-group.lo: group.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-group.lo -MD -MP -MF $(DEPDIR)/libmsn_la-group.Tpo -c -o libmsn_la-group.lo `test -f 'group.c' || echo '$(srcdir)/'`group.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-group.Tpo $(DEPDIR)/libmsn_la-group.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='group.c' object='libmsn_la-group.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-group.lo `test -f 'group.c' || echo '$(srcdir)/'`group.c
+-
+-libmsn_la-history.lo: history.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-history.lo -MD -MP -MF $(DEPDIR)/libmsn_la-history.Tpo -c -o libmsn_la-history.lo `test -f 'history.c' || echo '$(srcdir)/'`history.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-history.Tpo $(DEPDIR)/libmsn_la-history.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='history.c' object='libmsn_la-history.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-history.lo `test -f 'history.c' || echo '$(srcdir)/'`history.c
+-
+-libmsn_la-httpconn.lo: httpconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-httpconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-httpconn.Tpo -c -o libmsn_la-httpconn.lo `test -f 'httpconn.c' || echo '$(srcdir)/'`httpconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-httpconn.Tpo $(DEPDIR)/libmsn_la-httpconn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='httpconn.c' object='libmsn_la-httpconn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-httpconn.lo `test -f 'httpconn.c' || echo '$(srcdir)/'`httpconn.c
+-
+-libmsn_la-msg.lo: msg.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msg.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msg.Tpo -c -o libmsn_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msg.Tpo $(DEPDIR)/libmsn_la-msg.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msg.c' object='libmsn_la-msg.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msg.lo `test -f 'msg.c' || echo '$(srcdir)/'`msg.c
+-
+-libmsn_la-msn.lo: msn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msn.Tpo -c -o libmsn_la-msn.lo `test -f 'msn.c' || echo '$(srcdir)/'`msn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msn.Tpo $(DEPDIR)/libmsn_la-msn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msn.c' object='libmsn_la-msn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msn.lo `test -f 'msn.c' || echo '$(srcdir)/'`msn.c
+-
+-libmsn_la-nexus.lo: nexus.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-nexus.lo -MD -MP -MF $(DEPDIR)/libmsn_la-nexus.Tpo -c -o libmsn_la-nexus.lo `test -f 'nexus.c' || echo '$(srcdir)/'`nexus.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-nexus.Tpo $(DEPDIR)/libmsn_la-nexus.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nexus.c' object='libmsn_la-nexus.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-nexus.lo `test -f 'nexus.c' || echo '$(srcdir)/'`nexus.c
+-
+-libmsn_la-notification.lo: notification.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-notification.lo -MD -MP -MF $(DEPDIR)/libmsn_la-notification.Tpo -c -o libmsn_la-notification.lo `test -f 'notification.c' || echo '$(srcdir)/'`notification.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-notification.Tpo $(DEPDIR)/libmsn_la-notification.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='notification.c' object='libmsn_la-notification.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-notification.lo `test -f 'notification.c' || echo '$(srcdir)/'`notification.c
+-
+-libmsn_la-object.lo: object.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-object.lo -MD -MP -MF $(DEPDIR)/libmsn_la-object.Tpo -c -o libmsn_la-object.lo `test -f 'object.c' || echo '$(srcdir)/'`object.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-object.Tpo $(DEPDIR)/libmsn_la-object.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='object.c' object='libmsn_la-object.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-object.lo `test -f 'object.c' || echo '$(srcdir)/'`object.c
+-
+-libmsn_la-oim.lo: oim.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-oim.lo -MD -MP -MF $(DEPDIR)/libmsn_la-oim.Tpo -c -o libmsn_la-oim.lo `test -f 'oim.c' || echo '$(srcdir)/'`oim.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-oim.Tpo $(DEPDIR)/libmsn_la-oim.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oim.c' object='libmsn_la-oim.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-oim.lo `test -f 'oim.c' || echo '$(srcdir)/'`oim.c
+-
+-libmsn_la-p2p.lo: p2p.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-p2p.lo -MD -MP -MF $(DEPDIR)/libmsn_la-p2p.Tpo -c -o libmsn_la-p2p.lo `test -f 'p2p.c' || echo '$(srcdir)/'`p2p.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-p2p.Tpo $(DEPDIR)/libmsn_la-p2p.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='p2p.c' object='libmsn_la-p2p.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-p2p.lo `test -f 'p2p.c' || echo '$(srcdir)/'`p2p.c
+-
+-libmsn_la-page.lo: page.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-page.lo -MD -MP -MF $(DEPDIR)/libmsn_la-page.Tpo -c -o libmsn_la-page.lo `test -f 'page.c' || echo '$(srcdir)/'`page.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-page.Tpo $(DEPDIR)/libmsn_la-page.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='page.c' object='libmsn_la-page.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-page.lo `test -f 'page.c' || echo '$(srcdir)/'`page.c
+-
+-libmsn_la-servconn.lo: servconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-servconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-servconn.Tpo -c -o libmsn_la-servconn.lo `test -f 'servconn.c' || echo '$(srcdir)/'`servconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-servconn.Tpo $(DEPDIR)/libmsn_la-servconn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='servconn.c' object='libmsn_la-servconn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-servconn.lo `test -f 'servconn.c' || echo '$(srcdir)/'`servconn.c
+-
+-libmsn_la-session.lo: session.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-session.lo -MD -MP -MF $(DEPDIR)/libmsn_la-session.Tpo -c -o libmsn_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-session.Tpo $(DEPDIR)/libmsn_la-session.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='session.c' object='libmsn_la-session.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
+-
+-libmsn_la-slp.lo: slp.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slp.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slp.Tpo -c -o libmsn_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slp.Tpo $(DEPDIR)/libmsn_la-slp.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slp.c' object='libmsn_la-slp.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slp.lo `test -f 'slp.c' || echo '$(srcdir)/'`slp.c
+-
+-libmsn_la-slpcall.lo: slpcall.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpcall.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpcall.Tpo -c -o libmsn_la-slpcall.lo `test -f 'slpcall.c' || echo '$(srcdir)/'`slpcall.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpcall.Tpo $(DEPDIR)/libmsn_la-slpcall.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpcall.c' object='libmsn_la-slpcall.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpcall.lo `test -f 'slpcall.c' || echo '$(srcdir)/'`slpcall.c
+-
+-libmsn_la-slplink.lo: slplink.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slplink.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slplink.Tpo -c -o libmsn_la-slplink.lo `test -f 'slplink.c' || echo '$(srcdir)/'`slplink.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slplink.Tpo $(DEPDIR)/libmsn_la-slplink.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slplink.c' object='libmsn_la-slplink.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slplink.lo `test -f 'slplink.c' || echo '$(srcdir)/'`slplink.c
+-
+-libmsn_la-slpmsg.lo: slpmsg.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpmsg.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpmsg.Tpo -c -o libmsn_la-slpmsg.lo `test -f 'slpmsg.c' || echo '$(srcdir)/'`slpmsg.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpmsg.Tpo $(DEPDIR)/libmsn_la-slpmsg.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpmsg.c' object='libmsn_la-slpmsg.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpmsg.lo `test -f 'slpmsg.c' || echo '$(srcdir)/'`slpmsg.c
+-
+-libmsn_la-slpmsg_part.lo: slpmsg_part.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-slpmsg_part.lo -MD -MP -MF $(DEPDIR)/libmsn_la-slpmsg_part.Tpo -c -o libmsn_la-slpmsg_part.lo `test -f 'slpmsg_part.c' || echo '$(srcdir)/'`slpmsg_part.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-slpmsg_part.Tpo $(DEPDIR)/libmsn_la-slpmsg_part.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='slpmsg_part.c' object='libmsn_la-slpmsg_part.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-slpmsg_part.lo `test -f 'slpmsg_part.c' || echo '$(srcdir)/'`slpmsg_part.c
+-
+-libmsn_la-soap.lo: soap.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-soap.lo -MD -MP -MF $(DEPDIR)/libmsn_la-soap.Tpo -c -o libmsn_la-soap.lo `test -f 'soap.c' || echo '$(srcdir)/'`soap.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-soap.Tpo $(DEPDIR)/libmsn_la-soap.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='soap.c' object='libmsn_la-soap.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-soap.lo `test -f 'soap.c' || echo '$(srcdir)/'`soap.c
+-
+-libmsn_la-state.lo: state.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-state.lo -MD -MP -MF $(DEPDIR)/libmsn_la-state.Tpo -c -o libmsn_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-state.Tpo $(DEPDIR)/libmsn_la-state.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='state.c' object='libmsn_la-state.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-state.lo `test -f 'state.c' || echo '$(srcdir)/'`state.c
+-
+-libmsn_la-sbconn.lo: sbconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-sbconn.lo -MD -MP -MF $(DEPDIR)/libmsn_la-sbconn.Tpo -c -o libmsn_la-sbconn.lo `test -f 'sbconn.c' || echo '$(srcdir)/'`sbconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-sbconn.Tpo $(DEPDIR)/libmsn_la-sbconn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sbconn.c' object='libmsn_la-sbconn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-sbconn.lo `test -f 'sbconn.c' || echo '$(srcdir)/'`sbconn.c
+-
+-libmsn_la-switchboard.lo: switchboard.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-switchboard.lo -MD -MP -MF $(DEPDIR)/libmsn_la-switchboard.Tpo -c -o libmsn_la-switchboard.lo `test -f 'switchboard.c' || echo '$(srcdir)/'`switchboard.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-switchboard.Tpo $(DEPDIR)/libmsn_la-switchboard.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='switchboard.c' object='libmsn_la-switchboard.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-switchboard.lo `test -f 'switchboard.c' || echo '$(srcdir)/'`switchboard.c
+-
+-libmsn_la-table.lo: table.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-table.lo -MD -MP -MF $(DEPDIR)/libmsn_la-table.Tpo -c -o libmsn_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-table.Tpo $(DEPDIR)/libmsn_la-table.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='table.c' object='libmsn_la-table.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-table.lo `test -f 'table.c' || echo '$(srcdir)/'`table.c
+-
+-libmsn_la-tlv.lo: tlv.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-tlv.lo -MD -MP -MF $(DEPDIR)/libmsn_la-tlv.Tpo -c -o libmsn_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-tlv.Tpo $(DEPDIR)/libmsn_la-tlv.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tlv.c' object='libmsn_la-tlv.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
+-
+-libmsn_la-transaction.lo: transaction.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-transaction.lo -MD -MP -MF $(DEPDIR)/libmsn_la-transaction.Tpo -c -o libmsn_la-transaction.lo `test -f 'transaction.c' || echo '$(srcdir)/'`transaction.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-transaction.Tpo $(DEPDIR)/libmsn_la-transaction.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='transaction.c' object='libmsn_la-transaction.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-transaction.lo `test -f 'transaction.c' || echo '$(srcdir)/'`transaction.c
+-
+-libmsn_la-user.lo: user.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-user.lo -MD -MP -MF $(DEPDIR)/libmsn_la-user.Tpo -c -o libmsn_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-user.Tpo $(DEPDIR)/libmsn_la-user.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libmsn_la-user.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
+-
+-libmsn_la-userlist.lo: userlist.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-userlist.lo -MD -MP -MF $(DEPDIR)/libmsn_la-userlist.Tpo -c -o libmsn_la-userlist.lo `test -f 'userlist.c' || echo '$(srcdir)/'`userlist.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-userlist.Tpo $(DEPDIR)/libmsn_la-userlist.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='userlist.c' object='libmsn_la-userlist.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-userlist.lo `test -f 'userlist.c' || echo '$(srcdir)/'`userlist.c
+-
+-libmsn_la-xfer.lo: xfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-xfer.lo -MD -MP -MF $(DEPDIR)/libmsn_la-xfer.Tpo -c -o libmsn_la-xfer.lo `test -f 'xfer.c' || echo '$(srcdir)/'`xfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-xfer.Tpo $(DEPDIR)/libmsn_la-xfer.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='xfer.c' object='libmsn_la-xfer.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-xfer.lo `test -f 'xfer.c' || echo '$(srcdir)/'`xfer.c
+-
+-libmsn_la-msnutils.lo: msnutils.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -MT libmsn_la-msnutils.lo -MD -MP -MF $(DEPDIR)/libmsn_la-msnutils.Tpo -c -o libmsn_la-msnutils.lo `test -f 'msnutils.c' || echo '$(srcdir)/'`msnutils.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmsn_la-msnutils.Tpo $(DEPDIR)/libmsn_la-msnutils.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msnutils.c' object='libmsn_la-msnutils.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmsn_la_CFLAGS) $(CFLAGS) -c -o libmsn_la-msnutils.lo `test -f 'msnutils.c' || echo '$(srcdir)/'`msnutils.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/msn/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,110 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libmsn
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libmsn
+-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 = cmdproc.c \
+- command.c \
+- contact.c\
+- directconn.c \
+- error.c \
+- group.c \
+- history.c \
+- httpconn.c \
+- msg.c \
+- msn.c \
+- nexus.c \
+- notification.c \
+- object.c \
+- oim.c\
+- p2p.c \
+- page.c \
+- servconn.c \
+- session.c \
+- slp.c \
+- slpcall.c \
+- slplink.c \
+- slpmsg.c \
+- slpmsg_part.c \
+- soap.c\
+- state.c \
+- sbconn.c \
+- switchboard.c \
+- table.c \
+- tlv.c \
+- transaction.c \
+- user.c \
+- userlist.c \
+- xfer.c \
+- msnutils.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)
+- 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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msg.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.c
+--- pidgin-2.10.7/libpurple/protocols/msn/msg.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1215 +0,0 @@
+-/**
+- * @file msg.c Message functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msn.h"
+-#include "msg.h"
+-#include "msnutils.h"
+-#include "slpmsg.h"
+-#include "slpmsg_part.h"
+-
+-MsnMessage *
+-msn_message_new(MsnMsgType type)
+-{
+- MsnMessage *msg;
+-
+- msg = g_new0(MsnMessage, 1);
+- msg->type = type;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "message new (%p)(%d)\n", msg, type);
+-
+- msg->header_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+- g_free, g_free);
+-
+- msn_message_ref(msg);
+-
+- return msg;
+-}
+-
+-/**
+- * Destroys a message.
+- *
+- * @param msg The message to destroy.
+- */
+-static void
+-msn_message_destroy(MsnMessage *msg)
+-{
+- g_return_if_fail(msg != NULL);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "message destroy (%p)\n", msg);
+-
+- g_free(msg->remote_user);
+- g_free(msg->body);
+- g_free(msg->content_type);
+- g_free(msg->charset);
+-
+- g_hash_table_destroy(msg->header_table);
+- g_list_free(msg->header_list);
+- if (msg->part)
+- msn_slpmsgpart_unref(msg->part);
+-
+- g_free(msg);
+-}
+-
+-MsnMessage *
+-msn_message_ref(MsnMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- msg->ref_count++;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "message ref (%p)[%u]\n", msg, msg->ref_count);
+-
+- return msg;
+-}
+-
+-void
+-msn_message_unref(MsnMessage *msg)
+-{
+- g_return_if_fail(msg != NULL);
+- g_return_if_fail(msg->ref_count > 0);
+-
+- msg->ref_count--;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "message unref (%p)[%u]\n", msg, msg->ref_count);
+-
+- if (msg->ref_count == 0)
+- msn_message_destroy(msg);
+-}
+-
+-MsnMessage *
+-msn_message_new_plain(const char *message)
+-{
+- MsnMessage *msg;
+- char *message_cr;
+-
+- msg = msn_message_new(MSN_MSG_TEXT);
+- msg->retries = 1;
+- msn_message_set_header(msg, "User-Agent", PACKAGE_NAME "/" VERSION);
+- msn_message_set_content_type(msg, "text/plain");
+- msn_message_set_charset(msg, "UTF-8");
+- msn_message_set_flag(msg, 'A');
+- msn_message_set_header(msg, "X-MMS-IM-Format",
+- "FN=Segoe%20UI; EF=; CO=0; CS=1;PF=0");
+-
+- message_cr = purple_str_add_cr(message);
+- msn_message_set_bin_data(msg, message_cr, strlen(message_cr));
+- g_free(message_cr);
+-
+- return msg;
+-}
+-
+-MsnMessage *
+-msn_message_new_msnslp(void)
+-{
+- MsnMessage *msg;
+-
+- msg = msn_message_new(MSN_MSG_SLP);
+-
+- msn_message_set_header(msg, "User-Agent", NULL);
+-
+- msn_message_set_flag(msg, 'D');
+- msn_message_set_content_type(msg, "application/x-msnmsgrp2p");
+-
+- return msg;
+-}
+-
+-MsnMessage *
+-msn_message_new_nudge(void)
+-{
+- MsnMessage *msg;
+-
+- msg = msn_message_new(MSN_MSG_NUDGE);
+- msn_message_set_content_type(msg, "text/x-msnmsgr-datacast");
+- msn_message_set_flag(msg, 'N');
+- msn_message_set_bin_data(msg, "ID: 1\r\n", 7);
+-
+- return msg;
+-}
+-
+-void
+-msn_message_parse_payload(MsnMessage *msg,
+- const char *payload, size_t payload_len,
+- const char *line_dem,const char *body_dem)
+-{
+- char *tmp_base, *tmp;
+- const char *content_type;
+- char *end;
+- char **elems, **cur, **tokens;
+-
+- g_return_if_fail(payload != NULL);
+- tmp_base = tmp = g_malloc(payload_len + 1);
+- memcpy(tmp_base, payload, payload_len);
+- tmp_base[payload_len] = '\0';
+-
+- /* Find the end of the headers */
+- end = strstr(tmp, body_dem);
+- /* TODO? some clients use \r delimiters instead of \r\n, the official client
+- * doesn't send such messages, but does handle receiving them. We'll just
+- * avoid crashing for now */
+- if (end == NULL) {
+- g_free(tmp_base);
+- g_return_if_reached();
+- }
+- *end = '\0';
+-
+- /* Split the headers and parse each one */
+- elems = g_strsplit(tmp, line_dem, 0);
+- for (cur = elems; *cur != NULL; cur++)
+- {
+- const char *key, *value;
+-
+- /* If this line starts with whitespace, it's been folded from the
+- previous line and won't have ':'. */
+- if ((**cur == ' ') || (**cur == '\t')) {
+- tokens = g_strsplit(g_strchug(*cur), "=\"", 2);
+- key = tokens[0];
+- value = tokens[1];
+-
+- /* The only one I care about is 'boundary' (which is folded from
+- the key 'Content-Type'), so only process that. */
+- if (!strcmp(key, "boundary")) {
+- char *end = strchr(value, '\"');
+- *end = '\0';
+- msn_message_set_header(msg, key, value);
+- }
+-
+- g_strfreev(tokens);
+- continue;
+- }
+-
+- tokens = g_strsplit(*cur, ": ", 2);
+-
+- key = tokens[0];
+- value = tokens[1];
+-
+- /*if not MIME content ,then return*/
+- if (!strcmp(key, "MIME-Version"))
+- {
+- g_strfreev(tokens);
+- continue;
+- }
+-
+- if (!strcmp(key, "Content-Type"))
+- {
+- char *charset, *c;
+-
+- if ((c = strchr(value, ';')) != NULL)
+- {
+- if ((charset = strchr(c, '=')) != NULL)
+- {
+- charset++;
+- msn_message_set_charset(msg, charset);
+- }
+-
+- *c = '\0';
+- }
+-
+- msn_message_set_content_type(msg, value);
+- }
+- else
+- {
+- msn_message_set_header(msg, key, value);
+- }
+-
+- g_strfreev(tokens);
+- }
+- g_strfreev(elems);
+-
+- /* Proceed to the end of the "\r\n\r\n" */
+- tmp = end + strlen(body_dem);
+-
+- /* Now we *should* be at the body. */
+- content_type = msn_message_get_content_type(msg);
+-
+- if (payload_len - (tmp - tmp_base) > 0) {
+- msg->body_len = payload_len - (tmp - tmp_base);
+- g_free(msg->body);
+- msg->body = g_malloc(msg->body_len + 1);
+- memcpy(msg->body, tmp, msg->body_len);
+- msg->body[msg->body_len] = '\0';
+- }
+-
+- if (msg->body && content_type && purple_str_has_prefix(content_type, "text/")) {
+- char *body = NULL;
+-
+- if (msg->charset == NULL || g_str_equal(msg->charset, "UTF-8")) {
+- /* Charset is UTF-8 */
+- if (!g_utf8_validate(msg->body, msg->body_len, NULL)) {
+- purple_debug_warning("msn", "Message contains invalid "
+- "UTF-8. Attempting to salvage.\n");
+- body = purple_utf8_salvage(msg->body);
+- payload_len = strlen(body);
+- }
+- } else {
+- /* Charset is something other than UTF-8 */
+- GError *err = NULL;
+- body = g_convert(msg->body, msg->body_len, "UTF-8",
+- msg->charset, NULL, &payload_len, &err);
+- if (!body || err) {
+- purple_debug_warning("msn", "Unable to convert message from "
+- "%s to UTF-8: %s\n", msg->charset,
+- err ? err->message : "Unknown error");
+- if (err)
+- g_error_free(err);
+-
+- /* Fallback to ISO-8859-1 */
+- g_free(body);
+- body = g_convert(msg->body, msg->body_len, "UTF-8",
+- "ISO-8859-1", NULL, &payload_len, NULL);
+- if (!body) {
+- g_free(msg->body);
+- msg->body = NULL;
+- msg->body_len = 0;
+- }
+- }
+- }
+-
+- if (body) {
+- g_free(msg->body);
+- msg->body = body;
+- msg->body_len = payload_len;
+- msn_message_set_charset(msg, "UTF-8");
+- }
+- }
+-
+- g_free(tmp_base);
+-}
+-
+-MsnMessage *
+-msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd)
+-{
+- MsnMessage *msg;
+-
+- g_return_val_if_fail(cmd != NULL, NULL);
+-
+- msg = msn_message_new(MSN_MSG_UNKNOWN);
+-
+- msg->remote_user = g_strdup(cmd->params[0]);
+- /* msg->size = atoi(cmd->params[2]); */
+- msg->cmd = cmd;
+-
+- return msg;
+-}
+-
+-char *
+-msn_message_gen_payload(MsnMessage *msg, size_t *ret_size)
+-{
+- GList *l;
+- char *n, *base, *end;
+- int len;
+- size_t body_len = 0;
+- const void *body;
+-
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- len = MSN_BUF_LEN;
+-
+- base = n = end = g_malloc(len + 1);
+- end += len;
+-
+- /* Standard header. */
+- if (msg->charset == NULL)
+- {
+- g_snprintf(n, len,
+- "MIME-Version: 1.0\r\n"
+- "Content-Type: %s\r\n",
+- msg->content_type);
+- }
+- else
+- {
+- g_snprintf(n, len,
+- "MIME-Version: 1.0\r\n"
+- "Content-Type: %s; charset=%s\r\n",
+- msg->content_type, msg->charset);
+- }
+-
+- n += strlen(n);
+-
+- for (l = msg->header_list; l != NULL; l = l->next)
+- {
+- const char *key;
+- const char *value;
+-
+- key = l->data;
+- value = msn_message_get_header_value(msg, key);
+-
+- g_snprintf(n, end - n, "%s: %s\r\n", key, value);
+- n += strlen(n);
+- }
+-
+- n += g_strlcpy(n, "\r\n", end - n);
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+-
+- if (body != NULL)
+- {
+- memcpy(n, body, body_len);
+- n += body_len;
+- *n = '\0';
+- }
+-
+- if (ret_size != NULL)
+- {
+- *ret_size = n - base;
+-
+- if (*ret_size > 1664)
+- *ret_size = 1664;
+- }
+-
+- return base;
+-}
+-
+-void
+-msn_message_set_flag(MsnMessage *msg, char flag)
+-{
+- g_return_if_fail(msg != NULL);
+- g_return_if_fail(flag != 0);
+-
+- msg->flag = flag;
+-}
+-
+-char
+-msn_message_get_flag(const MsnMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, 0);
+-
+- return msg->flag;
+-}
+-
+-void
+-msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len)
+-{
+- g_return_if_fail(msg != NULL);
+-
+- /* There is no need to waste memory on data we cannot send anyway */
+- if (len > 1664)
+- len = 1664;
+-
+- if (msg->body != NULL)
+- g_free(msg->body);
+-
+- if (data != NULL && len > 0)
+- {
+- msg->body = g_malloc(len + 1);
+- memcpy(msg->body, data, len);
+- msg->body[len] = '\0';
+- msg->body_len = len;
+- }
+- else
+- {
+- msg->body = NULL;
+- msg->body_len = 0;
+- }
+-}
+-
+-const void *
+-msn_message_get_bin_data(const MsnMessage *msg, size_t *len)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- if (len)
+- *len = msg->body_len;
+-
+- return msg->body;
+-}
+-
+-void
+-msn_message_set_content_type(MsnMessage *msg, const char *type)
+-{
+- g_return_if_fail(msg != NULL);
+-
+- g_free(msg->content_type);
+- msg->content_type = g_strdup(type);
+-}
+-
+-const char *
+-msn_message_get_content_type(const MsnMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- return msg->content_type;
+-}
+-
+-void
+-msn_message_set_charset(MsnMessage *msg, const char *charset)
+-{
+- g_return_if_fail(msg != NULL);
+-
+- g_free(msg->charset);
+- msg->charset = g_strdup(charset);
+-}
+-
+-const char *
+-msn_message_get_charset(const MsnMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- return msg->charset;
+-}
+-
+-void
+-msn_message_set_header(MsnMessage *msg, const char *name, const char *value)
+-{
+- const char *temp;
+- char *new_name;
+-
+- g_return_if_fail(msg != NULL);
+- g_return_if_fail(name != NULL);
+-
+- temp = msn_message_get_header_value(msg, name);
+-
+- if (value == NULL)
+- {
+- if (temp != NULL)
+- {
+- GList *l;
+-
+- for (l = msg->header_list; l != NULL; l = l->next)
+- {
+- if (!g_ascii_strcasecmp(l->data, name))
+- {
+- msg->header_list = g_list_remove(msg->header_list, l->data);
+-
+- break;
+- }
+- }
+-
+- g_hash_table_remove(msg->header_table, name);
+- }
+-
+- return;
+- }
+-
+- new_name = g_strdup(name);
+-
+- g_hash_table_insert(msg->header_table, new_name, g_strdup(value));
+-
+- if (temp == NULL)
+- msg->header_list = g_list_append(msg->header_list, new_name);
+-}
+-
+-const char *
+-msn_message_get_header_value(const MsnMessage *msg, const char *name)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+- g_return_val_if_fail(name != NULL, NULL);
+-
+- return g_hash_table_lookup(msg->header_table, name);
+-}
+-
+-GHashTable *
+-msn_message_get_hashtable_from_body(const MsnMessage *msg)
+-{
+- GHashTable *table;
+- size_t body_len;
+- const char *body;
+- char **elems, **cur, **tokens, *body_str;
+-
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- table = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+-
+- g_return_val_if_fail(body != NULL, NULL);
+-
+- body_str = g_strndup(body, body_len);
+- elems = g_strsplit(body_str, "\r\n", 0);
+- g_free(body_str);
+-
+- for (cur = elems; *cur != NULL; cur++)
+- {
+- if (**cur == '\0')
+- break;
+-
+- tokens = g_strsplit(*cur, ": ", 2);
+-
+- if (tokens[0] != NULL && tokens[1] != NULL) {
+- g_hash_table_insert(table, tokens[0], tokens[1]);
+- g_free(tokens);
+- } else
+- g_strfreev(tokens);
+- }
+-
+- g_strfreev(elems);
+-
+- return table;
+-}
+-
+-char *
+-msn_message_to_string(MsnMessage *msg)
+-{
+- size_t body_len;
+- const char *body;
+-
+- g_return_val_if_fail(msg != NULL, NULL);
+- g_return_val_if_fail(msg->type == MSN_MSG_TEXT, NULL);
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+-
+- return g_strndup(body, body_len);
+-}
+-
+-void
+-msn_message_show_readable(MsnMessage *msg, const char *info,
+- gboolean text_body)
+-{
+- GString *str;
+- size_t body_len;
+- const char *body;
+- GList *l;
+-
+- g_return_if_fail(msg != NULL);
+-
+- str = g_string_new(NULL);
+-
+- /* Standard header. */
+- if (msg->charset == NULL)
+- {
+- g_string_append_printf(str,
+- "MIME-Version: 1.0\r\n"
+- "Content-Type: %s\r\n",
+- msg->content_type);
+- }
+- else
+- {
+- g_string_append_printf(str,
+- "MIME-Version: 1.0\r\n"
+- "Content-Type: %s; charset=%s\r\n",
+- msg->content_type, msg->charset);
+- }
+-
+- for (l = msg->header_list; l; l = l->next)
+- {
+- char *key;
+- const char *value;
+-
+- key = l->data;
+- value = msn_message_get_header_value(msg, key);
+-
+- g_string_append_printf(str, "%s: %s\r\n", key, value);
+- }
+-
+- g_string_append(str, "\r\n");
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+-
+- if (body != NULL)
+- {
+- if (msg->type == MSN_MSG_TEXT)
+- {
+- g_string_append_len(str, body, body_len);
+- g_string_append(str, "\r\n");
+- }
+- else
+- {
+- size_t i;
+- for (i = 0; i < body_len; i++, body++)
+- {
+- g_string_append_printf(str, "%02x ", (unsigned char)*body);
+- if (i % 16 == 0 && i != 0)
+- g_string_append_c(str, '\n');
+- }
+- g_string_append_c(str, '\n');
+- }
+- }
+-
+- purple_debug_info("msn", "Message %s:\n{%s}\n", info, str->str);
+-
+- g_string_free(str, TRUE);
+-}
+-
+-/**************************************************************************
+- * Message Handlers
+- **************************************************************************/
+-void
+-msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- PurpleConnection *gc;
+- const char *body;
+- char *body_enc;
+- char *body_final;
+- size_t body_len;
+- const char *passport;
+- const char *value;
+-
+- gc = cmdproc->session->account->gc;
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+- body_enc = g_markup_escape_text(body, body_len);
+-
+- passport = msg->remote_user;
+-
+- if (!strcmp(passport, "messenger@microsoft.com") &&
+- strstr(body, "immediate security update"))
+- {
+- return;
+- }
+-
+-#if 0
+- if ((value = msn_message_get_header_value(msg, "User-Agent")) != NULL)
+- {
+- purple_debug_misc("msn", "User-Agent = '%s'\n", value);
+- }
+-#endif
+-
+- if ((value = msn_message_get_header_value(msg, "X-MMS-IM-Format")) != NULL)
+- {
+- char *pre, *post;
+-
+- msn_parse_format(value, &pre, &post);
+-
+- body_final = g_strdup_printf("%s%s%s", pre ? pre : "",
+- body_enc ? body_enc : "", post ? post : "");
+-
+- g_free(pre);
+- g_free(post);
+- g_free(body_enc);
+- }
+- else
+- {
+- body_final = body_enc;
+- }
+-
+- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
+- MsnSwitchBoard *swboard = cmdproc->data;
+-
+- swboard->flag |= MSN_SB_FLAG_IM;
+-
+- if (swboard->current_users > 1 ||
+- ((swboard->conv != NULL) &&
+- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+- {
+- /* If current_users is always ok as it should then there is no need to
+- * check if this is a chat. */
+- if (swboard->current_users <= 1)
+- purple_debug_misc("msn", "plain_msg: current_users(%d)\n",
+- swboard->current_users);
+-
+- serv_got_chat_in(gc, swboard->chat_id, passport, 0, body_final,
+- time(NULL));
+- if (swboard->conv == NULL)
+- {
+- swboard->conv = purple_find_chat(gc, swboard->chat_id);
+- swboard->flag |= MSN_SB_FLAG_IM;
+- }
+- }
+- else if (!g_str_equal(passport, purple_account_get_username(gc->account)))
+- {
+- /* Don't im ourselves ... */
+- serv_got_im(gc, passport, body_final, 0, time(NULL));
+- if (swboard->conv == NULL)
+- {
+- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- passport, purple_connection_get_account(gc));
+- swboard->flag |= MSN_SB_FLAG_IM;
+- }
+- }
+-
+- } else {
+- serv_got_im(gc, passport, body_final, 0, time(NULL));
+- }
+-
+- g_free(body_final);
+-}
+-
+-void
+-msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- PurpleConnection *gc;
+- char *passport;
+-
+- gc = cmdproc->session->account->gc;
+- passport = msg->remote_user;
+-
+- if (msn_message_get_header_value(msg, "TypingUser") == NULL)
+- return;
+-
+- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
+- MsnSwitchBoard *swboard = cmdproc->data;
+-
+- if (swboard->current_users == 1)
+- {
+- serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
+- PURPLE_TYPING);
+- }
+-
+- } else {
+- serv_got_typing(gc, passport, MSN_TYPING_RECV_TIMEOUT,
+- PURPLE_TYPING);
+- }
+-}
+-
+-static void
+-datacast_inform_user(MsnSwitchBoard *swboard, const char *who,
+- const char *msg, const char *filename)
+-{
+- char *username, *str;
+- PurpleAccount *account;
+- PurpleBuddy *b;
+- PurpleConnection *pc;
+- gboolean chat;
+-
+- account = swboard->session->account;
+- pc = purple_account_get_connection(account);
+-
+- if ((b = purple_find_buddy(account, who)) != NULL)
+- username = g_markup_escape_text(purple_buddy_get_alias(b), -1);
+- else
+- username = g_markup_escape_text(who, -1);
+- str = g_strdup_printf(msg, username, filename);
+- g_free(username);
+-
+- swboard->flag |= MSN_SB_FLAG_IM;
+- if (swboard->current_users > 1)
+- chat = TRUE;
+- else
+- chat = FALSE;
+-
+- if (swboard->conv == NULL) {
+- if (chat)
+- swboard->conv = purple_find_chat(account->gc, swboard->chat_id);
+- else {
+- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- who, account);
+- if (swboard->conv == NULL)
+- swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, who);
+- }
+- }
+-
+- if (chat)
+- serv_got_chat_in(pc,
+- purple_conv_chat_get_id(PURPLE_CONV_CHAT(swboard->conv)),
+- who, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM, str,
+- time(NULL));
+- else
+- serv_got_im(pc, who, str, PURPLE_MESSAGE_RECV|PURPLE_MESSAGE_SYSTEM,
+- time(NULL));
+- g_free(str);
+-
+-}
+-
+-/* TODO: Make these not be such duplicates of each other */
+-static void
+-got_wink_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
+-{
+- FILE *f = NULL;
+- char *path = NULL;
+- const char *who = slpcall->slplink->remote_user;
+- purple_debug_info("msn", "Received wink from %s\n", who);
+-
+- if ((f = purple_mkstemp(&path, TRUE)) &&
+- (fwrite(data, 1, size, f) == size)) {
+- datacast_inform_user(slpcall->slplink->swboard,
+- who,
+- _("%s sent a wink. <a href='msn-wink://%s'>Click here to play it</a>"),
+- path);
+- } else {
+- purple_debug_error("msn", "Couldn\'t create temp file to store wink\n");
+- datacast_inform_user(slpcall->slplink->swboard,
+- who,
+- _("%s sent a wink, but it could not be saved"),
+- NULL);
+- }
+- if (f)
+- fclose(f);
+- g_free(path);
+-}
+-
+-static void
+-got_voiceclip_cb(MsnSlpCall *slpcall, const guchar *data, gsize size)
+-{
+- FILE *f = NULL;
+- char *path = NULL;
+- const char *who = slpcall->slplink->remote_user;
+- purple_debug_info("msn", "Received voice clip from %s\n", who);
+-
+- if ((f = purple_mkstemp(&path, TRUE)) &&
+- (fwrite(data, 1, size, f) == size)) {
+- datacast_inform_user(slpcall->slplink->swboard,
+- who,
+- _("%s sent a voice clip. <a href='audio://%s'>Click here to play it</a>"),
+- path);
+- } else {
+- purple_debug_error("msn", "Couldn\'t create temp file to store sound\n");
+- datacast_inform_user(slpcall->slplink->swboard,
+- who,
+- _("%s sent a voice clip, but it could not be saved"),
+- NULL);
+- }
+- if (f)
+- fclose(f);
+- g_free(path);
+-}
+-
+-void
+-msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- MsnSlpLink *slplink;
+- MsnP2PVersion p2p;
+-
+- session = cmdproc->servconn->session;
+- slplink = msn_session_get_slplink(session, msg->remote_user);
+-
+- if (slplink->swboard == NULL)
+- {
+- /*
+- * We will need swboard in order to change its flags. If its
+- * NULL, something has probably gone wrong earlier on. I
+- * didn't want to do this, but MSN 7 is somehow causing us
+- * to crash here, I couldn't reproduce it to debug more,
+- * and people are reporting bugs. Hopefully this doesn't
+- * cause more crashes. Stu.
+- */
+- if (cmdproc->data == NULL)
+- g_warning("msn_p2p_msg cmdproc->data was NULL\n");
+- else {
+- slplink->swboard = (MsnSwitchBoard *)cmdproc->data;
+- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
+- }
+- }
+-
+- p2p = msn_slplink_get_p2p_version(slplink);
+- msg->part = msn_slpmsgpart_new_from_data(p2p, msg->body, msg->body_len);
+-
+- if (msg->part)
+- msn_slplink_process_msg(slplink, msg->part);
+- else
+- purple_debug_warning("msn", "P2P message failed to parse.\n");
+-}
+-
+-static void
+-got_emoticon(MsnSlpCall *slpcall,
+- const guchar *data, gsize size)
+-{
+- PurpleConversation *conv;
+- MsnSwitchBoard *swboard;
+-
+- swboard = slpcall->slplink->swboard;
+- conv = swboard->conv;
+-
+- if (conv) {
+- /* FIXME: it would be better if we wrote the data as we received it
+- instead of all at once, calling write multiple times and
+- close once at the very end
+- */
+- purple_conv_custom_smiley_write(conv, slpcall->data_info, data, size);
+- purple_conv_custom_smiley_close(conv, slpcall->data_info );
+- }
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Got smiley: %s\n", slpcall->data_info);
+-}
+-
+-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- MsnSlpLink *slplink;
+- MsnSwitchBoard *swboard;
+- MsnObject *obj;
+- char **tokens;
+- char *smile, *body_str;
+- const char *body, *who, *sha1;
+- guint tok;
+- size_t body_len;
+-
+- PurpleConversation *conv;
+-
+- session = cmdproc->servconn->session;
+-
+- if (!purple_account_get_bool(session->account, "custom_smileys", TRUE))
+- return;
+-
+- swboard = cmdproc->data;
+- conv = swboard->conv;
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+- if (!body || !body_len)
+- return;
+- body_str = g_strndup(body, body_len);
+-
+- /* MSN Messenger 7 may send more than one MSNObject in a single message...
+- * Maybe 10 tokens is a reasonable max value. */
+- tokens = g_strsplit(body_str, "\t", 10);
+-
+- g_free(body_str);
+-
+- for (tok = 0; tok < 9; tok += 2) {
+- if (tokens[tok] == NULL || tokens[tok + 1] == NULL) {
+- break;
+- }
+-
+- smile = tokens[tok];
+- obj = msn_object_new_from_string(purple_url_decode(tokens[tok + 1]));
+-
+- if (obj == NULL)
+- break;
+-
+- who = msn_object_get_creator(obj);
+- sha1 = msn_object_get_sha1(obj);
+-
+- slplink = msn_session_get_slplink(session, who);
+- if (slplink->swboard != swboard) {
+- if (slplink->swboard != NULL)
+- /*
+- * Apparently we're using a different switchboard now or
+- * something? I don't know if this is normal, but it
+- * definitely happens. So make sure the old switchboard
+- * doesn't still have a reference to us.
+- */
+- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
+- slplink->swboard = swboard;
+- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
+- }
+-
+- /* If the conversation doesn't exist then this is a custom smiley
+- * used in the first message in a MSN conversation: we need to create
+- * the conversation now, otherwise the custom smiley won't be shown.
+- * This happens because every GtkIMHtml has its own smiley tree: if
+- * the conversation doesn't exist then we cannot associate the new
+- * smiley with its GtkIMHtml widget. */
+- if (!conv) {
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, who);
+- }
+-
+- if (purple_conv_custom_smiley_add(conv, smile, "sha1", sha1, TRUE)) {
+- msn_slplink_request_object(slplink, smile, got_emoticon, NULL, obj);
+- }
+-
+- msn_object_destroy(obj);
+- obj = NULL;
+- who = NULL;
+- sha1 = NULL;
+- }
+- g_strfreev(tokens);
+-}
+-
+-void
+-msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- GHashTable *body;
+- const char *id;
+- body = msn_message_get_hashtable_from_body(msg);
+-
+- id = g_hash_table_lookup(body, "ID");
+-
+- if (!strcmp(id, "1")) {
+- /* Nudge */
+- PurpleAccount *account;
+- const char *user;
+-
+- account = cmdproc->session->account;
+- user = msg->remote_user;
+-
+- if (cmdproc->servconn->type == MSN_SERVCONN_SB) {
+- MsnSwitchBoard *swboard = cmdproc->data;
+- if (swboard->current_users > 1 ||
+- ((swboard->conv != NULL) &&
+- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+- purple_prpl_got_attention_in_chat(account->gc, swboard->chat_id, user, MSN_NUDGE);
+-
+- else
+- purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
+- } else {
+- purple_prpl_got_attention(account->gc, user, MSN_NUDGE);
+- }
+-
+- } else if (!strcmp(id, "2")) {
+- /* Wink */
+- MsnSession *session;
+- MsnSlpLink *slplink;
+- MsnObject *obj;
+- const char *who;
+- const char *data;
+-
+- session = cmdproc->session;
+-
+- data = g_hash_table_lookup(body, "Data");
+- obj = msn_object_new_from_string(data);
+- who = msn_object_get_creator(obj);
+-
+- slplink = msn_session_get_slplink(session, who);
+- msn_slplink_request_object(slplink, data, got_wink_cb, NULL, obj);
+-
+- msn_object_destroy(obj);
+-
+-
+- } else if (!strcmp(id, "3")) {
+- /* Voiceclip */
+- MsnSession *session;
+- MsnSlpLink *slplink;
+- MsnObject *obj;
+- const char *who;
+- const char *data;
+-
+- session = cmdproc->session;
+-
+- data = g_hash_table_lookup(body, "Data");
+- obj = msn_object_new_from_string(data);
+- who = msn_object_get_creator(obj);
+-
+- slplink = msn_session_get_slplink(session, who);
+- msn_slplink_request_object(slplink, data, got_voiceclip_cb, NULL, obj);
+-
+- msn_object_destroy(obj);
+-
+- } else if (!strcmp(id, "4")) {
+- /* Action */
+-
+- } else {
+- purple_debug_warning("msn", "Got unknown datacast with ID %s.\n", id);
+- }
+-
+- g_hash_table_destroy(body);
+-}
+-
+-void
+-msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- GHashTable *body;
+- const gchar *command;
+- const gchar *cookie;
+- gboolean accepted = FALSE;
+-
+- g_return_if_fail(cmdproc != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- body = msn_message_get_hashtable_from_body(msg);
+-
+- if (body == NULL) {
+- purple_debug_warning("msn",
+- "Unable to parse invite msg body.\n");
+- return;
+- }
+-
+- /*
+- * GUID is NOT always present but Invitation-Command and Invitation-Cookie
+- * are mandatory.
+- */
+- command = g_hash_table_lookup(body, "Invitation-Command");
+- cookie = g_hash_table_lookup(body, "Invitation-Cookie");
+-
+- if (command == NULL || cookie == NULL) {
+- purple_debug_warning("msn",
+- "Invalid invitation message: either Invitation-Command "
+- "or Invitation-Cookie is missing or invalid.\n"
+- );
+- return;
+-
+- } else if (!strcmp(command, "INVITE")) {
+- const gchar *guid = g_hash_table_lookup(body, "Application-GUID");
+-
+- if (guid == NULL) {
+- purple_debug_warning("msn",
+- "Invite msg missing Application-GUID.\n");
+-
+- accepted = TRUE;
+-
+- } else if (!strcmp(guid, MSN_FT_GUID)) {
+-
+- } else if (!strcmp(guid, "{02D3C01F-BF30-4825-A83A-DE7AF41648AA}")) {
+- purple_debug_info("msn", "Computer call\n");
+-
+- if (cmdproc->session) {
+- PurpleConversation *conv = NULL;
+- gchar *from = msg->remote_user;
+- gchar *buf = NULL;
+-
+- if (from)
+- conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, from,
+- cmdproc->session->account);
+- if (conv)
+- buf = g_strdup_printf(
+- _("%s sent you a voice chat "
+- "invite, which is not yet "
+- "supported."), from);
+- if (buf) {
+- purple_conversation_write(conv, NULL, buf,
+- PURPLE_MESSAGE_SYSTEM |
+- PURPLE_MESSAGE_NOTIFY,
+- time(NULL));
+- g_free(buf);
+- }
+- }
+- } else {
+- const gchar *application = g_hash_table_lookup(body, "Application-Name");
+- purple_debug_warning("msn", "Unhandled invite msg with GUID %s: %s.\n",
+- guid, application ? application : "(null)");
+- }
+-
+- if (!accepted) {
+- MsnSwitchBoard *swboard = cmdproc->data;
+- char *text;
+- MsnMessage *cancel;
+-
+- cancel = msn_message_new(MSN_MSG_TEXT);
+- msn_message_set_content_type(cancel, "text/x-msmsgsinvite");
+- msn_message_set_charset(cancel, "UTF-8");
+- msn_message_set_flag(cancel, 'U');
+-
+- text = g_strdup_printf("Invitation-Command: CANCEL\r\n"
+- "Invitation-Cookie: %s\r\n"
+- "Cancel-Code: REJECT_NOT_INSTALLED\r\n",
+- cookie);
+- msn_message_set_bin_data(cancel, text, strlen(text));
+- g_free(text);
+-
+- msn_switchboard_send_msg(swboard, cancel, TRUE);
+- msn_message_unref(cancel);
+- }
+-
+- } else if (!strcmp(command, "CANCEL")) {
+- const gchar *code = g_hash_table_lookup(body, "Cancel-Code");
+- purple_debug_info("msn", "MSMSGS invitation cancelled: %s.\n",
+- code ? code : "no reason given");
+-
+- } else {
+- /*
+- * Some other already established invitation session.
+- * Can be retrieved by Invitation-Cookie.
+- */
+- }
+-
+- g_hash_table_destroy(body);
+-}
+-
+-/* Only called from chats. Handwritten messages for IMs come as a SLP message */
+-void
+-msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- const char *body;
+- size_t body_len;
+-
+- body = msn_message_get_bin_data(msg, &body_len);
+- msn_switchboard_show_ink(cmdproc->data, msg->remote_user, body);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msg.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.h
+--- pidgin-2.10.7/libpurple/protocols/msn/msg.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msg.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,325 +0,0 @@
+-/**
+- * @file msg.h Message functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_MSG_H
+-#define MSN_MSG_H
+-
+-typedef struct _MsnMessage MsnMessage;
+-
+-/*
+-typedef enum
+-{
+- MSN_MSG_NORMAL,
+- MSN_MSG_SLP_SB,
+- MSN_MSG_SLP_DC
+-} MsnMsgType;
+-*/
+-
+-typedef enum
+-{
+- MSN_MSG_UNKNOWN,
+- MSN_MSG_TEXT,
+- MSN_MSG_TYPING,
+- MSN_MSG_CAPS,
+- MSN_MSG_SLP,
+- MSN_MSG_NUDGE
+-} MsnMsgType;
+-
+-typedef enum
+-{
+- MSN_MSG_ERROR_NONE, /**< No error. */
+- MSN_MSG_ERROR_TIMEOUT, /**< The message timedout. */
+- MSN_MSG_ERROR_NAK, /**< The message could not be sent. */
+- MSN_MSG_ERROR_SB, /**< The error comes from the switchboard. */
+- MSN_MSG_ERROR_UNKNOWN /**< An unknown error occurred. */
+-} MsnMsgErrorType;
+-
+-#include "command.h"
+-#include "session.h"
+-#include "transaction.h"
+-#include "user.h"
+-#include "slpmsg.h"
+-#include "slpmsg_part.h"
+-
+-typedef void (*MsnMsgCb)(MsnMessage *, void *data);
+-
+-#define MSG_BODY_DEM "\r\n\r\n"
+-#define MSG_LINE_DEM "\r\n"
+-
+-#define MSG_OIM_BODY_DEM "\n\n"
+-#define MSG_OIM_LINE_DEM "\n"
+-
+-/**
+- * A message.
+- */
+-struct _MsnMessage
+-{
+- guint ref_count; /**< The reference count. */
+-
+- MsnMsgType type;
+-
+- MsnSlpMessagePart *part;
+-
+- char *remote_user;
+- char flag;
+-
+- char *content_type;
+- char *charset;
+- char *body;
+- gsize body_len;
+- guint total_chunks; /**< How many chunks in this multi-part message */
+- guint received_chunks; /**< How many chunks we've received so far */
+-
+- GHashTable *header_table;
+- GList *header_list;
+-
+- gboolean ack_ref; /**< A flag that states if this message has
+- been ref'ed for using it in a callback. */
+-
+- MsnCommand *cmd;
+-
+- MsnMsgCb ack_cb; /**< The callback to call when we receive an ACK of this
+- message. */
+- MsnMsgCb nak_cb; /**< The callback to call when we receive a NAK of this
+- message. */
+- void *ack_data; /**< The data used by callbacks. */
+-
+- guint32 retries;
+-};
+-
+-/**
+- * Creates a new, empty message.
+- *
+- * @return A new message.
+- */
+-MsnMessage *msn_message_new(MsnMsgType type);
+-
+-/**
+- * Creates a new, empty MSNSLP message.
+- *
+- * @return A new MSNSLP message.
+- */
+-MsnMessage *msn_message_new_msnslp(void);
+-
+-/**
+- * Creates a new nudge message.
+- *
+- * @return A new nudge message.
+- */
+-MsnMessage *msn_message_new_nudge(void);
+-
+-/**
+- * Creates a new plain message.
+- *
+- * @return A new plain message.
+- */
+-MsnMessage *msn_message_new_plain(const char *message);
+-
+-/**
+- * Creates a new message based off a command.
+- *
+- * @param session The MSN session.
+- * @param cmd The command.
+- *
+- * @return The new message.
+- */
+-MsnMessage *msn_message_new_from_cmd(MsnSession *session, MsnCommand *cmd);
+-
+-/**
+- * Parses the payload of a message.
+- *
+- * @param msg The message.
+- * @param payload The payload.
+- * @param payload_len The length of the payload.
+- */
+-void msn_message_parse_payload(MsnMessage *msg, const char *payload,
+- size_t payload_len,
+- const char *line_dem,const char *body_dem);
+-
+-/**
+- * Increments the reference count on a message.
+- *
+- * @param msg The message.
+- *
+- * @return @a msg
+- */
+-MsnMessage *msn_message_ref(MsnMessage *msg);
+-
+-/**
+- * Decrements the reference count on a message.
+- *
+- * This will destroy the structure if the count hits 0.
+- *
+- * @param msg The message.
+- *
+- * @return @a msg, or @c NULL if the new count is 0.
+- */
+-void msn_message_unref(MsnMessage *msg);
+-
+-/**
+- * Generates the payload data of a message.
+- *
+- * @param msg The message.
+- * @param ret_size The returned size of the payload.
+- *
+- * @return The payload data of the message.
+- */
+-char *msn_message_gen_payload(MsnMessage *msg, size_t *ret_size);
+-
+-/**
+- * Sets the flag for an outgoing message.
+- *
+- * @param msg The message.
+- * @param flag The flag.
+- */
+-void msn_message_set_flag(MsnMessage *msg, char flag);
+-
+-/**
+- * Returns the flag for an outgoing message.
+- *
+- * @param msg The message.
+- *
+- * @return The flag.
+- */
+-char msn_message_get_flag(const MsnMessage *msg);
+-
+-/**
+- * Sets the binary content of the message.
+- *
+- * @param msg The message.
+- * @param data The binary data.
+- * @param len The length of the data.
+- */
+-void msn_message_set_bin_data(MsnMessage *msg, const void *data, size_t len);
+-
+-/**
+- * Returns the binary content of the message.
+- *
+- * @param msg The message.
+- * @param len The returned length of the data.
+- *
+- * @return The binary data.
+- */
+-const void *msn_message_get_bin_data(const MsnMessage *msg, size_t *len);
+-
+-/**
+- * Sets the content type in a message.
+- *
+- * @param msg The message.
+- * @param type The content-type.
+- */
+-void msn_message_set_content_type(MsnMessage *msg, const char *type);
+-
+-/**
+- * Returns the content type in a message.
+- *
+- * @param msg The message.
+- *
+- * @return The content-type.
+- */
+-const char *msn_message_get_content_type(const MsnMessage *msg);
+-
+-/**
+- * Sets the charset in a message.
+- *
+- * @param msg The message.
+- * @param charset The charset.
+- */
+-void msn_message_set_charset(MsnMessage *msg, const char *charset);
+-
+-/**
+- * Returns the charset in a message.
+- *
+- * @param msg The message.
+- *
+- * @return The charset.
+- */
+-const char *msn_message_get_charset(const MsnMessage *msg);
+-
+-/**
+- * Sets a header in a message.
+- *
+- * @param msg The message.
+- * @param header The header name.
+- * @param value The header value.
+- */
+-void msn_message_set_header(MsnMessage *msg, const char *name,
+- const char *value);
+-
+-/**
+- * Returns the value of a header from a message.
+- *
+- * @param msg The message.
+- * @param header The header value.
+- *
+- * @return The value, or @c NULL if not found.
+- */
+-const char *msn_message_get_header_value(const MsnMessage *msg, const char *name);
+-
+-/**
+- * Parses the body and returns it in the form of a hashtable.
+- *
+- * @param msg The message.
+- *
+- * @return The resulting hashtable.
+- */
+-GHashTable *msn_message_get_hashtable_from_body(const MsnMessage *msg);
+-
+-void msn_message_show_readable(MsnMessage *msg, const char *info,
+- gboolean text_body);
+-
+-char *msn_message_to_string(MsnMessage *msg);
+-
+-void msn_plain_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-void msn_control_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-/**
+- * Processes peer to peer messages.
+- *
+- * @param cmdproc The command processor.
+- * @param msg The message.
+- */
+-void msn_p2p_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-/**
+- * Processes emoticon messages.
+- *
+- * @param cmdproc The command processor.
+- * @param msg The message.
+- */
+-void msn_emoticon_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-void msn_datacast_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-/**
+- * Processes INVITE messages.
+- *
+- * @param cmdproc The command processor.
+- * @param msg The message.
+- */
+-void msn_invite_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-void msn_handwritten_msg(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-#endif /* MSN_MSG_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.c
+--- pidgin-2.10.7/libpurple/protocols/msn/msn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,3070 +0,0 @@
+-/**
+- * @file msn.c The MSN protocol plugin
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#define PHOTO_SUPPORT 1
+-
+-#include "internal.h"
+-
+-#include "debug.h"
+-#include "request.h"
+-
+-#include "accountopt.h"
+-#include "contact.h"
+-#include "msg.h"
+-#include "page.h"
+-#include "pluginpref.h"
+-#include "prefs.h"
+-#include "session.h"
+-#include "smiley.h"
+-#include "state.h"
+-#include "util.h"
+-#include "cmds.h"
+-#include "core.h"
+-#include "prpl.h"
+-#include "msnutils.h"
+-#include "version.h"
+-
+-#include "error.h"
+-#include "msg.h"
+-#include "switchboard.h"
+-#include "notification.h"
+-#include "slplink.h"
+-
+-#if PHOTO_SUPPORT
+-#define MAX_HTTP_BUDDYICON_BYTES (200 * 1024)
+-#include "imgstore.h"
+-#endif
+-
+-typedef struct
+-{
+- PurpleConnection *gc;
+- const char *passport;
+-
+-} MsnMobileData;
+-
+-typedef struct
+-{
+- PurpleConnection *gc;
+- char *name;
+-
+-} MsnGetInfoData;
+-
+-typedef struct
+-{
+- MsnGetInfoData *info_data;
+- char *stripped;
+- char *url_buffer;
+- PurpleNotifyUserInfo *user_info;
+- char *photo_url_text;
+-
+-} MsnGetInfoStepTwoData;
+-
+-typedef struct
+-{
+- PurpleConnection *gc;
+- const char *who;
+- char *msg;
+- PurpleMessageFlags flags;
+- time_t when;
+-} MsnIMData;
+-
+-typedef struct
+-{
+- char *smile;
+- PurpleSmiley *ps;
+- MsnObject *obj;
+-} MsnEmoticon;
+-
+-static const char *
+-msn_normalize(const PurpleAccount *account, const char *str)
+-{
+- static char buf[BUF_LEN];
+- char *tmp;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+-
+- tmp = g_strchomp(g_utf8_strdown(str, -1));
+- g_snprintf(buf, sizeof(buf), "%s%s", tmp,
+- (strchr(tmp, '@') ? "" : "@hotmail.com"));
+- g_free(tmp);
+-
+- return buf;
+-}
+-
+-static gboolean
+-msn_send_attention(PurpleConnection *gc, const char *username, guint type)
+-{
+- MsnMessage *msg;
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+-
+- msg = msn_message_new_nudge();
+- session = gc->proto_data;
+- swboard = msn_session_get_swboard(session, username, MSN_SB_FLAG_IM);
+-
+- msn_switchboard_send_msg(swboard, msg, TRUE);
+- msn_message_unref(msg);
+-
+- return TRUE;
+-}
+-
+-static GList *
+-msn_attention_types(PurpleAccount *account)
+-{
+- static GList *list = NULL;
+-
+- if (!list) {
+- list = g_list_append(list, purple_attention_type_new("Nudge", _("Nudge"),
+- _("%s has nudged you!"), _("Nudging %s...")));
+- }
+-
+- return list;
+-}
+-
+-static GHashTable *
+-msn_get_account_text_table(PurpleAccount *unused)
+-{
+- GHashTable *table;
+-
+- table = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
+-
+- return table;
+-}
+-
+-static PurpleCmdRet
+-msn_cmd_nudge(PurpleConversation *conv, const gchar *cmd, gchar **args, gchar **error, void *data)
+-{
+- PurpleAccount *account = purple_conversation_get_account(conv);
+- PurpleConnection *gc = purple_account_get_connection(account);
+- const gchar *username;
+-
+- username = purple_conversation_get_name(conv);
+-
+- purple_prpl_send_attention(gc, username, MSN_NUDGE);
+-
+- return PURPLE_CMD_RET_OK;
+-}
+-
+-struct public_alias_closure
+-{
+- PurpleAccount *account;
+- gpointer success_cb;
+- gpointer failure_cb;
+-};
+-
+-static gboolean
+-set_public_alias_length_error(gpointer data)
+-{
+- struct public_alias_closure *closure = data;
+- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
+-
+- failure_cb(closure->account, _("Your new MSN friendly name is too long."));
+- g_free(closure);
+-
+- return FALSE;
+-}
+-
+-static void
+-prp_success_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- const char *type, *friendlyname;
+- struct public_alias_closure *closure;
+-
+- g_return_if_fail(cmd->param_count >= 3);
+- type = cmd->params[1];
+- g_return_if_fail(!strcmp(type, "MFN"));
+-
+- closure = cmd->trans->data;
+- friendlyname = purple_url_decode(cmd->params[2]);
+-
+- msn_update_contact(cmdproc->session, "Me", MSN_UPDATE_DISPLAY, friendlyname);
+-
+- purple_connection_set_display_name(
+- purple_account_get_connection(closure->account),
+- friendlyname);
+- purple_account_set_string(closure->account, "display-name", friendlyname);
+-
+- if (closure->success_cb) {
+- PurpleSetPublicAliasSuccessCallback success_cb = closure->success_cb;
+- success_cb(closure->account, friendlyname);
+- }
+-}
+-
+-static void
+-prp_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- struct public_alias_closure *closure = trans->data;
+- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
+- gboolean debug;
+- const char *error_text;
+-
+- error_text = msn_error_get_text(error, &debug);
+- failure_cb(closure->account, error_text);
+-}
+-
+-static void
+-prp_timeout_cb(MsnCmdProc *cmdproc, MsnTransaction *trans)
+-{
+- struct public_alias_closure *closure = trans->data;
+- PurpleSetPublicAliasFailureCallback failure_cb = closure->failure_cb;
+- failure_cb(closure->account, _("Connection Timeout"));
+-}
+-
+-void
+-msn_set_public_alias(PurpleConnection *pc, const char *alias,
+- PurpleSetPublicAliasSuccessCallback success_cb,
+- PurpleSetPublicAliasFailureCallback failure_cb)
+-{
+- MsnCmdProc *cmdproc;
+- MsnSession *session;
+- MsnTransaction *trans;
+- PurpleAccount *account;
+- char real_alias[BUDDY_ALIAS_MAXLEN + 1];
+- struct public_alias_closure *closure;
+-
+- session = purple_connection_get_protocol_data(pc);
+- cmdproc = session->notification->cmdproc;
+- account = purple_connection_get_account(pc);
+-
+- if (alias && *alias) {
+- if (!msn_encode_spaces(alias, real_alias, BUDDY_ALIAS_MAXLEN + 1)) {
+- if (failure_cb) {
+- struct public_alias_closure *closure =
+- g_new0(struct public_alias_closure, 1);
+- closure->account = account;
+- closure->failure_cb = failure_cb;
+- purple_timeout_add(0, set_public_alias_length_error, closure);
+- } else {
+- purple_notify_error(pc, NULL,
+- _("Your new MSN friendly name is too long."),
+- NULL);
+- }
+- return;
+- }
+-
+- if (real_alias[0] == '\0')
+- g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
+- } else
+- g_strlcpy(real_alias, purple_account_get_username(account), sizeof(real_alias));
+-
+- closure = g_new0(struct public_alias_closure, 1);
+- closure->account = account;
+- closure->success_cb = success_cb;
+- closure->failure_cb = failure_cb;
+-
+- trans = msn_transaction_new(cmdproc, "PRP", "MFN %s", real_alias);
+- msn_transaction_set_data(trans, closure);
+- msn_transaction_set_data_free(trans, g_free);
+- msn_transaction_add_cb(trans, "PRP", prp_success_cb);
+- if (failure_cb) {
+- msn_transaction_set_error_cb(trans, prp_error_cb);
+- msn_transaction_set_timeout_cb(trans, prp_timeout_cb);
+- }
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static gboolean
+-get_public_alias_cb(gpointer data)
+-{
+- struct public_alias_closure *closure = data;
+- PurpleGetPublicAliasSuccessCallback success_cb = closure->success_cb;
+- const char *alias;
+-
+- alias = purple_account_get_string(closure->account, "display-name",
+- purple_account_get_username(closure->account));
+- success_cb(closure->account, alias);
+- g_free(closure);
+-
+- return FALSE;
+-}
+-
+-static void
+-msn_get_public_alias(PurpleConnection *pc,
+- PurpleGetPublicAliasSuccessCallback success_cb,
+- PurpleGetPublicAliasFailureCallback failure_cb)
+-{
+- struct public_alias_closure *closure = g_new0(struct public_alias_closure, 1);
+- PurpleAccount *account = purple_connection_get_account(pc);
+-
+- closure->account = account;
+- closure->success_cb = success_cb;
+- purple_timeout_add(0, get_public_alias_cb, closure);
+-}
+-
+-static void
+-msn_act_id(PurpleConnection *gc, const char *entry)
+-{
+- msn_set_public_alias(gc, entry, NULL, NULL);
+-}
+-
+-static void
+-msn_set_prp(PurpleConnection *gc, const char *type, const char *entry)
+-{
+- MsnCmdProc *cmdproc;
+- MsnSession *session;
+- MsnTransaction *trans;
+-
+- session = gc->proto_data;
+- cmdproc = session->notification->cmdproc;
+-
+- if (entry == NULL || *entry == '\0')
+- {
+- trans = msn_transaction_new(cmdproc, "PRP", "%s", type);
+- }
+- else
+- {
+- trans = msn_transaction_new(cmdproc, "PRP", "%s %s", type,
+- purple_url_encode(entry));
+- }
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-msn_set_home_phone_cb(PurpleConnection *gc, const char *entry)
+-{
+- msn_set_prp(gc, "PHH", entry);
+-}
+-
+-static void
+-msn_set_work_phone_cb(PurpleConnection *gc, const char *entry)
+-{
+- msn_set_prp(gc, "PHW", entry);
+-}
+-
+-static void
+-msn_set_mobile_phone_cb(PurpleConnection *gc, const char *entry)
+-{
+- msn_set_prp(gc, "PHM", entry);
+-}
+-
+-static void
+-enable_msn_pages_cb(PurpleConnection *gc)
+-{
+- msn_set_prp(gc, "MOB", "Y");
+-}
+-
+-static void
+-disable_msn_pages_cb(PurpleConnection *gc)
+-{
+- msn_set_prp(gc, "MOB", "N");
+-}
+-
+-static void
+-send_to_mobile(PurpleConnection *gc, const char *who, const char *entry)
+-{
+- MsnTransaction *trans;
+- MsnSession *session;
+- MsnCmdProc *cmdproc;
+- MsnPage *page;
+- MsnMessage *msg;
+- MsnUser *user;
+- char *payload = NULL;
+- const char *mobile_number = NULL;
+- gsize payload_len;
+-
+- session = gc->proto_data;
+- cmdproc = session->notification->cmdproc;
+-
+- page = msn_page_new();
+- msn_page_set_body(page, entry);
+-
+- payload = msn_page_gen_payload(page, &payload_len);
+-
+- if ((user = msn_userlist_find_user(session->userlist, who)) &&
+- (mobile_number = msn_user_get_mobile_phone(user)) &&
+- mobile_number[0] == '+') {
+- /* if msn_user_get_mobile_phone() has a + in front, it's a number
+- that from the buddy's contact card */
+- trans = msn_transaction_new(cmdproc, "PGD", "tel:%s 1 %" G_GSIZE_FORMAT,
+- mobile_number, payload_len);
+- } else {
+- /* otherwise we send to whatever phone number the buddy registered
+- with msn */
+- trans = msn_transaction_new(cmdproc, "PGD", "%s 1 %" G_GSIZE_FORMAT,
+- who, payload_len);
+- }
+-
+- msn_transaction_set_payload(trans, payload, payload_len);
+- g_free(payload);
+-
+- msg = msn_message_new_plain(entry);
+- msn_transaction_set_data(trans, msg);
+-
+- msn_page_destroy(page);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-send_to_mobile_cb(MsnMobileData *data, const char *entry)
+-{
+- send_to_mobile(data->gc, data->passport, entry);
+- g_free(data);
+-}
+-
+-static void
+-close_mobile_page_cb(MsnMobileData *data, const char *entry)
+-{
+- g_free(data);
+-}
+-
+-/* -- */
+-
+-static void
+-msn_show_set_friendly_name(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- char *tmp;
+-
+- gc = (PurpleConnection *) action->context;
+- account = purple_connection_get_account(gc);
+-
+- tmp = g_strdup_printf(_("Set friendly name for %s."),
+- purple_account_get_username(account));
+- purple_request_input(gc, _("Set Friendly Name"), tmp,
+- _("This is the name that other MSN buddies will "
+- "see you as."),
+- purple_connection_get_display_name(gc), FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msn_act_id),
+- _("Cancel"), NULL,
+- account, NULL, NULL,
+- gc);
+- g_free(tmp);
+-}
+-
+-typedef struct MsnLocationData {
+- PurpleAccount *account;
+- MsnSession *session;
+- PurpleRequestFieldGroup *group;
+-} MsnLocationData;
+-
+-static void
+-update_endpoint_cb(MsnLocationData *data, PurpleRequestFields *fields)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- const char *old_name;
+- const char *name;
+- GList *others;
+-
+- session = data->session;
+- account = data->account;
+-
+- /* Update the current location's name */
+- old_name = purple_account_get_string(account, "endpoint-name", NULL);
+- name = purple_request_fields_get_string(fields, "endpoint-name");
+- if (!g_str_equal(old_name, name)) {
+- purple_account_set_string(account, "endpoint-name", name);
+- msn_notification_send_uux_private_endpointdata(session);
+- }
+-
+- /* Sign out other locations */
+- for (others = purple_request_field_group_get_fields(data->group);
+- others;
+- others = g_list_next(others)) {
+- PurpleRequestField *field = others->data;
+- if (purple_request_field_get_type(field) != PURPLE_REQUEST_FIELD_BOOLEAN)
+- continue;
+- if (purple_request_field_bool_get_value(field)) {
+- const char *id = purple_request_field_get_id(field);
+- char *user;
+- purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
+-
+- user = g_strdup_printf("%s;%s", purple_account_get_username(account), id);
+- msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+- g_free(user);
+- }
+- }
+-
+- g_free(data);
+-}
+-
+-static void
+-msn_show_locations(PurplePluginAction *action)
+-{
+- PurpleConnection *pc;
+- PurpleAccount *account;
+- MsnSession *session;
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+- gboolean have_other_endpoints;
+- GSList *l;
+- MsnLocationData *data;
+-
+- pc = (PurpleConnection *)action->context;
+- account = purple_connection_get_account(pc);
+- session = purple_connection_get_protocol_data(pc);
+-
+- fields = purple_request_fields_new();
+-
+- group = purple_request_field_group_new(_("This Location"));
+- purple_request_fields_add_group(fields, group);
+- field = purple_request_field_label_new("endpoint-label", _("This is the name that identifies this location"));
+- purple_request_field_group_add_field(group, field);
+- field = purple_request_field_string_new("endpoint-name",
+- _("Name"),
+- purple_account_get_string(account, "endpoint-name", NULL),
+- FALSE);
+- purple_request_field_set_required(field, TRUE);
+- purple_request_field_group_add_field(group, field);
+-
+- group = purple_request_field_group_new(_("Other Locations"));
+- purple_request_fields_add_group(fields, group);
+-
+- have_other_endpoints = FALSE;
+- for (l = session->user->endpoints; l; l = l->next) {
+- MsnUserEndpoint *ep = l->data;
+-
+- if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
+- /* Don't add myself to the list */
+- continue;
+-
+- if (!have_other_endpoints) {
+- /* We do in fact have an endpoint other than ourselves... let's
+- add a label */
+- field = purple_request_field_label_new("others-label",
+- _("You can sign out from other locations here"));
+- purple_request_field_group_add_field(group, field);
+- }
+-
+- have_other_endpoints = TRUE;
+- field = purple_request_field_bool_new(ep->id, ep->name, FALSE);
+- purple_request_field_group_add_field(group, field);
+- }
+- if (!have_other_endpoints) {
+- /* TODO: Due to limitations in our current request field API, the
+- following string will show up with a trailing colon. This should
+- be fixed either by adding an "include_colon" boolean, or creating
+- a separate purple_request_field_label_new_without_colon function,
+- or by never automatically adding the colon and requiring that
+- callers add the colon themselves. */
+- field = purple_request_field_label_new("others-label", _("You are not signed in from any other locations."));
+- purple_request_field_group_add_field(group, field);
+- }
+-
+- data = g_new0(MsnLocationData, 1);
+- data->account = account;
+- data->session = session;
+- data->group = group;
+-
+- purple_request_fields(pc, NULL, NULL, NULL,
+- fields,
+- _("OK"), G_CALLBACK(update_endpoint_cb),
+- _("Cancel"), G_CALLBACK(g_free),
+- account, NULL, NULL,
+- data);
+-}
+-
+-static void
+-enable_mpop_cb(PurpleConnection *pc)
+-{
+- MsnSession *session = purple_connection_get_protocol_data(pc);
+-
+- purple_debug_info("msn", "Enabling MPOP\n");
+-
+- session->enable_mpop = TRUE;
+- msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "1", NULL);
+-
+- purple_prpl_got_account_actions(purple_connection_get_account(pc));
+-}
+-
+-static void
+-disable_mpop_cb(PurpleConnection *pc)
+-{
+- PurpleAccount *account = purple_connection_get_account(pc);
+- MsnSession *session = purple_connection_get_protocol_data(pc);
+- GSList *l;
+-
+- purple_debug_info("msn", "Disabling MPOP\n");
+-
+- session->enable_mpop = FALSE;
+- msn_annotate_contact(session, "Me", "MSN.IM.MPOP", "0", NULL);
+-
+- for (l = session->user->endpoints; l; l = l->next) {
+- MsnUserEndpoint *ep = l->data;
+- char *user;
+-
+- if (ep->id[0] != '\0' && strncasecmp(ep->id + 1, session->guid, 36) == 0)
+- /* Don't kick myself */
+- continue;
+-
+- purple_debug_info("msn", "Disconnecting Endpoint %s\n", ep->id);
+-
+- user = g_strdup_printf("%s;%s", purple_account_get_username(account), ep->id);
+- msn_notification_send_uun(session, user, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+- g_free(user);
+- }
+-
+- purple_prpl_got_account_actions(account);
+-}
+-
+-static void
+-msn_show_set_mpop(PurplePluginAction *action)
+-{
+- PurpleConnection *pc;
+-
+- pc = (PurpleConnection *)action->context;
+-
+- purple_request_action(pc, NULL, _("Allow multiple logins?"),
+- _("Do you want to allow or disallow connecting from "
+- "multiple locations simultaneously?"),
+- PURPLE_DEFAULT_ACTION_NONE,
+- purple_connection_get_account(pc), NULL, NULL,
+- pc, 3,
+- _("Allow"), G_CALLBACK(enable_mpop_cb),
+- _("Disallow"), G_CALLBACK(disable_mpop_cb),
+- _("Cancel"), NULL);
+-}
+-
+-static void
+-msn_show_set_home_phone(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+-
+- gc = (PurpleConnection *) action->context;
+- session = gc->proto_data;
+-
+- purple_request_input(gc, NULL, _("Set your home phone number."), NULL,
+- msn_user_get_home_phone(session->user), FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msn_set_home_phone_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void
+-msn_show_set_work_phone(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+-
+- gc = (PurpleConnection *) action->context;
+- session = gc->proto_data;
+-
+- purple_request_input(gc, NULL, _("Set your work phone number."), NULL,
+- msn_user_get_work_phone(session->user), FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msn_set_work_phone_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void
+-msn_show_set_mobile_phone(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+-
+- gc = (PurpleConnection *) action->context;
+- session = gc->proto_data;
+-
+- purple_request_input(gc, NULL, _("Set your mobile phone number."), NULL,
+- msn_user_get_mobile_phone(session->user), FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msn_set_mobile_phone_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void
+-msn_show_set_mobile_pages(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+-
+- gc = (PurpleConnection *) action->context;
+-
+- purple_request_action(gc, NULL, _("Allow MSN Mobile pages?"),
+- _("Do you want to allow or disallow people on "
+- "your buddy list to send you MSN Mobile pages "
+- "to your cell phone or other mobile device?"),
+- PURPLE_DEFAULT_ACTION_NONE,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc, 3,
+- _("Allow"), G_CALLBACK(enable_msn_pages_cb),
+- _("Disallow"), G_CALLBACK(disable_msn_pages_cb),
+- _("Cancel"), NULL);
+-}
+-
+-/* QuLogic: Disabled until confirmed correct. */
+-#if 0
+-static void
+-msn_show_blocked_text(PurplePluginAction *action)
+-{
+- PurpleConnection *pc = (PurpleConnection *) action->context;
+- MsnSession *session;
+- char *title;
+-
+- session = pc->proto_data;
+-
+- title = g_strdup_printf(_("Blocked Text for %s"), session->account->username);
+- if (session->blocked_text == NULL) {
+- purple_notify_formatted(pc, title, title, NULL, _("No text is blocked for this account."), NULL, NULL);
+- } else {
+- char *blocked_text;
+- blocked_text = g_strdup_printf(_("MSN servers are currently blocking the following regular expressions:<br/>%s"),
+- session->blocked_text);
+-
+- purple_notify_formatted(pc, title, title, NULL, blocked_text, NULL, NULL);
+- g_free(blocked_text);
+- }
+- g_free(title);
+-}
+-#endif
+-
+-static void
+-msn_show_hotmail_inbox(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+-
+- gc = (PurpleConnection *) action->context;
+- session = gc->proto_data;
+-
+- if (!session->passport_info.email_enabled) {
+- purple_notify_error(gc, NULL,
+- _("This account does not have email enabled."), NULL);
+- return;
+- }
+-
+- /** apparently the correct value is 777, use 750 as a failsafe */
+- if ((session->passport_info.mail_url == NULL)
+- || (time (NULL) - session->passport_info.mail_timestamp >= 750)) {
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+-
+- cmdproc = session->notification->cmdproc;
+-
+- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
+- msn_transaction_set_data(trans, GUINT_TO_POINTER(TRUE));
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- } else
+- purple_notify_uri(gc, session->passport_info.mail_url);
+-}
+-
+-static void
+-show_send_to_mobile_cb(PurpleBlistNode *node, gpointer ignored)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- MsnMobileData *data;
+- PurpleAccount *account;
+- const char *name;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- name = purple_buddy_get_name(buddy);
+-
+- data = g_new0(MsnMobileData, 1);
+- data->gc = gc;
+- data->passport = name;
+-
+- purple_request_input(gc, NULL, _("Send a mobile message."), NULL,
+- NULL, TRUE, FALSE, NULL,
+- _("Page"), G_CALLBACK(send_to_mobile_cb),
+- _("Close"), G_CALLBACK(close_mobile_page_cb),
+- account, name, NULL,
+- data);
+-}
+-
+-static gboolean
+-msn_offline_message(const PurpleBuddy *buddy) {
+- return TRUE;
+-}
+-
+-void
+-msn_send_privacy(PurpleConnection *gc)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+-
+- account = purple_connection_get_account(gc);
+- session = gc->proto_data;
+- cmdproc = session->notification->cmdproc;
+-
+- if (account->perm_deny == PURPLE_PRIVACY_ALLOW_ALL ||
+- account->perm_deny == PURPLE_PRIVACY_DENY_USERS)
+- trans = msn_transaction_new(cmdproc, "BLP", "%s", "AL");
+- else
+- trans = msn_transaction_new(cmdproc, "BLP", "%s", "BL");
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-initiate_chat_cb(PurpleBlistNode *node, gpointer data)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+-
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+-
+- const char *alias;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+-
+- session = gc->proto_data;
+-
+- swboard = msn_switchboard_new(session);
+- msn_switchboard_request(swboard);
+- msn_switchboard_request_add_user(swboard, purple_buddy_get_name(buddy));
+-
+- /* TODO: This might move somewhere else, after USR might be */
+- swboard->chat_id = msn_switchboard_get_chat_id();
+- swboard->conv = serv_got_joined_chat(gc, swboard->chat_id, "MSN Chat");
+- swboard->flag = MSN_SB_FLAG_IM;
+-
+- /* Local alias > Display name > Username */
+- if ((alias = purple_account_get_alias(account)) == NULL)
+- if ((alias = purple_connection_get_display_name(gc)) == NULL)
+- alias = purple_account_get_username(account);
+-
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
+- alias, NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-static void
+-t_msn_xfer_init(PurpleXfer *xfer)
+-{
+- msn_request_ft(xfer);
+-}
+-
+-static void
+-t_msn_xfer_cancel_send(PurpleXfer *xfer)
+-{
+- MsnSlpLink *slplink = xfer->data;
+- msn_slplink_unref(slplink);
+-}
+-
+-static PurpleXfer*
+-msn_new_xfer(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- PurpleXfer *xfer;
+-
+- session = gc->proto_data;
+-
+- xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+-
+- g_return_val_if_fail(xfer != NULL, NULL);
+-
+- xfer->data = msn_slplink_ref(msn_session_get_slplink(session, who));
+-
+- purple_xfer_set_init_fnc(xfer, t_msn_xfer_init);
+- purple_xfer_set_cancel_send_fnc(xfer, t_msn_xfer_cancel_send);
+-
+- return xfer;
+-}
+-
+-static void
+-msn_send_file(PurpleConnection *gc, const char *who, const char *file)
+-{
+- PurpleXfer *xfer = msn_new_xfer(gc, who);
+-
+- if (file)
+- purple_xfer_request_accepted(xfer, file);
+- else
+- purple_xfer_request(xfer);
+-}
+-
+-static gboolean
+-msn_can_receive_file(PurpleConnection *gc, const char *who)
+-{
+- PurpleAccount *account;
+- gchar *normal;
+- gboolean ret;
+-
+- account = purple_connection_get_account(gc);
+-
+- normal = g_strdup(msn_normalize(account, purple_account_get_username(account)));
+- ret = strcmp(normal, msn_normalize(account, who));
+- g_free(normal);
+-
+- if (ret) {
+- MsnSession *session = gc->proto_data;
+- if (session) {
+- MsnUser *user = msn_userlist_find_user(session->userlist, who);
+- if (user) {
+- /* Include these too: MSN_CAP_MOBILE_ON|MSN_CAP_WEB_WATCH ? */
+- if ((user->clientid & MSN_CAP_VIA_WEBIM) ||
+- user->networkid == MSN_NETWORK_YAHOO)
+- ret = FALSE;
+- else
+- ret = TRUE;
+- }
+- } else
+- ret = FALSE;
+- }
+-
+- return ret;
+-}
+-
+-/**************************************************************************
+- * Protocol Plugin ops
+- **************************************************************************/
+-
+-static const char *
+-msn_list_icon(PurpleAccount *a, PurpleBuddy *b)
+-{
+- return "msn";
+-}
+-
+-static const char *
+-msn_list_emblems(PurpleBuddy *b)
+-{
+- MsnUser *user = purple_buddy_get_protocol_data(b);
+-
+- if (user != NULL) {
+- if (user->clientid & MSN_CAP_BOT)
+- return "bot";
+- if (user->clientid & MSN_CAP_VIA_MOBILE)
+- return "mobile";
+-#if 0
+- /* XXX: Since we don't support this, there's no point in showing it just yet */
+- if (user->clientid & MSN_CAP_SCHANNEL)
+- return "secure";
+-#endif
+- if (user->clientid & MSN_CAP_VIA_WEBIM)
+- return "external";
+- if (user->networkid == MSN_NETWORK_YAHOO)
+- return "yahoo";
+- }
+-
+- return NULL;
+-}
+-
+-/*
+- * Set the User status text
+- */
+-static char *
+-msn_status_text(PurpleBuddy *buddy)
+-{
+- PurplePresence *presence;
+- PurpleStatus *status;
+- const char *msg;
+-
+- presence = purple_buddy_get_presence(buddy);
+- status = purple_presence_get_active_status(presence);
+-
+- /* Official client says media takes precedence over message */
+- /* I say message take precedence over media! Plus prpl-jabber agrees
+- too */
+- msg = purple_status_get_attr_string(status, "message");
+- if (msg && *msg)
+- return g_markup_escape_text(msg, -1);
+-
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+- const char *title, *game, *office;
+- char *media, *esc;
+- status = purple_presence_get_status(presence, "tune");
+- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+-
+- game = purple_status_get_attr_string(status, "game");
+- office = purple_status_get_attr_string(status, "office");
+-
+- if (title && *title) {
+- const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+- const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
+- media = purple_util_format_song_info(title, artist, album, NULL);
+- return media;
+- }
+- else if (game && *game)
+- media = g_strdup_printf("Playing %s", game);
+- else if (office && *office)
+- media = g_strdup_printf("Editing %s", office);
+- else
+- return NULL;
+- esc = g_markup_escape_text(media, -1);
+- g_free(media);
+- return esc;
+- }
+-
+- return NULL;
+-}
+-
+-static void
+-msn_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info, gboolean full)
+-{
+- MsnUser *user;
+- PurplePresence *presence = purple_buddy_get_presence(buddy);
+- PurpleStatus *status = purple_presence_get_active_status(presence);
+-
+- user = purple_buddy_get_protocol_data(buddy);
+-
+- if (purple_presence_is_online(presence))
+- {
+- const char *psm, *name;
+- const char *mediatype = NULL;
+- char *currentmedia = NULL;
+-
+- psm = purple_status_get_attr_string(status, "message");
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+- PurpleStatus *tune = purple_presence_get_status(presence, "tune");
+- const char *title = purple_status_get_attr_string(tune, PURPLE_TUNE_TITLE);
+- const char *game = purple_status_get_attr_string(tune, "game");
+- const char *office = purple_status_get_attr_string(tune, "office");
+- if (title && *title) {
+- const char *artist = purple_status_get_attr_string(tune, PURPLE_TUNE_ARTIST);
+- const char *album = purple_status_get_attr_string(tune, PURPLE_TUNE_ALBUM);
+- mediatype = _("Now Listening");
+- currentmedia = purple_util_format_song_info(title, artist, album, NULL);
+- } else if (game && *game) {
+- mediatype = _("Playing a game");
+- currentmedia = g_strdup(game);
+- } else if (office && *office) {
+- mediatype = _("Working");
+- currentmedia = g_strdup(office);
+- }
+- }
+-
+- if (!purple_status_is_available(status)) {
+- name = purple_status_get_name(status);
+- } else {
+- name = NULL;
+- }
+-
+- if (name != NULL && *name) {
+- char *tmp2;
+-
+- tmp2 = g_markup_escape_text(name, -1);
+- if (purple_presence_is_idle(presence)) {
+- char *idle;
+- char *tmp3;
+- /* Never know what those translations might end up like... */
+- idle = g_markup_escape_text(_("Idle"), -1);
+- tmp3 = g_strdup_printf("%s/%s", tmp2, idle);
+- g_free(idle);
+- g_free(tmp2);
+- tmp2 = tmp3;
+- }
+-
+- if (psm != NULL && *psm) {
+- purple_notify_user_info_add_pair_plaintext(user_info, tmp2, psm);
+- } else {
+- purple_notify_user_info_add_pair(user_info, _("Status"), tmp2);
+- }
+-
+- g_free(tmp2);
+- } else {
+- if (psm != NULL && *psm) {
+- if (purple_presence_is_idle(presence)) {
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), psm);
+- } else {
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), psm);
+- }
+- } else {
+- if (purple_presence_is_idle(presence)) {
+- purple_notify_user_info_add_pair(user_info, _("Status"),
+- _("Idle"));
+- } else {
+- purple_notify_user_info_add_pair(user_info, _("Status"),
+- purple_status_get_name(status));
+- }
+- }
+- }
+-
+- if (currentmedia) {
+- purple_notify_user_info_add_pair(user_info, mediatype, currentmedia);
+- g_free(currentmedia);
+- }
+- }
+-
+- /* XXX: This is being shown in non-full tooltips because the
+- * XXX: blocked icon overlay isn't always accurate for MSN.
+- * XXX: This can die as soon as purple_privacy_check() knows that
+- * XXX: this prpl always honors both the allow and deny lists. */
+- /* While the above comment may be strictly correct (the privacy API needs
+- * rewriteing), purple_privacy_check() is going to be more accurate at
+- * indicating whether a particular buddy is going to be able to message
+- * you, which is the important information that this is trying to convey.
+- */
+- if (full && user)
+- {
+- const char *phone;
+-
+- purple_notify_user_info_add_pair(user_info, _("Has you"),
+- ((user->list_op & (1 << MSN_LIST_RL)) ? _("Yes") : _("No")));
+-
+- purple_notify_user_info_add_pair(user_info, _("Blocked"),
+- ((user->list_op & (1 << MSN_LIST_BL)) ? _("Yes") : _("No")));
+-
+- phone = msn_user_get_home_phone(user);
+- if (phone != NULL)
+- purple_notify_user_info_add_pair(user_info, _("Home Phone Number"), phone);
+-
+- phone = msn_user_get_work_phone(user);
+- if (phone != NULL)
+- purple_notify_user_info_add_pair(user_info, _("Work Phone Number"), phone);
+-
+- phone = msn_user_get_mobile_phone(user);
+- if (phone != NULL)
+- purple_notify_user_info_add_pair(user_info, _("Mobile Phone Number"), phone);
+- }
+-}
+-
+-static GList *
+-msn_status_types(PurpleAccount *account)
+-{
+- PurpleStatusType *status;
+- GList *types = NULL;
+-
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AVAILABLE, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AWAY, NULL, NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AWAY, "brb", _("Be Right Back"), TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_UNAVAILABLE, "busy", _("Busy"), TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_UNAVAILABLE, "phone", _("On the Phone"), TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_AWAY, "lunch", _("Out to Lunch"), TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE,
+- NULL, NULL, TRUE, TRUE, FALSE);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
+- NULL, NULL, TRUE, TRUE, FALSE);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
+- "mobile", NULL, FALSE, FALSE, TRUE);
+- types = g_list_append(types, status);
+-
+- status = purple_status_type_new_with_attrs(PURPLE_STATUS_TUNE,
+- "tune", NULL, FALSE, TRUE, TRUE,
+- PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
+- PURPLE_TUNE_ALBUM, _("Tune Album"), purple_value_new(PURPLE_TYPE_STRING),
+- PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
+- "game", _("Game Title"), purple_value_new(PURPLE_TYPE_STRING),
+- "office", _("Office Title"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, status);
+-
+- return types;
+-}
+-
+-static GList *
+-msn_actions(PurplePlugin *plugin, gpointer context)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+- GList *m = NULL;
+- PurplePluginAction *act;
+-
+- gc = (PurpleConnection *) context;
+- session = gc->proto_data;
+-
+- act = purple_plugin_action_new(_("Set Friendly Name..."),
+- msn_show_set_friendly_name);
+- m = g_list_append(m, act);
+- m = g_list_append(m, NULL);
+-
+- if (session->enable_mpop)
+- {
+- act = purple_plugin_action_new(_("View Locations..."),
+- msn_show_locations);
+- m = g_list_append(m, act);
+- m = g_list_append(m, NULL);
+- }
+-
+- act = purple_plugin_action_new(_("Set Home Phone Number..."),
+- msn_show_set_home_phone);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Set Work Phone Number..."),
+- msn_show_set_work_phone);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Set Mobile Phone Number..."),
+- msn_show_set_mobile_phone);
+- m = g_list_append(m, act);
+- m = g_list_append(m, NULL);
+-
+-#if 0
+- act = purple_plugin_action_new(_("Enable/Disable Mobile Devices..."),
+- msn_show_set_mobile_support);
+- m = g_list_append(m, act);
+-#endif
+-
+- act = purple_plugin_action_new(_("Allow/Disallow Multiple Logins..."),
+- msn_show_set_mpop);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Allow/Disallow Mobile Pages..."),
+- msn_show_set_mobile_pages);
+- m = g_list_append(m, act);
+-
+-/* QuLogic: Disabled until confirmed correct. */
+-#if 0
+- m = g_list_append(m, NULL);
+- act = purple_plugin_action_new(_("View Blocked Text..."),
+- msn_show_blocked_text);
+- m = g_list_append(m, act);
+-#endif
+-
+- m = g_list_append(m, NULL);
+- act = purple_plugin_action_new(_("Open Hotmail Inbox"),
+- msn_show_hotmail_inbox);
+- m = g_list_append(m, act);
+-
+- return m;
+-}
+-
+-static GList *
+-msn_buddy_menu(PurpleBuddy *buddy)
+-{
+- MsnUser *user;
+-
+- GList *m = NULL;
+- PurpleMenuAction *act;
+-
+- g_return_val_if_fail(buddy != NULL, NULL);
+-
+- user = purple_buddy_get_protocol_data(buddy);
+-
+- if (user != NULL)
+- {
+- if (user->mobile)
+- {
+- act = purple_menu_action_new(_("Send to Mobile"),
+- PURPLE_CALLBACK(show_send_to_mobile_cb),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+- }
+-
+- if (g_ascii_strcasecmp(purple_buddy_get_name(buddy),
+- purple_account_get_username(purple_buddy_get_account(buddy))))
+- {
+- act = purple_menu_action_new(_("Initiate _Chat"),
+- PURPLE_CALLBACK(initiate_chat_cb),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+-
+- return m;
+-}
+-
+-static GList *
+-msn_blist_node_menu(PurpleBlistNode *node)
+-{
+- if(PURPLE_BLIST_NODE_IS_BUDDY(node))
+- {
+- return msn_buddy_menu((PurpleBuddy *) node);
+- }
+- else
+- {
+- return NULL;
+- }
+-}
+-
+-static void
+-msn_login(PurpleAccount *account)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+- const char *username;
+- const char *host;
+- gboolean http_method = FALSE;
+- int port;
+-
+- gc = purple_account_get_connection(account);
+-
+- if (!purple_ssl_is_supported())
+- {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+- _("SSL support is needed for MSN. Please install a supported "
+- "SSL library."));
+- return;
+- }
+-
+- http_method = purple_account_get_bool(account, "http_method", FALSE);
+-
+- if (http_method)
+- host = purple_account_get_string(account, "http_method_server", MSN_HTTPCONN_SERVER);
+- else
+- host = purple_account_get_string(account, "server", MSN_SERVER);
+- port = purple_account_get_int(account, "port", MSN_PORT);
+-
+- session = msn_session_new(account);
+-
+- gc->proto_data = session;
+- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_FORMATTING_WBFO | PURPLE_CONNECTION_NO_BGCOLOR |
+- PURPLE_CONNECTION_NO_FONTSIZE | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_ALLOW_CUSTOM_SMILEY;
+-
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_START);
+-
+- /* Hmm, I don't like this. */
+- /* XXX shx: Me neither */
+- username = msn_normalize(account, purple_account_get_username(account));
+-
+- if (strcmp(username, purple_account_get_username(account)))
+- purple_account_set_username(account, username);
+-
+- username = purple_account_get_string(account, "display-name", NULL);
+- purple_connection_set_display_name(gc, username);
+-
+- if (purple_account_get_string(account, "endpoint-name", NULL) == NULL) {
+- GHashTable *ui_info = purple_core_get_ui_info();
+- const gchar *ui_name = ui_info ? g_hash_table_lookup(ui_info, "name") : NULL;
+- purple_account_set_string(account, "endpoint-name",
+- ui_name && *ui_name ? ui_name : PACKAGE_NAME);
+- }
+-
+- if (!msn_session_connect(session, host, port, http_method))
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+-}
+-
+-static void
+-msn_close(PurpleConnection *gc)
+-{
+- MsnSession *session;
+-
+- session = gc->proto_data;
+-
+- g_return_if_fail(session != NULL);
+-
+- msn_session_destroy(session);
+-
+- gc->proto_data = NULL;
+-}
+-
+-static gboolean
+-msn_send_me_im(gpointer data)
+-{
+- MsnIMData *imdata = data;
+- serv_got_im(imdata->gc, imdata->who, imdata->msg, imdata->flags, imdata->when);
+- g_free(imdata->msg);
+- g_free(imdata);
+- return FALSE;
+-}
+-
+-static GString*
+-msn_msg_emoticon_add(GString *current, MsnEmoticon *emoticon)
+-{
+- MsnObject *obj;
+- char *strobj;
+-
+- if (emoticon == NULL)
+- return current;
+-
+- obj = emoticon->obj;
+-
+- if (!obj)
+- return current;
+-
+- strobj = msn_object_to_string(obj);
+-
+- if (current)
+- g_string_append_printf(current, "\t%s\t%s", emoticon->smile, strobj);
+- else {
+- current = g_string_new("");
+- g_string_printf(current, "%s\t%s", emoticon->smile, strobj);
+- }
+-
+- g_free(strobj);
+-
+- return current;
+-}
+-
+-static void
+-msn_send_emoticons(MsnSwitchBoard *swboard, GString *body)
+-{
+- MsnMessage *msg;
+-
+- g_return_if_fail(body != NULL);
+-
+- msg = msn_message_new(MSN_MSG_SLP);
+- msn_message_set_content_type(msg, "text/x-mms-emoticon");
+- msn_message_set_flag(msg, 'N');
+- msn_message_set_bin_data(msg, body->str, body->len);
+-
+- msn_switchboard_send_msg(swboard, msg, TRUE);
+- msn_message_unref(msg);
+-}
+-
+-static void msn_emoticon_destroy(MsnEmoticon *emoticon)
+-{
+- if (emoticon->obj)
+- msn_object_destroy(emoticon->obj);
+- g_free(emoticon->smile);
+- g_free(emoticon);
+-}
+-
+-static GSList* msn_msg_grab_emoticons(const char *msg, const char *username)
+-{
+- GSList *list;
+- GList *smileys;
+- PurpleSmiley *smiley;
+- PurpleStoredImage *img;
+- char *ptr;
+- MsnEmoticon *emoticon;
+- int length;
+-
+- list = NULL;
+- smileys = purple_smileys_get_all();
+- length = strlen(msg);
+-
+- for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
+- smiley = smileys->data;
+-
+- ptr = g_strstr_len(msg, length, purple_smiley_get_shortcut(smiley));
+-
+- if (!ptr)
+- continue;
+-
+- img = purple_smiley_get_stored_image(smiley);
+-
+- emoticon = g_new0(MsnEmoticon, 1);
+- emoticon->smile = g_strdup(purple_smiley_get_shortcut(smiley));
+- emoticon->ps = smiley;
+- emoticon->obj = msn_object_new_from_image(img,
+- purple_imgstore_get_filename(img),
+- username, MSN_OBJECT_EMOTICON);
+-
+- purple_imgstore_unref(img);
+- list = g_slist_prepend(list, emoticon);
+- }
+-
+- return list;
+-}
+-
+-void
+-msn_send_im_message(MsnSession *session, MsnMessage *msg)
+-{
+- MsnEmoticon *smile;
+- GSList *smileys;
+- GString *emoticons = NULL;
+- const char *username = purple_account_get_username(session->account);
+- MsnSwitchBoard *swboard = msn_session_get_swboard(session, msg->remote_user, MSN_SB_FLAG_IM);
+-
+- smileys = msn_msg_grab_emoticons(msg->body, username);
+- while (smileys) {
+- smile = (MsnEmoticon *)smileys->data;
+- emoticons = msn_msg_emoticon_add(emoticons, smile);
+- msn_emoticon_destroy(smile);
+- smileys = g_slist_delete_link(smileys, smileys);
+- }
+-
+- if (emoticons) {
+- msn_send_emoticons(swboard, emoticons);
+- g_string_free(emoticons, TRUE);
+- }
+-
+- msn_switchboard_send_msg(swboard, msg, TRUE);
+-}
+-
+-static int
+-msn_send_im(PurpleConnection *gc, const char *who, const char *message,
+- PurpleMessageFlags flags)
+-{
+- PurpleAccount *account;
+- PurpleBuddy *buddy = purple_find_buddy(gc->account, who);
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- MsnMessage *msg;
+- char *msgformat;
+- char *msgtext;
+- size_t msglen;
+- const char *username;
+-
+- purple_debug_info("msn", "send IM {%s} to %s\n", message, who);
+- account = purple_connection_get_account(gc);
+- username = purple_account_get_username(account);
+-
+- session = gc->proto_data;
+- swboard = msn_session_find_swboard(session, who);
+-
+- if (!strncmp("tel:+", who, 5)) {
+- char *text = purple_markup_strip_html(message);
+- send_to_mobile(gc, who, text);
+- g_free(text);
+- return 1;
+- }
+-
+- if (buddy) {
+- PurplePresence *p = purple_buddy_get_presence(buddy);
+- if (purple_presence_is_status_primitive_active(p, PURPLE_STATUS_MOBILE)) {
+- char *text = purple_markup_strip_html(message);
+- send_to_mobile(gc, who, text);
+- g_free(text);
+- return 1;
+- }
+- }
+-
+- msn_import_html(message, &msgformat, &msgtext);
+- msglen = strlen(msgtext);
+- if (msglen == 0) {
+- /* Stuff like <hr> will be ignored. Don't send an empty message
+- if that's all there is. */
+- g_free(msgtext);
+- g_free(msgformat);
+-
+- return 0;
+- }
+-
+- if (msglen + strlen(msgformat) + strlen(VERSION) > 1564)
+- {
+- g_free(msgformat);
+- g_free(msgtext);
+-
+- return -E2BIG;
+- }
+-
+- msg = msn_message_new_plain(msgtext);
+- msg->remote_user = g_strdup(who);
+- msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
+-
+- g_free(msgformat);
+- g_free(msgtext);
+-
+- purple_debug_info("msn", "prepare to send online Message\n");
+- if (g_ascii_strcasecmp(who, username))
+- {
+- if (flags & PURPLE_MESSAGE_AUTO_RESP) {
+- msn_message_set_flag(msg, 'U');
+- }
+-
+- if (msn_user_is_yahoo(account, who) || !(msn_user_is_online(account, who) || swboard != NULL)) {
+- /*we send the online and offline Message to Yahoo User via UBM*/
+- purple_debug_info("msn", "send to Yahoo User\n");
+- msn_notification_send_uum(session, msg);
+- } else {
+- purple_debug_info("msn", "send via switchboard\n");
+- msn_send_im_message(session, msg);
+- }
+- }
+- else
+- {
+- char *body_str, *body_enc, *pre, *post;
+- const char *format;
+- MsnIMData *imdata = g_new0(MsnIMData, 1);
+- /*
+- * In MSN, you can't send messages to yourself, so
+- * we'll fake like we received it ;)
+- */
+- body_str = msn_message_to_string(msg);
+- body_enc = g_markup_escape_text(body_str, -1);
+- g_free(body_str);
+-
+- format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
+- msn_parse_format(format, &pre, &post);
+- body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
+- body_enc ? body_enc : "", post ? post : "");
+- g_free(body_enc);
+- g_free(pre);
+- g_free(post);
+-
+- serv_got_typing_stopped(gc, who);
+- imdata->gc = gc;
+- imdata->who = who;
+- imdata->msg = body_str;
+- imdata->flags = flags & ~PURPLE_MESSAGE_SEND;
+- imdata->when = time(NULL);
+- purple_timeout_add(0, msn_send_me_im, imdata);
+- }
+-
+- msn_message_unref(msg);
+-
+- return 1;
+-}
+-
+-static unsigned int
+-msn_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- MsnMessage *msg;
+-
+- account = purple_connection_get_account(gc);
+- session = gc->proto_data;
+-
+- /*
+- * TODO: I feel like this should be "if (state != PURPLE_TYPING)"
+- * but this is how it was before, and I don't want to break
+- * anything. --KingAnt
+- */
+- if (state == PURPLE_NOT_TYPING)
+- return 0;
+-
+- if (!g_ascii_strcasecmp(who, purple_account_get_username(account)))
+- {
+- /* We'll just fake it, since we're sending to ourself. */
+- serv_got_typing(gc, who, MSN_TYPING_RECV_TIMEOUT, PURPLE_TYPING);
+-
+- return MSN_TYPING_SEND_TIMEOUT;
+- }
+-
+- swboard = msn_session_find_swboard(session, who);
+-
+- if (swboard == NULL || !msn_switchboard_can_send(swboard))
+- return 0;
+-
+- swboard->flag |= MSN_SB_FLAG_IM;
+-
+- msg = msn_message_new(MSN_MSG_TYPING);
+- msn_message_set_content_type(msg, "text/x-msmsgscontrol");
+- msn_message_set_flag(msg, 'U');
+- msn_message_set_header(msg, "TypingUser",
+- purple_account_get_username(account));
+- msn_message_set_bin_data(msg, "\r\n", 2);
+-
+- msn_switchboard_send_msg(swboard, msg, FALSE);
+-
+- msn_message_unref(msg);
+-
+- return MSN_TYPING_SEND_TIMEOUT;
+-}
+-
+-static void
+-msn_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleConnection *gc;
+- MsnSession *session;
+-
+- gc = purple_account_get_connection(account);
+-
+- if (gc != NULL)
+- {
+- session = gc->proto_data;
+- msn_change_status(session);
+- }
+-}
+-
+-static void
+-msn_set_idle(PurpleConnection *gc, int idle)
+-{
+- MsnSession *session;
+-
+- session = gc->proto_data;
+-
+- msn_change_status(session);
+-}
+-
+-/*
+- * Actually adds a buddy once we have the response from FQY
+- */
+-static void
+-add_pending_buddy(MsnSession *session,
+- const char *who,
+- MsnNetwork network,
+- MsnUser *user)
+-{
+- char *group;
+- MsnUserList *userlist;
+- MsnUser *user2;
+-
+- g_return_if_fail(user != NULL);
+-
+- if (network == MSN_NETWORK_UNKNOWN) {
+- purple_debug_error("msn", "Network in FQY response was unknown. "
+- "Assuming %s is a passport user and adding anyway.\n", who);
+- network = MSN_NETWORK_PASSPORT;
+- }
+-
+- group = msn_user_remove_pending_group(user);
+-
+- userlist = session->userlist;
+- user2 = msn_userlist_find_user(userlist, who);
+- if (user2 != NULL) {
+- /* User already in userlist, so just update it. */
+- msn_user_unref(user);
+- user = user2;
+- } else {
+- msn_userlist_add_user(userlist, user);
+- msn_user_unref(user);
+- }
+-
+- msn_user_set_network(user, network);
+- msn_userlist_add_buddy(userlist, who, group);
+-
+- g_free(group);
+-}
+-
+-static void
+-msn_add_buddy(PurpleConnection *pc, PurpleBuddy *buddy, PurpleGroup *group, const char *message)
+-{
+- PurpleAccount *account;
+- const char *bname, *gname;
+- MsnSession *session;
+- MsnUserList *userlist;
+- MsnUser *user;
+-
+- account = purple_connection_get_account(pc);
+- session = purple_connection_get_protocol_data(pc);
+- bname = purple_buddy_get_name(buddy);
+-
+- if (!session->logged_in)
+- {
+- purple_debug_error("msn", "msn_add_buddy called before connected\n");
+-
+- return;
+- }
+-
+- /* XXX - Would group ever be NULL here? I don't think so...
+- * shx: Yes it should; MSN handles non-grouped buddies, and this is only
+- * internal.
+- * KingAnt: But PurpleBuddys must always exist inside PurpleGroups, so
+- * won't group always be non-NULL here?
+- */
+- bname = msn_normalize(account, bname);
+- gname = group ? purple_group_get_name(group) : NULL;
+- purple_debug_info("msn", "Add user:%s to group:%s\n",
+- bname, gname ? gname : "(null)");
+-
+- if (!msn_email_is_valid(bname)) {
+- gchar *buf;
+- buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be valid email addresses."), bname);
+- if (!purple_conv_present_error(bname, account, buf))
+- purple_notify_error(pc, NULL, _("Unable to Add"), buf);
+- g_free(buf);
+-
+- /* Remove from local list */
+- purple_blist_remove_buddy(buddy);
+-
+- return;
+- }
+-
+- /* Make sure name is normalized */
+- purple_blist_rename_buddy(buddy, bname);
+-
+- userlist = session->userlist;
+- user = msn_userlist_find_user(userlist, bname);
+- if (user && user->authorized) {
+- message = NULL;
+- }
+- if ((user != NULL) && (user->networkid != MSN_NETWORK_UNKNOWN)) {
+- /* We already know this buddy and their network. This function knows
+- what to do with users already in the list and stuff... */
+- msn_user_set_invite_message(user, message);
+- msn_userlist_add_buddy(userlist, bname, gname);
+- } else {
+- char **tokens;
+- char *fqy;
+- /* We need to check the network for this buddy first */
+- user = msn_user_new(userlist, bname, NULL);
+- msn_user_set_invite_message(user, message);
+- msn_user_set_pending_group(user, gname);
+- msn_user_set_network(user, MSN_NETWORK_UNKNOWN);
+- /* Should probably re-use the msn_add_contact_xml function here */
+- tokens = g_strsplit(bname, "@", 2);
+- fqy = g_strdup_printf("<ml><d n=\"%s\"><c n=\"%s\"/></d></ml>",
+- tokens[1],
+- tokens[0]);
+- /* TODO: I think user will leak if we disconnect before receiving
+- a response to this FQY request */
+- msn_notification_send_fqy(session, fqy, strlen(fqy),
+- (MsnFqyCb)add_pending_buddy, user);
+- g_free(fqy);
+- g_strfreev(tokens);
+- }
+-}
+-
+-static void
+-msn_rem_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+-
+- if (!session->logged_in)
+- return;
+-
+- /* XXX - Does buddy->name need to be msn_normalize'd here? --KingAnt */
+- msn_userlist_rem_buddy(userlist, purple_buddy_get_name(buddy));
+-}
+-
+-static void
+-msn_add_permit(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+- MsnUser *user;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+- user = msn_userlist_find_user(userlist, who);
+-
+- if (!session->logged_in)
+- return;
+-
+- if (user != NULL && user->list_op & MSN_LIST_BL_OP) {
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
+-
+- /* delete contact from Block list and add it to Allow in the callback */
+- msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
+- } else {
+- /* just add the contact to Allow list */
+- msn_add_contact_to_list(session, NULL, who, MSN_LIST_AL);
+- }
+-
+-
+- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
+-}
+-
+-static void
+-msn_add_deny(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+- MsnUser *user;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+- user = msn_userlist_find_user(userlist, who);
+-
+- if (!session->logged_in)
+- return;
+-
+- if (user != NULL && user->list_op & MSN_LIST_AL_OP) {
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
+-
+- /* delete contact from Allow list and add it to Block in the callback */
+- msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
+- } else {
+- /* just add the contact to Block list */
+- msn_add_contact_to_list(session, NULL, who, MSN_LIST_BL);
+- }
+-
+- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
+-}
+-
+-static void
+-msn_rem_permit(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+- MsnUser *user;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+-
+- if (!session->logged_in)
+- return;
+-
+- user = msn_userlist_find_user(userlist, who);
+-
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_AL);
+-
+- msn_del_contact_from_list(session, NULL, who, MSN_LIST_AL);
+-
+- if (user != NULL && user->list_op & MSN_LIST_RL_OP)
+- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_BL);
+-}
+-
+-static void
+-msn_rem_deny(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+- MsnUser *user;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+-
+- if (!session->logged_in)
+- return;
+-
+- user = msn_userlist_find_user(userlist, who);
+-
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
+-
+- msn_del_contact_from_list(session, NULL, who, MSN_LIST_BL);
+-
+- if (user != NULL && user->list_op & MSN_LIST_RL_OP)
+- msn_userlist_add_buddy_to_list(userlist, who, MSN_LIST_AL);
+-}
+-
+-static void
+-msn_set_permit_deny(PurpleConnection *gc)
+-{
+- msn_send_privacy(gc);
+-}
+-
+-static void
+-msn_chat_invite(PurpleConnection *gc, int id, const char *msg,
+- const char *who)
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+-
+- session = gc->proto_data;
+-
+- swboard = msn_session_find_swboard_with_id(session, id);
+-
+- if (swboard == NULL)
+- {
+- /* if we have no switchboard, everyone else left the chat already */
+- swboard = msn_switchboard_new(session);
+- msn_switchboard_request(swboard);
+- swboard->chat_id = id;
+- swboard->conv = purple_find_chat(gc, id);
+- }
+-
+- swboard->flag |= MSN_SB_FLAG_IM;
+-
+- msn_switchboard_request_add_user(swboard, who);
+-}
+-
+-static void
+-msn_chat_leave(PurpleConnection *gc, int id)
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- PurpleConversation *conv;
+-
+- session = gc->proto_data;
+-
+- swboard = msn_session_find_swboard_with_id(session, id);
+-
+- /* if swboard is NULL we were the only person left anyway */
+- if (swboard == NULL)
+- return;
+-
+- conv = swboard->conv;
+-
+- msn_switchboard_release(swboard, MSN_SB_FLAG_IM);
+-
+- /* If other switchboards managed to associate themselves with this
+- * conv, make sure they know it's gone! */
+- if (conv != NULL)
+- {
+- while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
+- swboard->conv = NULL;
+- }
+-}
+-
+-static int
+-msn_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- const char *username;
+- MsnSwitchBoard *swboard;
+- MsnMessage *msg;
+- char *msgformat;
+- char *msgtext;
+- size_t msglen;
+- MsnEmoticon *smile;
+- GSList *smileys;
+- GString *emoticons = NULL;
+-
+- account = purple_connection_get_account(gc);
+- session = gc->proto_data;
+- username = purple_account_get_username(account);
+- swboard = msn_session_find_swboard_with_id(session, id);
+-
+- if (swboard == NULL)
+- return -EINVAL;
+-
+- if (!swboard->ready)
+- return 0;
+-
+- swboard->flag |= MSN_SB_FLAG_IM;
+-
+- msn_import_html(message, &msgformat, &msgtext);
+- msglen = strlen(msgtext);
+-
+- if ((msglen == 0) || (msglen + strlen(msgformat) + strlen(VERSION) > 1564))
+- {
+- g_free(msgformat);
+- g_free(msgtext);
+-
+- return -E2BIG;
+- }
+-
+- msg = msn_message_new_plain(msgtext);
+- msn_message_set_header(msg, "X-MMS-IM-Format", msgformat);
+-
+- smileys = msn_msg_grab_emoticons(msg->body, username);
+- while (smileys) {
+- smile = (MsnEmoticon *)smileys->data;
+- emoticons = msn_msg_emoticon_add(emoticons, smile);
+- if (purple_conv_custom_smiley_add(swboard->conv, smile->smile,
+- "sha1", purple_smiley_get_checksum(smile->ps),
+- FALSE)) {
+- gconstpointer data;
+- size_t len;
+- data = purple_smiley_get_data(smile->ps, &len);
+- purple_conv_custom_smiley_write(swboard->conv, smile->smile, data, len);
+- purple_conv_custom_smiley_close(swboard->conv, smile->smile);
+- }
+- msn_emoticon_destroy(smile);
+- smileys = g_slist_delete_link(smileys, smileys);
+- }
+-
+- if (emoticons) {
+- msn_send_emoticons(swboard, emoticons);
+- g_string_free(emoticons, TRUE);
+- }
+-
+- msn_switchboard_send_msg(swboard, msg, FALSE);
+- msn_message_unref(msg);
+-
+- g_free(msgformat);
+- g_free(msgtext);
+-
+- serv_got_chat_in(gc, id, purple_account_get_username(account), flags,
+- message, time(NULL));
+-
+- return 0;
+-}
+-
+-static void
+-msn_keepalive(PurpleConnection *gc)
+-{
+- MsnSession *session;
+- MsnTransaction *trans;
+-
+- session = gc->proto_data;
+-
+- if (!session->http_method)
+- {
+- MsnCmdProc *cmdproc;
+-
+- cmdproc = session->notification->cmdproc;
+-
+- trans = msn_transaction_new(cmdproc, "PNG", NULL);
+- msn_transaction_set_saveable(trans, FALSE);
+- msn_cmdproc_send_trans(cmdproc, trans);
+- }
+-}
+-
+-static void msn_alias_buddy(PurpleConnection *pc, const char *name, const char *alias)
+-{
+- MsnSession *session;
+-
+- session = pc->proto_data;
+-
+- msn_update_contact(session, name, MSN_UPDATE_ALIAS, alias);
+-}
+-
+-static void
+-msn_group_buddy(PurpleConnection *gc, const char *who,
+- const char *old_group_name, const char *new_group_name)
+-{
+- MsnSession *session;
+- MsnUserList *userlist;
+-
+- session = gc->proto_data;
+- userlist = session->userlist;
+-
+- msn_userlist_move_buddy(userlist, who, old_group_name, new_group_name);
+-}
+-
+-static void
+-msn_rename_group(PurpleConnection *gc, const char *old_name,
+- PurpleGroup *group, GList *moved_buddies)
+-{
+- MsnSession *session;
+- const char *gname;
+-
+- session = gc->proto_data;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->userlist != NULL);
+-
+- gname = purple_group_get_name(group);
+- if (msn_userlist_find_group_with_name(session->userlist, old_name) != NULL)
+- {
+- msn_contact_rename_group(session, old_name, gname);
+- }
+- else
+- {
+- /* not found */
+- msn_add_group(session, NULL, gname);
+- }
+-}
+-
+-static void
+-msn_convo_closed(PurpleConnection *gc, const char *who)
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- PurpleConversation *conv;
+-
+- session = gc->proto_data;
+-
+- swboard = msn_session_find_swboard(session, who);
+-
+- /*
+- * Don't perform an assertion here. If swboard is NULL, then the
+- * switchboard was either closed by the other party, or the person
+- * is talking to himself.
+- */
+- if (swboard == NULL)
+- return;
+-
+- conv = swboard->conv;
+-
+- /* If we release the switchboard here, it may still have messages
+- pending ACK which would result in incorrect unsent message errors.
+- Just let it timeout... This is *so* going to screw with people who
+- use dumb clients that report "User has closed the conversation window" */
+- /* msn_switchboard_release(swboard, MSN_SB_FLAG_IM); */
+- swboard->conv = NULL;
+-
+- /* If other switchboards managed to associate themselves with this
+- * conv, make sure they know it's gone! */
+- if (conv != NULL)
+- {
+- while ((swboard = msn_session_find_swboard_with_conv(session, conv)) != NULL)
+- swboard->conv = NULL;
+- }
+-}
+-
+-static void
+-msn_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
+-{
+- MsnSession *session;
+- MsnUser *user;
+-
+- session = gc->proto_data;
+- user = session->user;
+-
+- msn_user_set_buddy_icon(user, img);
+-
+- msn_change_status(session);
+-}
+-
+-static void
+-msn_remove_group(PurpleConnection *gc, PurpleGroup *group)
+-{
+- MsnSession *session;
+- const char *gname;
+-
+- session = gc->proto_data;
+- gname = purple_group_get_name(group);
+-
+- purple_debug_info("msn", "Remove group %s\n", gname);
+- /*we can't delete the default group*/
+- if(!strcmp(gname, MSN_INDIVIDUALS_GROUP_NAME)||
+- !strcmp(gname, MSN_NON_IM_GROUP_NAME))
+- {
+- purple_debug_info("msn", "This group can't be removed, returning.\n");
+- return ;
+- }
+-
+- msn_del_group(session, gname);
+-}
+-
+-/**
+- * Extract info text from info_data and add it to user_info
+- */
+-static gboolean
+-msn_tooltip_extract_info_text(PurpleNotifyUserInfo *user_info, MsnGetInfoData *info_data)
+-{
+- PurpleBuddy *b;
+-
+- b = purple_find_buddy(purple_connection_get_account(info_data->gc),
+- info_data->name);
+-
+- if (b)
+- {
+- char *tmp;
+- const char *alias;
+-
+- alias = purple_buddy_get_local_buddy_alias(b);
+- if (alias && alias[0])
+- {
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), alias);
+- }
+-
+- if ((alias = purple_buddy_get_server_alias(b)) != NULL)
+- {
+- char *nicktext = g_markup_escape_text(alias, -1);
+- tmp = g_strdup_printf("<font sml=\"msn\">%s</font>", nicktext);
+- purple_notify_user_info_add_pair(user_info, _("Nickname"), tmp);
+- g_free(tmp);
+- g_free(nicktext);
+- }
+-
+- /* Add the tooltip information */
+- msn_tooltip_text(b, user_info, TRUE);
+-
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-#if PHOTO_SUPPORT
+-
+-static char *
+-msn_get_photo_url(const char *url_text)
+-{
+- char *p, *q;
+-
+- if ((p = strstr(url_text, PHOTO_URL)) != NULL)
+- {
+- p += strlen(PHOTO_URL);
+- }
+- if (p && (strncmp(p, "http://", strlen("http://")) == 0) && ((q = strchr(p, '"')) != NULL))
+- return g_strndup(p, q - p);
+-
+- return NULL;
+-}
+-
+-static void msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
+- const gchar *url_text, gsize len, const gchar *error_message);
+-
+-#endif
+-
+-#if 0
+-static char *msn_info_date_reformat(const char *field, size_t len)
+-{
+- char *tmp = g_strndup(field, len);
+- time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
+-
+- g_free(tmp);
+- return g_strdup(purple_date_format_short(localtime(&t)));
+-}
+-#endif
+-
+-#define MSN_GOT_INFO_GET_FIELD(a, b) \
+- found = purple_markup_extract_info_field(stripped, stripped_len, user_info, \
+- "\n" a ":", 0, "\n", 0, "Undisclosed", b, 0, NULL, NULL); \
+- 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://")) == 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)
+-{
+- MsnGetInfoData *info_data = (MsnGetInfoData *)data;
+- MsnSession *session;
+- PurpleNotifyUserInfo *user_info;
+- char *stripped, *p, *q, *tmp;
+- char *user_url = NULL;
+- gboolean found;
+- gboolean has_tooltip_text = FALSE;
+- gboolean has_info = FALSE;
+- gboolean sect_info = FALSE;
+- gboolean has_contact_info = FALSE;
+- char *url_buffer;
+- int stripped_len;
+-#if PHOTO_SUPPORT
+- char *photo_url_text = NULL;
+- MsnGetInfoStepTwoData *info2_data = NULL;
+-#endif
+-
+- purple_debug_info("msn", "In msn_got_info,url_text:{%s}\n",url_text);
+-
+- session = purple_connection_get_protocol_data(info_data->gc);
+- session->url_datas = g_slist_remove(session->url_datas, url_data);
+-
+- user_info = purple_notify_user_info_new();
+- has_tooltip_text = msn_tooltip_extract_info_text(user_info, info_data);
+-
+- if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0)
+- {
+- purple_notify_user_info_add_pair(user_info,
+- _("Error retrieving profile"), NULL);
+-
+- purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-
+- g_free(info_data->name);
+- g_free(info_data);
+- return;
+- }
+-
+- url_buffer = g_strdup(url_text);
+-
+- /* If they have a homepage link, MSN masks it such that we need to
+- * fetch the url out before purple_markup_strip_html() nukes it */
+- /* I don't think this works with the new spaces profiles - Stu 3/2/06 */
+- if ((p = strstr(url_text,
+- "Take a look at my </font><A class=viewDesc title=\"")) != NULL)
+- {
+- p += 50;
+-
+- if ((q = strchr(p, '"')) != NULL)
+- user_url = g_strndup(p, q - p);
+- }
+-
+- /*
+- * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
+- * and &#183;
+- */
+- while ((p = strstr(url_buffer, "&nbsp;")) != NULL)
+- {
+- *p = ' '; /* Turn &nbsp;'s into ordinary blanks */
+- p += 1;
+- memmove(p, p + 5, strlen(p + 5));
+- url_buffer[strlen(url_buffer) - 5] = '\0';
+- }
+-
+- while ((p = strstr(url_buffer, "&#183;")) != NULL)
+- {
+- memmove(p, p + 6, strlen(p + 6));
+- url_buffer[strlen(url_buffer) - 6] = '\0';
+- }
+-
+- /* Nuke the nasty \r's that just get in the way */
+- purple_str_strip_char(url_buffer, '\r');
+-
+- /* MSN always puts in &#39; for apostrophes...replace them */
+- while ((p = strstr(url_buffer, "&#39;")) != NULL)
+- {
+- *p = '\'';
+- memmove(p + 1, p + 5, strlen(p + 5));
+- url_buffer[strlen(url_buffer) - 4] = '\0';
+- }
+-
+- /* Nuke the html, it's easier than trying to parse the horrid stuff */
+- stripped = purple_markup_strip_html(url_buffer);
+- stripped_len = strlen(stripped);
+-
+- purple_debug_misc("msn", "stripped = %p\n", stripped);
+- purple_debug_misc("msn", "url_buffer = %p\n", url_buffer);
+-
+- /* General section header */
+- if (has_tooltip_text)
+- purple_notify_user_info_add_section_break(user_info);
+-
+- purple_notify_user_info_add_section_header(user_info, _("General"));
+-
+- /* Extract their Name and put it in */
+- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
+-
+- /* General */
+- MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname"));
+- 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,
+- "\nInterests\t", 0, " (/default.aspx?page=searchresults", 0,
+- "Undisclosed", _("Hobbies and Interests") /* _("Interests") */,
+- 0, NULL, NULL);
+-
+- if (found)
+- sect_info = TRUE;
+-
+- MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me"));
+-
+- if (sect_info)
+- {
+- has_info = TRUE;
+- sect_info = FALSE;
+- }
+- else
+- {
+- /* Remove the section header */
+- purple_notify_user_info_remove_last_item(user_info);
+- if (has_tooltip_text)
+- purple_notify_user_info_remove_last_item(user_info);
+- }
+-
+- /* Social */
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_section_header(user_info, _("Social"));
+-
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Marital status", _("Marital Status"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Interested in", _("Interests"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Pets", _("Pets"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Hometown", _("Hometown"));
+- MSN_GOT_INFO_GET_FIELD("Places lived", _("Places Lived"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Fashion", _("Fashion"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Humor", _("Humor"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Music", _("Music"));
+- MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Favorite quote", _("Favorite Quote"));
+-
+- if (sect_info)
+- {
+- has_info = TRUE;
+- sect_info = FALSE;
+- }
+- else
+- {
+- /* Remove the section header */
+- purple_notify_user_info_remove_last_item(user_info);
+- purple_notify_user_info_remove_last_item(user_info);
+- }
+-
+- /* Contact Info */
+- /* Personal */
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_section_header(user_info, _("Contact Info"));
+- purple_notify_user_info_add_section_header(user_info, _("Personal"));
+-
+- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
+- MSN_GOT_INFO_GET_FIELD("Significant other", _("Significant Other"));
+- MSN_GOT_INFO_GET_FIELD("Home phone", _("Home Phone"));
+- MSN_GOT_INFO_GET_FIELD("Home phone 2", _("Home Phone 2"));
+- MSN_GOT_INFO_GET_FIELD("Home address", _("Home Address"));
+- MSN_GOT_INFO_GET_FIELD("Personal Mobile", _("Personal Mobile"));
+- MSN_GOT_INFO_GET_FIELD("Home fax", _("Home Fax"));
+- MSN_GOT_INFO_GET_FIELD("Personal email", _("Personal Email"));
+- MSN_GOT_INFO_GET_FIELD("Personal IM", _("Personal IM"));
+- MSN_GOT_INFO_GET_FIELD("Birthday", _("Birthday"));
+- MSN_GOT_INFO_GET_FIELD("Anniversary", _("Anniversary"));
+- MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
+-
+- if (sect_info)
+- {
+- has_info = TRUE;
+- sect_info = FALSE;
+- has_contact_info = TRUE;
+- }
+- else
+- {
+- /* Remove the section header */
+- purple_notify_user_info_remove_last_item(user_info);
+- }
+-
+- /* Business */
+- purple_notify_user_info_add_section_header(user_info, _("Work"));
+- MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
+- MSN_GOT_INFO_GET_FIELD("Job title", _("Job Title"));
+- MSN_GOT_INFO_GET_FIELD("Company", _("Company"));
+- MSN_GOT_INFO_GET_FIELD("Department", _("Department"));
+- MSN_GOT_INFO_GET_FIELD("Profession", _("Profession"));
+- MSN_GOT_INFO_GET_FIELD("Work phone 1", _("Work Phone"));
+- MSN_GOT_INFO_GET_FIELD("Work phone 2", _("Work Phone 2"));
+- MSN_GOT_INFO_GET_FIELD("Work address", _("Work Address"));
+- MSN_GOT_INFO_GET_FIELD("Work mobile", _("Work Mobile"));
+- MSN_GOT_INFO_GET_FIELD("Work pager", _("Work Pager"));
+- MSN_GOT_INFO_GET_FIELD("Work fax", _("Work Fax"));
+- MSN_GOT_INFO_GET_FIELD("Work email", _("Work Email"));
+- MSN_GOT_INFO_GET_FIELD("Work IM", _("Work IM"));
+- MSN_GOT_INFO_GET_FIELD("Start date", _("Start Date"));
+- MSN_GOT_INFO_GET_FIELD("Notes", _("Notes"));
+-
+- if (sect_info)
+- {
+- has_info = TRUE;
+- sect_info = FALSE;
+- has_contact_info = TRUE;
+- }
+- else
+- {
+- /* Remove the section header */
+- purple_notify_user_info_remove_last_item(user_info);
+- }
+-
+- if (!has_contact_info)
+- {
+- /* Remove the Contact Info section header */
+- purple_notify_user_info_remove_last_item(user_info);
+- }
+-
+-#if 0 /* these probably don't show up any more */
+- /*
+- * The fields, 'A Little About Me', 'Favorite Things', 'Hobbies
+- * and Interests', 'Favorite Quote', and 'My Homepage' may or may
+- * not appear, in any combination. However, they do appear in
+- * certain order, so we can successively search to pin down the
+- * distinct values.
+- */
+-
+- /* Check if they have A Little About Me */
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " A Little About Me \n\n", 0, "Favorite Things", '\n', NULL,
+- _("A Little About Me"), 0, NULL, NULL);
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " A Little About Me \n\n", 0, "Hobbies and Interests", '\n',
+- NULL, _("A Little About Me"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " A Little About Me \n\n", 0, "Favorite Quote", '\n', NULL,
+- _("A Little About Me"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " A Little About Me \n\n", 0, "My Homepage \n\nTake a look",
+- '\n',
+- NULL, _("A Little About Me"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- purple_markup_extract_info_field(stripped, stripped_len, s,
+- " A Little About Me \n\n", 0, "last updated", '\n', NULL,
+- _("A Little About Me"), 0, NULL, NULL);
+- }
+-
+- if (found)
+- has_info = TRUE;
+-
+- /* Check if they have Favorite Things */
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Favorite Things \n\n", 0, "Hobbies and Interests", '\n', NULL,
+- _("Favorite Things"), 0, NULL, NULL);
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Favorite Things \n\n", 0, "Favorite Quote", '\n', NULL,
+- _("Favorite Things"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Favorite Things \n\n", 0, "My Homepage \n\nTake a look", '\n',
+- NULL, _("Favorite Things"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Favorite Things \n\n", 0, "last updated", '\n', NULL,
+- _("Favorite Things"), 0, NULL, NULL);
+- }
+-
+- if (found)
+- has_info = TRUE;
+-
+- /* Check if they have Hobbies and Interests */
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Hobbies and Interests \n\n", 0, "Favorite Quote", '\n', NULL,
+- _("Hobbies and Interests"), 0, NULL, NULL);
+-
+- if (!found)
+- {
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Hobbies and Interests \n\n", 0, "My Homepage \n\nTake a look",
+- '\n', NULL, _("Hobbies and Interests"), 0, NULL, NULL);
+- }
+-
+- if (!found)
+- {
+- purple_markup_extract_info_field(stripped, stripped_len, s,
+- " Hobbies and Interests \n\n", 0, "last updated", '\n', NULL,
+- _("Hobbies and Interests"), 0, NULL, NULL);
+- }
+-
+- if (found)
+- has_info = TRUE;
+-
+- /* Check if they have Favorite Quote */
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- "Favorite Quote \n\n", 0, "My Homepage \n\nTake a look", '\n', NULL,
+- _("Favorite Quote"), 0, NULL, NULL);
+-
+- if (!found)
+- {
+- purple_markup_extract_info_field(stripped, stripped_len, s,
+- "Favorite Quote \n\n", 0, "last updated", '\n', NULL,
+- _("Favorite Quote"), 0, NULL, NULL);
+- }
+-
+- if (found)
+- has_info = TRUE;
+-
+- /* Extract the last updated date and put it in */
+- found = purple_markup_extract_info_field(stripped, stripped_len, s,
+- " last updated:", 1, "\n", 0, NULL, _("Last Updated"), 0,
+- NULL, msn_info_date_reformat);
+-
+- if (found)
+- has_info = TRUE;
+-#endif
+-
+- /* If we were able to fetch a homepage url earlier, stick it in there */
+- if (user_url != NULL)
+- {
+- tmp = g_strdup_printf("<a href=\"%s\">%s</a>", user_url, user_url);
+- purple_notify_user_info_add_pair(user_info, _("Homepage"), tmp);
+- g_free(tmp);
+- g_free(user_url);
+-
+- has_info = TRUE;
+- }
+-
+- if (!has_info)
+- {
+- /* MSN doesn't actually distinguish between "unknown member" and
+- * a known member with an empty profile. Try to explain this fact.
+- * Note that if we have a nonempty tooltip_text, we know the user
+- * exists.
+- */
+- /* 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"), NULL);
+- purple_notify_user_info_add_pair(user_info, NULL,
+- ((p && b) ? _("The user has not created a public profile.") :
+- (p ? _("MSN reported not being able to find the user's profile. "
+- "This either means that the user does not exist, "
+- "or that the user exists "
+- "but has not created a public profile.") :
+- _("Could not find " /* This should never happen */
+- "any information in the user's profile. "
+- "The user most likely does not exist."))));
+- }
+-
+- /* put a link to the actual profile URL */
+- purple_notify_user_info_add_section_break(user_info);
+- tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>",
+- PROFILE_URL, info_data->name, _("View web profile"));
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+-
+-#if PHOTO_SUPPORT
+- /* Find the URL to the photo; must be before the marshalling [Bug 994207] */
+- photo_url_text = msn_get_photo_url(url_text);
+- purple_debug_info("msn", "photo url:{%s}\n", photo_url_text ? photo_url_text : "(null)");
+-
+- /* Marshall the existing state */
+- info2_data = g_new0(MsnGetInfoStepTwoData, 1);
+- info2_data->info_data = info_data;
+- info2_data->stripped = stripped;
+- info2_data->url_buffer = url_buffer;
+- info2_data->user_info = user_info;
+- info2_data->photo_url_text = photo_url_text;
+-
+- /* Try to put the photo in there too, if there's one */
+- if (photo_url_text)
+- {
+- url_data = purple_util_fetch_url_len(photo_url_text, FALSE, NULL, FALSE,
+- MAX_HTTP_BUDDYICON_BYTES,
+- msn_got_photo, info2_data);
+- session->url_datas = g_slist_prepend(session->url_datas, url_data);
+- }
+- else
+- {
+- /* Finish the Get Info and show the user something */
+- msn_got_photo(NULL, info2_data, NULL, 0, NULL);
+- }
+-}
+-
+-static void
+-msn_got_photo(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *url_text, gsize len, const gchar *error_message)
+-{
+- MsnGetInfoStepTwoData *info2_data = (MsnGetInfoStepTwoData *)user_data;
+- int id = -1;
+-
+- /* Unmarshall the saved state */
+- MsnGetInfoData *info_data = info2_data->info_data;
+- char *stripped = info2_data->stripped;
+- char *url_buffer = info2_data->url_buffer;
+- PurpleNotifyUserInfo *user_info = info2_data->user_info;
+- char *photo_url_text = info2_data->photo_url_text;
+-
+- if (url_data) {
+- MsnSession *session = purple_connection_get_protocol_data(info_data->gc);
+- session->url_datas = g_slist_remove(session->url_datas, url_data);
+- }
+-
+- if (url_text && error_message)
+- {
+- purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n");
+- g_free(stripped);
+- g_free(url_buffer);
+- purple_notify_user_info_destroy(user_info);
+- g_free(info_data->name);
+- g_free(info_data);
+- g_free(photo_url_text);
+- g_free(info2_data);
+-
+- return;
+- }
+-
+- /* Try to put the photo in there too, if there's one and is readable */
+- if (user_data && url_text && len != 0)
+- {
+- if (strstr(url_text, "400 Bad Request")
+- || strstr(url_text, "403 Forbidden")
+- || strstr(url_text, "404 Not Found"))
+- {
+-
+- purple_debug_info("msn", "Error getting %s: %s\n",
+- photo_url_text, url_text);
+- }
+- else
+- {
+- char buf[1024];
+- purple_debug_info("msn", "%s is %" G_GSIZE_FORMAT " bytes\n", photo_url_text, len);
+- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
+- g_snprintf(buf, sizeof(buf), "<img id=\"%d\"><br>", id);
+- purple_notify_user_info_prepend_pair(user_info, NULL, buf);
+- }
+- }
+-
+- /* We continue here from msn_got_info, as if nothing has happened */
+-#endif
+- purple_notify_userinfo(info_data->gc, info_data->name, user_info, NULL, NULL);
+-
+- g_free(stripped);
+- g_free(url_buffer);
+- purple_notify_user_info_destroy(user_info);
+- g_free(info_data->name);
+- g_free(info_data);
+-#if PHOTO_SUPPORT
+- g_free(photo_url_text);
+- g_free(info2_data);
+- if (id != -1)
+- purple_imgstore_unref_by_id(id);
+-#endif
+-}
+-
+-static void
+-msn_get_info(PurpleConnection *gc, const char *name)
+-{
+- MsnSession *session = purple_connection_get_protocol_data(gc);
+- MsnGetInfoData *data;
+- char *url;
+- PurpleUtilFetchUrlData *url_data;
+-
+- data = g_new0(MsnGetInfoData, 1);
+- data->gc = gc;
+- data->name = g_strdup(name);
+-
+- url = g_strdup_printf("%s%s", PROFILE_URL, name);
+-
+- url_data = purple_util_fetch_url(url, FALSE,
+- "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)",
+- TRUE, msn_got_info, data);
+- session->url_datas = g_slist_prepend(session->url_datas, url_data);
+-
+- g_free(url);
+-}
+-
+-static gboolean msn_load(PurplePlugin *plugin)
+-{
+- msn_notification_init();
+- msn_switchboard_init();
+-
+- return TRUE;
+-}
+-
+-static gboolean msn_unload(PurplePlugin *plugin)
+-{
+- msn_notification_end();
+- msn_switchboard_end();
+-
+- return TRUE;
+-}
+-
+-static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
+-{
+- PurpleAccount *acct = NULL;
+-
+- /* If we have a specific acct, use it */
+- if (acct_id) {
+- acct = purple_accounts_find(acct_id, prpl);
+- if (acct && !purple_account_is_connected(acct))
+- acct = NULL;
+- } else { /* Otherwise find an active account for the protocol */
+- GList *l = purple_accounts_get_all();
+- while (l) {
+- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
+- && purple_account_is_connected(l->data)) {
+- acct = l->data;
+- break;
+- }
+- l = l->next;
+- }
+- }
+-
+- return acct;
+-}
+-
+-static gboolean msn_uri_handler(const char *proto, const char *cmd, GHashTable *params)
+-{
+- char *acct_id = g_hash_table_lookup(params, "account");
+- PurpleAccount *acct;
+-
+- if (g_ascii_strcasecmp(proto, "msnim"))
+- return FALSE;
+-
+- acct = find_acct("prpl-msn", acct_id);
+-
+- if (!acct)
+- return FALSE;
+-
+- /* msnim:chat?contact=user@domain.tld */
+- if (!g_ascii_strcasecmp(cmd, "Chat")) {
+- char *sname = g_hash_table_lookup(params, "contact");
+- if (sname) {
+- PurpleConversation *conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, sname, acct);
+- if (conv == NULL)
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname);
+- purple_conversation_present(conv);
+- }
+- /*else
+- **If pidgindialogs_im() was in the core, we could use it here.
+- * It is all purple_request_* based, but I'm not sure it really belongs in the core
+- pidgindialogs_im();*/
+-
+- return TRUE;
+- }
+- /* msnim:add?contact=user@domain.tld */
+- else if (!g_ascii_strcasecmp(cmd, "Add")) {
+- char *name = g_hash_table_lookup(params, "contact");
+- purple_blist_request_add_buddy(acct, name, NULL, NULL);
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_MAIL_CHECK|OPT_PROTO_INVITE_MESSAGE,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"png,gif", 0, 0, 96, 96, 0, PURPLE_ICON_SCALE_SEND}, /* icon_spec */
+- msn_list_icon, /* list_icon */
+- msn_list_emblems, /* list_emblems */
+- msn_status_text, /* status_text */
+- msn_tooltip_text, /* tooltip_text */
+- msn_status_types, /* away_states */
+- msn_blist_node_menu, /* blist_node_menu */
+- NULL, /* chat_info */
+- NULL, /* chat_info_defaults */
+- msn_login, /* login */
+- msn_close, /* close */
+- msn_send_im, /* send_im */
+- NULL, /* set_info */
+- msn_send_typing, /* send_typing */
+- msn_get_info, /* get_info */
+- msn_set_status, /* set_away */
+- msn_set_idle, /* set_idle */
+- NULL, /* change_passwd */
+- NULL, /* add_buddy */
+- NULL, /* add_buddies */
+- msn_rem_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- msn_add_permit, /* add_permit */
+- msn_add_deny, /* add_deny */
+- msn_rem_permit, /* rem_permit */
+- msn_rem_deny, /* rem_deny */
+- msn_set_permit_deny, /* set_permit_deny */
+- NULL, /* join_chat */
+- NULL, /* reject chat invite */
+- NULL, /* get_chat_name */
+- msn_chat_invite, /* chat_invite */
+- msn_chat_leave, /* chat_leave */
+- NULL, /* chat_whisper */
+- msn_chat_send, /* chat_send */
+- msn_keepalive, /* keepalive */
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- msn_alias_buddy, /* alias_buddy */
+- msn_group_buddy, /* group_buddy */
+- msn_rename_group, /* rename_group */
+- NULL, /* buddy_free */
+- msn_convo_closed, /* convo_closed */
+- msn_normalize, /* normalize */
+- msn_set_buddy_icon, /* set_buddy_icon */
+- msn_remove_group, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- msn_can_receive_file, /* can_receive_file */
+- msn_send_file, /* send_file */
+- msn_new_xfer, /* new_xfer */
+- msn_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- msn_send_attention, /* send_attention */
+- msn_attention_types, /* attention_types */
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- msn_get_account_text_table, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- msn_set_public_alias, /* set_public_alias */
+- msn_get_public_alias, /* get_public_alias */
+- msn_add_buddy, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-msn", /**< id */
+- "MSN", /**< name */
+- DISPLAY_VERSION, /**< version */
+- N_("Windows Live Messenger Protocol Plugin"), /**< summary */
+- N_("Windows Live Messenger Protocol Plugin"), /**< description */
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+-
+- msn_load, /**< load */
+- msn_unload, /**< unload */
+- NULL, /**< destroy */
+-
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL, /**< prefs_info */
+- msn_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- PurpleAccountOption *option;
+-
+- option = purple_account_option_string_new(_("Server"), "server",
+- MSN_SERVER);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_int_new(_("Port"), "port", MSN_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_bool_new(_("Use HTTP Method"),
+- "http_method", FALSE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_string_new(_("HTTP Method Server"),
+- "http_method_server", MSN_HTTPCONN_SERVER);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_bool_new(_("Show custom smileys"),
+- "custom_smileys", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_bool_new(_("Allow direct connections"),
+- "direct_connect", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- option = purple_account_option_bool_new(_("Allow connecting from multiple locations"),
+- "mpop", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+- option);
+-
+- purple_cmd_register("nudge", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-msn", msn_cmd_nudge,
+- _("nudge: nudge a user to get their attention"), NULL);
+-
+- purple_prefs_remove("/plugins/prpl/msn");
+-
+- purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+- PURPLE_CALLBACK(msn_uri_handler), NULL);
+-}
+-
+-PURPLE_INIT_PLUGIN(msn, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.h
+--- pidgin-2.10.7/libpurple/protocols/msn/msn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,158 +0,0 @@
+-/**
+- * @file msn.h The MSN protocol plugin
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_H
+-#define MSN_H
+-
+-typedef enum
+-{
+- MSN_CAP_VIA_MOBILE = 0x0000001,
+- MSN_CAP_VIA_TEXAS = 0x0000002,
+- MSN_CAP_INK_GIF = 0x0000004,
+- MSN_CAP_INK_ISF = 0x0000008,
+- MSN_CAP_VIDEO_CHAT = 0x0000010,
+- MSN_CAP_PACKET = 0x0000020,
+- MSN_CAP_MOBILE_ON = 0x0000040,
+- MSN_CAP_WEB_WATCH = 0x0000080,
+- MSN_CAP_ACTIVITIES = 0x0000100,
+- MSN_CAP_VIA_WEBIM = 0x0000200,
+- MSN_CAP_MOBILE_DEV = 0x0000400,
+- MSN_CAP_VIA_FEDERATED = 0x0000800,
+- MSN_CAP_SPACE = 0x0001000,
+- MSN_CAP_MCE = 0x0002000,
+- MSN_CAP_DIRECTIM = 0x0004000,
+- MSN_CAP_WINKS = 0x0008000,
+- MSN_CAP_SEARCH = 0x0010000,
+- MSN_CAP_BOT = 0x0020000,
+- MSN_CAP_VOICEIM = 0x0040000,
+- MSN_CAP_SCHANNEL = 0x0080000,
+- MSN_CAP_SIP_INVITE = 0x0100000,
+- MSN_CAP_MULTI_VV = 0x0200000,
+- MSN_CAP_SDRIVE = 0x0400000,
+- MSN_CAP_PAGEMODE_MSG = 0x080000,
+- MSN_CAP_ONECARE = 0x1000000,
+- MSN_CAP_P2P_TURN = 0x2000000,
+- MSN_CAP_P2P_BOOTSTRAP_VIA_UUN = 0x4000000,
+- MSN_CAP_ALIASED = 0x8000000
+-} MsnClientCaps;
+-
+-typedef enum
+-{
+- MSN_EXT_CAP_SMS_ONLY = 0x1,
+- MSN_EXT_CAP_VOICE_OVER_MSNP = 0x2,
+- MSN_EXT_CAP_UUCP_SIP = 0x4,
+- MSN_EXT_CAP_APP_MSGS = 0x8,
+- MSN_EXT_CAP_RTC_VIDEO = 0x10,
+- MSN_EXT_CAP_P2PV2 = 0x20,
+- MSN_EXT_CAP_AUTH_WEBIM = 0x40,
+- MSN_EXT_CAP_1ON1_VIA_GROUP = 0x80,
+- MSN_EXT_CAP_OFFLINEIM = 0x100,
+- MSN_EXT_CAP_SHARING_VIDEO = 0x200,
+- MSN_EXT_CAP_NUDGE = 0x400,
+- MSN_EXT_CAP_CIRCLE_VOICEIM = 0x800,
+- MSN_EXT_CAP_SHARING = 0x1000,
+- MSN_EXT_CAP_P2P_MIXER_RELAY = 0x8000,
+- MSN_EXT_CAP_CONV_WINDOW_FT = 0x20000,
+- MSN_EXT_CAP_VIDEO_16x9 = 0x40000,
+- MSN_EXT_CAP_P2P_ENVELOPE = 0x80000,
+- MSN_EXT_CAP_YAHOOIM_DISABLE = 0x400000,
+- MSN_EXT_CAP_SIP_TUNNELv2 = 0x800000,
+- MSN_EXT_CAP_VOICE_CLIP_WMA = 0x1000000,
+- MSN_EXT_CAP_VOICE_CLIP_CIRCLEIM = 0x2000000,
+- MSN_EXT_CAP_SOCIAL_NEWS = 0x4000000,
+- MSN_EXT_CAP_CUSTOM_SMILEY = 0x8000000,
+- MSN_EXT_CAP_UTF8_MOODS = 0x10000000,
+- MSN_EXT_CAP_FTURN = 0x20000000,
+- MSN_EXT_CAP_P4_ACTIVITY = 0x40000000,
+- MSN_EXT_CAP_MUC = 0x80000000
+-} MsnClientExtCaps;
+-
+-typedef enum
+-{
+- MSN_CLIENT_VER_5_0 = 0x00,
+- MSN_CLIENT_VER_6_0 = 0x10, /* MSNC1 */
+- MSN_CLIENT_VER_6_1 = 0x20, /* MSNC2 */
+- MSN_CLIENT_VER_6_2 = 0x30, /* MSNC3 */
+- MSN_CLIENT_VER_7_0 = 0x40, /* MSNC4 */
+- MSN_CLIENT_VER_7_5 = 0x50, /* MSNC5 */
+- MSN_CLIENT_VER_8_0 = 0x60, /* MSNC6 */
+- MSN_CLIENT_VER_8_1 = 0x70, /* MSNC7 */
+- MSN_CLIENT_VER_8_5 = 0x80, /* MSNC8 */
+- MSN_CLIENT_VER_9_0 = 0x90, /* MSNC9 */
+- MSN_CLIENT_VER_14_0 = 0xA0, /* MSNC10 */
+- MSN_CLIENT_VER_15_0 = 0xB0 /* MSNC11 */
+-} MsnClientVerId;
+-
+-#include "internal.h"
+-
+-#include "session.h"
+-
+-#include "msg.h"
+-
+-#define MSN_BUF_LEN 8192
+-
+-/* Windows Live Messenger Server*/
+-#define MSN_SERVER "messenger.hotmail.com"
+-#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
+-#define MSN_PORT 1863
+-#define WLM_PROT_VER 18
+-
+-#define WLM_MAX_PROTOCOL 18
+-#define WLM_MIN_PROTOCOL 18
+-
+-#define MSN_TYPING_RECV_TIMEOUT 6
+-#define MSN_TYPING_SEND_TIMEOUT 4
+-
+-#define PROFILE_URL "http://spaces.live.com/profile.aspx?mem="
+-#define PHOTO_URL " contactparams:photopreauthurl=\""
+-
+-#define BUDDY_ALIAS_MAXLEN 387
+-
+-#define MSN_CAM_GUID "4BD96FC0-AB17-4425-A14A-439185962DC8"
+-#define MSN_CAM_REQUEST_GUID "1C9AA97E-9C05-4583-A3BD-908A196F1E92"
+-#define MSN_FT_GUID "5D3E02AB-6190-11D3-BBBB-00C04F795683"
+-#define MSN_OBJ_GUID "A4268EEC-FEC5-49E5-95C3-F126696BDBF6"
+-
+-#define MSN_CLIENTINFO \
+- "Client-Name: Purple/" VERSION "\r\n" \
+- "Chat-Logging: Y\r\n"
+-
+-/* Index into attention_types */
+-#define MSN_NUDGE 0
+-
+-#define MSN_CLIENT_ID_VERSION MSN_CLIENT_VER_9_0
+-#define MSN_CLIENT_ID_CAPABILITIES (MSN_CAP_PACKET|MSN_CAP_INK_GIF|MSN_CAP_VOICEIM)
+-#define MSN_CLIENT_ID_EXT_CAPS (0)
+-
+-#define MSN_CLIENT_ID \
+- ((MSN_CLIENT_ID_VERSION << 24) | \
+- (MSN_CLIENT_ID_CAPABILITIES))
+-
+-void
+-msn_set_public_alias(PurpleConnection *gc, const char *alias,
+- PurpleSetPublicAliasSuccessCallback success_cb,
+- PurpleSetPublicAliasFailureCallback failure_cb);
+-void msn_send_privacy(PurpleConnection *gc);
+-void msn_send_im_message(MsnSession *session, MsnMessage *msg);
+-
+-#endif /* MSN_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msnutils.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.c
+--- pidgin-2.10.7/libpurple/protocols/msn/msnutils.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,718 +0,0 @@
+-/**
+- * @file msnutils.c Utility functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-
+-#include "msn.h"
+-#include "msnutils.h"
+-
+-#include "cipher.h"
+-
+-/**************************************************************************
+- * Util
+- **************************************************************************/
+-char *
+-rand_guid(void)
+-{
+- return g_strdup_printf("%4X%4X-%4X-%4X-%4X-%4X%4X%4X",
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111,
+- rand() % 0xAAFF + 0x1111);
+-}
+-
+-void
+-msn_parse_format(const char *mime, char **pre_ret, char **post_ret)
+-{
+- char *cur;
+- GString *pre = g_string_new(NULL);
+- GString *post = g_string_new(NULL);
+- unsigned int colors[3];
+-
+- if (pre_ret != NULL) *pre_ret = NULL;
+- if (post_ret != NULL) *post_ret = NULL;
+-
+- cur = strstr(mime, "FN=");
+-
+- if (cur && (*(cur = cur + 3) != ';'))
+- {
+- pre = g_string_append(pre, "<FONT FACE=\"");
+-
+- while (*cur && *cur != ';')
+- {
+- pre = g_string_append_c(pre, *cur);
+- cur++;
+- }
+-
+- pre = g_string_append(pre, "\">");
+- post = g_string_prepend(post, "</FONT>");
+- }
+-
+- cur = strstr(mime, "EF=");
+-
+- if (cur && (*(cur = cur + 3) != ';'))
+- {
+- while (*cur && *cur != ';')
+- {
+- pre = g_string_append_c(pre, '<');
+- pre = g_string_append_c(pre, *cur);
+- pre = g_string_append_c(pre, '>');
+- post = g_string_prepend_c(post, '>');
+- post = g_string_prepend_c(post, *cur);
+- post = g_string_prepend_c(post, '/');
+- post = g_string_prepend_c(post, '<');
+- cur++;
+- }
+- }
+-
+- cur = strstr(mime, "CO=");
+-
+- if (cur && (*(cur = cur + 3) != ';'))
+- {
+- int i;
+-
+- i = sscanf(cur, "%02x%02x%02x;", &colors[0], &colors[1], &colors[2]);
+-
+- if (i > 0)
+- {
+- char tag[64];
+-
+- if (i == 1)
+- {
+- colors[1] = 0;
+- colors[2] = 0;
+- }
+- else if (i == 2)
+- {
+- unsigned int temp = colors[0];
+-
+- colors[0] = colors[1];
+- colors[1] = temp;
+- colors[2] = 0;
+- }
+- else if (i == 3)
+- {
+- unsigned int temp = colors[2];
+-
+- colors[2] = colors[0];
+- colors[0] = temp;
+- }
+-
+- g_snprintf(tag, sizeof(tag),
+- "<FONT COLOR=\"#%02hhx%02hhx%02hhx\">",
+- colors[0], colors[1], colors[2]);
+-
+- pre = g_string_append(pre, tag);
+- post = g_string_prepend(post, "</FONT>");
+- }
+- }
+-
+- cur = strstr(mime, "RL=");
+-
+- if (cur && (*(cur = cur + 3) != ';'))
+- {
+- if (*cur == '1')
+- {
+- /* RTL text was received */
+- pre = g_string_append(pre, "<SPAN style=\"direction:rtl;text-align:right;\">");
+- post = g_string_prepend(post, "</SPAN>");
+- }
+- }
+-
+- cur = g_strdup(purple_url_decode(pre->str));
+- g_string_free(pre, TRUE);
+-
+- if (pre_ret != NULL)
+- *pre_ret = cur;
+- else
+- g_free(cur);
+-
+- cur = g_strdup(purple_url_decode(post->str));
+- g_string_free(post, TRUE);
+-
+- if (post_ret != NULL)
+- *post_ret = cur;
+- else
+- g_free(cur);
+-}
+-
+-/*encode the str to RFC2047 style
+- * Currently only support the UTF-8 and base64 encode
+- */
+-char *
+-msn_encode_mime(const char *str)
+-{
+- gchar *base64, *retval;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+-
+- base64 = purple_base64_encode((guchar *)str, strlen(str));
+- retval = g_strdup_printf("=?utf-8?B?%s?=", base64);
+- g_free(base64);
+-
+- return retval;
+-}
+-
+-/*
+- * We need this because we're only supposed to encode spaces in the font
+- * names. purple_url_encode() isn't acceptable.
+- */
+-gboolean
+-msn_encode_spaces(const char *str, char *buf, size_t len)
+-{
+- char *nonspace = buf;
+-
+- while (isspace(*str))
+- str++;
+-
+- for (; *str && len > 1; str++) {
+- if (*str == '%') {
+- if (len < 4)
+- break;
+- *buf++ = '%';
+- *buf++ = '2';
+- *buf++ = '5';
+- len -= 3;
+- nonspace = buf;
+- } else if (*str == ' ') {
+- if (len < 4)
+- break;
+- *buf++ = '%';
+- *buf++ = '2';
+- *buf++ = '0';
+- len -= 3;
+- } else {
+- *buf++ = *str;
+- len--;
+- nonspace = buf;
+- }
+- }
+-
+- *nonspace = '\0';
+-
+- return (*str == '\0');
+-}
+-
+-/*
+- * Taken from the zephyr plugin.
+- * This parses HTML formatting (put out by one of the gtkimhtml widgets
+- * and converts it to msn formatting. It doesn't deal with the tag closing,
+- * but gtkimhtml widgets give valid html.
+- * It currently deals properly with <b>, <u>, <i>, <font face=...>,
+- * <font color=...>, <span dir=...>, <span style="direction: ...">.
+- * It ignores <font back=...> and <font size=...>
+- */
+-void
+-msn_import_html(const char *html, char **attributes, char **message)
+-{
+- int len, retcount = 0;
+- const char *c;
+- char *msg;
+- char *fontface = NULL;
+- char fontface_encoded[BUF_LEN];
+- char fonteffect[5];
+- char fontcolor[7];
+- char direction = '0';
+-
+- gboolean has_bold = FALSE;
+- gboolean has_italic = FALSE;
+- gboolean has_underline = FALSE;
+- gboolean has_strikethrough = FALSE;
+-
+- g_return_if_fail(html != NULL);
+- g_return_if_fail(attributes != NULL);
+- g_return_if_fail(message != NULL);
+-
+- len = strlen(html);
+- msg = g_malloc0(len + 1);
+-
+- memset(fontcolor, 0, sizeof(fontcolor));
+- strcat(fontcolor, "0");
+- memset(fonteffect, 0, sizeof(fonteffect));
+-
+- for (c = html; *c != '\0';)
+- {
+- if (*c == '<')
+- {
+- if (!g_ascii_strncasecmp(c + 1, "br>", 3))
+- {
+- msg[retcount++] = '\r';
+- msg[retcount++] = '\n';
+- c += 4;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "i>", 2))
+- {
+- if (!has_italic)
+- {
+- strcat(fonteffect, "I");
+- has_italic = TRUE;
+- }
+- c += 3;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "b>", 2))
+- {
+- if (!has_bold)
+- {
+- strcat(fonteffect, "B");
+- has_bold = TRUE;
+- }
+- c += 3;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "u>", 2))
+- {
+- if (!has_underline)
+- {
+- strcat(fonteffect, "U");
+- has_underline = TRUE;
+- }
+- c += 3;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "s>", 2))
+- {
+- if (!has_strikethrough)
+- {
+- strcat(fonteffect, "S");
+- has_strikethrough = TRUE;
+- }
+- c += 3;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "a href=\"", 8))
+- {
+- c += 9;
+-
+- if (!g_ascii_strncasecmp(c, "mailto:", 7))
+- c += 7;
+-
+- while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
+- msg[retcount++] = *c++;
+-
+- if (*c != '\0')
+- c += 2;
+-
+- /* ignore descriptive string */
+- while ((*c != '\0') && g_ascii_strncasecmp(c, "</a>", 4))
+- c++;
+-
+- if (*c != '\0')
+- c += 4;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "span", 4))
+- {
+- /* Bi-directional text support using CSS properties in span tags */
+- c += 5;
+-
+- while (*c != '\0' && *c != '>')
+- {
+- while (*c == ' ')
+- c++;
+- if (!g_ascii_strncasecmp(c, "dir=\"rtl\"", 9))
+- {
+- c += 9;
+- direction = '1';
+- }
+- else if (!g_ascii_strncasecmp(c, "style=\"", 7))
+- {
+- /* Parse inline CSS attributes */
+- char *attributes;
+- int attr_len = 0;
+- c += 7;
+- while (*(c + attr_len) != '\0' && *(c + attr_len) != '"')
+- attr_len++;
+- if (*(c + attr_len) == '"')
+- {
+- char *attr_dir;
+- attributes = g_strndup(c, attr_len);
+- attr_dir = purple_markup_get_css_property(attributes, "direction");
+- if (attr_dir && (!g_ascii_strncasecmp(attr_dir, "RTL", 3)))
+- direction = '1';
+- g_free(attr_dir);
+- g_free(attributes);
+- }
+-
+- }
+- else
+- {
+- c++;
+- }
+- }
+- if (*c == '>')
+- c++;
+- }
+- else if (!g_ascii_strncasecmp(c + 1, "font", 4))
+- {
+- c += 5;
+-
+- while ((*c != '\0') && !g_ascii_strncasecmp(c, " ", 1))
+- c++;
+-
+- if (!g_ascii_strncasecmp(c, "color=\"#", 7))
+- {
+- c += 8;
+-
+- fontcolor[0] = *(c + 4);
+- fontcolor[1] = *(c + 5);
+- fontcolor[2] = *(c + 2);
+- fontcolor[3] = *(c + 3);
+- fontcolor[4] = *c;
+- fontcolor[5] = *(c + 1);
+-
+- c += 8;
+- }
+- else if (!g_ascii_strncasecmp(c, "face=\"", 6))
+- {
+- const char *end = NULL;
+- const char *comma = NULL;
+- unsigned int namelen = 0;
+-
+- c += 6;
+- end = strchr(c, '\"');
+- comma = strchr(c, ',');
+-
+- if (comma == NULL || comma > end)
+- namelen = (unsigned int)(end - c);
+- else
+- namelen = (unsigned int)(comma - c);
+-
+- fontface = g_strndup(c, namelen);
+- c = end + 2;
+- }
+- else
+- {
+- /* Drop all unrecognized/misparsed font tags */
+- while ((*c != '\0') && g_ascii_strncasecmp(c, "\">", 2))
+- c++;
+-
+- if (*c != '\0')
+- c += 2;
+- }
+- }
+- else
+- {
+- while ((*c != '\0') && (*c != '>'))
+- c++;
+- if (*c != '\0')
+- c++;
+- }
+- }
+- else if (*c == '&')
+- {
+- if (!g_ascii_strncasecmp(c, "&lt;", 4))
+- {
+- msg[retcount++] = '<';
+- c += 4;
+- }
+- else if (!g_ascii_strncasecmp(c, "&gt;", 4))
+- {
+- msg[retcount++] = '>';
+- c += 4;
+- }
+- else if (!g_ascii_strncasecmp(c, "&nbsp;", 6))
+- {
+- msg[retcount++] = ' ';
+- c += 6;
+- }
+- else if (!g_ascii_strncasecmp(c, "&quot;", 6))
+- {
+- msg[retcount++] = '"';
+- c += 6;
+- }
+- else if (!g_ascii_strncasecmp(c, "&amp;", 5))
+- {
+- msg[retcount++] = '&';
+- c += 5;
+- }
+- else if (!g_ascii_strncasecmp(c, "&apos;", 6))
+- {
+- msg[retcount++] = '\'';
+- c += 6;
+- }
+- else
+- msg[retcount++] = *c++;
+- }
+- else
+- msg[retcount++] = *c++;
+- }
+-
+- if (fontface == NULL)
+- fontface = g_strdup("Segoe UI");
+-
+- msn_encode_spaces(fontface, fontface_encoded, BUF_LEN);
+- *attributes = g_strdup_printf("FN=%s; EF=%s; CO=%s; PF=0; RL=%c",
+- fontface_encoded,
+- fonteffect, fontcolor, direction);
+- *message = msg;
+-
+- g_free(fontface);
+-}
+-
+-void
+-msn_parse_socket(const char *str, char **ret_host, int *ret_port)
+-{
+- char *host;
+- char *c;
+- int port;
+-
+- host = g_strdup(str);
+-
+- if ((c = strchr(host, ':')) != NULL) {
+- *c = '\0';
+- port = atoi(c + 1);
+- } else {
+- port = 1863;
+- }
+-
+- *ret_host = host;
+- *ret_port = port;
+-}
+-
+-void
+-msn_parse_user(const char *str, char **ret_user, int *ret_network)
+-{
+- char **tokens;
+-
+- tokens = g_strsplit(str, ":", 2);
+-
+- *ret_network = atoi(tokens[0]);
+- *ret_user = tokens[1];
+-
+- g_free(tokens[0]);
+- /* tokens[1] is returned */
+- g_free(tokens);
+-}
+-
+-gboolean
+-msn_email_is_valid(const char *passport)
+-{
+- if (purple_email_is_valid(passport)) {
+- /* Special characters aren't allowed in domains, so only go to '@' */
+- while (*passport != '@') {
+- if (*passport == '/')
+- return FALSE;
+- else if (*passport == '?')
+- return FALSE;
+- else if (*passport == '=')
+- return FALSE;
+- /* MSN also doesn't like colons, but that's checked already */
+-
+- passport++;
+- }
+-
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-/***************************************************************************
+- * MSN Challenge Computing Function
+- ***************************************************************************/
+-
+-/*
+- * Handle MSN Challenge computation
+- * This algorithm references
+- * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
+- */
+-#define BUFSIZE 256
+-void
+-msn_handle_chl(char *input, char *output)
+-{
+- PurpleCipher *cipher;
+- PurpleCipherContext *context;
+- const guchar productKey[] = MSNP15_WLM_PRODUCT_KEY;
+- const guchar productID[] = MSNP15_WLM_PRODUCT_ID;
+- const char hexChars[] = "0123456789abcdef";
+- char buf[BUFSIZE];
+- unsigned char md5Hash[16];
+- unsigned char *newHash;
+- unsigned int *md5Parts;
+- unsigned int *chlStringParts;
+- unsigned int newHashParts[5];
+-
+- long long nHigh = 0, nLow = 0;
+-
+- int len;
+- int i;
+-
+- /* Create the MD5 hash by using Purple MD5 algorithm */
+- cipher = purple_ciphers_find_cipher("md5");
+- context = purple_cipher_context_new(cipher, NULL);
+-
+- purple_cipher_context_append(context, (guchar *)input, strlen(input));
+- purple_cipher_context_append(context, productKey, sizeof(productKey) - 1);
+- purple_cipher_context_digest(context, sizeof(md5Hash), md5Hash, NULL);
+- purple_cipher_context_destroy(context);
+-
+- /* Split it into four integers */
+- md5Parts = (unsigned int *)md5Hash;
+- for (i = 0; i < 4; i++) {
+- /* adjust endianess */
+- md5Parts[i] = GUINT_TO_LE(md5Parts[i]);
+-
+- /* & each integer with 0x7FFFFFFF */
+- /* and save one unmodified array for later */
+- newHashParts[i] = md5Parts[i];
+- md5Parts[i] &= 0x7FFFFFFF;
+- }
+-
+- /* make a new string and pad with '0' to length that's a multiple of 8 */
+- snprintf(buf, BUFSIZE - 5, "%s%s", input, productID);
+- len = strlen(buf);
+- if ((len % 8) != 0) {
+- int fix = 8 - (len % 8);
+- memset(&buf[len], '0', fix);
+- buf[len + fix] = '\0';
+- len += fix;
+- }
+-
+- /* split into integers */
+- chlStringParts = (unsigned int *)buf;
+-
+- /* this is magic */
+- for (i = 0; i < (len / 4); i += 2) {
+- long long temp;
+-
+- chlStringParts[i] = GUINT_TO_LE(chlStringParts[i]);
+- chlStringParts[i + 1] = GUINT_TO_LE(chlStringParts[i + 1]);
+-
+- temp = (0x0E79A9C1 * (long long)chlStringParts[i]) % 0x7FFFFFFF;
+- temp = (md5Parts[0] * (temp + nLow) + md5Parts[1]) % 0x7FFFFFFF;
+- nHigh += temp;
+-
+- temp = ((long long)chlStringParts[i + 1] + temp) % 0x7FFFFFFF;
+- nLow = (md5Parts[2] * temp + md5Parts[3]) % 0x7FFFFFFF;
+- nHigh += nLow;
+- }
+- nLow = (nLow + md5Parts[1]) % 0x7FFFFFFF;
+- nHigh = (nHigh + md5Parts[3]) % 0x7FFFFFFF;
+-
+- newHashParts[0] ^= nLow;
+- newHashParts[1] ^= nHigh;
+- newHashParts[2] ^= nLow;
+- newHashParts[3] ^= nHigh;
+-
+- /* adjust endianness */
+- for(i = 0; i < 4; i++)
+- newHashParts[i] = GUINT_TO_LE(newHashParts[i]);
+-
+- /* make a string of the parts */
+- newHash = (unsigned char *)newHashParts;
+-
+- /* convert to hexadecimal */
+- for (i = 0; i < 16; i++)
+- {
+- output[i * 2] = hexChars[(newHash[i] >> 4) & 0xF];
+- output[(i * 2) + 1] = hexChars[newHash[i] & 0xF];
+- }
+-
+- output[32] = '\0';
+-}
+-
+-guint8
+-msn_read8(const char *buf)
+-{
+- return (guint8)buf[0];
+-}
+-
+-guint16
+-msn_read16le(const char *buf)
+-{
+- return GUINT16_FROM_LE(*(guint16 *)buf);
+-}
+-
+-guint16
+-msn_read16be(const char *buf)
+-{
+- return GUINT16_FROM_BE(*(guint16 *)buf);
+-}
+-
+-guint32
+-msn_read32le(const char *buf)
+-{
+- return GUINT32_FROM_LE(*(guint32 *)buf);
+-}
+-
+-guint32
+-msn_read32be(const char *buf)
+-{
+- return GUINT32_FROM_BE(*(guint32 *)buf);
+-}
+-
+-guint64
+-msn_read64le(const char *buf)
+-{
+- return GUINT64_FROM_LE(*(guint64 *)buf);
+-}
+-
+-guint64
+-msn_read64be(const char *buf)
+-{
+- return GUINT64_FROM_BE(*(guint64 *)buf);
+-}
+-
+-void
+-msn_write8(char *buf, guint8 data)
+-{
+- *(guint8 *)buf = data;
+-}
+-
+-void
+-msn_write16le(char *buf, guint16 data)
+-{
+- *(guint16 *)buf = GUINT16_TO_LE(data);
+-}
+-
+-void
+-msn_write16be(char *buf, guint16 data)
+-{
+- *(guint16 *)buf = GUINT16_TO_BE(data);
+-}
+-
+-void
+-msn_write32le(char *buf, guint32 data)
+-{
+- *(guint32 *)buf = GUINT32_TO_LE(data);
+-}
+-
+-void
+-msn_write32be(char *buf, guint32 data)
+-{
+- *(guint32 *)buf = GUINT32_TO_BE(data);
+-}
+-
+-void
+-msn_write64le(char *buf, guint64 data)
+-{
+- *(guint64 *)buf = GUINT64_TO_LE(data);
+-}
+-
+-void
+-msn_write64be(char *buf, guint64 data)
+-{
+- *(guint64 *)buf = GUINT64_TO_BE(data);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/msnutils.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.h
+--- pidgin-2.10.7/libpurple/protocols/msn/msnutils.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/msnutils.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,244 +0,0 @@
+-/**
+- * @file msnutils.h Utility functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_UTILS_H
+-#define MSN_UTILS_H
+-
+-/*encode the str to RFC2047 style*/
+-char *msn_encode_mime(const char *str);
+-
+-/**
+- * Generate the Random GUID
+- */
+-char *rand_guid(void);
+-
+-/**
+- * Encodes the spaces in a string
+- *
+- * @param str The string to be encoded.
+- * @param buf The buffer to hold the encoded string.
+- * @param len The maximum length (including NUL) to put in @buf.
+- *
+- * @return Whether @str was able to fit in @buf.
+- */
+-gboolean
+-msn_encode_spaces(const char *str, char *buf, size_t len);
+-
+-/**
+- * Parses the MSN message formatting into a format compatible with Purple.
+- *
+- * @param mime The mime header with the formatting.
+- * @param pre_ret The returned prefix string.
+- * @param post_ret The returned postfix string.
+- *
+- * @return The new message.
+- */
+-void msn_parse_format(const char *mime, char **pre_ret, char **post_ret);
+-
+-/**
+- * Parses the Purple message formatting (html) into the MSN format.
+- *
+- * @param html The html message to format.
+- * @param attributes The returned attributes string.
+- * @param message The returned message string.
+- *
+- * @return The new message.
+- */
+-void msn_import_html(const char *html, char **attributes, char **message);
+-
+-/**
+- * Parses a socket string.
+- *
+- * @param str A host:port string.
+- * @param ret_host Return string value of the host.
+- * @param ret_port Return integer value of the port.
+- */
+-void msn_parse_socket(const char *str, char **ret_host, int *ret_port);
+-
+-/**
+- * Parses a user name
+- *
+- * @param str A network:username string.
+- * @param ret_user Return of the user's passport.
+- * @param ret_network Return of the user's network.
+- */
+-void msn_parse_user(const char *str, char **ret_user, int *ret_network);
+-
+-/**
+- * Verify if the email is a vaild passport.
+- *
+- * @param passport The email
+- *
+- * @return True if it is a valid passport, else FALSE
+- */
+-gboolean msn_email_is_valid(const char *passport);
+-
+-/**
+- * Handle MSN Challenge Computation
+- * This algorithm references
+- * http://imfreedom.org/wiki/index.php/MSN:NS/Challenges
+- *
+- * @param input Challenge input.
+- * @param output Callenge output.
+- */
+-void msn_handle_chl(char *input, char *output);
+-
+-/**
+- * Read a byte from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 8-bit byte
+- */
+-guint8 msn_read8(const char *buf);
+-
+-/**
+- * Read a little-endian short from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 16-bit short
+- */
+-guint16 msn_read16le(const char *buf);
+-
+-/**
+- * Read a big-endian short from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 16-bit short
+- */
+-guint16 msn_read16be(const char *buf);
+-
+-/**
+- * Read a little-endian int from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 32-bit int
+- */
+-guint32 msn_read32le(const char *buf);
+-
+-/**
+- * Read a big-endian int from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 32-bit int
+- */
+-guint32 msn_read32be(const char *buf);
+-
+-/**
+- * Read a little-endian long from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 64-bit long
+- */
+-guint64 msn_read64le(const char *buf);
+-
+-/**
+- * Read a big-endian long from a buffer
+- *
+- * @param buf Pointer to buffer.
+- *
+- * @return 64-bit long
+- */
+-guint64 msn_read64be(const char *buf);
+-
+-/**
+- * Write a byte to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data 8-bit byte.
+- */
+-void msn_write8(char *buf, guint8 data);
+-
+-/**
+- * Write a little-endian short to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data short.
+- */
+-void msn_write16le(char *buf, guint16 data);
+-
+-/**
+- * Write a big-endian short to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data short.
+- */
+-void msn_write16be(char *buf, guint16 data);
+-
+-/**
+- * Write a little-endian int to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data int.
+- */
+-void msn_write32le(char *buf, guint32 data);
+-
+-/**
+- * Write a big-endian int to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data int.
+- */
+-void msn_write32be(char *buf, guint32 data);
+-
+-/**
+- * Write a little-endian long to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data long.
+- */
+-void msn_write64le(char *buf, guint64 data);
+-
+-/**
+- * Write a big-endian long to a buffer
+- *
+- * @param buf Pointer to buffer.
+- * @param data short
+- */
+-void msn_write64be(char *buf, guint64 data);
+-
+-/**
+- * Same as above, but these increment the buf pointer.
+- */
+-#define msn_pop8(buf) msn_read8((buf+=1)-1)
+-#define msn_pop16le(buf) msn_read16le((buf+=2)-2)
+-#define msn_pop16be(buf) msn_read16be((buf+=2)-2)
+-#define msn_pop32le(buf) msn_read32le((buf+=4)-4)
+-#define msn_pop32be(buf) msn_read32be((buf+=4)-4)
+-#define msn_pop64le(buf) msn_read64le((buf+=8)-8)
+-#define msn_pop64be(buf) msn_read64be((buf+=8)-8)
+-#define msn_push8(buf, data) msn_write8(buf, data), buf+=1
+-#define msn_push16le(buf, data) msn_write16le(buf, data), buf+=2
+-#define msn_push16be(buf, data) msn_write16be(buf, data), buf+=2
+-#define msn_push32le(buf, data) msn_write32le(buf, data), buf+=4
+-#define msn_push32be(buf, data) msn_write32be(buf, data), buf+=4
+-#define msn_push64le(buf, data) msn_write64le(buf, data), buf+=8
+-#define msn_push64be(buf, data) msn_write64be(buf, data), buf+=8
+-
+-#endif /* MSN_UTILS_H */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/nexus.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.c
+--- pidgin-2.10.7/libpurple/protocols/msn/nexus.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,670 +0,0 @@
+-/**
+- * @file nexus.c MSN Nexus functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "cipher.h"
+-#include "debug.h"
+-
+-#include "msnutils.h"
+-#include "soap.h"
+-#include "nexus.h"
+-#include "notification.h"
+-
+-/**************************************************************************
+- * Valid Ticket Tokens
+- **************************************************************************/
+-
+-#define SSO_VALID_TICKET_DOMAIN 0
+-#define SSO_VALID_TICKET_POLICY 1
+-static char *ticket_domains[][2] = {
+- /* http://msnpiki.msnfanatic.com/index.php/MSNP15:SSO */
+- /* {"Domain", "Policy Ref URI"}, Purpose */
+- {"messengerclear.live.com", NULL}, /* Authentication for messenger. */
+- {"messenger.msn.com", "?id=507"}, /* Authentication for receiving OIMs. */
+- {"contacts.msn.com", "MBI"}, /* Authentication for the Contact server. */
+- {"messengersecure.live.com", "MBI_SSL"}, /* Authentication for sending OIMs. */
+- {"storage.live.com", "MBI"}, /* Storage REST API */
+- {"sup.live.com", "MBI"}, /* What's New service */
+-};
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-MsnNexus *
+-msn_nexus_new(MsnSession *session)
+-{
+- MsnNexus *nexus;
+- int i;
+-
+- nexus = g_new0(MsnNexus, 1);
+- nexus->session = session;
+-
+- nexus->token_len = sizeof(ticket_domains) / sizeof(char *[2]);
+- nexus->tokens = g_new0(MsnTicketToken, nexus->token_len);
+-
+- for (i = 0; i < nexus->token_len; i++)
+- nexus->tokens[i].token = g_hash_table_new_full(g_str_hash, g_str_equal,
+- g_free, g_free);
+-
+- return nexus;
+-}
+-
+-void
+-msn_nexus_destroy(MsnNexus *nexus)
+-{
+- int i;
+- for (i = 0; i < nexus->token_len; i++) {
+- g_hash_table_destroy(nexus->tokens[i].token);
+- g_free(nexus->tokens[i].secret);
+- g_slist_free(nexus->tokens[i].updates);
+- }
+-
+- g_free(nexus->tokens);
+- g_free(nexus->policy);
+- g_free(nexus->nonce);
+- g_free(nexus->cipher);
+- g_free(nexus->secret);
+- g_free(nexus);
+-}
+-
+-/**************************************************************************
+- * RPS/SSO Authentication
+- **************************************************************************/
+-
+-static char *
+-rps_create_key(const char *key, int key_len, const char *data, size_t data_len)
+-{
+- const guchar magic[] = "WS-SecureConversation";
+- const int magic_len = sizeof(magic) - 1;
+-
+- PurpleCipherContext *hmac;
+- guchar hash1[20], hash2[20], hash3[20], hash4[20];
+- char *result;
+-
+- hmac = purple_cipher_context_new_by_name("hmac", NULL);
+-
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
+- purple_cipher_context_append(hmac, magic, magic_len);
+- purple_cipher_context_append(hmac, (guchar *)data, data_len);
+- purple_cipher_context_digest(hmac, sizeof(hash1), hash1, NULL);
+-
+- purple_cipher_context_reset(hmac, NULL);
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
+- purple_cipher_context_append(hmac, hash1, 20);
+- purple_cipher_context_append(hmac, magic, magic_len);
+- purple_cipher_context_append(hmac, (guchar *)data, data_len);
+- purple_cipher_context_digest(hmac, sizeof(hash2), hash2, NULL);
+-
+- purple_cipher_context_reset(hmac, NULL);
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
+- purple_cipher_context_append(hmac, hash1, 20);
+- purple_cipher_context_digest(hmac, sizeof(hash3), hash3, NULL);
+-
+- purple_cipher_context_reset(hmac, NULL);
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, key_len);
+- purple_cipher_context_append(hmac, hash3, sizeof(hash3));
+- purple_cipher_context_append(hmac, magic, magic_len);
+- purple_cipher_context_append(hmac, (guchar *)data, data_len);
+- purple_cipher_context_digest(hmac, sizeof(hash4), hash4, NULL);
+-
+- purple_cipher_context_destroy(hmac);
+-
+- result = g_malloc(24);
+- memcpy(result, hash2, sizeof(hash2));
+- memcpy(result + sizeof(hash2), hash4, 4);
+-
+- return result;
+-}
+-
+-static char *
+-des3_cbc(const char *key, const char *iv, const char *data, int len, gboolean decrypt)
+-{
+- PurpleCipherContext *des3;
+- char *out;
+- size_t outlen;
+-
+- des3 = purple_cipher_context_new_by_name("des3", NULL);
+- purple_cipher_context_set_key(des3, (guchar *)key);
+- purple_cipher_context_set_batch_mode(des3, PURPLE_CIPHER_BATCH_MODE_CBC);
+- purple_cipher_context_set_iv(des3, (guchar *)iv, 8);
+-
+- out = g_malloc(len);
+- if (decrypt)
+- purple_cipher_context_decrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
+- else
+- purple_cipher_context_encrypt(des3, (guchar *)data, len, (guchar *)out, &outlen);
+-
+- purple_cipher_context_destroy(des3);
+-
+- return out;
+-}
+-
+-#define MSN_USER_KEY_SIZE (7*4 + 8 + 20 + 72)
+-#define CRYPT_MODE_CBC 1
+-#define CIPHER_TRIPLE_DES 0x6603
+-#define HASH_SHA1 0x8004
+-static char *
+-msn_rps_encrypt(MsnNexus *nexus)
+-{
+- char usr_key_base[MSN_USER_KEY_SIZE], *usr_key;
+- const char magic1[] = "SESSION KEY HASH";
+- const char magic2[] = "SESSION KEY ENCRYPTION";
+- PurpleCipherContext *hmac;
+- size_t len;
+- guchar *hash;
+- char *key1, *key2, *key3;
+- gsize key1_len;
+- const char *iv;
+- char *nonce_fixed;
+- char *cipher;
+- char *response;
+-
+- usr_key = &usr_key_base[0];
+- /* Header */
+- msn_push32le(usr_key, 28); /* Header size */
+- msn_push32le(usr_key, CRYPT_MODE_CBC); /* Crypt mode */
+- msn_push32le(usr_key, CIPHER_TRIPLE_DES); /* Cipher type */
+- msn_push32le(usr_key, HASH_SHA1); /* Hash type */
+- msn_push32le(usr_key, 8); /* IV size */
+- msn_push32le(usr_key, 20); /* Hash size */
+- msn_push32le(usr_key, 72); /* Cipher size */
+- /* Data */
+- iv = usr_key;
+- msn_push32le(usr_key, rand());
+- msn_push32le(usr_key, rand());
+- hash = (guchar *)usr_key;
+- usr_key += 20; /* Remaining is cipher data */
+-
+- key1 = (char *)purple_base64_decode((const char *)nexus->tokens[MSN_AUTH_MESSENGER].secret, &key1_len);
+- key2 = rps_create_key(key1, key1_len, magic1, sizeof(magic1) - 1);
+- key3 = rps_create_key(key1, key1_len, magic2, sizeof(magic2) - 1);
+-
+- len = strlen(nexus->nonce);
+- hmac = purple_cipher_context_new_by_name("hmac", NULL);
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key2, 24);
+- purple_cipher_context_append(hmac, (guchar *)nexus->nonce, len);
+- purple_cipher_context_digest(hmac, 20, hash, NULL);
+- purple_cipher_context_destroy(hmac);
+-
+- /* We need to pad this to 72 bytes, apparently */
+- nonce_fixed = g_malloc(len + 8);
+- memcpy(nonce_fixed, nexus->nonce, len);
+- memset(nonce_fixed + len, 0x08, 8);
+- cipher = des3_cbc(key3, iv, nonce_fixed, len + 8, FALSE);
+- g_free(nonce_fixed);
+-
+- memcpy(usr_key, cipher, 72);
+-
+- g_free(key1);
+- g_free(key2);
+- g_free(key3);
+- g_free(cipher);
+-
+- response = purple_base64_encode((guchar *)usr_key_base, MSN_USER_KEY_SIZE);
+-
+- return response;
+-}
+-
+-/**************************************************************************
+- * Login
+- **************************************************************************/
+-
+-/* Used to specify which token to update when only doing single updates */
+-typedef struct _MsnNexusUpdateData MsnNexusUpdateData;
+-struct _MsnNexusUpdateData {
+- MsnNexus *nexus;
+- int id;
+-};
+-
+-typedef struct _MsnNexusUpdateCallback MsnNexusUpdateCallback;
+-struct _MsnNexusUpdateCallback {
+- GSourceFunc cb;
+- gpointer data;
+-};
+-
+-static gboolean
+-nexus_parse_token(MsnNexus *nexus, int id, xmlnode *node)
+-{
+- char *token_str, *expiry_str;
+- const char *id_str;
+- char **elems, **cur, **tokens;
+- xmlnode *token = xmlnode_get_child(node, "RequestedSecurityToken/BinarySecurityToken");
+- xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
+- xmlnode *expires = xmlnode_get_child(node, "LifeTime/Expires");
+-
+- if (!token)
+- return FALSE;
+-
+- /* Use the ID that the server sent us */
+- if (id == -1) {
+- id_str = xmlnode_get_attrib(token, "Id");
+- if (id_str == NULL)
+- return FALSE;
+-
+- id = atol(id_str + 7) - 1; /* 'Compact#' or 'PPToken#' */
+- if (id >= nexus->token_len)
+- return FALSE; /* Where did this come from? */
+- }
+-
+- token_str = xmlnode_get_data(token);
+- if (token_str == NULL)
+- return FALSE;
+-
+- g_hash_table_remove_all(nexus->tokens[id].token);
+-
+- elems = g_strsplit(token_str, "&", 0);
+-
+- for (cur = elems; *cur != NULL; cur++) {
+- tokens = g_strsplit(*cur, "=", 2);
+- g_hash_table_insert(nexus->tokens[id].token, tokens[0], tokens[1]);
+- /* Don't free each of the tokens, only the array. */
+- g_free(tokens);
+- }
+- g_strfreev(elems);
+- g_free(token_str);
+-
+- if (secret)
+- nexus->tokens[id].secret = xmlnode_get_data(secret);
+- else
+- nexus->tokens[id].secret = NULL;
+-
+- /* Yay for MS using ISO-8601 */
+- expiry_str = xmlnode_get_data(expires);
+- nexus->tokens[id].expiry = purple_str_to_time(expiry_str,
+- FALSE, NULL, NULL, NULL);
+- g_free(expiry_str);
+-
+- purple_debug_info("msn", "Updated ticket for domain '%s', expires at %" G_GINT64_FORMAT ".\n",
+- ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
+- (gint64)nexus->tokens[id].expiry);
+- return TRUE;
+-}
+-
+-static gboolean
+-nexus_parse_collection(MsnNexus *nexus, int id, xmlnode *collection)
+-{
+- xmlnode *node;
+- gboolean result;
+-
+- node = xmlnode_get_child(collection, "RequestSecurityTokenResponse");
+-
+- if (!node)
+- return FALSE;
+-
+- result = TRUE;
+- for (; node && result; node = node->next) {
+- xmlnode *endpoint = xmlnode_get_child(node, "AppliesTo/EndpointReference/Address");
+- char *address = xmlnode_get_data(endpoint);
+-
+- if (g_str_equal(address, "http://Passport.NET/tb")) {
+- /* This node contains the stuff for updating tokens. */
+- char *data;
+- xmlnode *cipher = xmlnode_get_child(node, "RequestedSecurityToken/EncryptedData/CipherData/CipherValue");
+- xmlnode *secret = xmlnode_get_child(node, "RequestedProofToken/BinarySecret");
+-
+- g_free(nexus->cipher);
+- nexus->cipher = xmlnode_get_data(cipher);
+- data = xmlnode_get_data(secret);
+- g_free(nexus->secret);
+- nexus->secret = (char *)purple_base64_decode(data, NULL);
+- g_free(data);
+-
+- } else {
+- result = nexus_parse_token(nexus, id, node);
+- }
+- g_free(address);
+- }
+-
+- return result;
+-}
+-
+-static void
+-nexus_got_response_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- MsnNexus *nexus = data;
+- MsnSession *session = nexus->session;
+- const char *ticket;
+- char *response;
+-
+- if (resp == NULL) {
+- msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Unable to connect"));
+- return;
+- }
+-
+- if (!nexus_parse_collection(nexus, -1,
+- xmlnode_get_child(resp->xml,
+- "Body/RequestSecurityTokenResponseCollection"))) {
+- msn_session_set_error(session, MSN_ERROR_SERVCONN, _("Windows Live ID authentication:Invalid response"));
+- return;
+- }
+-
+- ticket = msn_nexus_get_token_str(nexus, MSN_AUTH_MESSENGER);
+- response = msn_rps_encrypt(nexus);
+- msn_got_login_params(session, ticket, response);
+- g_free(response);
+-}
+-
+-/*when connect, do the SOAP Style windows Live ID authentication */
+-void
+-msn_nexus_connect(MsnNexus *nexus)
+-{
+- MsnSession *session = nexus->session;
+- const char *username;
+- const char *password;
+- char *password_xml;
+- GString *domains;
+- char *request;
+- int i;
+-
+- MsnSoapMessage *soap;
+-
+- purple_debug_info("msn", "Starting Windows Live ID authentication\n");
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_GET_COOKIE);
+-
+- username = purple_account_get_username(session->account);
+- password = purple_connection_get_password(session->account->gc);
+- if (g_utf8_strlen(password, -1) > 16) {
+- /* max byte size for 16 utf8 characters is 64 + 1 for the null */
+- gchar truncated[65];
+- g_utf8_strncpy(truncated, password, 16);
+- password_xml = g_markup_escape_text(truncated, -1);
+- } else {
+- password_xml = g_markup_escape_text(password, -1);
+- }
+-
+- purple_debug_info("msn", "Logging on %s, with policy '%s', nonce '%s'\n",
+- username, nexus->policy, nexus->nonce);
+-
+- domains = g_string_new(NULL);
+- for (i = 0; i < nexus->token_len; i++) {
+- g_string_append_printf(domains, MSN_SSO_RST_TEMPLATE,
+- i+1,
+- ticket_domains[i][SSO_VALID_TICKET_DOMAIN],
+- ticket_domains[i][SSO_VALID_TICKET_POLICY] != NULL ?
+- ticket_domains[i][SSO_VALID_TICKET_POLICY] :
+- nexus->policy);
+- }
+-
+- request = g_strdup_printf(MSN_SSO_TEMPLATE, username, password_xml, domains->str);
+- g_free(password_xml);
+- g_string_free(domains, TRUE);
+-
+- soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
+- g_free(request);
+- msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
+- nexus_got_response_cb, nexus);
+-}
+-
+-static void
+-nexus_got_update_cb(MsnSoapMessage *req, MsnSoapMessage *resp, gpointer data)
+-{
+- MsnNexusUpdateData *ud = data;
+- MsnNexus *nexus = ud->nexus;
+- char iv[8] = {0,0,0,0,0,0,0,0};
+- xmlnode *enckey;
+- char *tmp;
+- char *nonce;
+- gsize len;
+- char *key;
+- GSList *updates;
+-
+-#if 0
+- char *decrypted_pp;
+-#endif
+- char *decrypted_data;
+-
+- if (resp == NULL)
+- return;
+-
+- purple_debug_info("msn", "Got Update Response for %s.\n", ticket_domains[ud->id][SSO_VALID_TICKET_DOMAIN]);
+-
+- enckey = xmlnode_get_child(resp->xml, "Header/Security/DerivedKeyToken");
+- while (enckey) {
+- if (g_str_equal(xmlnode_get_attrib(enckey, "Id"), "EncKey"))
+- break;
+- enckey = xmlnode_get_next_twin(enckey);
+- }
+- if (!enckey) {
+- purple_debug_error("msn", "Invalid response in token update.\n");
+- return;
+- }
+-
+- tmp = xmlnode_get_data(xmlnode_get_child(enckey, "Nonce"));
+- nonce = (char *)purple_base64_decode(tmp, &len);
+- key = rps_create_key(nexus->secret, 24, nonce, len);
+- g_free(tmp);
+- g_free(nonce);
+-
+-#if 0
+- /* Don't know what this is for yet */
+- tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
+- "Header/EncryptedPP/EncryptedData/CipherData/CipherValue"));
+- if (tmp) {
+- decrypted_pp = des3_cbc(key, iv, tmp, len, TRUE);
+- g_free(tmp);
+- purple_debug_info("msn", "Got Response Header EncryptedPP: %s\n", decrypted_pp);
+- g_free(decrypted_pp);
+- }
+-#endif
+-
+- tmp = xmlnode_get_data(xmlnode_get_child(resp->xml,
+- "Body/EncryptedData/CipherData/CipherValue"));
+- if (tmp) {
+- char *unescaped;
+- xmlnode *rstresponse;
+-
+- unescaped = (char *)purple_base64_decode(tmp, &len);
+- g_free(tmp);
+-
+- decrypted_data = des3_cbc(key, iv, unescaped, len, TRUE);
+- g_free(unescaped);
+- purple_debug_info("msn", "Got Response Body EncryptedData: %s\n", decrypted_data);
+-
+- rstresponse = xmlnode_from_str(decrypted_data, -1);
+- if (g_str_equal(rstresponse->name, "RequestSecurityTokenResponse"))
+- nexus_parse_token(nexus, ud->id, rstresponse);
+- else
+- nexus_parse_collection(nexus, ud->id, rstresponse);
+- g_free(decrypted_data);
+- }
+-
+- updates = nexus->tokens[ud->id].updates;
+- nexus->tokens[ud->id].updates = NULL;
+- while (updates != NULL) {
+- MsnNexusUpdateCallback *update = updates->data;
+- if (update->cb)
+- purple_timeout_add(0, update->cb, update->data);
+- g_free(update);
+- updates = g_slist_delete_link(updates, updates);
+- }
+-
+- g_free(ud);
+- g_free(key);
+-}
+-
+-void
+-msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data)
+-{
+- MsnSession *session = nexus->session;
+- MsnNexusUpdateData *ud;
+- MsnNexusUpdateCallback *update;
+- PurpleCipherContext *sha1;
+- PurpleCipherContext *hmac;
+-
+- char *key;
+-
+- guchar digest[20];
+-
+- struct tm *tm;
+- time_t now;
+- char *now_str;
+- char *timestamp;
+- char *timestamp_b64;
+-
+- char *domain;
+- char *domain_b64;
+-
+- char *signedinfo;
+- gint32 nonce[6];
+- int i;
+- char *nonce_b64;
+- char *signature_b64;
+- guchar signature[20];
+-
+- char *request;
+- MsnSoapMessage *soap;
+-
+- update = g_new0(MsnNexusUpdateCallback, 1);
+- update->cb = cb;
+- update->data = data;
+-
+- if (nexus->tokens[id].updates != NULL) {
+- /* Update already in progress. Just add to list and return. */
+- purple_debug_info("msn",
+- "Ticket update for user '%s' on domain '%s' in progress. Adding request to queue.\n",
+- purple_account_get_username(session->account),
+- ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
+- nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
+- update);
+- return;
+- } else {
+- purple_debug_info("msn",
+- "Updating ticket for user '%s' on domain '%s'\n",
+- purple_account_get_username(session->account),
+- ticket_domains[id][SSO_VALID_TICKET_DOMAIN]);
+- nexus->tokens[id].updates = g_slist_prepend(nexus->tokens[id].updates,
+- update);
+- }
+-
+- ud = g_new0(MsnNexusUpdateData, 1);
+- ud->nexus = nexus;
+- ud->id = id;
+-
+- sha1 = purple_cipher_context_new_by_name("sha1", NULL);
+-
+- domain = g_strdup_printf(MSN_SSO_RST_TEMPLATE,
+- id,
+- ticket_domains[id][SSO_VALID_TICKET_DOMAIN],
+- ticket_domains[id][SSO_VALID_TICKET_POLICY] != NULL ?
+- ticket_domains[id][SSO_VALID_TICKET_POLICY] :
+- nexus->policy);
+- purple_cipher_context_append(sha1, (guchar *)domain, strlen(domain));
+- purple_cipher_context_digest(sha1, 20, digest, NULL);
+- domain_b64 = purple_base64_encode(digest, 20);
+-
+- now = time(NULL);
+- tm = gmtime(&now);
+- now_str = g_strdup(purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
+- now += 5*60;
+- tm = gmtime(&now);
+- timestamp = g_strdup_printf(MSN_SSO_TIMESTAMP_TEMPLATE,
+- now_str,
+- purple_utf8_strftime("%Y-%m-%dT%H:%M:%SZ", tm));
+- purple_cipher_context_reset(sha1, NULL);
+- purple_cipher_context_append(sha1, (guchar *)timestamp, strlen(timestamp));
+- purple_cipher_context_digest(sha1, 20, digest, NULL);
+- timestamp_b64 = purple_base64_encode(digest, 20);
+- g_free(now_str);
+-
+- purple_cipher_context_destroy(sha1);
+-
+- signedinfo = g_strdup_printf(MSN_SSO_SIGNEDINFO_TEMPLATE,
+- id,
+- domain_b64,
+- timestamp_b64);
+-
+- for (i = 0; i < 6; i++)
+- nonce[i] = rand();
+- nonce_b64 = purple_base64_encode((guchar *)&nonce, sizeof(nonce));
+-
+- key = rps_create_key(nexus->secret, 24, (char *)nonce, sizeof(nonce));
+- hmac = purple_cipher_context_new_by_name("hmac", NULL);
+- purple_cipher_context_set_option(hmac, "hash", "sha1");
+- purple_cipher_context_set_key_with_len(hmac, (guchar *)key, 24);
+- purple_cipher_context_append(hmac, (guchar *)signedinfo, strlen(signedinfo));
+- purple_cipher_context_digest(hmac, 20, signature, NULL);
+- purple_cipher_context_destroy(hmac);
+- signature_b64 = purple_base64_encode(signature, 20);
+-
+- request = g_strdup_printf(MSN_SSO_TOKEN_UPDATE_TEMPLATE,
+- nexus->cipher,
+- nonce_b64,
+- timestamp,
+- signedinfo,
+- signature_b64,
+- domain);
+-
+- g_free(nonce_b64);
+- g_free(domain_b64);
+- g_free(timestamp_b64);
+- g_free(timestamp);
+- g_free(key);
+- g_free(signature_b64);
+- g_free(signedinfo);
+- g_free(domain);
+-
+- soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
+- g_free(request);
+- msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
+- nexus_got_update_cb, ud);
+-}
+-
+-GHashTable *
+-msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id)
+-{
+- g_return_val_if_fail(nexus != NULL, NULL);
+- g_return_val_if_fail(id < nexus->token_len, NULL);
+-
+- return nexus->tokens[id].token;
+-}
+-
+-const char *
+-msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id)
+-{
+- static char buf[1024];
+- GHashTable *token = msn_nexus_get_token(nexus, id);
+- const char *msn_t;
+- const char *msn_p;
+- gint ret;
+-
+- g_return_val_if_fail(token != NULL, NULL);
+-
+- msn_t = g_hash_table_lookup(token, "t");
+- msn_p = g_hash_table_lookup(token, "p");
+-
+- g_return_val_if_fail(msn_t != NULL, NULL);
+- g_return_val_if_fail(msn_p != NULL, NULL);
+-
+- ret = g_snprintf(buf, sizeof(buf) - 1, "t=%s&p=%s", msn_t, msn_p);
+- g_return_val_if_fail(ret != -1, NULL);
+-
+- return buf;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/nexus.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.h
+--- pidgin-2.10.7/libpurple/protocols/msn/nexus.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/nexus.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,219 +0,0 @@
+-/**
+- * @file nexus.h MSN Nexus functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_NEXUS_H
+-#define MSN_NEXUS_H
+-
+-#include "internal.h"
+-
+-typedef struct _MsnNexus MsnNexus;
+-typedef struct _MsnTicketToken MsnTicketToken;
+-
+-/* Index into ticket_tokens in nexus.c Keep updated! */
+-typedef enum
+-{
+- MSN_AUTH_MESSENGER = 0,
+- MSN_AUTH_MESSENGER_WEB = 1,
+- MSN_AUTH_CONTACTS = 2,
+- MSN_AUTH_LIVE_SECURE = 3,
+- MSN_AUTH_STORAGE = 4,
+- MSN_AUTH_WHATSNEW = 5
+-} MsnAuthDomains;
+-
+-#define MSN_SSO_SERVER "login.live.com"
+-#define SSO_POST_URL "/RST.srf"
+-
+-#define MSN_SSO_RST_TEMPLATE \
+-"<wst:RequestSecurityToken xmlns=\"http://schemas.xmlsoap.org/ws/2004/04/trust\" Id=\"RST%d\">"\
+- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+- "<wsp:AppliesTo xmlns=\"http://schemas.xmlsoap.org/ws/2002/12/policy\">"\
+- "<wsa:EndpointReference xmlns=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\">"\
+- "<wsa:Address>%s</wsa:Address>"\
+- "</wsa:EndpointReference>"\
+- "</wsp:AppliesTo>"\
+- "<wsse:PolicyReference xmlns=\"http://schemas.xmlsoap.org/ws/2003/06/secext\" URI=\"%s\"></wsse:PolicyReference>"\
+-"</wst:RequestSecurityToken>"
+-
+-#define MSN_SSO_TEMPLATE "<?xml version='1.0' encoding='utf-8'?>"\
+-"<Envelope xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
+- " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
+- " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
+- " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
+- " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
+- " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
+- " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
+- "<Header>"\
+- "<ps:AuthInfo"\
+- " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
+- " Id=\"PPAuthInfo\">"\
+- "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
+- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
+- "<ps:UIVersion>1</ps:UIVersion>"\
+- "<ps:Cookies></ps:Cookies>"\
+- "<ps:RequestParams>AQAAAAIAAABsYwQAAAAxMDMz</ps:RequestParams>"\
+- "</ps:AuthInfo>"\
+- "<wsse:Security>"\
+- "<wsse:UsernameToken Id=\"user\">"\
+- "<wsse:Username>%s</wsse:Username>"\
+- "<wsse:Password>%s</wsse:Password>"\
+- "</wsse:UsernameToken>"\
+- "</wsse:Security>"\
+- "</Header>"\
+- "<Body>"\
+- "<ps:RequestMultipleSecurityTokens"\
+- " xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\""\
+- " Id=\"RSTS\">"\
+- "<wst:RequestSecurityToken Id=\"RST0\">"\
+- "<wst:RequestType>http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue</wst:RequestType>"\
+- "<wsp:AppliesTo>"\
+- "<wsa:EndpointReference>"\
+- "<wsa:Address>http://Passport.NET/tb</wsa:Address>"\
+- "</wsa:EndpointReference>"\
+- "</wsp:AppliesTo>"\
+- "</wst:RequestSecurityToken>"\
+- "%s" /* Other RSTn tokens */\
+- "</ps:RequestMultipleSecurityTokens>"\
+- "</Body>"\
+-"</Envelope>"
+-
+-#define MSN_SSO_AUTHINFO_TEMPLATE \
+-"<ps:AuthInfo xmlns:ps=\"http://schemas.microsoft.com/Passport/SoapServices/PPCRL\" Id=\"PPAuthInfo\">"\
+- "<ps:HostingApp>{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}</ps:HostingApp>"\
+- "<ps:BinaryVersion>4</ps:BinaryVersion>"\
+- "<ps:UIVersion>1</ps:UIVersion>"\
+- "<ps:Cookies></ps:Cookies>"\
+- "<ps:RequestParams>AQAAAAIAAABsYwQAAAA0MTA1</ps:RequestParams>"\
+-"</ps:AuthInfo>"
+-/* Not sure what's editable here, so I'll just hard-code the SHA1 hash */
+-#define MSN_SSO_AUTHINFO_SHA1_BASE64 "d2IeTF4DAkPEa/tVETHznsivEpc="
+-
+-#define MSN_SSO_TIMESTAMP_TEMPLATE \
+-"<wsu:Timestamp xmlns=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\" Id=\"Timestamp\">"\
+- "<wsu:Created>%s</wsu:Created>"\
+- "<wsu:Expires>%s</wsu:Expires>"\
+-"</wsu:Timestamp>"
+-
+-#define MSN_SSO_SIGNEDINFO_TEMPLATE \
+-"<SignedInfo xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
+- "<CanonicalizationMethod Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></CanonicalizationMethod>"\
+- "<SignatureMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#hmac-sha1\"></SignatureMethod>"\
+- "<Reference URI=\"#RST%d\">"\
+- "<Transforms>"\
+- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
+- "</Transforms>"\
+- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
+- "<DigestValue>%s</DigestValue>"\
+- "</Reference>"\
+- "<Reference URI=\"#Timestamp\">"\
+- "<Transforms>"\
+- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
+- "</Transforms>"\
+- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
+- "<DigestValue>%s</DigestValue>"\
+- "</Reference>"\
+- "<Reference URI=\"#PPAuthInfo\">"\
+- "<Transforms>"\
+- "<Transform Algorithm=\"http://www.w3.org/2001/10/xml-exc-c14n#\"></Transform>"\
+- "</Transforms>"\
+- "<DigestMethod Algorithm=\"http://www.w3.org/2000/09/xmldsig#sha1\"></DigestMethod>"\
+- "<DigestValue>" MSN_SSO_AUTHINFO_SHA1_BASE64 "</DigestValue>"\
+- "</Reference>"\
+-"</SignedInfo>"
+-
+-#define MSN_SSO_TOKEN_UPDATE_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<Envelope"\
+- " xmlns=\"http://schemas.xmlsoap.org/soap/envelope/\""\
+- " xmlns:wsse=\"http://schemas.xmlsoap.org/ws/2003/06/secext\""\
+- " xmlns:saml=\"urn:oasis:names:tc:SAML:1.0:assertion\""\
+- " xmlns:wsp=\"http://schemas.xmlsoap.org/ws/2002/12/policy\""\
+- " xmlns:wsu=\"http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-utility-1.0.xsd\""\
+- " xmlns:wsa=\"http://schemas.xmlsoap.org/ws/2004/03/addressing\""\
+- " xmlns:wssc=\"http://schemas.xmlsoap.org/ws/2004/04/sc\""\
+- " xmlns:wst=\"http://schemas.xmlsoap.org/ws/2004/04/trust\">"\
+- "<Header>"\
+- MSN_SSO_AUTHINFO_TEMPLATE /* ps:AuthInfo */ \
+- "<wsse:Security>"\
+- "<EncryptedData xmlns=\"http://www.w3.org/2001/04/xmlenc#\" Id=\"BinaryDAToken0\" Type=\"http://www.w3.org/2001/04/xmlenc#Element\">"\
+- "<EncryptionMethod Algorithm=\"http://www.w3.org/2001/04/xmlenc#tripledes-cbc\"></EncryptionMethod>"\
+- "<ds:KeyInfo xmlns:ds=\"http://www.w3.org/2000/09/xmldsig#\">"\
+- "<ds:KeyName>http://Passport.NET/STS</ds:KeyName>"\
+- "</ds:KeyInfo>"\
+- "<CipherData>"\
+- "<CipherValue>%s</CipherValue>"\
+- "</CipherData>"\
+- "</EncryptedData>"\
+- "<wssc:DerivedKeyToken Id=\"SignKey\">"\
+- "<wsse:RequestedTokenReference>"\
+- "<wsse:KeyIdentifier ValueType=\"http://docs.oasis-open.org/wss/2004/XX/oasis-2004XX-wss-saml-token-profile-1.0#SAMLAssertionID\" />"\
+- "<wsse:Reference URI=\"#BinaryDAToken0\" />"\
+- "</wsse:RequestedTokenReference>"\
+- "<wssc:Nonce>%s</wssc:Nonce>"\
+- "</wssc:DerivedKeyToken>"\
+- "%s" /* wsu:Timestamp */\
+- "<Signature xmlns=\"http://www.w3.org/2000/09/xmldsig#\">"\
+- "%s" /* SignedInfo */\
+- "<SignatureValue>%s</SignatureValue>"\
+- "<KeyInfo>"\
+- "<wsse:SecurityTokenReference>"\
+- "<wsse:Reference URI=\"#SignKey\" />"\
+- "</wsse:SecurityTokenReference>"\
+- "</KeyInfo>"\
+- "</Signature>"\
+- "</wsse:Security>"\
+- "</Header>"\
+- "<Body>"\
+- "%s" /* wst:RequestSecurityToken */ \
+- "</Body>"\
+-"</Envelope>"
+-
+-struct _MsnTicketToken {
+- GHashTable *token;
+- char *secret;
+- time_t expiry;
+- GSList *updates;
+-};
+-
+-struct _MsnNexus
+-{
+- MsnSession *session;
+-
+- /* From server via USR command */
+- char *policy;
+- char *nonce;
+-
+- /* From server via SOAP stuff */
+- char *cipher;
+- char *secret;
+- MsnTicketToken *tokens;
+- int token_len;
+-};
+-
+-void msn_nexus_connect(MsnNexus *nexus);
+-MsnNexus *msn_nexus_new(MsnSession *session);
+-void msn_nexus_destroy(MsnNexus *nexus);
+-GHashTable *msn_nexus_get_token(MsnNexus *nexus, MsnAuthDomains id);
+-const char *msn_nexus_get_token_str(MsnNexus *nexus, MsnAuthDomains id);
+-void msn_nexus_update_token(MsnNexus *nexus, int id, GSourceFunc cb, gpointer data);
+-
+-#endif /* MSN_NEXUS_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/notification.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.c
+--- pidgin-2.10.7/libpurple/protocols/msn/notification.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2471 +0,0 @@
+-/**
+- * @file notification.c Notification server functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "cipher.h"
+-#include "core.h"
+-#include "debug.h"
+-
+-#include "notification.h"
+-
+-#include "contact.h"
+-#include "error.h"
+-#include "msnutils.h"
+-#include "state.h"
+-#include "userlist.h"
+-
+-static MsnTable *cbs_table;
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-static void
+-destroy_cb(MsnServConn *servconn)
+-{
+- MsnNotification *notification;
+-
+- notification = servconn->cmdproc->data;
+- g_return_if_fail(notification != NULL);
+-
+- msn_notification_destroy(notification);
+-}
+-
+-MsnNotification *
+-msn_notification_new(MsnSession *session)
+-{
+- MsnNotification *notification;
+- MsnServConn *servconn;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- notification = g_new0(MsnNotification, 1);
+-
+- notification->session = session;
+- notification->servconn = servconn = msn_servconn_new(session, MSN_SERVCONN_NS);
+- msn_servconn_set_destroy_cb(servconn, destroy_cb);
+-
+- notification->cmdproc = servconn->cmdproc;
+- notification->cmdproc->data = notification;
+- notification->cmdproc->cbs_table = cbs_table;
+-
+- return notification;
+-}
+-
+-void
+-msn_notification_destroy(MsnNotification *notification)
+-{
+- notification->cmdproc->data = NULL;
+-
+- msn_servconn_set_destroy_cb(notification->servconn, NULL);
+-
+- msn_servconn_destroy(notification->servconn);
+-
+- g_free(notification);
+-}
+-
+-/**************************************************************************
+- * Connect
+- **************************************************************************/
+-
+-static void
+-connect_cb(MsnServConn *servconn)
+-{
+- MsnCmdProc *cmdproc;
+- MsnSession *session;
+- MsnTransaction *trans;
+- GString *vers;
+- const char *ver_str;
+- int i;
+-
+- g_return_if_fail(servconn != NULL);
+-
+- cmdproc = servconn->cmdproc;
+- session = servconn->session;
+-
+- vers = g_string_new("");
+-
+- for (i = WLM_MAX_PROTOCOL; i >= WLM_MIN_PROTOCOL; i--)
+- g_string_append_printf(vers, " MSNP%d", i);
+-
+- g_string_append(vers, " CVR0");
+-
+- if (session->login_step == MSN_LOGIN_STEP_START)
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE);
+- else
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_HANDSHAKE2);
+-
+- /* Skip the initial space */
+- ver_str = (vers->str + 1);
+- trans = msn_transaction_new(cmdproc, "VER", "%s", ver_str);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- g_string_free(vers, TRUE);
+-}
+-
+-gboolean
+-msn_notification_connect(MsnNotification *notification, const char *host, int port)
+-{
+- MsnServConn *servconn;
+-
+- g_return_val_if_fail(notification != NULL, FALSE);
+-
+- servconn = notification->servconn;
+-
+- msn_servconn_set_connect_cb(servconn, connect_cb);
+- notification->in_use = msn_servconn_connect(servconn, host, port, TRUE);
+-
+- return notification->in_use;
+-}
+-
+-void
+-msn_notification_disconnect(MsnNotification *notification)
+-{
+- g_return_if_fail(notification != NULL);
+- g_return_if_fail(notification->in_use);
+-
+- msn_servconn_disconnect(notification->servconn);
+-
+- notification->in_use = FALSE;
+-}
+-
+-/**************************************************************************
+- * Login
+- **************************************************************************/
+-
+-void
+-msn_got_login_params(MsnSession *session, const char *ticket, const char *response)
+-{
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+-
+- cmdproc = session->notification->cmdproc;
+-
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_END);
+-
+- trans = msn_transaction_new(cmdproc, "USR", "SSO S %s %s %s", ticket, response, session->guid);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-cvr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- PurpleAccount *account;
+- MsnTransaction *trans;
+-
+- account = cmdproc->session->account;
+-
+- trans = msn_transaction_new(cmdproc, "USR", "SSO I %s", purple_account_get_username(account));
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session = cmdproc->session;
+-
+- if (!g_ascii_strcasecmp(cmd->params[1], "OK"))
+- {
+- /* authenticate OK */
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_SYN);
+- }
+- else if (!g_ascii_strcasecmp(cmd->params[1], "SSO"))
+- {
+- /* RPS authentication */
+-
+- if (session->nexus)
+- msn_nexus_destroy(session->nexus);
+-
+- session->nexus = msn_nexus_new(session);
+-
+- session->nexus->policy = g_strdup(cmd->params[3]);
+- session->nexus->nonce = g_strdup(cmd->params[4]);
+-
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_AUTH_START);
+-
+- msn_nexus_connect(session->nexus);
+- }
+-}
+-
+-static void
+-usr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- MsnErrorType msnerr = 0;
+-
+- switch (error)
+- {
+- case 500:
+- case 601:
+- case 910:
+- case 921:
+- msnerr = MSN_ERROR_SERV_UNAVAILABLE;
+- break;
+- case 911:
+- msnerr = MSN_ERROR_AUTH;
+- break;
+- default:
+- return;
+- break;
+- }
+-
+- msn_session_set_error(cmdproc->session, msnerr, NULL);
+-}
+-
+-static void
+-ver_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- MsnTransaction *trans;
+- PurpleAccount *account;
+- gboolean protocol_supported = FALSE;
+- int proto_ver;
+- size_t i;
+-
+- session = cmdproc->session;
+- account = session->account;
+-
+- session->protocol_ver = 0;
+- for (i = 1; i < cmd->param_count; i++)
+- {
+- if (sscanf(cmd->params[i], "MSNP%d", &proto_ver) == 1) {
+- if (proto_ver >= WLM_MIN_PROTOCOL
+- && proto_ver <= WLM_MAX_PROTOCOL
+- && proto_ver > session->protocol_ver) {
+- protocol_supported = TRUE;
+- session->protocol_ver = proto_ver;
+- }
+- }
+- }
+-
+- if (!protocol_supported)
+- {
+- msn_session_set_error(session, MSN_ERROR_UNSUPPORTED_PROTOCOL,
+- NULL);
+- return;
+- }
+-
+- purple_debug_info("msn", "Negotiated protocol version %d with the server.\n", session->protocol_ver);
+-
+- /*
+- * Windows Live Messenger 8.5
+- * Notice :CVR String discriminate!
+- * reference of http://www.microsoft.com/globaldev/reference/oslocversion.mspx
+- * to see the Local ID
+- */
+- trans = msn_transaction_new(cmdproc, "CVR",
+- "0x0409 winnt 5.1 i386 MSNMSGR 8.5.1302 BC01 %s",
+- purple_account_get_username(account));
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-/**************************************************************************
+- * Log out
+- **************************************************************************/
+-
+-static void
+-out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- if (cmd->param_count == 0)
+- msn_session_set_error(cmdproc->session, -1, NULL);
+- else if (!g_ascii_strcasecmp(cmd->params[0], "OTH"))
+- msn_session_set_error(cmdproc->session, MSN_ERROR_SIGN_OTHER,
+- NULL);
+- else if (!g_ascii_strcasecmp(cmd->params[0], "SSD"))
+- msn_session_set_error(cmdproc->session, MSN_ERROR_SERV_DOWN, NULL);
+-}
+-
+-void
+-msn_notification_close(MsnNotification *notification)
+-{
+- MsnTransaction *trans;
+-
+- g_return_if_fail(notification != NULL);
+-
+- if (!notification->in_use)
+- return;
+-
+- trans = msn_transaction_new(notification->cmdproc, "OUT", NULL);
+- msn_transaction_set_saveable(trans, FALSE);
+- msn_cmdproc_send_trans(notification->cmdproc, trans);
+-
+- msn_notification_disconnect(notification);
+-}
+-
+-/**************************************************************************
+- * Messages
+- **************************************************************************/
+-
+-static void
+-msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- MsnMessage *msg;
+-
+- msg = msn_message_new_from_cmd(cmdproc->session, cmd);
+-
+- msn_message_parse_payload(msg, payload, len, MSG_LINE_DEM, MSG_BODY_DEM);
+- if (purple_debug_is_verbose())
+- msn_message_show_readable(msg, "Notification", TRUE);
+-
+- msn_cmdproc_process_msg(cmdproc, msg);
+-
+- msn_message_unref(msg);
+-}
+-
+-static void
+-msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Processing MSG... \n");
+-
+- /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
+- * command and we are processing it */
+- if (cmd->payload == NULL) {
+- cmdproc->last_cmd->payload_cb = msg_cmd_post;
+- cmd->payload_len = atoi(cmd->params[2]);
+- } else {
+- g_return_if_fail(cmd->payload_cb != NULL);
+-
+-#if 0 /* glib on win32 doesn't correctly support precision modifiers for a string */
+- purple_debug_info("msn", "MSG payload:{%.*s}\n", (guint)cmd->payload_len, cmd->payload);
+-#endif
+- cmd->payload_cb(cmdproc, cmd, cmd->payload, cmd->payload_len);
+- }
+-}
+-
+-/*send Message to Yahoo Messenger*/
+-void
+-msn_notification_send_uum(MsnSession *session, MsnMessage *msg)
+-{
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+- char *payload;
+- gsize payload_len;
+- int type;
+- MsnUser *user;
+- int network;
+-
+- g_return_if_fail(msg != NULL);
+-
+- cmdproc = session->notification->cmdproc;
+-
+- payload = msn_message_gen_payload(msg, &payload_len);
+- type = msg->type;
+- user = msn_userlist_find_user(session->userlist, msg->remote_user);
+- if (user)
+- network = msn_user_get_network(user);
+- else
+- network = MSN_NETWORK_PASSPORT;
+-
+- purple_debug_info("msn",
+- "send UUM, payload{%s}, strlen:%" G_GSIZE_FORMAT ", len:%" G_GSIZE_FORMAT "\n",
+- payload, strlen(payload), payload_len);
+-
+- trans = msn_transaction_new(cmdproc, "UUM", "%s %d %d %" G_GSIZE_FORMAT,
+- msg->remote_user, network, type, payload_len);
+- msn_transaction_set_payload(trans, payload, strlen(payload));
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-/*Yahoo msg process*/
+-static void
+-ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Processing UBM... \n");
+-
+- /* NOTE: cmd is not always cmdproc->last_cmd, sometimes cmd is a queued
+- * command and we are processing it */
+- if (cmd->payload == NULL) {
+- cmdproc->last_cmd->payload_cb = msg_cmd_post;
+- cmd->payload_len = atoi(cmd->params[5]);
+- } else {
+- g_return_if_fail(cmd->payload_cb != NULL);
+-
+- purple_debug_info("msn", "UBM payload:{%.*s}\n", (guint)(cmd->payload_len), cmd->payload);
+- msg_cmd_post(cmdproc, cmd, cmd->payload, cmd->payload_len);
+- }
+-}
+-
+-/**************************************************************************
+- * Challenges
+- * we use MD5 to caculate the Challenges
+- **************************************************************************/
+-static void
+-chl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnTransaction *trans;
+- char buf[33];
+-
+- msn_handle_chl(cmd->params[1], buf);
+- trans = msn_transaction_new(cmdproc, "QRY", "%s 32", MSNP15_WLM_PRODUCT_ID);
+-
+- msn_transaction_set_payload(trans, buf, 32);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-/**************************************************************************
+- * Buddy Lists
+- **************************************************************************/
+-
+-typedef struct MsnFqyCbData {
+- MsnFqyCb cb;
+- gpointer data;
+-} MsnFqyCbData;
+-
+-/* add contact to xmlnode */
+-static void
+-msn_add_contact_xml(xmlnode *mlNode, const char *passport, MsnListOp list_op, MsnNetwork networkId)
+-{
+- xmlnode *d_node,*c_node;
+- char **tokens;
+- const char *email,*domain;
+- char fmt_str[3];
+-
+- g_return_if_fail(passport != NULL);
+-
+- purple_debug_info("msn", "Passport: %s, type: %d\n", passport, networkId);
+- tokens = g_strsplit(passport, "@", 2);
+- email = tokens[0];
+- domain = tokens[1];
+-
+- if (email == NULL || domain == NULL) {
+- purple_debug_error("msn", "Invalid passport (%s) specified to add to contact xml.\n", passport);
+- g_strfreev(tokens);
+- g_return_if_reached();
+- }
+-
+- /*find a domain Node*/
+- for (d_node = xmlnode_get_child(mlNode, "d"); d_node;
+- d_node = xmlnode_get_next_twin(d_node)) {
+- const char *attr = xmlnode_get_attrib(d_node,"n");
+- if (attr == NULL)
+- continue;
+- if (!strcmp(attr, domain))
+- break;
+- }
+-
+- if (d_node == NULL) {
+- /*domain not found, create a new domain Node*/
+- purple_debug_info("msn", "Didn't find existing domain node, adding one.\n");
+- d_node = xmlnode_new("d");
+- xmlnode_set_attrib(d_node, "n", domain);
+- xmlnode_insert_child(mlNode, d_node);
+- }
+-
+- /*create contact node*/
+- c_node = xmlnode_new("c");
+- xmlnode_set_attrib(c_node, "n", email);
+-
+- if (list_op != 0) {
+- purple_debug_info("msn", "list_op: %d\n", list_op);
+- g_snprintf(fmt_str, sizeof(fmt_str), "%d", list_op);
+- xmlnode_set_attrib(c_node, "l", fmt_str);
+- }
+-
+- if (networkId != MSN_NETWORK_UNKNOWN) {
+- g_snprintf(fmt_str, sizeof(fmt_str), "%d", networkId);
+- /*mobile*/
+- /*type_str = g_strdup_printf("4");*/
+- xmlnode_set_attrib(c_node, "t", fmt_str);
+- }
+-
+- xmlnode_insert_child(d_node, c_node);
+-
+- g_strfreev(tokens);
+-}
+-
+-static void
+-msn_notification_post_adl(MsnCmdProc *cmdproc, const char *payload, int payload_len)
+-{
+- MsnTransaction *trans;
+- purple_debug_info("msn", "Sending ADL with payload: %s\n", payload);
+- trans = msn_transaction_new(cmdproc, "ADL", "%i", payload_len);
+- msn_transaction_set_payload(trans, payload, payload_len);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-msn_notification_post_rml(MsnCmdProc *cmdproc, const char *payload, int payload_len)
+-{
+- MsnTransaction *trans;
+- purple_debug_info("msn", "Sending RML with payload: %s\n", payload);
+- trans = msn_transaction_new(cmdproc, "RML", "%i", payload_len);
+- msn_transaction_set_payload(trans, payload, payload_len);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-void
+-msn_notification_send_fqy(MsnSession *session,
+- const char *payload, int payload_len,
+- MsnFqyCb cb,
+- gpointer cb_data)
+-{
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+- MsnFqyCbData *data;
+-
+- cmdproc = session->notification->cmdproc;
+-
+- data = g_new(MsnFqyCbData, 1);
+- data->cb = cb;
+- data->data = cb_data;
+-
+- trans = msn_transaction_new(cmdproc, "FQY", "%d", payload_len);
+- msn_transaction_set_payload(trans, payload, payload_len);
+- msn_transaction_set_data(trans, data);
+- msn_transaction_set_data_free(trans, g_free);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-update_contact_network(MsnSession *session, const char *passport, MsnNetwork network, gpointer unused)
+-{
+- MsnUser *user;
+-
+- if (network == MSN_NETWORK_UNKNOWN)
+- {
+- purple_debug_warning("msn",
+- "Ignoring user %s about which server knows nothing.\n",
+- passport);
+- /* Decrement the count for unknown results so that we'll continue login.
+- Also, need to finish the login process here as well, because ADL OK
+- will not be called. */
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "ADL/FQY count is %d\n", session->adl_fqy);
+- if (--session->adl_fqy == 0)
+- msn_session_finish_login(session);
+- return;
+- }
+-
+- /* TODO: Also figure out how to update membership lists */
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (user) {
+- xmlnode *adl_node;
+- char *payload;
+- int payload_len;
+-
+- msn_user_set_network(user, network);
+-
+- adl_node = xmlnode_new("ml");
+- xmlnode_set_attrib(adl_node, "l", "1");
+- msn_add_contact_xml(adl_node, passport,
+- user->list_op & MSN_LIST_OP_MASK, network);
+- payload = xmlnode_to_str(adl_node, &payload_len);
+- msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
+- g_free(payload);
+- xmlnode_free(adl_node);
+- } else {
+- purple_debug_error("msn",
+- "Got FQY update for unknown user %s on network %d.\n",
+- passport, network);
+- }
+-}
+-
+-/*dump contact info to NS*/
+-void
+-msn_notification_dump_contact(MsnSession *session)
+-{
+- MsnUser *user;
+- GList *l;
+- xmlnode *adl_node;
+- xmlnode *fqy_node;
+- char *payload;
+- int payload_len;
+- int adl_count = 0;
+- int fqy_count = 0;
+- PurpleConnection *pc;
+- const char *display_name;
+-
+- adl_node = xmlnode_new("ml");
+- adl_node->child = NULL;
+- xmlnode_set_attrib(adl_node, "l", "1");
+- fqy_node = xmlnode_new("ml");
+-
+- /*get the userlist*/
+- for (l = session->userlist->users; l != NULL; l = l->next) {
+- user = l->data;
+-
+- /* skip RL & PL during initial dump */
+- if (!(user->list_op & MSN_LIST_OP_MASK))
+- continue;
+-
+- if (user->passport && !strcmp(user->passport, "messenger@microsoft.com"))
+- continue;
+-
+- if ((user->list_op & MSN_LIST_OP_MASK & ~MSN_LIST_FL_OP)
+- == (MSN_LIST_AL_OP | MSN_LIST_BL_OP)) {
+- /* The server will complain if we send it a user on both the
+- Allow and Block lists. So assume they're on the Block list
+- and remove them from the Allow list in the membership lists to
+- stop this from happening again. */
+- purple_debug_warning("msn",
+- "User %s is on both Allow and Block list; "
+- "removing from Allow list.\n",
+- user->passport);
+- msn_user_unset_op(user, MSN_LIST_AL_OP);
+- }
+-
+- if (user->networkid != MSN_NETWORK_UNKNOWN) {
+- msn_add_contact_xml(adl_node, user->passport,
+- user->list_op & MSN_LIST_OP_MASK,
+- user->networkid);
+-
+- /* each ADL command may contain up to 150 contacts */
+- if (++adl_count % 150 == 0) {
+- payload = xmlnode_to_str(adl_node, &payload_len);
+-
+- /* ADL's are returned all-together */
+- session->adl_fqy++;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Posting ADL, count is %d\n",
+- session->adl_fqy);
+-
+- msn_notification_post_adl(session->notification->cmdproc,
+- payload, payload_len);
+-
+- g_free(payload);
+- xmlnode_free(adl_node);
+-
+- adl_node = xmlnode_new("ml");
+- adl_node->child = NULL;
+- xmlnode_set_attrib(adl_node, "l", "1");
+- }
+- } else {
+- /* FQY's are returned one-at-a-time */
+- session->adl_fqy++;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Adding FQY address, count is %d\n",
+- session->adl_fqy);
+-
+- msn_add_contact_xml(fqy_node, user->passport, 0, user->networkid);
+-
+- /* each FQY command may contain up to 150 contacts, probably */
+- if (++fqy_count % 150 == 0) {
+- payload = xmlnode_to_str(fqy_node, &payload_len);
+-
+- msn_notification_send_fqy(session, payload, payload_len,
+- update_contact_network, NULL);
+-
+- g_free(payload);
+- xmlnode_free(fqy_node);
+- fqy_node = xmlnode_new("ml");
+- }
+- }
+- }
+-
+- /* Send the rest, or just an empty one to let the server set us online */
+- if (adl_count == 0 || adl_count % 150 != 0) {
+- payload = xmlnode_to_str(adl_node, &payload_len);
+-
+- /* ADL's are returned all-together */
+- session->adl_fqy++;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Posting ADL, count is %d\n",
+- session->adl_fqy);
+-
+- msn_notification_post_adl(session->notification->cmdproc, payload, payload_len);
+-
+- g_free(payload);
+- }
+-
+- if (fqy_count % 150 != 0) {
+- payload = xmlnode_to_str(fqy_node, &payload_len);
+-
+- msn_notification_send_fqy(session, payload, payload_len,
+- update_contact_network, NULL);
+-
+- g_free(payload);
+- }
+-
+- xmlnode_free(adl_node);
+- xmlnode_free(fqy_node);
+-
+- msn_session_activate_login_timeout(session);
+-
+- pc = purple_account_get_connection(session->account);
+- display_name = purple_connection_get_display_name(pc);
+- if (display_name
+- && strcmp(display_name,
+- purple_account_get_username(session->account))) {
+- msn_set_public_alias(pc, display_name, NULL, NULL);
+- }
+-
+-}
+-
+-static void
+-blp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+-}
+-
+-static void
+-adl_cmd_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- xmlnode *root, *domain_node;
+-
+- purple_debug_misc("msn", "Parsing received ADL XML data\n");
+-
+- g_return_if_fail(payload != NULL);
+-
+- root = xmlnode_from_str(payload, (gssize) len);
+-
+- if (root == NULL) {
+- purple_debug_info("msn", "Invalid XML in ADL!\n");
+- return;
+- }
+- for (domain_node = xmlnode_get_child(root, "d");
+- domain_node;
+- domain_node = xmlnode_get_next_twin(domain_node)) {
+- xmlnode *contact_node = NULL;
+-
+- for (contact_node = xmlnode_get_child(domain_node, "c");
+- contact_node;
+- contact_node = xmlnode_get_next_twin(contact_node)) {
+- const gchar *list;
+- gint list_op = 0;
+-
+- list = xmlnode_get_attrib(contact_node, "l");
+- if (list != NULL) {
+- list_op = atoi(list);
+- }
+-
+- if (list_op & MSN_LIST_RL_OP) {
+- /* someone is adding us */
+- msn_get_contact_list(cmdproc->session, MSN_PS_PENDING_LIST, NULL);
+- }
+- }
+- }
+-
+- xmlnode_free(root);
+-}
+-
+-static void
+-adl_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+-
+- g_return_if_fail(cmdproc != NULL);
+- g_return_if_fail(cmdproc->session != NULL);
+- g_return_if_fail(cmdproc->last_cmd != NULL);
+- g_return_if_fail(cmd != NULL);
+-
+- session = cmdproc->session;
+-
+- if (!strcmp(cmd->params[1], "OK")) {
+- /* ADL ack */
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "ADL ACK, count is %d\n",
+- session->adl_fqy);
+- if (--session->adl_fqy == 0)
+- msn_session_finish_login(session);
+- } else {
+- cmdproc->last_cmd->payload_cb = adl_cmd_parse;
+- cmd->payload_len = atoi(cmd->params[1]);
+- }
+-
+- return;
+-}
+-
+-static void
+-adl_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
+-{
+- MsnSession *session;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- int error = GPOINTER_TO_INT(cmd->payload_cbdata);
+-
+- session = cmdproc->session;
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- if (error == 241) {
+- /* khc: some googling suggests that error 241 means the buddy is somehow
+- in the local list, but not the server list, and that we should add
+- those buddies to the addressbook. For now I will just notify the user
+- about the raw payload, because I am lazy */
+- xmlnode *adl = xmlnode_from_str(payload, len);
+- GString *emails = g_string_new(NULL);
+-
+- xmlnode *domain = xmlnode_get_child(adl, "d");
+- while (domain) {
+- const char *domain_str = xmlnode_get_attrib(domain, "n");
+- xmlnode *contact = xmlnode_get_child(domain, "c");
+- while (contact) {
+- g_string_append_printf(emails, "%s@%s\n",
+- xmlnode_get_attrib(contact, "n"), domain_str);
+- contact = xmlnode_get_next_twin(contact);
+- }
+- domain = xmlnode_get_next_twin(domain);
+- }
+-
+- purple_notify_error(gc, NULL,
+- _("The following users are missing from your addressbook"),
+- emails->str);
+- g_string_free(emails, TRUE);
+- xmlnode_free(adl);
+- }
+- else
+- {
+- char *adl = g_strndup(payload, len);
+- char *reason = g_strdup_printf(_("Unknown error (%d): %s"),
+- error, adl);
+- g_free(adl);
+-
+- purple_notify_error(gc, NULL, _("Unable to add user"), reason);
+- g_free(reason);
+- }
+-}
+-
+-static void
+-adl_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- MsnSession *session;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- MsnCommand *cmd = cmdproc->last_cmd;
+-
+- session = cmdproc->session;
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- purple_debug_error("msn", "ADL error\n");
+- if (cmd->param_count > 1) {
+- cmd->payload_cb = adl_error_parse;
+- cmd->payload_len = atoi(cmd->params[1]);
+- cmd->payload_cbdata = GINT_TO_POINTER(error);
+- } else {
+- char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
+- purple_notify_error(gc, NULL, _("Unable to add user"), reason);
+- g_free(reason);
+- }
+-}
+-
+-static void
+-rml_error_parse(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
+-{
+- MsnSession *session;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- char *adl, *reason;
+- int error = GPOINTER_TO_INT(cmd->payload_cbdata);
+-
+- session = cmdproc->session;
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- adl = g_strndup(payload, len);
+- reason = g_strdup_printf(_("Unknown error (%d): %s"),
+- error, adl);
+- g_free(adl);
+-
+- purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
+- g_free(reason);
+-}
+-
+-static void
+-rml_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- MsnSession *session;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- MsnCommand *cmd = cmdproc->last_cmd;
+-
+- session = cmdproc->session;
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- purple_debug_error("msn", "RML error\n");
+- if (cmd->param_count > 1) {
+- cmd->payload_cb = rml_error_parse;
+- cmd->payload_len = atoi(cmd->params[1]);
+- cmd->payload_cbdata = GINT_TO_POINTER(error);
+- } else {
+- char *reason = g_strdup_printf(_("Unknown error (%d)"), error);
+- purple_notify_error(gc, NULL, _("Unable to remove user"), reason);
+- g_free(reason);
+- }
+-}
+-
+-static void
+-fqy_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- MsnSession *session;
+- xmlnode *ml, *d, *c;
+- const char *domain;
+- const char *local;
+- const char *type;
+- char *passport;
+- MsnNetwork network = MSN_NETWORK_PASSPORT;
+-
+- session = cmdproc->session;
+-
+- /* FQY response:
+- <ml><d n="domain.com"><c n="local-node" t="network" /></d></ml> */
+- ml = xmlnode_from_str(payload, len);
+- for (d = xmlnode_get_child(ml, "d");
+- d != NULL;
+- d = xmlnode_get_next_twin(d)) {
+- domain = xmlnode_get_attrib(d, "n");
+- for (c = xmlnode_get_child(d, "c");
+- c != NULL;
+- c = xmlnode_get_next_twin(c)) {
+- local = xmlnode_get_attrib(c, "n");
+- type = xmlnode_get_attrib(c, "t");
+-
+- passport = g_strdup_printf("%s@%s", local, domain);
+-
+- if (g_ascii_isdigit(cmd->command[0]))
+- network = MSN_NETWORK_UNKNOWN;
+- else if (type != NULL)
+- network = (MsnNetwork)strtoul(type, NULL, 10);
+-
+- purple_debug_info("msn", "FQY response says %s is from network %d\n",
+- passport, network);
+- if (cmd->trans->data) {
+- MsnFqyCbData *fqy_data = cmd->trans->data;
+- fqy_data->cb(session, passport, network, fqy_data->data);
+- /* Don't free fqy_data yet since the server responds to FQY multiple times.
+- It will be freed when cmd->trans is freed. */
+- }
+-
+- g_free(passport);
+- }
+- }
+-
+- xmlnode_free(ml);
+-}
+-
+-static void
+-fqy_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- MsnCommand *cmd = cmdproc->last_cmd;
+-
+- purple_debug_warning("msn", "FQY error %d\n", error);
+- if (cmd->param_count > 1) {
+- cmd->payload_cb = fqy_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+- cmd->payload_cbdata = GINT_TO_POINTER(error);
+- }
+-#if 0
+- /* If the server didn't send us a corresponding email address for this
+- FQY error, it's probably going to disconnect us. So it isn't necessary
+- to tell the handler about it. */
+- else if (trans->data)
+- ((MsnFqyCb)trans->data)(session, NULL, MSN_NETWORK_UNKNOWN, NULL);
+-#endif
+-}
+-
+-static void
+-fqy_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Process FQY\n");
+- cmdproc->last_cmd->payload_cb = fqy_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+-}
+-
+-static void
+-rml_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- if (payload != NULL)
+- purple_debug_info("msn", "Received RML:\n%s\n", payload);
+-}
+-
+-static void
+-rml_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Process RML\n");
+- cmd->payload_len = atoi(cmd->params[1]);
+- cmdproc->last_cmd->payload_cb = rml_cmd_post;
+-}
+-
+-static void
+-qng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- /* TODO: Call PNG after the timeout specified. */
+-}
+-
+-
+-static void
+-fln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnUser *user;
+- char *passport;
+- int networkid;
+-
+- /* Tell libpurple that the user has signed off */
+- msn_parse_user(cmd->params[0], &passport, &networkid);
+- user = msn_userlist_find_user(cmdproc->session->userlist, passport);
+- msn_user_set_state(user, NULL);
+- msn_user_update(user);
+-
+- g_free(passport);
+-}
+-
+-static void
+-iln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- MsnUser *user;
+- MsnObject *msnobj = NULL;
+- unsigned long clientid, extcaps;
+- char *extcap_str;
+- int networkid = 0;
+- const char *state, *passport;
+- char *friendly;
+-
+- session = cmdproc->session;
+-
+- state = cmd->params[1];
+- passport = cmd->params[2];
+-
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (user == NULL)
+- /* Where'd this come from? */
+- return;
+-
+- if (cmd->param_count == 8) {
+- /* Yahoo! Buddy, looks like */
+- networkid = atoi(cmd->params[3]);
+- friendly = g_strdup(purple_url_decode(cmd->params[4]));
+- clientid = strtoul(cmd->params[5], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+-
+- /* cmd->params[7] seems to be a URL to a Yahoo! icon:
+- https://sec.yimg.com/i/us/nt/b/purpley.1.0.png
+- ... and it's purple, HAH!
+- */
+- } else if (cmd->param_count == 7) {
+- /* MSNP14+ with Display Picture object */
+- networkid = atoi(cmd->params[3]);
+- friendly = g_strdup(purple_url_decode(cmd->params[4]));
+- clientid = strtoul(cmd->params[5], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[6]));
+- } else if (cmd->param_count == 6) {
+- /* Yes, this is 5. The friendly name could start with a number,
+- but the display picture object can't... */
+- if (isdigit(cmd->params[5][0])) {
+- /* MSNP14 without Display Picture object */
+- networkid = atoi(cmd->params[3]);
+- friendly = g_strdup(purple_url_decode(cmd->params[4]));
+- clientid = strtoul(cmd->params[5], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+- } else {
+- /* MSNP8+ with Display Picture object */
+- friendly = g_strdup(purple_url_decode(cmd->params[3]));
+- clientid = strtoul(cmd->params[4], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[5]));
+- }
+- } else if (cmd->param_count == 5) {
+- /* MSNP8+ without Display Picture object */
+- friendly = g_strdup(purple_url_decode(cmd->params[3]));
+- clientid = strtoul(cmd->params[4], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+- } else {
+- purple_debug_warning("msn", "Received ILN with unknown number of parameters.\n");
+- return;
+- }
+-
+- if (msn_user_set_friendly_name(user, friendly)) {
+- msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
+- }
+- g_free(friendly);
+-
+- msn_user_set_object(user, msnobj);
+-
+- user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
+- msn_user_set_clientid(user, clientid);
+- msn_user_set_extcaps(user, extcaps);
+- msn_user_set_network(user, networkid);
+-
+- msn_user_set_state(user, state);
+- msn_user_update(user);
+-}
+-
+-static void
+-ipg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
+-{
+- PurpleConnection *gc;
+- MsnUserList *userlist;
+- const char *who = NULL;
+- char *text = NULL;
+- const char *id = NULL;
+- xmlnode *payloadNode, *from, *msg, *textNode;
+-
+- purple_debug_misc("msn", "Incoming Page: {%s}\n", payload);
+-
+- userlist = cmdproc->session->userlist;
+- gc = purple_account_get_connection(cmdproc->session->account);
+-
+- /* payload looks like this:
+- <?xml version="1.0"?>
+- <NOTIFICATION id="0" siteid="111100400" siteurl="http://mobile.msn.com/">
+- <TO name="passport@example.com">
+- <VIA agent="mobile"/>
+- </TO>
+- <FROM name="tel:+XXXXXXXXXXX"/>
+- <MSG pri="1" id="1">
+- <CAT Id="110110001"/>
+- <ACTION url="2wayIM.asp"/>
+- <SUBSCR url="2wayIM.asp"/>
+- <BODY lcid="1033">
+- <TEXT>Message was here</TEXT>
+- </BODY>
+- </MSG>
+- </NOTIFICATION>
+- */
+-
+- /* This is the payload if your message was too long:
+- <NOTIFICATION id="TrID" siteid="111100400" siteurl="http://mobile.msn.com/">
+- <TO name="passport@example.com">
+- <VIA agent="mobile"/>
+- </TO>
+- <FROM name="tel:+XXXXXXXXXXX"/>
+- <MSG pri="1" id="407">
+- <CAT Id="110110001"/>
+- <ACTION url="2wayIM.asp"/>
+- <SUBSCR url="2wayIM.asp"/>
+- <BODY lcid="1033">
+- <TEXT></TEXT>
+- </BODY>
+- </MSG>
+- </NOTIFICATION>
+- */
+-
+- payloadNode = xmlnode_from_str(payload, len);
+- if (!payloadNode)
+- return;
+-
+- if (!(from = xmlnode_get_child(payloadNode, "FROM")) ||
+- !(msg = xmlnode_get_child(payloadNode, "MSG")) ||
+- !(textNode = xmlnode_get_child(msg, "BODY/TEXT"))) {
+- xmlnode_free(payloadNode);
+- return;
+- }
+-
+- who = xmlnode_get_attrib(from, "name");
+- if (!who) return;
+-
+- text = xmlnode_get_data(textNode);
+-
+- /* Match number to user's mobile number, FROM is a phone number if the
+- other side page you using your phone number */
+- if (!strncmp(who, "tel:+", 5)) {
+- MsnUser *user =
+- msn_userlist_find_user_with_mobile_phone(userlist, who + 4);
+-
+- if (user && user->passport)
+- who = user->passport;
+- }
+-
+- id = xmlnode_get_attrib(msg, "id");
+-
+- if (id && strcmp(id, "1")) {
+- PurpleConversation *conv
+- = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+- who, gc->account);
+- if (conv != NULL) {
+- const char *error;
+- if (!strcmp(id, "407"))
+- error = _("Mobile message was not sent because it was too long.");
+- else
+- error = _("Mobile message was not sent because an unknown error occurred.");
+-
+- purple_conversation_write(conv, NULL, error,
+- PURPLE_MESSAGE_ERROR, time(NULL));
+-
+- if ((id = xmlnode_get_attrib(payloadNode, "id")) != NULL) {
+- unsigned int trId = atol(id);
+- MsnTransaction *trans;
+-
+- trans = msn_history_find(cmdproc->history, trId);
+- if (trans) {
+- MsnMessage *msg = (MsnMessage *)trans->data;
+-
+- if (msg) {
+- char *body_str = msn_message_to_string(msg);
+- char *body_enc = g_markup_escape_text(body_str, -1);
+-
+- purple_conversation_write(conv, NULL, body_enc,
+- PURPLE_MESSAGE_RAW, time(NULL));
+-
+- g_free(body_str);
+- g_free(body_enc);
+- msn_message_unref(msg);
+- trans->data = NULL;
+- }
+- }
+- }
+- }
+- } else {
+- serv_got_im(gc, who, text, 0, time(NULL));
+- }
+-
+- g_free(text);
+- xmlnode_free(payloadNode);
+-}
+-
+-static void
+-ipg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- cmd->payload_len = atoi(cmd->params[0]);
+- cmdproc->last_cmd->payload_cb = ipg_cmd_post;
+-}
+-
+-static void
+-nln_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- MsnUser *user;
+- MsnObject *msnobj;
+- unsigned long clientid, extcaps;
+- char *extcap_str;
+- char *passport;
+- int networkid;
+- const char *state, *friendly;
+-
+- session = cmdproc->session;
+-
+- state = cmd->params[0];
+- msn_parse_user(cmd->params[1], &passport, &networkid);
+- friendly = purple_url_decode(cmd->params[2]);
+-
+- user = msn_userlist_find_user(session->userlist, passport);
+- if (user == NULL) return;
+-
+- if (msn_user_set_friendly_name(user, friendly) && user != session->user)
+- {
+- msn_update_contact(session, passport, MSN_UPDATE_DISPLAY, friendly);
+- }
+-
+- if (cmd->param_count == 5)
+- {
+- msnobj = msn_object_new_from_string(purple_url_decode(cmd->params[4]));
+- msn_user_set_object(user, msnobj);
+- }
+- else
+- {
+- msn_user_set_object(user, NULL);
+- }
+-
+- clientid = strtoul(cmd->params[3], &extcap_str, 10);
+- if (extcap_str && *extcap_str)
+- extcaps = strtoul(extcap_str+1, NULL, 10);
+- else
+- extcaps = 0;
+-
+- user->mobile = (clientid & MSN_CAP_MOBILE_ON) || (user->extinfo && user->extinfo->phone_mobile && user->extinfo->phone_mobile[0] == '+');
+-
+- msn_user_set_clientid(user, clientid);
+- msn_user_set_extcaps(user, extcaps);
+- msn_user_set_network(user, networkid);
+-
+- msn_user_set_state(user, state);
+- msn_user_update(user);
+-
+- g_free(passport);
+-}
+-
+-#if 0
+-static void
+-chg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- char *state = cmd->params[1];
+- int state_id = 0;
+-
+- if (!strcmp(state, "NLN"))
+- state_id = MSN_ONLINE;
+- else if (!strcmp(state, "BSY"))
+- state_id = MSN_BUSY;
+- else if (!strcmp(state, "IDL"))
+- state_id = MSN_IDLE;
+- else if (!strcmp(state, "BRB"))
+- state_id = MSN_BRB;
+- else if (!strcmp(state, "AWY"))
+- state_id = MSN_AWAY;
+- else if (!strcmp(state, "PHN"))
+- state_id = MSN_PHONE;
+- else if (!strcmp(state, "LUN"))
+- state_id = MSN_LUNCH;
+- else if (!strcmp(state, "HDN"))
+- state_id = MSN_HIDDEN;
+-
+- cmdproc->session->state = state_id;
+-}
+-#endif
+-
+-
+-static void
+-not_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
+-{
+-#if 0
+- MSN_SET_PARAMS("NOT %d\r\n%s", cmdproc->servconn->payload, payload);
+- purple_debug_misc("msn", "Notification: {%s}\n", payload);
+-#endif
+-}
+-
+-static void
+-not_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- cmd->payload_len = atoi(cmd->params[0]);
+- cmdproc->last_cmd->payload_cb = not_cmd_post;
+-}
+-
+-static void
+-prp_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session = cmdproc->session;
+- const char *type, *value;
+-
+- g_return_if_fail(cmd->param_count >= 3);
+-
+- type = cmd->params[2];
+-
+- if (cmd->param_count == 4)
+- {
+- value = cmd->params[3];
+- if (!strcmp(type, "PHH"))
+- msn_user_set_home_phone(session->user, purple_url_decode(value));
+- else if (!strcmp(type, "PHW"))
+- msn_user_set_work_phone(session->user, purple_url_decode(value));
+- else if (!strcmp(type, "PHM"))
+- msn_user_set_mobile_phone(session->user, purple_url_decode(value));
+- }
+- else
+- {
+- if (!strcmp(type, "PHH"))
+- msn_user_set_home_phone(session->user, NULL);
+- else if (!strcmp(type, "PHW"))
+- msn_user_set_work_phone(session->user, NULL);
+- else if (!strcmp(type, "PHM"))
+- msn_user_set_mobile_phone(session->user, NULL);
+- }
+-}
+-
+-/**************************************************************************
+- * Misc commands
+- **************************************************************************/
+-
+-static void
+-url_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- const char *rru;
+- const char *url;
+- PurpleCipherContext *cipher;
+- gchar creds[33];
+- char *buf;
+-
+- gulong tmp_timestamp;
+-
+- session = cmdproc->session;
+- account = session->account;
+- gc = account->gc;
+-
+- rru = cmd->params[1];
+- url = cmd->params[2];
+-
+- session->passport_info.mail_timestamp = time(NULL);
+- tmp_timestamp = session->passport_info.mail_timestamp - session->passport_info.sl;
+-
+- buf = g_strdup_printf("%s%lu%s",
+- session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS",
+- tmp_timestamp,
+- purple_connection_get_password(gc));
+-
+- cipher = purple_cipher_context_new_by_name("md5", NULL);
+- purple_cipher_context_append(cipher, (const guchar *)buf, strlen(buf));
+- purple_cipher_context_digest_to_str(cipher, sizeof(creds), creds, NULL);
+- purple_cipher_context_destroy(cipher);
+- g_free(buf);
+-
+- g_free(session->passport_info.mail_url);
+- session->passport_info.mail_url =
+- g_strdup_printf("%s&auth=%s&creds=%s&sl=%ld&username=%s&mode=ttl&sid=%s&id=2&rru=%s&svc=mail&js=yes",
+- url,
+- session->passport_info.mspauth ? purple_url_encode(session->passport_info.mspauth) : "BOGUS",
+- creds,
+- tmp_timestamp,
+- msn_user_get_passport(session->user),
+- session->passport_info.sid,
+- rru);
+-
+- /* The user wants to check his or her email */
+- if (cmd->trans && cmd->trans->data)
+- purple_notify_uri(purple_account_get_connection(account), session->passport_info.mail_url);
+-}
+-/**************************************************************************
+- * Switchboards
+- **************************************************************************/
+-
+-static void
+-rng_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- const char *session_id;
+- char *host;
+- int port;
+-
+- session = cmdproc->session;
+- session_id = cmd->params[0];
+-
+- msn_parse_socket(cmd->params[1], &host, &port);
+-
+- if (session->http_method)
+- port = 80;
+-
+- swboard = msn_switchboard_new(session);
+-
+- msn_switchboard_set_invited(swboard, TRUE);
+- msn_switchboard_set_session_id(swboard, session_id);
+- msn_switchboard_set_auth_key(swboard, cmd->params[3]);
+- swboard->im_user = g_strdup(cmd->params[4]);
+- /* msn_switchboard_add_user(swboard, cmd->params[4]); */
+-
+- if (!msn_switchboard_connect(swboard, host, port))
+- msn_switchboard_destroy(swboard);
+-
+- g_free(host);
+-}
+-
+-static void
+-xfr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- char *host;
+- int port;
+-
+- if (strcmp(cmd->params[1], "SB") && strcmp(cmd->params[1], "NS"))
+- {
+- /* Maybe we can have a generic bad command error. */
+- purple_debug_error("msn", "Bad XFR command (%s)\n", cmd->params[1]);
+- return;
+- }
+-
+- msn_parse_socket(cmd->params[2], &host, &port);
+-
+- if (!strcmp(cmd->params[1], "SB"))
+- {
+- purple_debug_error("msn", "This shouldn't be handled here.\n");
+- }
+- else if (!strcmp(cmd->params[1], "NS"))
+- {
+- MsnSession *session;
+-
+- session = cmdproc->session;
+-
+- msn_session_set_login_step(session, MSN_LOGIN_STEP_TRANSFER);
+-
+- msn_notification_connect(session->notification, host, port);
+- }
+-
+- g_free(host);
+-}
+-
+-static void
+-gcf_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+-/* QuLogic: Disabled until confirmed correct. */
+-#if 0
+- xmlnode *root;
+- xmlnode *policy;
+-
+- g_return_if_fail(cmd->payload != NULL);
+-
+- if ( (root = xmlnode_from_str(cmd->payload, cmd->payload_len)) == NULL)
+- {
+- purple_debug_error("msn", "Unable to parse GCF payload into a XML tree\n");
+- return;
+- }
+-
+-
+- g_free(cmdproc->session->blocked_text);
+- cmdproc->session->blocked_text = NULL;
+-
+- /* We need a get_child with attrib... */
+- policy = xmlnode_get_child(root, "Policy");
+- while (policy) {
+- if (g_str_equal(xmlnode_get_attrib(policy, "type"), "SHIELDS"))
+- break;
+- policy = xmlnode_get_next_twin(policy);
+- }
+-
+- if (policy) {
+- GString *blocked = g_string_new(NULL);
+- xmlnode *imtext = xmlnode_get_child(policy,
+- "config/block/regexp/imtext");
+- while (imtext) {
+- const char *value = xmlnode_get_attrib(imtext, "value");
+- g_string_append_printf(blocked, "%s<br/>\n",
+- purple_base64_decode(value, NULL));
+- imtext = xmlnode_get_next_twin(imtext);
+- }
+-
+- cmdproc->session->blocked_text = g_string_free(blocked, FALSE);
+- }
+-
+- xmlnode_free(root);
+-#endif
+-}
+-
+-static void
+-gcf_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Processing GCF command\n");
+-
+- cmdproc->last_cmd->payload_cb = gcf_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+-}
+-
+-static void
+-sbs_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "Processing SBS... \n");
+- /*get the payload content*/
+-}
+-
+-static void
+-parse_user_endpoints(MsnUser *user, xmlnode *payloadNode)
+-{
+- MsnSession *session;
+- xmlnode *epNode, *capsNode;
+- MsnUserEndpoint data;
+- const char *id;
+- char *caps, *tmp;
+- gboolean is_me;
+-
+- purple_debug_info("msn", "Get EndpointData\n");
+-
+- session = user->userlist->session;
+- is_me = (user == session->user);
+-
+- msn_user_clear_endpoints(user);
+- for (epNode = xmlnode_get_child(payloadNode, "EndpointData");
+- epNode;
+- epNode = xmlnode_get_next_twin(epNode)) {
+- id = xmlnode_get_attrib(epNode, "id");
+- capsNode = xmlnode_get_child(epNode, "Capabilities");
+-
+- /* Disconnect others, if MPOP is disabled */
+- if (is_me
+- && !session->enable_mpop
+- && strncasecmp(id + 1, session->guid, 36) != 0) {
+- purple_debug_info("msn", "Disconnecting Endpoint %s\n", id);
+-
+- tmp = g_strdup_printf("%s;%s", user->passport, id);
+- msn_notification_send_uun(session, tmp, MSN_UNIFIED_NOTIFICATION_MPOP, "goawyplzthxbye");
+- g_free(tmp);
+- } else {
+- if (capsNode != NULL) {
+- caps = xmlnode_get_data(capsNode);
+-
+- data.clientid = strtoul(caps, &tmp, 10);
+- if (tmp && *tmp)
+- data.extcaps = strtoul(tmp + 1, NULL, 10);
+- else
+- data.extcaps = 0;
+-
+- g_free(caps);
+- } else {
+- data.clientid = 0;
+- data.extcaps = 0;
+- }
+-
+- msn_user_set_endpoint_data(user, id, &data);
+- }
+- }
+-
+- if (is_me && session->enable_mpop) {
+- for (epNode = xmlnode_get_child(payloadNode, "PrivateEndpointData");
+- epNode;
+- epNode = xmlnode_get_next_twin(epNode)) {
+- MsnUserEndpoint *ep;
+- xmlnode *nameNode, *clientNode;
+-
+- /* <PrivateEndpointData id='{GUID}'>
+- <EpName>Endpoint Name</EpName>
+- <Idle>true/false</Idle>
+- <ClientType>1</ClientType>
+- <State>NLN</State>
+- </PrivateEndpointData>
+- */
+- id = xmlnode_get_attrib(epNode, "id");
+- ep = msn_user_get_endpoint_data(user, id);
+-
+- if (ep != NULL) {
+- nameNode = xmlnode_get_child(epNode, "EpName");
+- if (nameNode != NULL) {
+- g_free(ep->name);
+- ep->name = xmlnode_get_data(nameNode);
+- }
+-
+- clientNode = xmlnode_get_child(epNode, "ClientType");
+- if (clientNode != NULL) {
+- tmp = xmlnode_get_data(clientNode);
+- ep->type = strtoul(tmp, NULL, 10);
+- g_free(tmp);
+- }
+- }
+- }
+- }
+-}
+-
+-static void parse_currentmedia(MsnUser *user, const char *cmedia)
+-{
+- char **cmedia_array;
+- int strings = 0;
+-
+- if (!cmedia || cmedia[0] == '\0') {
+- purple_debug_info("msn", "No currentmedia string\n");
+- return;
+- }
+-
+- purple_debug_info("msn", "Parsing currentmedia string: \"%s\"\n", cmedia);
+-
+- cmedia_array = g_strsplit(cmedia, "\\0", 0);
+-
+- /*
+- * 0: Application
+- * 1: 'Music'/'Games'/'Office'
+- * 2: '1' if enabled, '0' if not
+- * 3: Format (eg. {0} by {1})
+- * 4: Title
+- * If 'Music':
+- * 5: Artist
+- * 6: Album
+- * 7: ?
+- */
+- strings = g_strv_length(cmedia_array);
+-
+- if (strings >= 4 && !strcmp(cmedia_array[2], "1")) {
+- if (user->extinfo == NULL)
+- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+- else {
+- g_free(user->extinfo->media_album);
+- g_free(user->extinfo->media_artist);
+- g_free(user->extinfo->media_title);
+- }
+-
+- if (!strcmp(cmedia_array[1], "Music"))
+- user->extinfo->media_type = CURRENT_MEDIA_MUSIC;
+- else if (!strcmp(cmedia_array[1], "Games"))
+- user->extinfo->media_type = CURRENT_MEDIA_GAMES;
+- else if (!strcmp(cmedia_array[1], "Office"))
+- user->extinfo->media_type = CURRENT_MEDIA_OFFICE;
+- else
+- user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
+-
+- user->extinfo->media_title = g_strdup(cmedia_array[strings == 4 ? 3 : 4]);
+- user->extinfo->media_artist = strings > 5 ? g_strdup(cmedia_array[5]) : NULL;
+- user->extinfo->media_album = strings > 6 ? g_strdup(cmedia_array[6]) : NULL;
+- }
+-
+- g_strfreev(cmedia_array);
+-}
+-
+-/*
+- * Get the UBX's PSM info
+- * Post it to the User status
+- * Thanks for Chris <ukdrizzle@yahoo.co.uk>'s code
+- */
+-static void
+-ubx_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- MsnSession *session;
+- MsnUser *user;
+- char *passport;
+- int network;
+- xmlnode *payloadNode;
+- char *psm_str, *str;
+-
+- session = cmdproc->session;
+-
+- msn_parse_user(cmd->params[0], &passport, &network);
+- user = msn_userlist_find_user(session->userlist, passport);
+-
+- if (user == NULL) {
+- str = g_strndup(payload, len);
+- purple_debug_info("msn", "unknown user %s, payload is %s\n",
+- passport, str);
+- g_free(passport);
+- g_free(str);
+- return;
+- }
+-
+- g_free(passport);
+-
+- /* Free any existing media info for this user */
+- if (user->extinfo) {
+- g_free(user->extinfo->media_album);
+- g_free(user->extinfo->media_artist);
+- g_free(user->extinfo->media_title);
+- user->extinfo->media_album = NULL;
+- user->extinfo->media_artist = NULL;
+- user->extinfo->media_title = NULL;
+- user->extinfo->media_type = CURRENT_MEDIA_UNKNOWN;
+- }
+-
+- if (len != 0) {
+- payloadNode = xmlnode_from_str(payload, len);
+- if (!payloadNode) {
+- purple_debug_error("msn", "UBX XML parse Error!\n");
+-
+- msn_user_set_statusline(user, NULL);
+-
+- msn_user_update(user);
+- return;
+- }
+-
+- psm_str = msn_get_psm(payloadNode);
+- msn_user_set_statusline(user, psm_str);
+- g_free(psm_str);
+-
+- str = msn_get_currentmedia(payloadNode);
+- parse_currentmedia(user, str);
+- g_free(str);
+-
+- parse_user_endpoints(user, payloadNode);
+-
+- xmlnode_free(payloadNode);
+-
+- } else {
+- msn_user_set_statusline(user, NULL);
+- }
+-
+- msn_user_update(user);
+-}
+-
+-static void
+-ubx_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_misc("msn", "UBX received.\n");
+- cmdproc->last_cmd->payload_cb = ubx_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+-}
+-
+-static void
+-uux_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- /* Do Nothing, right now. */
+- if (payload != NULL)
+- purple_debug_info("msn", "UUX payload:\n%s\n", payload);
+-}
+-
+-static void
+-uux_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_misc("msn", "UUX received.\n");
+- cmdproc->last_cmd->payload_cb = uux_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+-}
+-
+-void
+-msn_notification_send_uux(MsnSession *session, const char *payload)
+-{
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+- size_t len = strlen(payload);
+-
+- cmdproc = session->notification->cmdproc;
+- purple_debug_misc("msn", "Sending UUX command with payload: %s\n", payload);
+- trans = msn_transaction_new(cmdproc, "UUX", "%" G_GSIZE_FORMAT, len);
+- msn_transaction_set_payload(trans, payload, len);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-void msn_notification_send_uux_endpointdata(MsnSession *session)
+-{
+- xmlnode *epDataNode;
+- xmlnode *capNode;
+- char *caps;
+- char *payload;
+- int length;
+-
+- epDataNode = xmlnode_new("EndpointData");
+-
+- capNode = xmlnode_new_child(epDataNode, "Capabilities");
+- caps = g_strdup_printf("%d:%02d", MSN_CLIENT_ID_CAPABILITIES, MSN_CLIENT_ID_EXT_CAPS);
+- xmlnode_insert_data(capNode, caps, -1);
+- g_free(caps);
+-
+- payload = xmlnode_to_str(epDataNode, &length);
+-
+- msn_notification_send_uux(session, payload);
+-
+- xmlnode_free(epDataNode);
+- g_free(payload);
+-}
+-
+-void msn_notification_send_uux_private_endpointdata(MsnSession *session)
+-{
+- xmlnode *private;
+- const char *name;
+- xmlnode *epname;
+- xmlnode *idle;
+- GHashTable *ui_info;
+- const gchar *ui_type;
+- xmlnode *client_type;
+- xmlnode *state;
+- char *payload;
+- int length;
+-
+- private = xmlnode_new("PrivateEndpointData");
+-
+- name = purple_account_get_string(session->account, "endpoint-name", NULL);
+- epname = xmlnode_new_child(private, "EpName");
+- xmlnode_insert_data(epname, name, -1);
+-
+- idle = xmlnode_new_child(private, "Idle");
+- xmlnode_insert_data(idle, "false", -1);
+-
+- /* ClientType info (from amsn guys):
+- 0: None
+- 1: Computer
+- 2: Website
+- 3: Mobile / none
+- 4: Xbox / phone /mobile
+- 9: MsnGroup
+- 32: Email member, currently Yahoo!
+- */
+- client_type = xmlnode_new_child(private, "ClientType");
+- ui_info = purple_core_get_ui_info();
+- ui_type = ui_info ? g_hash_table_lookup(ui_info, "client_type") : NULL;
+- if (ui_type) {
+- if (strcmp(ui_type, "pc") == 0)
+- xmlnode_insert_data(client_type, "1", -1);
+- else if (strcmp(ui_type, "web") == 0)
+- xmlnode_insert_data(client_type, "2", -1);
+- else if (strcmp(ui_type, "phone") == 0)
+- xmlnode_insert_data(client_type, "3", -1);
+- else if (strcmp(ui_type, "handheld") == 0)
+- xmlnode_insert_data(client_type, "3", -1);
+- else
+- xmlnode_insert_data(client_type, "1", -1);
+- }
+- else
+- xmlnode_insert_data(client_type, "1", -1);
+-
+- state = xmlnode_new_child(private, "State");
+- xmlnode_insert_data(state, msn_state_get_text(msn_state_from_account(session->account)), -1);
+-
+- payload = xmlnode_to_str(private, &length);
+-
+- msn_notification_send_uux(session, payload);
+-
+- xmlnode_free(private);
+- g_free(payload);
+-}
+-
+-static void
+-ubn_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- /* Do Nothing, right now. */
+- if (payload != NULL)
+- purple_debug_info("msn", "UBN payload:\n%s\n", payload);
+-}
+-
+-static void
+-ubn_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_misc("msn", "UBN received from %s.\n", cmd->params[0]);
+- cmdproc->last_cmd->payload_cb = ubn_cmd_post;
+- cmd->payload_len = atoi(cmd->params[2]);
+-}
+-
+-static void
+-uun_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload,
+- size_t len)
+-{
+- /* Do Nothing, right now. */
+- if (payload != NULL)
+- purple_debug_info("msn", "UUN payload:\n%s\n", payload);
+-}
+-
+-static void
+-uun_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- if (strcmp(cmd->params[1], "OK") != 0) {
+- purple_debug_misc("msn", "UUN received.\n");
+- cmdproc->last_cmd->payload_cb = uun_cmd_post;
+- cmd->payload_len = atoi(cmd->params[1]);
+- }
+- else
+- purple_debug_misc("msn", "UUN OK received.\n");
+-}
+-
+-void
+-msn_notification_send_uun(MsnSession *session, const char *user,
+- MsnUnifiedNotificationType type, const char *payload)
+-{
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+- size_t len = strlen(payload);
+-
+- cmdproc = session->notification->cmdproc;
+- purple_debug_misc("msn", "Sending UUN command %d to %s with payload: %s\n",
+- type, user, payload);
+- trans = msn_transaction_new(cmdproc, "UUN", "%s %d %" G_GSIZE_FORMAT,
+- user, type, len);
+- msn_transaction_set_payload(trans, payload, len);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-void
+-msn_notification_send_circle_auth(MsnSession *session, const char *ticket)
+-{
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+- char *encoded;
+-
+- cmdproc = session->notification->cmdproc;
+-
+- encoded = purple_base64_encode((guchar *)ticket, strlen(ticket));
+- trans = msn_transaction_new(cmdproc, "USR", "SHA A %s", encoded);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- g_free(encoded);
+-}
+-
+-/**************************************************************************
+- * Message Types
+- **************************************************************************/
+-
+-static void
+-profile_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- const char *value;
+-#ifdef MSN_PARTIAL_LISTS
+- const char *clLastChange;
+-#endif
+-
+- session = cmdproc->session;
+-
+- if (strcmp(msg->remote_user, "Hotmail"))
+- /* This isn't an official message. */
+- return;
+-
+- if ((value = msn_message_get_header_value(msg, "sid")) != NULL)
+- {
+- g_free(session->passport_info.sid);
+- session->passport_info.sid = g_strdup(value);
+- }
+-
+- if ((value = msn_message_get_header_value(msg, "MSPAuth")) != NULL)
+- {
+- g_free(session->passport_info.mspauth);
+- session->passport_info.mspauth = g_strdup(value);
+- }
+-
+- if ((value = msn_message_get_header_value(msg, "ClientIP")) != NULL)
+- {
+- g_free(session->passport_info.client_ip);
+- session->passport_info.client_ip = g_strdup(value);
+- }
+-
+- if ((value = msn_message_get_header_value(msg, "ClientPort")) != NULL)
+- {
+- session->passport_info.client_port = ntohs(atoi(value));
+- }
+-
+- if ((value = msn_message_get_header_value(msg, "LoginTime")) != NULL)
+- session->passport_info.sl = atol(value);
+-
+- if ((value = msn_message_get_header_value(msg, "EmailEnabled")) != NULL)
+- session->passport_info.email_enabled = (gboolean)atol(value);
+-
+-#ifdef MSN_PARTIAL_LISTS
+- /*starting retrieve the contact list*/
+- clLastChange = purple_account_get_string(session->account, "CLLastChange", NULL);
+- /* msn_userlist_load defeats all attempts at trying to detect blist sync issues */
+- msn_userlist_load(session);
+- msn_get_contact_list(session, MSN_PS_INITIAL, clLastChange);
+-#else
+- /* always get the full list? */
+- msn_get_contact_list(session, MSN_PS_INITIAL, NULL);
+-#endif
+-}
+-
+-static void
+-initial_email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- PurpleConnection *gc;
+- GHashTable *table;
+- const char *unread;
+-
+- session = cmdproc->session;
+- gc = session->account->gc;
+-
+- if (strcmp(msg->remote_user, "Hotmail"))
+- /* This isn't an official message. */
+- return;
+-
+- if (session->passport_info.mail_url == NULL)
+- {
+- MsnTransaction *trans;
+- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
+- msn_transaction_queue_cmd(trans, msg->cmd);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- return;
+- }
+-
+- if (!purple_account_get_check_mail(session->account))
+- return;
+-
+- table = msn_message_get_hashtable_from_body(msg);
+-
+- unread = g_hash_table_lookup(table, "Inbox-Unread");
+-
+- if (unread != NULL)
+- {
+- int count = atoi(unread);
+-
+- if (count > 0)
+- {
+- const char *passports[2] = { msn_user_get_passport(session->user) };
+- const char *urls[2] = { session->passport_info.mail_url };
+-
+- purple_notify_emails(gc, count, FALSE, NULL, NULL,
+- passports, urls, NULL, NULL);
+- }
+- }
+-
+- g_hash_table_destroy(table);
+-}
+-
+-/*offline Message notification process*/
+-static void
+-initial_mdata_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- PurpleConnection *gc;
+- GHashTable *table;
+- const char *mdata, *unread;
+-
+- session = cmdproc->session;
+- gc = session->account->gc;
+-
+- if (strcmp(msg->remote_user, "Hotmail"))
+- /* This isn't an official message. */
+- return;
+-
+- table = msn_message_get_hashtable_from_body(msg);
+-
+- mdata = g_hash_table_lookup(table, "Mail-Data");
+-
+- if (mdata != NULL)
+- msn_parse_oim_msg(session->oim, mdata);
+-
+- if (g_hash_table_lookup(table, "Inbox-URL") == NULL)
+- {
+- g_hash_table_destroy(table);
+- return;
+- }
+-
+- if (session->passport_info.mail_url == NULL)
+- {
+- MsnTransaction *trans;
+- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
+- msn_transaction_queue_cmd(trans, msg->cmd);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- g_hash_table_destroy(table);
+- return;
+- }
+-
+- if (!purple_account_get_check_mail(session->account))
+- {
+- g_hash_table_destroy(table);
+- return;
+- }
+-
+- unread = g_hash_table_lookup(table, "Inbox-Unread");
+-
+- if (unread != NULL)
+- {
+- int count = atoi(unread);
+-
+- if (count > 0)
+- {
+- const char *passports[2] = { msn_user_get_passport(session->user) };
+- const char *urls[2] = { session->passport_info.mail_url };
+-
+- purple_notify_emails(gc, count, FALSE, NULL, NULL,
+- passports, urls, NULL, NULL);
+- }
+- }
+-
+- g_hash_table_destroy(table);
+-}
+-
+-/*offline Message Notification*/
+-static void
+-delete_oim_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- purple_debug_misc("msn", "Delete OIM message.\n");
+-}
+-
+-static void
+-email_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- MsnSession *session;
+- PurpleConnection *gc;
+- GHashTable *table;
+- char *from, *subject, *tmp;
+-
+- session = cmdproc->session;
+- gc = session->account->gc;
+-
+- if (strcmp(msg->remote_user, "Hotmail"))
+- /* This isn't an official message. */
+- return;
+-
+- if (session->passport_info.mail_url == NULL)
+- {
+- MsnTransaction *trans;
+- trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
+- msn_transaction_queue_cmd(trans, msg->cmd);
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- return;
+- }
+-
+- if (!purple_account_get_check_mail(session->account))
+- return;
+-
+- table = msn_message_get_hashtable_from_body(msg);
+-
+- from = subject = NULL;
+-
+- tmp = g_hash_table_lookup(table, "From");
+- if (tmp != NULL)
+- from = purple_mime_decode_field(tmp);
+-
+- tmp = g_hash_table_lookup(table, "Subject");
+- if (tmp != NULL)
+- subject = purple_mime_decode_field(tmp);
+-
+- purple_notify_email(gc,
+- (subject != NULL ? subject : ""),
+- (from != NULL ? from : ""),
+- msn_user_get_passport(session->user),
+- session->passport_info.mail_url, NULL, NULL);
+-
+- g_free(from);
+- g_free(subject);
+-
+- g_hash_table_destroy(table);
+-}
+-
+-static void
+-system_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+- GHashTable *table;
+- const char *type_s;
+-
+- if (strcmp(msg->remote_user, "Hotmail"))
+- /* This isn't an official message. */
+- return;
+-
+- table = msn_message_get_hashtable_from_body(msg);
+-
+- if ((type_s = g_hash_table_lookup(table, "Type")) != NULL)
+- {
+- int type = atoi(type_s);
+- char buf[MSN_BUF_LEN] = "";
+- int minutes;
+-
+- switch (type)
+- {
+- case 1:
+- minutes = atoi(g_hash_table_lookup(table, "Arg1"));
+- g_snprintf(buf, sizeof(buf), dngettext(PACKAGE,
+- "The MSN server will shut down for maintenance "
+- "in %d minute. You will automatically be "
+- "signed out at that time. Please finish any "
+- "conversations in progress.\n\nAfter the "
+- "maintenance has been completed, you will be "
+- "able to successfully sign in.",
+- "The MSN server will shut down for maintenance "
+- "in %d minutes. You will automatically be "
+- "signed out at that time. Please finish any "
+- "conversations in progress.\n\nAfter the "
+- "maintenance has been completed, you will be "
+- "able to successfully sign in.", minutes),
+- minutes);
+- default:
+- break;
+- }
+-
+- if (*buf != '\0')
+- purple_notify_info(cmdproc->session->account->gc, NULL, buf, NULL);
+- }
+-
+- g_hash_table_destroy(table);
+-}
+-
+-/**************************************************************************
+- * Dispatch server list management
+- **************************************************************************/
+-typedef struct MsnAddRemoveListData {
+- MsnCmdProc *cmdproc;
+- MsnUser *user;
+- MsnListOp list_op;
+- gboolean add;
+-} MsnAddRemoveListData;
+-
+-static void
+-modify_unknown_buddy_on_list(MsnSession *session, const char *passport,
+- MsnNetwork network, gpointer data)
+-{
+- MsnAddRemoveListData *addrem = data;
+- MsnCmdProc *cmdproc;
+- xmlnode *node;
+- char *payload;
+- int payload_len;
+-
+- cmdproc = addrem->cmdproc;
+-
+- /* Update user first */
+- msn_user_set_network(addrem->user, network);
+-
+- node = xmlnode_new("ml");
+- node->child = NULL;
+-
+- msn_add_contact_xml(node, passport, addrem->list_op, network);
+-
+- payload = xmlnode_to_str(node, &payload_len);
+- xmlnode_free(node);
+-
+- if (addrem->add)
+- msn_notification_post_adl(cmdproc, payload, payload_len);
+- else
+- msn_notification_post_rml(cmdproc, payload, payload_len);
+-
+- g_free(payload);
+- g_free(addrem);
+-}
+-
+-void
+-msn_notification_add_buddy_to_list(MsnNotification *notification, MsnListId list_id,
+- MsnUser *user)
+-{
+- MsnAddRemoveListData *addrem;
+- MsnCmdProc *cmdproc;
+- MsnListOp list_op = 1 << list_id;
+- xmlnode *adl_node;
+- char *payload;
+- int payload_len;
+-
+- cmdproc = notification->servconn->cmdproc;
+-
+- adl_node = xmlnode_new("ml");
+- adl_node->child = NULL;
+-
+- msn_add_contact_xml(adl_node, user->passport, list_op, user->networkid);
+-
+- payload = xmlnode_to_str(adl_node, &payload_len);
+- xmlnode_free(adl_node);
+-
+- if (user->networkid != MSN_NETWORK_UNKNOWN) {
+- msn_notification_post_adl(cmdproc, payload, payload_len);
+-
+- } else {
+- addrem = g_new(MsnAddRemoveListData, 1);
+- addrem->cmdproc = cmdproc;
+- addrem->user = user;
+- addrem->list_op = list_op;
+- addrem->add = TRUE;
+-
+- msn_notification_send_fqy(notification->session, payload, payload_len,
+- modify_unknown_buddy_on_list, addrem);
+- }
+-
+- g_free(payload);
+-}
+-
+-void
+-msn_notification_rem_buddy_from_list(MsnNotification *notification, MsnListId list_id,
+- MsnUser *user)
+-{
+- MsnAddRemoveListData *addrem;
+- MsnCmdProc *cmdproc;
+- MsnListOp list_op = 1 << list_id;
+- xmlnode *rml_node;
+- char *payload;
+- int payload_len;
+-
+- cmdproc = notification->servconn->cmdproc;
+-
+- rml_node = xmlnode_new("ml");
+- rml_node->child = NULL;
+-
+- msn_add_contact_xml(rml_node, user->passport, list_op, user->networkid);
+-
+- payload = xmlnode_to_str(rml_node, &payload_len);
+- xmlnode_free(rml_node);
+-
+- if (user->networkid != MSN_NETWORK_UNKNOWN) {
+- msn_notification_post_rml(cmdproc, payload, payload_len);
+-
+- } else {
+- addrem = g_new(MsnAddRemoveListData, 1);
+- addrem->cmdproc = cmdproc;
+- addrem->user = user;
+- addrem->list_op = list_op;
+- addrem->add = FALSE;
+-
+- msn_notification_send_fqy(notification->session, payload, payload_len,
+- modify_unknown_buddy_on_list, addrem);
+- }
+-
+- g_free(payload);
+-}
+-
+-/**************************************************************************
+- * Init
+- **************************************************************************/
+-void
+-msn_notification_init(void)
+-{
+- cbs_table = msn_table_new();
+-
+- /* Synchronous */
+- msn_table_add_cmd(cbs_table, "CHG", "CHG", NULL);
+- msn_table_add_cmd(cbs_table, "CHG", "ILN", iln_cmd);
+- msn_table_add_cmd(cbs_table, "ADL", "ILN", iln_cmd);
+- msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
+- msn_table_add_cmd(cbs_table, "USR", "XFR", xfr_cmd);
+- msn_table_add_cmd(cbs_table, "USR", "GCF", gcf_cmd);
+- msn_table_add_cmd(cbs_table, "CVR", "CVR", cvr_cmd);
+- msn_table_add_cmd(cbs_table, "VER", "VER", ver_cmd);
+- msn_table_add_cmd(cbs_table, "PRP", "PRP", prp_cmd);
+- msn_table_add_cmd(cbs_table, "BLP", "BLP", blp_cmd);
+- msn_table_add_cmd(cbs_table, "XFR", "XFR", xfr_cmd);
+-
+- /* Asynchronous */
+- msn_table_add_cmd(cbs_table, NULL, "IPG", ipg_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "GCF", gcf_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "SBS", sbs_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "NOT", not_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "CHL", chl_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "RML", rml_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "ADL", adl_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "FQY", fqy_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "QRY", NULL);
+- msn_table_add_cmd(cbs_table, NULL, "QNG", qng_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "FLN", fln_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "NLN", nln_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "ILN", iln_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "RNG", rng_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "UBX", ubx_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "UUX", uux_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "UBN", ubn_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "UUN", uun_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "URL", url_cmd);
+-
+- msn_table_add_cmd(cbs_table, "fallback", "XFR", xfr_cmd);
+-
+- msn_table_add_error(cbs_table, "ADL", adl_error);
+- msn_table_add_error(cbs_table, "RML", rml_error);
+- msn_table_add_error(cbs_table, "FQY", fqy_error);
+- msn_table_add_error(cbs_table, "USR", usr_error);
+-
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsprofile",
+- profile_msg);
+- /*initial OIM notification*/
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsinitialmdatanotification",
+- initial_mdata_msg);
+- /*OIM notification when user online*/
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsoimnotification",
+- initial_mdata_msg);
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsinitialemailnotification",
+- initial_email_msg);
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsemailnotification",
+- email_msg);
+- /*delete an offline Message notification*/
+- msn_table_add_msg_type(cbs_table,
+- "text/x-msmsgsactivemailnotification",
+- delete_oim_msg);
+- msn_table_add_msg_type(cbs_table,
+- "application/x-msmsgssystemmessage",
+- system_msg);
+- /* generic message handlers */
+- msn_table_add_msg_type(cbs_table, "text/plain",
+- msn_plain_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
+- msn_control_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
+- msn_datacast_msg);
+-}
+-
+-void
+-msn_notification_end(void)
+-{
+- msn_table_destroy(cbs_table);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/notification.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.h
+--- pidgin-2.10.7/libpurple/protocols/msn/notification.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/notification.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,124 +0,0 @@
+-/**
+- * @file notification.h Notification server functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_NOTIFICATION_H
+-#define MSN_NOTIFICATION_H
+-
+-typedef struct _MsnNotification MsnNotification;
+-
+-/* MSN protocol challenge info */
+-
+-/* MSNP18 challenge: WLM Version 2009 (Build 14.0.8089.726) */
+-#define MSNP18_WLM_PRODUCT_KEY "C1BX{V4W}Q3*10SM"
+-#define MSNP18_WLM_PRODUCT_ID "PROD0120PW!CCV9@"
+-
+-/* MSNP15 challenge: WLM 8.5.1288.816 */
+-#define MSNP15_WLM_PRODUCT_KEY "ILTXC!4IXB5FB*PX"
+-#define MSNP15_WLM_PRODUCT_ID "PROD0119GSJUC$18"
+-
+-/* MSNP13 challenge */
+-#define MSNP13_WLM_PRODUCT_KEY "O4BG@C7BWLYQX?5G"
+-#define MSNP13_WLM_PRODUCT_ID "PROD01065C%ZFN6F"
+-
+-#define MSNP10_PRODUCT_KEY "VT6PX?UQTM4WM%YR"
+-#define MSNP10_PRODUCT_ID "PROD0038W!61ZTF9"
+-
+-#include "cmdproc.h"
+-#include "msg.h"
+-#include "session.h"
+-#include "servconn.h"
+-#include "state.h"
+-#include "user.h"
+-#include "userlist.h"
+-
+-struct _MsnNotification
+-{
+- MsnSession *session;
+-
+- /**
+- * This is a convenience pointer that always points to
+- * servconn->cmdproc
+- */
+- MsnCmdProc *cmdproc;
+- MsnServConn *servconn;
+-
+- gboolean in_use;
+-};
+-
+-typedef void (*MsnFqyCb)(MsnSession *session, const char *passport, MsnNetwork network, gpointer data);
+-
+-/* Type used for msn_notification_send_uun */
+-typedef enum {
+- MSN_UNIFIED_NOTIFICATION_SHARED_FOLDERS = 1,
+- MSN_UNIFIED_NOTIFICATION_UNKNOWN1 = 2,
+- MSN_UNIFIED_NOTIFICATION_P2P = 3,
+- MSN_UNIFIED_NOTIFICATION_MPOP = 4
+-
+-} MsnUnifiedNotificationType;
+-
+-void msn_notification_end(void);
+-void msn_notification_init(void);
+-
+-void msn_notification_add_buddy_to_list(MsnNotification *notification,
+- MsnListId list_id, MsnUser *user);
+-void msn_notification_rem_buddy_from_list(MsnNotification *notification,
+- MsnListId list_id, MsnUser *user);
+-
+-void msn_notification_send_fqy(MsnSession *session,
+- const char *payload, int payload_len,
+- MsnFqyCb cb, gpointer cb_data);
+-
+-MsnNotification *msn_notification_new(MsnSession *session);
+-void msn_notification_destroy(MsnNotification *notification);
+-gboolean msn_notification_connect(MsnNotification *notification,
+- const char *host, int port);
+-void msn_notification_disconnect(MsnNotification *notification);
+-void msn_notification_dump_contact(MsnSession *session);
+-
+-void msn_notification_send_uum(MsnSession *session, MsnMessage *msg);
+-
+-void msn_notification_send_uux(MsnSession *session, const char *payload);
+-
+-void msn_notification_send_uux_endpointdata(MsnSession *session);
+-
+-void msn_notification_send_uux_private_endpointdata(MsnSession *session);
+-
+-void msn_notification_send_uun(MsnSession *session,
+- const char *user,
+- MsnUnifiedNotificationType type,
+- const char *payload);
+-
+-void msn_notification_send_circle_auth(MsnSession *session, const char *ticket);
+-
+-/**
+- * Closes a notification.
+- *
+- * It's first closed, and then disconnected.
+- *
+- * @param notification The notification object to close.
+- */
+-void msn_notification_close(MsnNotification *notification);
+-
+-void msn_got_login_params(MsnSession *session, const char *ticket, const char *response);
+-
+-#endif /* MSN_NOTIFICATION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/object.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.c
+--- pidgin-2.10.7/libpurple/protocols/msn/object.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,459 +0,0 @@
+-/**
+- * @file object.c MSNObject API
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "msn.h"
+-#include "object.h"
+-#include "debug.h"
+-/* Sha1 stuff */
+-#include "cipher.h"
+-/* Base64 stuff */
+-#include "util.h"
+-
+-#define GET_STRING_TAG(field, id) \
+- if ((tag = strstr(str, id "=\"")) != NULL) \
+- { \
+- tag += strlen(id "=\""); \
+- c = strchr(tag, '"'); \
+- if (c != NULL) \
+- { \
+- if (obj->field != NULL) \
+- g_free(obj->field); \
+- obj->field = g_strndup(tag, c - tag); \
+- } \
+- }
+-
+-#define GET_INT_TAG(field, id) \
+- if ((tag = strstr(str, id "=\"")) != NULL) \
+- { \
+- char buf[16]; \
+- size_t offset; \
+- tag += strlen(id "=\""); \
+- c = strchr(tag, '"'); \
+- if (c != NULL) \
+- { \
+- memset(buf, 0, sizeof(buf)); \
+- offset = c - tag; \
+- if (offset >= sizeof(buf)) \
+- offset = sizeof(buf) - 1; \
+- strncpy(buf, tag, offset); \
+- obj->field = atoi(buf); \
+- } \
+- }
+-
+-static GList *local_objs;
+-
+-MsnObject *
+-msn_object_new(void)
+-{
+- MsnObject *obj;
+-
+- obj = g_new0(MsnObject, 1);
+-
+- msn_object_set_type(obj, MSN_OBJECT_UNKNOWN);
+- msn_object_set_friendly(obj, "AAA=");
+-
+- return obj;
+-}
+-
+-MsnObject *
+-msn_object_new_from_string(const char *str)
+-{
+- MsnObject *obj;
+- char *tag, *c;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+-
+- if (strncmp(str, "<msnobj ", 8))
+- return NULL;
+-
+- obj = msn_object_new();
+-
+- GET_STRING_TAG(creator, "Creator");
+- GET_INT_TAG(size, "Size");
+- GET_INT_TAG(type, "Type");
+- GET_STRING_TAG(location, "Location");
+- GET_STRING_TAG(friendly, "Friendly");
+- GET_STRING_TAG(sha1d, "SHA1D");
+- GET_STRING_TAG(sha1c, "SHA1C");
+- GET_STRING_TAG(url, "Url");
+- GET_STRING_TAG(url1, "Url1");
+-
+- /* If we are missing any of the required elements then discard the object */
+- if (obj->creator == NULL || obj->size == 0 || obj->type == 0
+- || obj->sha1d == NULL) {
+- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
+- msn_object_destroy(obj);
+- return NULL;
+- }
+-
+- if (obj->location == NULL || obj->friendly == NULL) {
+- /* Location/friendly are required for non-buddyicon objects */
+- if (obj->type != MSN_OBJECT_USERTILE) {
+- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
+- msn_object_destroy(obj);
+- return NULL;
+- /* Buddy icon object can contain Url/Url1 instead */
+- } else if (obj->url == NULL || obj->url1 == NULL) {
+- purple_debug_error("msn", "Discarding invalid msnobj: '%s'\n", str);
+- msn_object_destroy(obj);
+- return NULL;
+- }
+- }
+-
+- return obj;
+-}
+-
+-MsnObject*
+-msn_object_new_from_image(PurpleStoredImage *img, const char *location,
+- const char *creator, MsnObjectType type)
+-{
+- MsnObject *msnobj;
+-
+- PurpleCipherContext *ctx;
+- char *buf;
+- gconstpointer data;
+- size_t size;
+- char *base64;
+- unsigned char digest[20];
+-
+- msnobj = NULL;
+-
+- if (img == NULL)
+- return msnobj;
+-
+- size = purple_imgstore_get_size(img);
+- data = purple_imgstore_get_data(img);
+-
+- /* New object */
+- msnobj = msn_object_new();
+- msn_object_set_local(msnobj);
+- msn_object_set_type(msnobj, type);
+- msn_object_set_location(msnobj, location);
+- msn_object_set_creator(msnobj, creator);
+-
+- msn_object_set_image(msnobj, img);
+-
+- /* Compute the SHA1D field. */
+- memset(digest, 0, sizeof(digest));
+-
+- ctx = purple_cipher_context_new_by_name("sha1", NULL);
+- purple_cipher_context_append(ctx, data, size);
+- purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
+-
+- base64 = purple_base64_encode(digest, sizeof(digest));
+- msn_object_set_sha1d(msnobj, base64);
+- g_free(base64);
+-
+- msn_object_set_size(msnobj, size);
+-
+- /* Compute the SHA1C field. */
+- buf = g_strdup_printf(
+- "Creator%sSize%dType%dLocation%sFriendly%sSHA1D%s",
+- msn_object_get_creator(msnobj),
+- msn_object_get_size(msnobj),
+- msn_object_get_type(msnobj),
+- msn_object_get_location(msnobj),
+- msn_object_get_friendly(msnobj),
+- msn_object_get_sha1d(msnobj));
+-
+- memset(digest, 0, sizeof(digest));
+-
+- purple_cipher_context_reset(ctx, NULL);
+- purple_cipher_context_append(ctx, (const guchar *)buf, strlen(buf));
+- purple_cipher_context_digest(ctx, sizeof(digest), digest, NULL);
+- purple_cipher_context_destroy(ctx);
+- g_free(buf);
+-
+- base64 = purple_base64_encode(digest, sizeof(digest));
+- msn_object_set_sha1c(msnobj, base64);
+- g_free(base64);
+-
+- return msnobj;
+-}
+-
+-void
+-msn_object_destroy(MsnObject *obj)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->creator);
+- g_free(obj->location);
+- g_free(obj->friendly);
+- g_free(obj->sha1d);
+- g_free(obj->sha1c);
+- g_free(obj->url);
+- g_free(obj->url1);
+-
+- purple_imgstore_unref(obj->img);
+-
+- if (obj->local)
+- local_objs = g_list_remove(local_objs, obj);
+-
+- g_free(obj);
+-}
+-
+-char *
+-msn_object_to_string(const MsnObject *obj)
+-{
+- char *str;
+- const char *sha1c;
+-
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- sha1c = msn_object_get_sha1c(obj);
+-
+- str = g_strdup_printf("<msnobj Creator=\"%s\" Size=\"%d\" Type=\"%d\" "
+- "Location=\"%s\" Friendly=\"%s\" SHA1D=\"%s\""
+- "%s%s%s/>",
+- msn_object_get_creator(obj),
+- msn_object_get_size(obj),
+- msn_object_get_type(obj),
+- msn_object_get_location(obj),
+- msn_object_get_friendly(obj),
+- msn_object_get_sha1d(obj),
+- sha1c ? " SHA1C=\"" : "",
+- sha1c ? sha1c : "",
+- sha1c ? "\"" : "");
+-
+- return str;
+-}
+-
+-void
+-msn_object_set_creator(MsnObject *obj, const char *creator)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->creator);
+- obj->creator = g_strdup(creator);
+-}
+-
+-void
+-msn_object_set_size(MsnObject *obj, int size)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- obj->size = size;
+-}
+-
+-void
+-msn_object_set_type(MsnObject *obj, MsnObjectType type)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- obj->type = type;
+-}
+-
+-void
+-msn_object_set_location(MsnObject *obj, const char *location)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->location);
+- obj->location = g_strdup(location);
+-}
+-
+-void
+-msn_object_set_friendly(MsnObject *obj, const char *friendly)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->friendly);
+- obj->friendly = g_strdup(friendly);
+-}
+-
+-void
+-msn_object_set_sha1d(MsnObject *obj, const char *sha1d)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->sha1d);
+- obj->sha1d = g_strdup(sha1d);
+-}
+-
+-void
+-msn_object_set_sha1c(MsnObject *obj, const char *sha1c)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->sha1c);
+- obj->sha1c = g_strdup(sha1c);
+-}
+-
+-void
+-msn_object_set_url(MsnObject *obj, const char *url)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->url);
+- obj->url = g_strdup(url);
+-}
+-
+-void
+-msn_object_set_url1(MsnObject *obj, const char *url)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- g_free(obj->url1);
+- obj->url1 = g_strdup(url);
+-}
+-
+-const char *
+-msn_object_get_creator(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->creator;
+-}
+-
+-int
+-msn_object_get_size(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, 0);
+-
+- return obj->size;
+-}
+-
+-MsnObjectType
+-msn_object_get_type(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, MSN_OBJECT_UNKNOWN);
+-
+- return obj->type;
+-}
+-
+-const char *
+-msn_object_get_location(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->location;
+-}
+-
+-const char *
+-msn_object_get_friendly(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->friendly;
+-}
+-
+-const char *
+-msn_object_get_sha1d(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->sha1d;
+-}
+-
+-const char *
+-msn_object_get_sha1c(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->sha1c;
+-}
+-
+-const char *
+-msn_object_get_sha1(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- if(obj->sha1c != NULL) {
+- return obj->sha1c;
+- } else {
+- return obj->sha1d;
+- }
+-}
+-
+-const char *
+-msn_object_get_url(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->url;
+-}
+-
+-const char *
+-msn_object_get_url1(const MsnObject *obj)
+-{
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- return obj->url1;
+-}
+-
+-MsnObject *
+-msn_object_find_local(const char *sha1)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(sha1 != NULL, NULL);
+-
+- for (l = local_objs; l != NULL; l = l->next)
+- {
+- MsnObject *local_obj = l->data;
+-
+- if (!strcmp(msn_object_get_sha1(local_obj), sha1))
+- return local_obj;
+- }
+-
+- return NULL;
+-
+-}
+-
+-void
+-msn_object_set_local(MsnObject *obj)
+-{
+- g_return_if_fail(obj != NULL);
+-
+- obj->local = TRUE;
+-
+- local_objs = g_list_append(local_objs, obj);
+-}
+-
+-void
+-msn_object_set_image(MsnObject *obj, PurpleStoredImage *img)
+-{
+- g_return_if_fail(obj != NULL);
+- g_return_if_fail(img != NULL);
+-
+- /* obj->local = TRUE; */
+-
+- purple_imgstore_unref(obj->img);
+- obj->img = purple_imgstore_ref(img);
+-}
+-
+-PurpleStoredImage *
+-msn_object_get_image(const MsnObject *obj)
+-{
+- MsnObject *local_obj;
+-
+- g_return_val_if_fail(obj != NULL, NULL);
+-
+- local_obj = msn_object_find_local(msn_object_get_sha1(obj));
+-
+- if (local_obj != NULL)
+- return local_obj->img;
+-
+- return NULL;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/object.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.h
+--- pidgin-2.10.7/libpurple/protocols/msn/object.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/object.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,276 +0,0 @@
+-/**
+- * @file object.h MSNObject API
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_OBJECT_H
+-#define MSN_OBJECT_H
+-
+-typedef enum
+-{
+- MSN_OBJECT_UNKNOWN = -1, /**< Unknown object */
+- MSN_OBJECT_RESERVED1 = 1, /**< Reserved */
+- MSN_OBJECT_EMOTICON = 2, /**< Custom Emoticon */
+- MSN_OBJECT_USERTILE = 3, /**< UserTile (buddy icon) */
+- MSN_OBJECT_RESERVED2 = 4, /**< Reserved */
+- MSN_OBJECT_BACKGROUND = 5 /**< Background */
+-} MsnObjectType;
+-
+-#include "internal.h"
+-
+-#include "imgstore.h"
+-
+-typedef struct
+-{
+- gboolean local;
+-
+- char *creator;
+- int size;
+- MsnObjectType type;
+- PurpleStoredImage *img;
+- char *location;
+- char *friendly;
+- char *sha1d;
+- char *sha1c;
+- char *url;
+- char *url1;
+-} MsnObject;
+-
+-/**
+- * Creates a MsnObject structure.
+- *
+- * @return A new MsnObject structure.
+- */
+-MsnObject *msn_object_new(void);
+-
+-/**
+- * Creates a MsnObject structure from a string.
+- *
+- * @param str The string.
+- *
+- * @return The new MsnObject structure.
+- */
+-MsnObject *msn_object_new_from_string(const char *str);
+-
+-/**
+- * Creates a MsnObject structure from a stored image
+- *
+- * @param img The image associated to object
+- * @param location The object location as stored in MsnObject
+- * @param creator The creator of the object
+- * @param type The type of the object
+- *
+- * @return A new MsnObject structure
+- */
+-MsnObject *msn_object_new_from_image(PurpleStoredImage *img,
+- const char *location, const char *creator, MsnObjectType type);
+-
+-/**
+- * Destroys an MsnObject structure.
+- *
+- * @param obj The object structure.
+- */
+-void msn_object_destroy(MsnObject *obj);
+-
+-/**
+- * Outputs a string representation of an MsnObject.
+- *
+- * @param obj The object.
+- *
+- * @return The string representation. This must be freed.
+- */
+-char *msn_object_to_string(const MsnObject *obj);
+-
+-/**
+- * Sets the creator field in a MsnObject.
+- *
+- * @param creator The creator value.
+- */
+-void msn_object_set_creator(MsnObject *obj, const char *creator);
+-
+-/**
+- * Sets the size field in a MsnObject.
+- *
+- * @param size The size value.
+- */
+-void msn_object_set_size(MsnObject *obj, int size);
+-
+-/**
+- * Sets the type field in a MsnObject.
+- *
+- * @param type The type value.
+- */
+-void msn_object_set_type(MsnObject *obj, MsnObjectType type);
+-
+-/**
+- * Sets the location field in a MsnObject.
+- *
+- * @param location The location value.
+- */
+-void msn_object_set_location(MsnObject *obj, const char *location);
+-
+-/**
+- * Sets the friendly name field in a MsnObject.
+- *
+- * @param friendly The friendly name value.
+- */
+-void msn_object_set_friendly(MsnObject *obj, const char *friendly);
+-
+-/**
+- * Sets the SHA1D field in a MsnObject.
+- *
+- * @param sha1d The sha1d value.
+- */
+-void msn_object_set_sha1d(MsnObject *obj, const char *sha1d);
+-
+-/**
+- * Sets the SHA1C field in a MsnObject.
+- *
+- * @param sha1c The sha1c value.
+- */
+-void msn_object_set_sha1c(MsnObject *obj, const char *sha1c);
+-
+-/**
+- * Associates an image with a MsnObject.
+- *
+- * @param obj The object.
+- * @param img The image to associate.
+- */
+-void msn_object_set_image(MsnObject *obj, PurpleStoredImage *img);
+-
+-/**
+- * Sets the url field in a MsnObject.
+- *
+- * @param url The url value.
+- */
+-void msn_object_set_url(MsnObject *obj, const char *url);
+-
+-/**
+- * Sets the url1 field in a MsnObject.
+- *
+- * @param url1 The url1 value.
+- */
+-void msn_object_set_url1(MsnObject *obj, const char *url);
+-
+-/**
+- * Returns a MsnObject's creator value.
+- *
+- * @param obj The object.
+- *
+- * @return The creator value.
+- */
+-const char *msn_object_get_creator(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's size value.
+- *
+- * @param obj The object.
+- *
+- * @return The size value.
+- */
+-int msn_object_get_size(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's type.
+- *
+- * @param obj The object.
+- *
+- * @return The object type.
+- */
+-MsnObjectType msn_object_get_type(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's location value.
+- *
+- * @param obj The object.
+- *
+- * @return The location value.
+- */
+-const char *msn_object_get_location(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's friendly name value.
+- *
+- * @param obj The object.
+- *
+- * @return The friendly name value.
+- */
+-const char *msn_object_get_friendly(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's SHA1D value.
+- *
+- * @param obj The object.
+- *
+- * @return The SHA1D value.
+- */
+-const char *msn_object_get_sha1d(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's SHA1C value.
+- *
+- * @param obj The object.
+- *
+- * @return The SHA1C value.
+- */
+-const char *msn_object_get_sha1c(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's SHA1C value if it exists, otherwise SHA1D.
+- *
+- * @param obj The object.
+- *
+- * @return The SHA1C value.
+- */
+-const char *msn_object_get_sha1(const MsnObject *obj);
+-
+-/**
+- * Returns the image associated with the MsnObject.
+- *
+- * @param obj The object.
+- *
+- * @return The associated image.
+- */
+-PurpleStoredImage *msn_object_get_image(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's url value.
+- *
+- * @param obj The object.
+- *
+- * @return The url value.
+- */
+-const char *msn_object_get_url(const MsnObject *obj);
+-
+-/**
+- * Returns a MsnObject's url1 value.
+- *
+- * @param obj The object.
+- *
+- * @return The url1 value.
+- */
+-const char *msn_object_get_url1(const MsnObject *obj);
+-
+-MsnObject * msn_object_find_local(const char *sha1);
+-
+-void msn_object_set_local(MsnObject *obj);
+-
+-#endif /* MSN_OBJECT_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/oim.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.c
+--- pidgin-2.10.7/libpurple/protocols/msn/oim.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,885 +0,0 @@
+-/**
+- * @file oim.c
+- * get and send MSN offline Instant Message via SOAP request
+- * Author
+- * MaYuan<mayuan2006@gmail.com>
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "soap.h"
+-#include "oim.h"
+-#include "msnutils.h"
+-
+-typedef struct _MsnOimSendReq {
+- char *from_member;
+- char *friendname;
+- char *to_member;
+- char *oim_msg;
+-} MsnOimSendReq;
+-
+-typedef struct {
+- MsnOim *oim;
+- char *msg_id;
+-} MsnOimRecvData;
+-
+-/*Local Function Prototype*/
+-static void msn_parse_oim_xml(MsnOim *oim, xmlnode *node);
+-static void msn_oim_free_send_req(MsnOimSendReq *req);
+-static void msn_oim_recv_data_free(MsnOimRecvData *data);
+-static void msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data);
+-
+-/*new a OIM object*/
+-MsnOim *
+-msn_oim_new(MsnSession *session)
+-{
+- MsnOim *oim;
+-
+- oim = g_new0(MsnOim, 1);
+- oim->session = session;
+- oim->oim_list = NULL;
+- oim->run_id = rand_guid();
+- oim->challenge = NULL;
+- oim->send_queue = g_queue_new();
+- oim->send_seq = 1;
+- return oim;
+-}
+-
+-/*destroy the oim object*/
+-void
+-msn_oim_destroy(MsnOim *oim)
+-{
+- MsnOimSendReq *request;
+-
+- purple_debug_info("msn", "destroy the OIM %p\n", oim);
+- g_free(oim->run_id);
+- g_free(oim->challenge);
+-
+- while ((request = g_queue_pop_head(oim->send_queue)) != NULL)
+- msn_oim_free_send_req(request);
+- g_queue_free(oim->send_queue);
+-
+- while (oim->oim_list != NULL)
+- msn_oim_recv_data_free((MsnOimRecvData *)oim->oim_list->data);
+-
+- g_free(oim);
+-}
+-
+-static MsnOimSendReq *
+-msn_oim_new_send_req(const char *from_member, const char*friendname,
+- const char* to_member, const char *msg)
+-{
+- MsnOimSendReq *request;
+-
+- request = g_new0(MsnOimSendReq, 1);
+- request->from_member = g_strdup(from_member);
+- request->friendname = g_strdup(friendname);
+- request->to_member = g_strdup(to_member);
+- request->oim_msg = g_strdup(msg);
+- return request;
+-}
+-
+-static void
+-msn_oim_free_send_req(MsnOimSendReq *req)
+-{
+- g_return_if_fail(req != NULL);
+-
+- g_free(req->from_member);
+- g_free(req->friendname);
+- g_free(req->to_member);
+- g_free(req->oim_msg);
+-
+- g_free(req);
+-}
+-
+-static MsnOimRecvData *
+-msn_oim_recv_data_new(MsnOim *oim, char *msg_id)
+-{
+- MsnOimRecvData *data;
+-
+- data = g_new0(MsnOimRecvData, 1);
+- data->oim = oim;
+- data->msg_id = msg_id;
+-
+- oim->oim_list = g_list_append(oim->oim_list, data);
+-
+- return data;
+-}
+-
+-/* Probably only good for g_list_find_custom */
+-static gint
+-msn_recv_data_equal(MsnOimRecvData *a, const char *msg_id)
+-{
+- return strcmp(a->msg_id, msg_id);
+-}
+-
+-static void
+-msn_oim_recv_data_free(MsnOimRecvData *data)
+-{
+- data->oim->oim_list = g_list_remove(data->oim->oim_list, data);
+- g_free(data->msg_id);
+-
+- g_free(data);
+-}
+-
+-/****************************************
+- * Manage OIM Tokens
+- ****************************************/
+-typedef struct _MsnOimRequestData {
+- MsnOim *oim;
+- gboolean send;
+- const char *action;
+- const char *host;
+- const char *url;
+- xmlnode *body;
+- MsnSoapCallback cb;
+- gpointer cb_data;
+-} MsnOimRequestData;
+-
+-static gboolean msn_oim_request_helper(MsnOimRequestData *data);
+-
+-static void
+-msn_oim_request_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+- gpointer req_data)
+-{
+- MsnOimRequestData *data = (MsnOimRequestData *)req_data;
+- xmlnode *fault = NULL;
+- xmlnode *faultcode = NULL;
+-
+- if (response != NULL)
+- fault = xmlnode_get_child(response->xml, "Body/Fault");
+-
+- if (fault && (faultcode = xmlnode_get_child(fault, "faultcode"))) {
+- gchar *faultcode_str = xmlnode_get_data(faultcode);
+- gboolean need_token_update = FALSE;
+-
+- if (faultcode_str) {
+- if (g_str_equal(faultcode_str, "q0:BadContextToken") ||
+- g_str_equal(faultcode_str, "AuthenticationFailed") ||
+- g_str_equal(faultcode_str, "s:AuthenticationFailed"))
+- need_token_update = TRUE;
+- else if (g_str_equal(faultcode_str, "q0:AuthenticationFailed") &&
+- xmlnode_get_child(fault, "detail/RequiredAuthPolicy") != NULL)
+- need_token_update = TRUE;
+- }
+-
+- if (need_token_update) {
+- purple_debug_warning("msn", "OIM Request Error, Updating token now.\n");
+- msn_nexus_update_token(data->oim->session->nexus,
+- data->send ? MSN_AUTH_LIVE_SECURE : MSN_AUTH_MESSENGER_WEB,
+- (GSourceFunc)msn_oim_request_helper, data);
+- g_free(faultcode_str);
+- return;
+-
+- }
+-
+- g_free(faultcode_str);
+- }
+-
+- if (data->cb)
+- data->cb(request, response, data->cb_data);
+- xmlnode_free(data->body);
+- g_free(data);
+-}
+-
+-static gboolean
+-msn_oim_request_helper(MsnOimRequestData *data)
+-{
+- MsnSession *session = data->oim->session;
+-
+- if (data->send) {
+- /* The Sending of OIM's uses a different token for some reason. */
+- xmlnode *ticket;
+- ticket = xmlnode_get_child(data->body, "Header/Ticket");
+- xmlnode_set_attrib(ticket, "passport",
+- msn_nexus_get_token_str(session->nexus, MSN_AUTH_LIVE_SECURE));
+- }
+- else
+- {
+- xmlnode *passport;
+- xmlnode *xml_t;
+- xmlnode *xml_p;
+- GHashTable *token;
+- const char *msn_t;
+- const char *msn_p;
+-
+- token = msn_nexus_get_token(session->nexus, MSN_AUTH_MESSENGER_WEB);
+- g_return_val_if_fail(token != NULL, FALSE);
+-
+- msn_t = g_hash_table_lookup(token, "t");
+- msn_p = g_hash_table_lookup(token, "p");
+-
+- g_return_val_if_fail(msn_t != NULL, FALSE);
+- g_return_val_if_fail(msn_p != NULL, FALSE);
+-
+- passport = xmlnode_get_child(data->body, "Header/PassportCookie");
+- xml_t = xmlnode_get_child(passport, "t");
+- xml_p = xmlnode_get_child(passport, "p");
+-
+- /* frees old token text, or the 'EMPTY' text if first time */
+- xmlnode_free(xml_t->child);
+- xmlnode_free(xml_p->child);
+-
+- xmlnode_insert_data(xml_t, msn_t, -1);
+- xmlnode_insert_data(xml_p, msn_p, -1);
+- }
+-
+- msn_soap_message_send(session,
+- msn_soap_message_new(data->action, xmlnode_copy(data->body)),
+- data->host, data->url, FALSE,
+- msn_oim_request_cb, data);
+-
+- return FALSE;
+-}
+-
+-
+-static void
+-msn_oim_make_request(MsnOim *oim, gboolean send, const char *action,
+- const char *host, const char *url, xmlnode *body, MsnSoapCallback cb,
+- gpointer cb_data)
+-{
+- MsnOimRequestData *data = g_new0(MsnOimRequestData, 1);
+- data->oim = oim;
+- data->send = send;
+- data->action = action;
+- data->host = host;
+- data->url = url;
+- data->body = body;
+- data->cb = cb;
+- data->cb_data = cb_data;
+-
+- msn_oim_request_helper(data);
+-}
+-
+-/****************************************
+- * OIM GetMetadata request
+- * **************************************/
+-static void
+-msn_oim_get_metadata_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+- gpointer data)
+-{
+- MsnOim *oim = data;
+-
+- if (response) {
+- msn_parse_oim_xml(oim,
+- xmlnode_get_child(response->xml, "Body/GetMetadataResponse/MD"));
+- }
+-}
+-
+-/* Post to get the OIM Metadata */
+-static void
+-msn_oim_get_metadata(MsnOim *oim)
+-{
+- msn_oim_make_request(oim, FALSE, MSN_OIM_GET_METADATA_ACTION,
+- MSN_OIM_RETRIEVE_HOST, MSN_OIM_RETRIEVE_URL,
+- xmlnode_from_str(MSN_OIM_GET_METADATA_TEMPLATE, -1),
+- msn_oim_get_metadata_cb, oim);
+-}
+-
+-/****************************************
+- * OIM send SOAP request
+- * **************************************/
+-/*encode the message to OIM Message Format*/
+-static gchar *
+-msn_oim_msg_to_str(MsnOim *oim, const char *body)
+-{
+- GString *oim_body;
+- char *oim_base64;
+- char *c;
+- int len;
+- size_t base64_len;
+-
+- purple_debug_info("msn", "Encoding OIM Message...\n");
+- len = strlen(body);
+- c = oim_base64 = purple_base64_encode((const guchar *)body, len);
+- base64_len = strlen(oim_base64);
+- purple_debug_info("msn", "Encoded base64 body:{%s}\n", oim_base64);
+-
+- oim_body = g_string_new(NULL);
+- g_string_printf(oim_body, MSN_OIM_MSG_TEMPLATE,
+- oim->run_id, oim->send_seq);
+-
+-#define OIM_LINE_LEN 76
+- while (base64_len > OIM_LINE_LEN) {
+- g_string_append_len(oim_body, c, OIM_LINE_LEN);
+- g_string_append_c(oim_body, '\n');
+- c += OIM_LINE_LEN;
+- base64_len -= OIM_LINE_LEN;
+- }
+-#undef OIM_LINE_LEN
+-
+- g_string_append(oim_body, c);
+-
+- g_free(oim_base64);
+-
+- return g_string_free(oim_body, FALSE);
+-}
+-
+-/*
+- * Process the send return SOAP string
+- * If got SOAP Fault,get the lock key,and resend it.
+- */
+-static void
+-msn_oim_send_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+- gpointer data)
+-{
+- MsnOim *oim = data;
+- MsnOimSendReq *msg = g_queue_pop_head(oim->send_queue);
+-
+- g_return_if_fail(msg != NULL);
+-
+- if (response == NULL) {
+- purple_debug_info("msn", "cannot send OIM: %s\n", msg->oim_msg);
+- } else {
+- xmlnode *faultNode = xmlnode_get_child(response->xml, "Body/Fault");
+-
+- if (faultNode == NULL) {
+- /*Send OK! return*/
+- purple_debug_info("msn", "sent OIM: %s\n", msg->oim_msg);
+- } else {
+- xmlnode *faultcode = xmlnode_get_child(faultNode, "faultcode");
+-
+- if (faultcode) {
+- char *faultcode_str = xmlnode_get_data(faultcode);
+-
+- if (g_str_equal(faultcode_str, "q0:AuthenticationFailed")) {
+- xmlnode *challengeNode = xmlnode_get_child(faultNode,
+- "detail/LockKeyChallenge");
+-
+- if (challengeNode == NULL) {
+- if (oim->challenge) {
+- g_free(oim->challenge);
+- oim->challenge = NULL;
+-
+- purple_debug_info("msn", "Resending OIM: %s\n",
+- msg->oim_msg);
+- g_queue_push_head(oim->send_queue, msg);
+- msn_oim_send_msg(oim);
+- msg = NULL;
+- } else {
+- purple_debug_info("msn",
+- "Can't find lock key for OIM: %s\n",
+- msg->oim_msg);
+- }
+- } else {
+- char buf[33];
+-
+- char *challenge = xmlnode_get_data(challengeNode);
+- msn_handle_chl(challenge, buf);
+-
+- g_free(oim->challenge);
+- oim->challenge = g_strndup(buf, sizeof(buf));
+- g_free(challenge);
+- purple_debug_info("msn", "Found lockkey:{%s}\n", oim->challenge);
+-
+- /*repost the send*/
+- purple_debug_info("msn", "Resending OIM: %s\n", msg->oim_msg);
+- g_queue_push_head(oim->send_queue, msg);
+- msn_oim_send_msg(oim);
+- msg = NULL;
+- }
+- } else {
+- /* Report the error */
+- const char *str_reason;
+-
+- if (g_str_equal(faultcode_str, "q0:SystemUnavailable")) {
+- str_reason = _("Message was not sent because the system is "
+- "unavailable. This normally happens when the "
+- "user is blocked or does not exist.");
+-
+- } else if (g_str_equal(faultcode_str, "q0:SenderThrottleLimitExceeded")) {
+- str_reason = _("Message was not sent because messages "
+- "are being sent too quickly.");
+-
+- } else if (g_str_equal(faultcode_str, "q0:InvalidContent")) {
+- str_reason = _("Message was not sent because an unknown "
+- "encoding error occurred.");
+-
+- } else {
+- str_reason = _("Message was not sent because an unknown "
+- "error occurred.");
+- }
+-
+- msn_session_report_user(oim->session, msg->to_member,
+- str_reason, PURPLE_MESSAGE_ERROR);
+- msn_session_report_user(oim->session, msg->to_member,
+- msg->oim_msg, PURPLE_MESSAGE_RAW);
+- }
+-
+- g_free(faultcode_str);
+- }
+- }
+- }
+-
+- if (msg)
+- msn_oim_free_send_req(msg);
+-}
+-
+-void
+-msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
+- const char* friendname, const char *tomember,
+- const char * msg)
+-{
+- g_return_if_fail(oim != NULL);
+-
+- g_queue_push_tail(oim->send_queue,
+- msn_oim_new_send_req(membername, friendname, tomember, msg));
+-}
+-
+-/*post send single message request to oim server*/
+-void
+-msn_oim_send_msg(MsnOim *oim)
+-{
+- MsnOimSendReq *oim_request;
+- char *soap_body;
+- char *msg_body;
+-
+- g_return_if_fail(oim != NULL);
+- oim_request = g_queue_peek_head(oim->send_queue);
+- g_return_if_fail(oim_request != NULL);
+-
+- purple_debug_info("msn", "Sending OIM: %s\n", oim_request->oim_msg);
+-
+- /* if we got the challenge lock key, we compute it
+- * else we go for the SOAP fault and resend it.
+- */
+- if (oim->challenge == NULL){
+- purple_debug_info("msn", "No lock key challenge, waiting for SOAP Fault and Resend\n");
+- }
+-
+- msg_body = msn_oim_msg_to_str(oim, oim_request->oim_msg);
+- soap_body = g_strdup_printf(MSN_OIM_SEND_TEMPLATE,
+- oim_request->from_member,
+- oim_request->friendname,
+- oim_request->to_member,
+- MSNP15_WLM_PRODUCT_ID,
+- oim->challenge ? oim->challenge : "",
+- oim->send_seq,
+- msg_body);
+-
+- msn_oim_make_request(oim, TRUE, MSN_OIM_SEND_SOAP_ACTION, MSN_OIM_SEND_HOST,
+- MSN_OIM_SEND_URL, xmlnode_from_str(soap_body, -1), msn_oim_send_read_cb,
+- oim);
+-
+- /*increase the offline Sequence control*/
+- if (oim->challenge != NULL) {
+- oim->send_seq++;
+- }
+-
+- g_free(msg_body);
+- g_free(soap_body);
+-}
+-
+-/****************************************
+- * OIM delete SOAP request
+- * **************************************/
+-static void
+-msn_oim_delete_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+- gpointer data)
+-{
+- MsnOimRecvData *rdata = data;
+-
+- if (response && xmlnode_get_child(response->xml, "Body/Fault") == NULL)
+- purple_debug_info("msn", "Delete OIM success\n");
+- else
+- purple_debug_info("msn", "Delete OIM failed\n");
+-
+- msn_oim_recv_data_free(rdata);
+-}
+-
+-/*Post to get the Offline Instant Message*/
+-static void
+-msn_oim_post_delete_msg(MsnOimRecvData *rdata)
+-{
+- MsnOim *oim = rdata->oim;
+- char *msgid = rdata->msg_id;
+- char *soap_body;
+-
+- purple_debug_info("msn", "Delete single OIM Message {%s}\n",msgid);
+-
+- soap_body = g_strdup_printf(MSN_OIM_DEL_TEMPLATE, msgid);
+-
+- msn_oim_make_request(oim, FALSE, MSN_OIM_DEL_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
+- MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_delete_read_cb, rdata);
+-
+- g_free(soap_body);
+-}
+-
+-/****************************************
+- * OIM get SOAP request
+- * **************************************/
+-/* like purple_str_to_time, but different. The format of the timestamp
+- * is like this: 5 Sep 2007 21:42:12 -0700 */
+-static time_t
+-msn_oim_parse_timestamp(const char *timestamp)
+-{
+- char month_str[4], tz_str[6];
+- char *tz_ptr = tz_str;
+- static const char *months[] = {
+- "Jan", "Feb", "Mar", "Apr", "May", "Jun",
+- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", NULL
+- };
+- time_t tval = 0;
+- struct tm t;
+- memset(&t, 0, sizeof(t));
+-
+- time(&tval);
+- localtime_r(&tval, &t);
+-
+- if (sscanf(timestamp, "%02d %03s %04d %02d:%02d:%02d %05s",
+- &t.tm_mday, month_str, &t.tm_year,
+- &t.tm_hour, &t.tm_min, &t.tm_sec, tz_str) == 7) {
+- gboolean offset_positive = TRUE;
+- int tzhrs;
+- int tzmins;
+-
+- for (t.tm_mon = 0;
+- months[t.tm_mon] != NULL &&
+- strcmp(months[t.tm_mon], month_str) != 0; t.tm_mon++);
+- if (months[t.tm_mon] != NULL) {
+- if (*tz_str == '-') {
+- offset_positive = FALSE;
+- tz_ptr++;
+- } else if (*tz_str == '+') {
+- tz_ptr++;
+- }
+-
+- if (sscanf(tz_ptr, "%02d%02d", &tzhrs, &tzmins) == 2) {
+- time_t tzoff = tzhrs * 60 * 60 + tzmins * 60;
+-#ifdef _WIN32
+- long sys_tzoff;
+-#endif
+-
+- if (offset_positive)
+- tzoff *= -1;
+-
+- t.tm_year -= 1900;
+-
+-#ifdef _WIN32
+- if ((sys_tzoff = wpurple_get_tz_offset()) != -1)
+- tzoff += sys_tzoff;
+-#else
+-#ifdef HAVE_TM_GMTOFF
+- tzoff += t.tm_gmtoff;
+-#else
+-# ifdef HAVE_TIMEZONE
+- tzset(); /* making sure */
+- tzoff -= timezone;
+-# endif
+-#endif
+-#endif /* _WIN32 */
+-
+- return mktime(&t) + tzoff;
+- }
+- }
+- }
+-
+- purple_debug_info("msn", "Can't parse timestamp %s\n", timestamp);
+- return tval;
+-}
+-
+-/*Post the Offline Instant Message to User Conversation*/
+-static void
+-msn_oim_report_to_user(MsnOimRecvData *rdata, const char *msg_str)
+-{
+- MsnMessage *message;
+- const char *date;
+- const char *from;
+- const char *boundary;
+- char *decode_msg = NULL, *clean_msg = NULL;
+- gsize body_len;
+- char **tokens;
+- char *passport = NULL;
+- time_t stamp;
+- const char *charset = NULL;
+-
+- message = msn_message_new(MSN_MSG_UNKNOWN);
+-
+- msn_message_parse_payload(message, msg_str, strlen(msg_str),
+- MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
+- purple_debug_info("msn", "oim body:{%s}\n", message->body);
+-
+- boundary = msn_message_get_header_value(message, "boundary");
+-
+- if (boundary != NULL) {
+- char *bounds;
+- char **part;
+-
+- bounds = g_strdup_printf("--%s" MSG_OIM_LINE_DEM, boundary);
+- tokens = g_strsplit(message->body, bounds, 0);
+-
+- /* tokens+1 to skip the "This is a multipart message..." text */
+- for (part = tokens+1; *part != NULL; part++) {
+- MsnMessage *multipart;
+- const char *type;
+- multipart = msn_message_new(MSN_MSG_UNKNOWN);
+- msn_message_parse_payload(multipart, *part, strlen(*part),
+- MSG_OIM_LINE_DEM, MSG_OIM_BODY_DEM);
+-
+- type = msn_message_get_content_type(multipart);
+- if (type && !strcmp(type, "text/plain")) {
+- decode_msg = (char *)purple_base64_decode(multipart->body, &body_len);
+- charset = msn_message_get_charset(multipart);
+-
+- msn_message_unref(multipart);
+- break;
+- }
+- msn_message_unref(multipart);
+- }
+-
+- g_strfreev(tokens);
+- g_free(bounds);
+-
+- if (decode_msg == NULL) {
+- purple_debug_error("msn", "Couldn't find text/plain OIM message.\n");
+- msn_message_unref(message);
+- return;
+- }
+- } else {
+- decode_msg = (char *)purple_base64_decode(message->body, &body_len);
+- charset = msn_message_get_charset(message);
+- }
+-
+- if (charset && !((g_ascii_strncasecmp(charset, "UTF-8", 5) == 0) || (g_ascii_strncasecmp(charset, "UTF8", 4) == 0))) {
+- clean_msg = g_convert(decode_msg, body_len, "UTF-8", charset, NULL, NULL, NULL);
+-
+- if (!clean_msg) {
+- char *clean = purple_utf8_salvage(decode_msg);
+-
+- purple_debug_error("msn", "Failed to convert charset from %s to UTF-8 for OIM message: %s\n", charset, clean);
+-
+- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message. "
+- "Converting the encoding from %s to UTF-8 failed.)"),
+- clean, charset);
+- g_free(clean);
+- }
+-
+- g_free(decode_msg);
+-
+- } else if (!g_utf8_validate(decode_msg, body_len, NULL)) {
+- char *clean = purple_utf8_salvage(decode_msg);
+-
+- purple_debug_error("msn", "Received an OIM message that is not UTF-8,"
+- " and no encoding specified: %s\n", clean);
+-
+- if (charset) {
+- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
+- " The charset was %s, but it was not valid UTF-8.)"),
+- clean, charset);
+- } else {
+- clean_msg = g_strdup_printf(_("%s (There was an error receiving this message."
+- " The charset was missing, but it was not valid UTF-8.)"),
+- clean);
+- }
+-
+- g_free(clean);
+- g_free(decode_msg);
+-
+- } else {
+- clean_msg = decode_msg;
+- }
+-
+- from = msn_message_get_header_value(message, "X-OIM-originatingSource");
+-
+- /* Match number to user's mobile number, FROM is a phone number
+- if the other side pages you using your phone number */
+- if (from && !strncmp(from, "tel:+", 5)) {
+- MsnUser *user = msn_userlist_find_user_with_mobile_phone(
+- rdata->oim->session->userlist, from + 4);
+-
+- if (user && user->passport)
+- passport = g_strdup(user->passport);
+- }
+-
+- if (passport == NULL) {
+- char *start, *end;
+-
+- from = msn_message_get_header_value(message, "From");
+-
+- tokens = g_strsplit(from, " ", 2);
+- if (tokens[1] != NULL)
+- from = (const char *)tokens[1];
+-
+- start = strchr(from, '<');
+- if (start != NULL) {
+- start++;
+- end = strchr(from, '>');
+- if (end != NULL)
+- passport = g_strndup(start, end - start);
+- }
+- if (passport == NULL)
+- passport = g_strdup(_("Unknown"));
+-
+- g_strfreev(tokens);
+- }
+-
+- date = msn_message_get_header_value(message, "Date");
+- stamp = msn_oim_parse_timestamp(date);
+- purple_debug_info("msn", "oim Date:{%s},passport{%s}\n",
+- date, passport);
+-
+- serv_got_im(purple_account_get_connection(rdata->oim->session->account), passport, clean_msg, 0,
+- stamp);
+-
+- /*Now get the oim message ID from the oim_list.
+- * and append to read list to prepare for deleting the Offline Message when sign out
+- */
+- msn_oim_post_delete_msg(rdata);
+-
+- g_free(passport);
+- g_free(clean_msg);
+- msn_message_unref(message);
+-}
+-
+-/* Parse the XML data,
+- * prepare to report the OIM to user
+- */
+-static void
+-msn_oim_get_read_cb(MsnSoapMessage *request, MsnSoapMessage *response,
+- gpointer data)
+-{
+- MsnOimRecvData *rdata = data;
+-
+- if (response != NULL) {
+- xmlnode *msg_node = xmlnode_get_child(response->xml,
+- "Body/GetMessageResponse/GetMessageResult");
+-
+- if (msg_node) {
+- char *msg_str = xmlnode_get_data(msg_node);
+- msn_oim_report_to_user(rdata, msg_str);
+- g_free(msg_str);
+- } else {
+- char *str = xmlnode_to_str(response->xml, NULL);
+- purple_debug_info("msn", "Unknown OIM response: %s\n", str);
+- g_free(str);
+- msn_oim_recv_data_free(rdata);
+- }
+- } else {
+- purple_debug_info("msn", "Failed to get OIM\n");
+- msn_oim_recv_data_free(rdata);
+- }
+-
+-}
+-
+-/* parse the oim XML data
+- * and post it to the soap server to get the Offline Message
+- * */
+-void
+-msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg)
+-{
+- xmlnode *node;
+-
+- purple_debug_info("msn", "%s\n", xmlmsg);
+-
+- if (!strcmp(xmlmsg, "too-large")) {
+- /* Too many OIM's to send via NS, so we need to request them via SOAP. */
+- msn_oim_get_metadata(oim);
+- } else {
+- node = xmlnode_from_str(xmlmsg, -1);
+- msn_parse_oim_xml(oim, node);
+- xmlnode_free(node);
+- }
+-}
+-
+-static void
+-msn_parse_oim_xml(MsnOim *oim, xmlnode *node)
+-{
+- xmlnode *mNode;
+- xmlnode *iu_node;
+- MsnSession *session = oim->session;
+-
+- g_return_if_fail(node != NULL);
+-
+- if (strcmp(node->name, "MD") != 0) {
+- char *xmlmsg = xmlnode_to_str(node, NULL);
+- purple_debug_info("msn", "WTF is this? %s\n", xmlmsg);
+- g_free(xmlmsg);
+- return;
+- }
+-
+- iu_node = xmlnode_get_child(node, "E/IU");
+-
+- if (iu_node != NULL && purple_account_get_check_mail(session->account))
+- {
+- char *unread = xmlnode_get_data(iu_node);
+- const char *passports[2] = { msn_user_get_passport(session->user) };
+- const char *urls[2] = { session->passport_info.mail_url };
+- int count = atoi(unread);
+-
+- /* XXX/khc: pretty sure this is wrong */
+- if (count > 0)
+- purple_notify_emails(session->account->gc, count, FALSE, NULL,
+- NULL, passports, urls, NULL, NULL);
+- g_free(unread);
+- }
+-
+- for(mNode = xmlnode_get_child(node, "M"); mNode;
+- mNode = xmlnode_get_next_twin(mNode)){
+- char *passport, *msgid, *nickname, *rtime = NULL;
+- xmlnode *e_node, *i_node, *n_node, *rt_node;
+-
+- e_node = xmlnode_get_child(mNode, "E");
+- passport = xmlnode_get_data(e_node);
+-
+- i_node = xmlnode_get_child(mNode, "I");
+- msgid = xmlnode_get_data(i_node);
+-
+- n_node = xmlnode_get_child(mNode, "N");
+- nickname = xmlnode_get_data(n_node);
+-
+- rt_node = xmlnode_get_child(mNode, "RT");
+- if (rt_node != NULL) {
+- rtime = xmlnode_get_data(rt_node);
+- }
+-/* purple_debug_info("msn", "E:{%s},I:{%s},rTime:{%s}\n",passport,msgid,rTime); */
+-
+- if (!g_list_find_custom(oim->oim_list, msgid, (GCompareFunc)msn_recv_data_equal)) {
+- MsnOimRecvData *data = msn_oim_recv_data_new(oim, msgid);
+- msn_oim_post_single_get_msg(oim, data);
+- msgid = NULL;
+- }
+-
+- g_free(passport);
+- g_free(msgid);
+- g_free(rtime);
+- g_free(nickname);
+- }
+-}
+-
+-/*Post to get the Offline Instant Message*/
+-static void
+-msn_oim_post_single_get_msg(MsnOim *oim, MsnOimRecvData *data)
+-{
+- char *soap_body;
+-
+- purple_debug_info("msn", "Get single OIM Message\n");
+-
+- soap_body = g_strdup_printf(MSN_OIM_GET_TEMPLATE, data->msg_id);
+-
+- msn_oim_make_request(oim, FALSE, MSN_OIM_GET_SOAP_ACTION, MSN_OIM_RETRIEVE_HOST,
+- MSN_OIM_RETRIEVE_URL, xmlnode_from_str(soap_body, -1), msn_oim_get_read_cb,
+- data);
+-
+- g_free(soap_body);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/oim.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.h
+--- pidgin-2.10.7/libpurple/protocols/msn/oim.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/oim.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,163 +0,0 @@
+-/**
+- * @file oim.h Header file for oim.c
+- * Author
+- * MaYuan<mayuan2006@gmail.com>
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-#ifndef MSN_OIM_H
+-#define MSN_OIM_H
+-
+-typedef struct _MsnOim MsnOim;
+-
+-/* OIM Retrieval Info */
+-#define MSN_OIM_RETRIEVE_HOST "rsi.hotmail.com"
+-#define MSN_OIM_RETRIEVE_URL "/rsi/rsi.asmx"
+-
+-/* OIM GetMetadata SOAP Template */
+-#define MSN_OIM_GET_METADATA_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMetadata"
+-
+-#define MSN_OIM_GET_METADATA_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<soap:Header>"\
+- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+- "<t>EMPTY</t>"\
+- "<p>EMPTY</p>"\
+- "</PassportCookie>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<GetMetadata xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\" />"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/*OIM GetMessage SOAP Template*/
+-#define MSN_OIM_GET_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/GetMessage"
+-
+-#define MSN_OIM_GET_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<soap:Header>"\
+- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+- "<t>EMPTY</t>"\
+- "<p>EMPTY</p>"\
+- "</PassportCookie>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<GetMessage xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+- "<messageId>%s</messageId>"\
+- "<alsoMarkAsRead>false</alsoMarkAsRead>"\
+- "</GetMessage>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/*OIM DeleteMessages SOAP Template*/
+-#define MSN_OIM_DEL_SOAP_ACTION "http://www.hotmail.msn.com/ws/2004/09/oim/rsi/DeleteMessages"
+-
+-#define MSN_OIM_DEL_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<soap:Header>"\
+- "<PassportCookie xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+- "<t>EMPTY</t>"\
+- "<p>EMPTY</p>"\
+- "</PassportCookie>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<DeleteMessages xmlns=\"http://www.hotmail.msn.com/ws/2004/09/oim/rsi\">"\
+- "<messageIds>"\
+- "<messageId>%s</messageId>"\
+- "</messageIds>"\
+- "</DeleteMessages>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-/*OIM Send SOAP Template*/
+-#define MSN_OIM_MSG_TEMPLATE "MIME-Version: 1.0\n"\
+- "Content-Type: text/plain; charset=UTF-8\n"\
+- "Content-Transfer-Encoding: base64\n"\
+- "X-OIM-Message-Type: OfflineMessage\n"\
+- "X-OIM-Run-Id: {%s}\n"\
+- "X-OIM-Sequence-Num: %d\n\n"
+-
+-#define MSN_OIM_SEND_HOST "ows.messenger.msn.com"
+-#define MSN_OIM_SEND_URL "/OimWS/oim.asmx"
+-#define MSN_OIM_SEND_SOAP_ACTION "http://messenger.live.com/ws/2006/09/oim/Store2"
+-#define MSN_OIM_SEND_TEMPLATE "<?xml version=\"1.0\" encoding=\"utf-8\"?>"\
+-"<soap:Envelope"\
+- " xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""\
+- " xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\""\
+- " xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">"\
+- "<soap:Header>"\
+- "<From"\
+- " memberName=\"%s\""\
+- " friendlyName=\"%s\""\
+- " xml:lang=\"en-US\""\
+- " proxy=\"MSNMSGR\""\
+- " xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\""\
+- " msnpVer=\"MSNP15\""\
+- " buildVer=\"8.5.1288\"/>"\
+- "<To memberName=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
+- "<Ticket passport=\"EMPTY\" appid=\"%s\" lockkey=\"%s\" xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\"/>"\
+- "<Sequence xmlns=\"http://schemas.xmlsoap.org/ws/2003/03/rm\">"\
+- "<Identifier xmlns=\"http://schemas.xmlsoap.org/ws/2002/07/utility\">http://messenger.msn.com</Identifier>"\
+- "<MessageNumber>%d</MessageNumber>"\
+- "</Sequence>"\
+- "</soap:Header>"\
+- "<soap:Body>"\
+- "<MessageType xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">text</MessageType>"\
+- "<Content xmlns=\"http://messenger.msn.com/ws/2004/09/oim/\">%s</Content>"\
+- "</soap:Body>"\
+-"</soap:Envelope>"
+-
+-struct _MsnOim
+-{
+- MsnSession *session;
+-
+- GList * oim_list;
+-
+- char *challenge;
+- char *run_id;
+- gint send_seq;
+- GQueue *send_queue;
+-};
+-
+-/****************************************************
+- * function prototype
+- * **************************************************/
+-MsnOim * msn_oim_new(MsnSession *session);
+-void msn_oim_destroy(MsnOim *oim);
+-
+-void msn_parse_oim_msg(MsnOim *oim,const char *xmlmsg);
+-
+-/*Send OIM Message*/
+-void msn_oim_prep_send_msg_info(MsnOim *oim, const char *membername,
+- const char *friendname, const char *tomember,
+- const char * msg);
+-
+-void msn_oim_send_msg(MsnOim *oim);
+-
+-#endif/* MSN_OIM_H*/
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/p2p.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.c
+--- pidgin-2.10.7/libpurple/protocols/msn/p2p.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,870 +0,0 @@
+-/**
+- * @file p2p.c MSN P2P functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "p2p.h"
+-#include "tlv.h"
+-#include "msnutils.h"
+-
+-MsnP2PInfo *
+-msn_p2p_info_new(MsnP2PVersion version)
+-{
+- MsnP2PInfo *info = g_new0(MsnP2PInfo, 1);
+- info->version = version;
+-
+- switch (version) {
+- case MSN_P2P_VERSION_ONE:
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", version);
+- g_free(info);
+- info = NULL;
+- }
+-
+- return info;
+-}
+-
+-MsnP2PInfo *
+-msn_p2p_info_dup(MsnP2PInfo *info)
+-{
+- MsnP2PInfo *new_info = g_new0(MsnP2PInfo, 1);
+-
+- new_info->version = info->version;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- *new_info = *info;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- *new_info = *info;
+- new_info->header.v2.header_tlv = msn_tlvlist_copy(info->header.v2.header_tlv);
+- new_info->header.v2.data_tlv = msn_tlvlist_copy(info->header.v2.data_tlv);
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- g_free(new_info);
+- new_info = NULL;
+- }
+-
+- return new_info;
+-}
+-
+-void
+-msn_p2p_info_free(MsnP2PInfo *info)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- /* Nothing to do! */
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- msn_tlvlist_free(info->header.v2.header_tlv);
+- msn_tlvlist_free(info->header.v2.data_tlv);
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- g_free(info);
+-}
+-
+-size_t
+-msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len)
+-{
+- size_t len = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- MsnP2PHeader *header = &info->header.v1;
+-
+- if (max_len < P2P_PACKET_HEADER_SIZE) {
+- /* Invalid packet length */
+- len = 0;
+- break;
+- }
+-
+- header->session_id = msn_pop32le(wire);
+- header->id = msn_pop32le(wire);
+- header->offset = msn_pop64le(wire);
+- header->total_size = msn_pop64le(wire);
+- header->length = msn_pop32le(wire);
+- header->flags = msn_pop32le(wire);
+- header->ack_id = msn_pop32le(wire);
+- header->ack_sub_id = msn_pop32le(wire);
+- header->ack_size = msn_pop64le(wire);
+-
+- len = P2P_PACKET_HEADER_SIZE;
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO: {
+- MsnP2Pv2Header *header = &info->header.v2;
+-
+- header->header_len = msn_pop8(wire);
+- header->opcode = msn_pop8(wire);
+- header->message_len = msn_pop16be(wire);
+- header->base_id = msn_pop32be(wire);
+- if (header->header_len + header->message_len + P2P_PACKET_FOOTER_SIZE > max_len) {
+- /* Invalid header and data length */
+- len = 0;
+- break;
+- }
+-
+- if (header->header_len > 8) {
+- header->header_tlv = msn_tlvlist_read(wire, header->header_len - 8);
+- wire += header->header_len - 8;
+- }
+-
+- if (header->message_len > 0) {
+- /* Parse Data packet */
+-
+- header->data_header_len = msn_pop8(wire);
+- if (header->data_header_len > header->message_len) {
+- /* Invalid data header length */
+- len = 0;
+- break;
+- }
+- header->data_tf = msn_pop8(wire);
+- header->package_number = msn_pop16be(wire);
+- header->session_id = msn_pop32be(wire);
+-
+- if (header->data_header_len > 8) {
+- header->data_tlv = msn_tlvlist_read(wire, header->data_header_len - 8);
+- wire += header->data_header_len - 8;
+- }
+- }
+-
+- len = header->header_len + header->message_len;
+-
+- break;
+- }
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return len;
+-}
+-
+-char *
+-msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len)
+-{
+- char *wire = NULL;
+- char *tmp;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- MsnP2PHeader *header = &info->header.v1;
+- tmp = wire = g_new(char, P2P_PACKET_HEADER_SIZE);
+-
+- msn_push32le(tmp, header->session_id);
+- msn_push32le(tmp, header->id);
+- msn_push64le(tmp, header->offset);
+- msn_push64le(tmp, header->total_size);
+- msn_push32le(tmp, header->length);
+- msn_push32le(tmp, header->flags);
+- msn_push32le(tmp, header->ack_id);
+- msn_push32le(tmp, header->ack_sub_id);
+- msn_push64le(tmp, header->ack_size);
+-
+- if (len)
+- *len = P2P_PACKET_HEADER_SIZE;
+-
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO: {
+- MsnP2Pv2Header *header = &info->header.v2;
+- char *header_wire = NULL;
+- char *data_header_wire = NULL;
+-
+- if (header->header_tlv != NULL)
+- header_wire = msn_tlvlist_write(header->header_tlv, (size_t *)&header->header_len);
+- else
+- header->header_len = 0;
+-
+- if (header->data_tlv != NULL)
+- data_header_wire = msn_tlvlist_write(header->data_tlv, (size_t *)&header->data_header_len);
+- else
+- header->data_header_len = 0;
+-
+- tmp = wire = g_new(char, 16 + header->header_len + header->data_header_len);
+-
+- msn_push8(tmp, header->header_len + 8);
+- msn_push8(tmp, header->opcode);
+- msn_push16be(tmp, header->data_header_len + 8 + header->message_len);
+- msn_push32be(tmp, header->base_id);
+-
+- if (header_wire != NULL) {
+- memcpy(tmp, header_wire, header->header_len);
+- tmp += header->header_len;
+- }
+-
+- msn_push8(tmp, header->data_header_len + 8);
+- msn_push8(tmp, header->data_tf);
+- msn_push16be(tmp, header->package_number);
+- msn_push32be(tmp, header->session_id);
+-
+- if (data_header_wire != NULL) {
+- memcpy(tmp, data_header_wire, header->data_header_len);
+- tmp += header->data_header_len;
+- }
+-
+- if (len)
+- *len = header->header_len + header->data_header_len + 16;
+-
+- break;
+- }
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return wire;
+-}
+-
+-size_t
+-msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire)
+-{
+- MsnP2PFooter *footer;
+-
+- footer = &info->footer;
+-
+- footer->value = msn_pop32be(wire);
+-
+- return P2P_PACKET_FOOTER_SIZE;
+-}
+-
+-char *
+-msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len)
+-{
+- MsnP2PFooter *footer;
+- char *wire;
+- char *tmp;
+-
+- footer = &info->footer;
+- tmp = wire = g_new(char, P2P_PACKET_FOOTER_SIZE);
+-
+- msn_push32be(tmp, footer->value);
+-
+- if (len)
+- *len = P2P_PACKET_FOOTER_SIZE;
+-
+- return wire;
+-}
+-
+-void
+-msn_p2p_info_to_string(MsnP2PInfo *info, GString *str)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- MsnP2PHeader *header = &info->header.v1;
+- g_string_append_printf(str, "Session ID: %u\r\n", header->session_id);
+- g_string_append_printf(str, "ID: %u\r\n", header->id);
+- g_string_append_printf(str, "Offset: %" G_GUINT64_FORMAT "\r\n", header->offset);
+- g_string_append_printf(str, "Total size: %" G_GUINT64_FORMAT "\r\n", header->total_size);
+- g_string_append_printf(str, "Length: %u\r\n", header->length);
+- g_string_append_printf(str, "Flags: 0x%x\r\n", header->flags);
+- g_string_append_printf(str, "ACK ID: %u\r\n", header->ack_id);
+- g_string_append_printf(str, "SUB ID: %u\r\n", header->ack_sub_id);
+- g_string_append_printf(str, "ACK Size: %" G_GUINT64_FORMAT "\r\n", header->ack_size);
+-
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- g_string_append_printf(str, "Footer: 0x%08X\r\n", info->footer.value);
+-}
+-
+-gboolean
+-msn_p2p_msg_is_data(const MsnP2PInfo *info)
+-{
+- gboolean data = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- guint32 flags = info->header.v1.flags;
+- data = (flags == P2P_MSN_OBJ_DATA ||
+- flags == (P2P_WLM2009_COMP | P2P_MSN_OBJ_DATA) ||
+- flags == P2P_FILE_DATA);
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO:
+- data = info->header.v2.message_len > 0;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return data;
+-}
+-
+-gboolean
+-msn_p2p_info_is_valid(MsnP2PInfo *info)
+-{
+- gboolean valid = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- valid = info->header.v1.total_size >= info->header.v1.length;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- valid = TRUE;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return valid;
+-}
+-
+-gboolean
+-msn_p2p_info_is_first(MsnP2PInfo *info)
+-{
+- gboolean first = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- first = info->header.v1.offset == 0;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- first = info->header.v2.data_tf & TF_FIRST;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return first;
+-}
+-
+-gboolean
+-msn_p2p_info_is_final(MsnP2PInfo *info)
+-{
+- gboolean final = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- final = info->header.v1.offset + info->header.v1.length >= info->header.v1.total_size;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- final = msn_tlv_gettlv(info->header.v2.data_tlv, P2P_DATA_TLV_REMAINING, 1) == NULL;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return final;
+-}
+-
+-void
+-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info)
+-{
+- switch (old_info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- MsnP2PHeader *old = &old_info->header.v1;
+- MsnP2PHeader *new = &new_info->header.v1;
+-
+- new->session_id = old->session_id;
+- new->flags = P2P_ACK;
+- new->ack_id = old->id;
+- new->ack_sub_id = old->ack_id;
+- new->ack_size = old->total_size;
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO: {
+- MsnP2Pv2Header *old = &old_info->header.v2;
+- MsnP2Pv2Header *new = &new_info->header.v2;
+-
+- msn_tlvlist_add_32(&new->header_tlv, P2P_HEADER_TLV_TYPE_ACK, old->base_id + old->message_len);
+- new->opcode = P2P_OPCODE_NONE;
+-
+- if (old->message_len > 0) {
+- if (!msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1)) {
+- if (old->opcode & P2P_OPCODE_SYN) {
+- msn_tlv_t *ack_tlv;
+- new->opcode |= P2P_OPCODE_RAK;
+-
+- ack_tlv = msn_tlv_gettlv(old->header_tlv, P2P_HEADER_TLV_TYPE_PEER_INFO, 1);
+- if (ack_tlv) {
+- msn_tlvlist_add_tlv(&new->header_tlv, ack_tlv);
+- new->opcode |= P2P_OPCODE_SYN;
+- }
+- }
+- }
+- }
+- break;
+- }
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", old_info->version);
+- }
+-}
+-
+-gboolean
+-msn_p2p_info_require_ack(MsnP2PInfo *info)
+-{
+- gboolean ret = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- guint32 flags = msn_p2p_info_get_flags(info);
+-
+- ret = flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP ||
+- msn_p2p_msg_is_data(info);
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO:
+- ret = (info->header.v2.opcode & P2P_OPCODE_RAK) > 0;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return ret;
+-}
+-
+-gboolean
+-msn_p2p_info_is_ack(MsnP2PInfo *info)
+-{
+- gboolean ret = FALSE;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE: {
+- ret = msn_p2p_info_get_flags(info) == P2P_ACK;
+- break;
+- }
+-
+- case MSN_P2P_VERSION_TWO:
+- ret = msn_tlv_gettlv(info->header.v2.header_tlv, P2P_HEADER_TLV_TYPE_ACK, 1) != NULL;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return ret;
+-}
+-
+-void
+-msn_p2p_info_init_first(MsnP2PInfo *info, MsnP2PInfo *old_info)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.session_id = old_info->header.v1.session_id;
+- info->header.v1.flags = old_info->header.v1.flags;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- info->header.v2.data_tf = TF_FIRST;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-guint32
+-msn_p2p_info_get_session_id(MsnP2PInfo *info)
+-{
+- guint32 session_id = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- session_id = info->header.v1.session_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- session_id = info->header.v2.session_id;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return session_id;
+-}
+-
+-guint32
+-msn_p2p_info_get_id(MsnP2PInfo *info)
+-{
+- guint32 id = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- id = info->header.v1.id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- id = info->header.v2.base_id;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return id;
+-}
+-
+-guint64
+-msn_p2p_info_get_offset(MsnP2PInfo *info)
+-{
+- guint64 offset = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- offset = info->header.v1.offset;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return offset;
+-}
+-
+-guint64
+-msn_p2p_info_get_total_size(MsnP2PInfo *info)
+-{
+- guint64 total_size = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- total_size = info->header.v1.total_size;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return total_size;
+-}
+-
+-guint32
+-msn_p2p_info_get_length(MsnP2PInfo *info)
+-{
+- guint32 length = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- length = info->header.v1.length;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return length;
+-}
+-
+-guint32
+-msn_p2p_info_get_flags(MsnP2PInfo *info)
+-{
+- guint32 flags = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- flags = info->header.v1.flags;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- flags = info->header.v2.data_tf;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return flags;
+-}
+-
+-guint32
+-msn_p2p_info_get_ack_id(MsnP2PInfo *info)
+-{
+- guint32 ack_id = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- ack_id = info->header.v1.ack_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return ack_id;
+-}
+-
+-guint32
+-msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info)
+-{
+- guint32 ack_sub_id = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- ack_sub_id = info->header.v1.ack_sub_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return ack_sub_id;
+-}
+-
+-guint64
+-msn_p2p_info_get_ack_size(MsnP2PInfo *info)
+-{
+- guint64 ack_size = 0;
+-
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- ack_size = info->header.v1.ack_size;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+- return ack_size;
+-}
+-
+-guint32
+-msn_p2p_info_get_app_id(MsnP2PInfo *info)
+-{
+- return info->footer.value;
+-}
+-
+-void
+-msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.session_id = session_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- info->header.v2.session_id = session_id;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+-}
+-
+-void
+-msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.id = id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- info->header.v2.base_id = id;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-
+-}
+-
+-void
+-msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.offset = offset;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.total_size = total_size;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.length = length;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.flags = flags;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- info->header.v2.data_tf = flags;
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.ack_id = ack_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.ack_sub_id = ack_sub_id;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size)
+-{
+- switch (info->version) {
+- case MSN_P2P_VERSION_ONE:
+- info->header.v1.ack_size = ack_size;
+- break;
+-
+- case MSN_P2P_VERSION_TWO:
+- /* Nothing to do! */
+- break;
+-
+- default:
+- purple_debug_error("msn", "Invalid P2P Info version: %d\n", info->version);
+- }
+-}
+-
+-void
+-msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id)
+-{
+- info->footer.value = app_id;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/p2p.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.h
+--- pidgin-2.10.7/libpurple/protocols/msn/p2p.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/p2p.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,264 +0,0 @@
+-/**
+- * @file p2p.h MSN P2P functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef MSN_P2P_H
+-#define MSN_P2P_H
+-
+-typedef struct {
+- guint32 session_id;
+- guint32 id;
+- /**
+- * In a MsnSlpMessage:
+- * For outgoing messages this is the number of bytes from buffer that
+- * have already been sent out. For incoming messages this is the
+- * number of bytes that have been written to buffer.
+- */
+- guint64 offset;
+- guint64 total_size;
+- guint32 length;
+- guint32 flags;
+- guint32 ack_id;
+- guint32 ack_sub_id;
+- guint64 ack_size;
+-/* guint8 body[1]; */
+-} MsnP2PHeader;
+-#define P2P_PACKET_HEADER_SIZE (6 * 4 + 3 * 8)
+-
+-typedef struct {
+- guint8 header_len;
+- guint8 opcode;
+- guint16 message_len;
+- guint32 base_id;
+- GSList *header_tlv;
+- guint8 data_header_len;
+- guint8 data_tf;
+- guint16 package_number;
+- guint32 session_id;
+- GSList *data_tlv;
+-/* guint8 body[1]; */
+-} MsnP2Pv2Header;
+-
+-typedef struct {
+- guint16 protocol_version;
+- guint16 implementation_id;
+- guint16 version;
+- guint16 reserved;
+- guint32 caps;
+-} P2PPeerInfo;
+-
+-typedef enum
+-{
+- TF_FIRST = 0x01, /**< The first package. */
+- TF_MSNOBJ = 0x04, /**< Payload contains binary data for MsnObject. */
+- TF_FILE = 0x06 /**< Payload contains binary data. */
+-} TF;
+-
+-typedef enum
+-{
+- P2P_HEADER_TLV_TYPE_PEER_INFO = 0x01, /**< Client peer info */
+- P2P_HEADER_TLV_TYPE_ACK = 0x02, /**< ACK */
+- P2P_HEADER_TLV_TYPE_NAK = 0x03 /**< NAK */
+-} P2PHeaderTLVType;
+-
+-typedef enum
+-{
+- P2P_DATA_TLV_REMAINING = 0x01, /**< Indicates the remaining data to transfer.*/
+-} P2PDataTLVType;
+-
+-typedef enum
+-{
+- P2P_PI_PVER = 0x0200,
+- P2P_PI_IMP_ID = 0,
+- P2P_PI_VER = 0x0e00,
+- P2P_PI_RES = 0,
+- P2P_PI_CAPS = 0x0000010f
+-} P2PPeerInfoVal;
+-
+-typedef struct
+-{
+- guint32 value;
+-} MsnP2PFooter;
+-#define P2P_PACKET_FOOTER_SIZE (1 * 4)
+-
+-typedef enum
+-{
+- MSN_P2P_VERSION_ONE = 0,
+- MSN_P2P_VERSION_TWO = 1,
+-} MsnP2PVersion;
+-
+-typedef struct {
+- MsnP2PVersion version;
+- union {
+- MsnP2PHeader v1;
+- MsnP2Pv2Header v2;
+- } header;
+- MsnP2PFooter footer;
+-} MsnP2PInfo;
+-
+-typedef enum
+-{
+- P2P_NO_FLAG = 0x0, /**< No flags specified */
+- P2P_OUT_OF_ORDER = 0x1, /**< Chunk out-of-order */
+- P2P_ACK = 0x2, /**< Acknowledgement */
+- P2P_PENDING_INVITE = 0x4, /**< There is a pending invite */
+- P2P_BINARY_ERROR = 0x8, /**< Error on the binary level */
+- P2P_FILE = 0x10, /**< File */
+- P2P_MSN_OBJ_DATA = 0x20, /**< MsnObject data */
+- P2P_CLOSE = 0x40, /**< Close session */
+- P2P_TLP_ERROR = 0x80, /**< Error at transport layer protocol */
+- P2P_DC_HANDSHAKE = 0x100, /**< Direct Handshake */
+- P2P_WLM2009_COMP = 0x1000000, /**< Compatibility with WLM 2009 */
+- P2P_FILE_DATA = 0x1000030 /**< File transfer data */
+-} MsnP2PHeaderFlag;
+-/* Info From:
+- * http://msnpiki.msnfanatic.com/index.php/MSNC:P2Pv1_Headers#Flags
+- * http://trac.kmess.org/changeset/ba04d0c825769d23370511031c47f6be75fe9b86
+- * #7180
+- */
+-
+-typedef enum
+-{
+- P2P_APPID_SESSION = 0x0, /**< Negotiating session */
+- P2P_APPID_OBJ = 0x1, /**< MsnObject (Display or Emoticon) */
+- P2P_APPID_FILE = 0x2, /**< File transfer */
+- P2P_APPID_EMOTE = 0xB, /**< CustomEmoticon */
+- P2P_APPID_DISPLAY = 0xC /**< Display Image */
+-} MsnP2PAppId;
+-
+-typedef enum
+-{
+- P2P_OPCODE_NONE = 0x00,
+- P2P_OPCODE_SYN = 0x01,
+- P2P_OPCODE_RAK = 0x02
+-} MsnP2Pv2OpCode;
+-
+-MsnP2PInfo *
+-msn_p2p_info_new(MsnP2PVersion version);
+-
+-MsnP2PInfo *
+-msn_p2p_info_dup(MsnP2PInfo *info);
+-
+-void
+-msn_p2p_info_free(MsnP2PInfo *info);
+-
+-size_t
+-msn_p2p_header_from_wire(MsnP2PInfo *info, const char *wire, size_t max_len);
+-
+-char *
+-msn_p2p_header_to_wire(MsnP2PInfo *info, size_t *len);
+-
+-size_t
+-msn_p2p_footer_from_wire(MsnP2PInfo *info, const char *wire);
+-
+-char *
+-msn_p2p_footer_to_wire(MsnP2PInfo *info, size_t *len);
+-
+-void
+-msn_p2p_info_to_string(MsnP2PInfo *info, GString *str);
+-
+-gboolean
+-msn_p2p_msg_is_data(const MsnP2PInfo *info);
+-
+-gboolean
+-msn_p2p_info_is_valid(MsnP2PInfo *info);
+-
+-gboolean
+-msn_p2p_info_is_first(MsnP2PInfo *info);
+-
+-gboolean
+-msn_p2p_info_is_final(MsnP2PInfo *info);
+-
+-void
+-msn_p2p_info_create_ack(MsnP2PInfo *old_info, MsnP2PInfo *new_info);
+-
+-gboolean
+-msn_p2p_info_require_ack(MsnP2PInfo *info);
+-
+-gboolean
+-msn_p2p_info_is_ack(MsnP2PInfo *info);
+-
+-void
+-msn_p2p_info_init_first(MsnP2PInfo *new_info, MsnP2PInfo *old_info);
+-
+-guint32
+-msn_p2p_info_get_session_id(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_id(MsnP2PInfo *info);
+-
+-guint64
+-msn_p2p_info_get_offset(MsnP2PInfo *info);
+-
+-guint64
+-msn_p2p_info_get_total_size(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_length(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_flags(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_ack_id(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_ack_sub_id(MsnP2PInfo *info);
+-
+-guint64
+-msn_p2p_info_get_ack_size(MsnP2PInfo *info);
+-
+-guint32
+-msn_p2p_info_get_app_id(MsnP2PInfo *info);
+-
+-void
+-msn_p2p_info_set_session_id(MsnP2PInfo *info, guint32 session_id);
+-
+-void
+-msn_p2p_info_set_id(MsnP2PInfo *info, guint32 id);
+-
+-void
+-msn_p2p_info_set_offset(MsnP2PInfo *info, guint64 offset);
+-
+-void
+-msn_p2p_info_set_total_size(MsnP2PInfo *info, guint64 total_size);
+-
+-void
+-msn_p2p_info_set_length(MsnP2PInfo *info, guint32 length);
+-
+-void
+-msn_p2p_info_set_flags(MsnP2PInfo *info, guint32 flags);
+-
+-void
+-msn_p2p_info_set_ack_id(MsnP2PInfo *info, guint32 ack_id);
+-
+-void
+-msn_p2p_info_set_ack_sub_id(MsnP2PInfo *info, guint32 ack_sub_id);
+-
+-void
+-msn_p2p_info_set_ack_size(MsnP2PInfo *info, guint64 ack_size);
+-
+-void
+-msn_p2p_info_set_app_id(MsnP2PInfo *info, guint32 app_id);
+-
+-#endif /* MSN_P2P_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/page.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.c
+--- pidgin-2.10.7/libpurple/protocols/msn/page.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,85 +0,0 @@
+-/**
+- * @file page.c Paging functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "msn.h"
+-#include "page.h"
+-
+-MsnPage *
+-msn_page_new(void)
+-{
+- MsnPage *page;
+-
+- page = g_new0(MsnPage, 1);
+-
+- return page;
+-}
+-
+-void
+-msn_page_destroy(MsnPage *page)
+-{
+- g_return_if_fail(page != NULL);
+-
+- g_free(page->body);
+- g_free(page->from_location);
+- g_free(page->from_phone);
+-
+- g_free(page);
+-}
+-
+-char *
+-msn_page_gen_payload(const MsnPage *page, size_t *ret_size)
+-{
+- char *str;
+- char *body;
+-
+- g_return_val_if_fail(page != NULL, NULL);
+-
+- body = g_markup_escape_text(msn_page_get_body(page), -1);
+- str = g_strdup_printf(
+- "<TEXT xml:space=\"preserve\" enc=\"utf-8\">%s</TEXT>",
+- body);
+- g_free(body);
+-
+- if (ret_size != NULL)
+- *ret_size = strlen(str);
+-
+- return str;
+-}
+-
+-void
+-msn_page_set_body(MsnPage *page, const char *body)
+-{
+- g_return_if_fail(page != NULL);
+- g_return_if_fail(body != NULL);
+-
+- g_free(page->body);
+- page->body = g_strdup(body);
+-}
+-
+-const char *
+-msn_page_get_body(const MsnPage *page)
+-{
+- g_return_val_if_fail(page != NULL, NULL);
+-
+- return page->body;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/page.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.h
+--- pidgin-2.10.7/libpurple/protocols/msn/page.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/page.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,81 +0,0 @@
+-/**
+- * @file page.h Paging functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_PAGE_H
+-#define MSN_PAGE_H
+-
+-typedef struct _MsnPage MsnPage;
+-
+-#include "session.h"
+-
+-/**
+- * A page.
+- */
+-struct _MsnPage
+-{
+- char *from_location;
+- char *from_phone;
+-
+- char *body;
+-};
+-
+-/**
+- * Creates a new, empty page.
+- *
+- * @return A new page.
+- */
+-MsnPage *msn_page_new(void);
+-
+-/**
+- * Destroys a page.
+- */
+-void msn_page_destroy(MsnPage *page);
+-
+-/**
+- * Generates the payload data of a page.
+- *
+- * @param page The page.
+- * @param ret_size The returned size of the payload.
+- *
+- * @return The payload data of a page.
+- */
+-char *msn_page_gen_payload(const MsnPage *page, size_t *ret_size);
+-
+-/**
+- * Sets the body of a page.
+- *
+- * @param page The page.
+- * @param body The body of the page.
+- */
+-void msn_page_set_body(MsnPage *page, const char *body);
+-
+-/**
+- * Returns the body of the page.
+- *
+- * @param page The page.
+- *
+- * @return The body of the page.
+- */
+-const char *msn_page_get_body(const MsnPage *page);
+-
+-#endif /* MSN_PAGE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/sbconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.c
+--- pidgin-2.10.7/libpurple/protocols/msn/sbconn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,174 +0,0 @@
+-/**
+- * @file sbconn.c MSN Switchboard Connection
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msg.h"
+-#include "sbconn.h"
+-
+-void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
+-{
+- MsnMessage *msg;
+- const char *passport;
+- char *data;
+- size_t size;
+-
+- msg = msn_message_new_msnslp();
+-
+- passport = purple_normalize(slplink->session->account, slplink->remote_user);
+- msn_message_set_header(msg, "P2P-Dest", passport);
+-
+- msg->part = msn_slpmsgpart_ref(part);
+- data = msn_slpmsgpart_serialize(part, &size);
+- msn_message_set_bin_data(msg, data, size);
+- g_free(data);
+-
+- if (slplink->swboard == NULL)
+- {
+- slplink->swboard = msn_session_get_swboard(slplink->session,
+- slplink->remote_user, MSN_SB_FLAG_FT);
+-
+- g_return_if_fail(slplink->swboard != NULL);
+-
+- /* If swboard is destroyed we will be too */
+- slplink->swboard->slplinks = g_list_prepend(slplink->swboard->slplinks, slplink);
+- }
+-
+- msn_switchboard_send_msg(slplink->swboard, msg, TRUE);
+- msn_message_unref(msg);
+-}
+-
+-/** Called when a message times out. */
+-static void
+-msg_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
+-{
+- MsnMessage *msg;
+-
+- msg = trans->data;
+-
+- msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_TIMEOUT);
+-}
+-
+-static void
+-release_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
+-{
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+- char *payload;
+- gsize payload_len;
+- char flag;
+-
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- cmdproc = swboard->cmdproc;
+-
+- payload = msn_message_gen_payload(msg, &payload_len);
+-
+- if (purple_debug_is_verbose()) {
+- purple_debug_info("msn", "SB length:{%" G_GSIZE_FORMAT "}\n", payload_len);
+- msn_message_show_readable(msg, "SB SEND", FALSE);
+- }
+-
+- flag = msn_message_get_flag(msg);
+- trans = msn_transaction_new(cmdproc, "MSG", "%c %" G_GSIZE_FORMAT,
+- flag, payload_len);
+-
+- /* Data for callbacks */
+- msn_transaction_set_data(trans, msg);
+-
+- if (flag != 'U') {
+- if (msg->type == MSN_MSG_TEXT)
+- {
+- msg->ack_ref = TRUE;
+- msn_message_ref(msg);
+- swboard->ack_list = g_list_append(swboard->ack_list, msg);
+- msn_transaction_set_timeout_cb(trans, msg_timeout);
+- }
+- else if (msg->type == MSN_MSG_SLP)
+- {
+- msg->ack_ref = TRUE;
+- msn_message_ref(msg);
+- swboard->ack_list = g_list_append(swboard->ack_list, msg);
+- msn_transaction_set_timeout_cb(trans, msg_timeout);
+-#if 0
+- if (msg->ack_cb != NULL)
+- {
+- msn_transaction_add_cb(trans, "ACK", msg_ack);
+- msn_transaction_add_cb(trans, "NAK", msg_nak);
+- }
+-#endif
+- }
+- }
+-
+- trans->payload = payload;
+- trans->payload_len = payload_len;
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-static void
+-queue_msg(MsnSwitchBoard *swboard, MsnMessage *msg)
+-{
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- purple_debug_info("msn", "Appending message to queue.\n");
+-
+- g_queue_push_tail(swboard->msg_queue, msg);
+-
+- msn_message_ref(msg);
+-}
+-
+-void
+-msn_sbconn_process_queue(MsnSwitchBoard *swboard)
+-{
+- MsnMessage *msg;
+-
+- g_return_if_fail(swboard != NULL);
+-
+- purple_debug_info("msn", "Processing queue\n");
+-
+- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
+- {
+- purple_debug_info("msn", "Sending message\n");
+- release_msg(swboard, msg);
+- msn_message_unref(msg);
+- }
+-}
+-
+-void
+-msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
+- gboolean queue)
+-{
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- purple_debug_info("msn", "switchboard send msg..\n");
+- if (msn_switchboard_can_send(swboard))
+- release_msg(swboard, msg);
+- else if (queue)
+- queue_msg(swboard, msg);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/sbconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.h
+--- pidgin-2.10.7/libpurple/protocols/msn/sbconn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/sbconn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,41 +0,0 @@
+-/**
+- * @file sbconn.h MSN Switchboard Connection
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef MSN_SBCONN_H
+-#define MSN_SBCONN_H
+-
+-#include "msg.h"
+-#include "slplink.h"
+-
+-#define MSN_SBCONN_MAX_SIZE 1202
+-
+-void msn_sbconn_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part);
+-
+-void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
+- gboolean queue);
+-
+-void
+-msn_sbconn_process_queue(MsnSwitchBoard *swboard);
+-
+-#endif /* MSN_SBCONN_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/servconn.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.c
+--- pidgin-2.10.7/libpurple/protocols/msn/servconn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,607 +0,0 @@
+-/**
+- * @file servconn.c Server connection functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "servconn.h"
+-#include "error.h"
+-
+-static void read_cb(gpointer data, gint source, PurpleInputCondition cond);
+-static void servconn_timeout_renew(MsnServConn *servconn);
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-MsnServConn *
+-msn_servconn_new(MsnSession *session, MsnServConnType type)
+-{
+- MsnServConn *servconn;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- servconn = g_new0(MsnServConn, 1);
+-
+- servconn->type = type;
+-
+- servconn->session = session;
+- servconn->cmdproc = msn_cmdproc_new(session);
+- servconn->cmdproc->servconn = servconn;
+-
+- servconn->httpconn = msn_httpconn_new(servconn);
+-
+- servconn->num = session->servconns_count++;
+-
+- servconn->tx_buf = purple_circ_buffer_new(MSN_BUF_LEN);
+- servconn->tx_handler = 0;
+- servconn->timeout_sec = 0;
+- servconn->timeout_handle = 0;
+-
+- servconn->fd = -1;
+-
+- return servconn;
+-}
+-
+-void
+-msn_servconn_destroy(MsnServConn *servconn)
+-{
+- g_return_if_fail(servconn != NULL);
+-
+- if (servconn->processing)
+- {
+- servconn->wasted = TRUE;
+- return;
+- }
+-
+- msn_servconn_disconnect(servconn);
+-
+- if (servconn->destroy_cb)
+- servconn->destroy_cb(servconn);
+-
+- if (servconn->httpconn != NULL)
+- msn_httpconn_destroy(servconn->httpconn);
+-
+- g_free(servconn->host);
+-
+- purple_circ_buffer_destroy(servconn->tx_buf);
+- if (servconn->tx_handler > 0)
+- purple_input_remove(servconn->tx_handler);
+- if (servconn->timeout_handle > 0)
+- purple_timeout_remove(servconn->timeout_handle);
+-
+- msn_cmdproc_destroy(servconn->cmdproc);
+- g_free(servconn);
+-}
+-
+-void
+-msn_servconn_set_connect_cb(MsnServConn *servconn,
+- void (*connect_cb)(MsnServConn *))
+-{
+- g_return_if_fail(servconn != NULL);
+- servconn->connect_cb = connect_cb;
+-}
+-
+-void
+-msn_servconn_set_disconnect_cb(MsnServConn *servconn,
+- void (*disconnect_cb)(MsnServConn *))
+-{
+- g_return_if_fail(servconn != NULL);
+-
+- servconn->disconnect_cb = disconnect_cb;
+-}
+-
+-void
+-msn_servconn_set_destroy_cb(MsnServConn *servconn,
+- void (*destroy_cb)(MsnServConn *))
+-{
+- g_return_if_fail(servconn != NULL);
+-
+- servconn->destroy_cb = destroy_cb;
+-}
+-
+-/**************************************************************************
+- * Utility
+- **************************************************************************/
+-
+-void
+-msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
+- const char *reason)
+-{
+- MsnSession *session = servconn->session;
+- MsnServConnType type = servconn->type;
+-
+- const char *names[] = { "Notification", "Switchboard" };
+- const char *name;
+-
+- name = names[type];
+-
+- if (reason == NULL) {
+- switch (error)
+- {
+- case MSN_SERVCONN_ERROR_CONNECT:
+- reason = _("Unable to connect"); break;
+- case MSN_SERVCONN_ERROR_WRITE:
+- reason = _("Writing error"); break;
+- case MSN_SERVCONN_ERROR_READ:
+- reason = _("Reading error"); break;
+- default:
+- reason = _("Unknown error"); break;
+- }
+- }
+-
+- purple_debug_error("msn", "Connection error from %s server (%s): %s\n",
+- name, servconn->host, reason);
+-
+- if (type == MSN_SERVCONN_SB)
+- {
+- MsnSwitchBoard *swboard;
+- swboard = servconn->cmdproc->data;
+- if (swboard != NULL)
+- swboard->error = MSN_SB_ERROR_CONNECTION;
+- }
+-
+- /* servconn->disconnect_cb may destroy servconn, so don't use it again */
+- msn_servconn_disconnect(servconn);
+-
+- if (type == MSN_SERVCONN_NS)
+- {
+- char *tmp = g_strdup_printf(_("Connection error from %s server:\n%s"),
+- name, reason);
+- msn_session_set_error(session, MSN_ERROR_SERVCONN, tmp);
+- g_free(tmp);
+- }
+-}
+-
+-/**************************************************************************
+- * Connect
+- **************************************************************************/
+-
+-static void
+-connect_cb(gpointer data, gint source, const char *error_message)
+-{
+- MsnServConn *servconn;
+-
+- servconn = data;
+- servconn->connect_data = NULL;
+-
+- servconn->fd = source;
+-
+- if (source >= 0)
+- {
+- servconn->connected = TRUE;
+-
+- /* Someone wants to know we connected. */
+- servconn->connect_cb(servconn);
+- servconn->inpa = purple_input_add(servconn->fd, PURPLE_INPUT_READ,
+- read_cb, data);
+- servconn_timeout_renew(servconn);
+- }
+- else
+- {
+- purple_debug_error("msn", "Connection error: %s\n", error_message);
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_CONNECT, error_message);
+- }
+-}
+-
+-gboolean
+-msn_servconn_connect(MsnServConn *servconn, const char *host, int port, gboolean force)
+-{
+- MsnSession *session;
+-
+- g_return_val_if_fail(servconn != NULL, FALSE);
+- g_return_val_if_fail(host != NULL, FALSE);
+- g_return_val_if_fail(port > 0, FALSE);
+-
+- session = servconn->session;
+-
+- if (servconn->connected)
+- msn_servconn_disconnect(servconn);
+-
+- g_free(servconn->host);
+- servconn->host = g_strdup(host);
+-
+- if (session->http_method)
+- {
+- /* HTTP Connection. */
+-
+- if (!servconn->httpconn->connected || force)
+- if (!msn_httpconn_connect(servconn->httpconn, host, port))
+- return FALSE;
+-
+- servconn->connected = TRUE;
+- servconn->httpconn->virgin = TRUE;
+- servconn_timeout_renew(servconn);
+-
+- /* Someone wants to know we connected. */
+- servconn->connect_cb(servconn);
+-
+- return TRUE;
+- }
+-
+- servconn->connect_data = purple_proxy_connect(NULL, session->account,
+- host, port, connect_cb, servconn);
+-
+- return (servconn->connect_data != NULL);
+-}
+-
+-void
+-msn_servconn_disconnect(MsnServConn *servconn)
+-{
+- g_return_if_fail(servconn != NULL);
+-
+- if (servconn->connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(servconn->connect_data);
+- servconn->connect_data = NULL;
+- }
+-
+- if (!servconn->connected)
+- {
+- /* We could not connect. */
+- if (servconn->disconnect_cb != NULL)
+- servconn->disconnect_cb(servconn);
+-
+- return;
+- }
+-
+- if (servconn->session->http_method)
+- {
+- /* Fake disconnection. */
+- if (servconn->disconnect_cb != NULL)
+- servconn->disconnect_cb(servconn);
+-
+- return;
+- }
+-
+- if (servconn->inpa > 0)
+- {
+- purple_input_remove(servconn->inpa);
+- servconn->inpa = 0;
+- }
+-
+- if (servconn->timeout_handle > 0)
+- {
+- purple_timeout_remove(servconn->timeout_handle);
+- servconn->timeout_handle = 0;
+- }
+-
+- close(servconn->fd);
+-
+- servconn->rx_buf = NULL;
+- servconn->rx_len = 0;
+- servconn->payload_len = 0;
+-
+- servconn->connected = FALSE;
+-
+- if (servconn->disconnect_cb != NULL)
+- servconn->disconnect_cb(servconn);
+-}
+-
+-static gboolean
+-servconn_idle_timeout_cb(MsnServConn *servconn)
+-{
+- servconn->timeout_handle = 0;
+- msn_servconn_disconnect(servconn);
+- return FALSE;
+-}
+-
+-static void
+-servconn_timeout_renew(MsnServConn *servconn)
+-{
+- if (servconn->timeout_handle) {
+- purple_timeout_remove(servconn->timeout_handle);
+- servconn->timeout_handle = 0;
+- }
+-
+- if (servconn->connected && servconn->timeout_sec) {
+- servconn->timeout_handle = purple_timeout_add_seconds(
+- servconn->timeout_sec, (GSourceFunc)servconn_idle_timeout_cb, servconn);
+- }
+-}
+-
+-void
+-msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds)
+-{
+- servconn->timeout_sec = seconds;
+- if (servconn->connected)
+- servconn_timeout_renew(servconn);
+-}
+-
+-static void
+-servconn_write_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- MsnServConn *servconn = data;
+- gssize ret;
+- int writelen;
+-
+- writelen = purple_circ_buffer_get_max_read(servconn->tx_buf);
+-
+- if (writelen == 0) {
+- purple_input_remove(servconn->tx_handler);
+- servconn->tx_handler = 0;
+- return;
+- }
+-
+- ret = write(servconn->fd, servconn->tx_buf->outptr, writelen);
+-
+- if (ret < 0 && errno == EAGAIN)
+- return;
+- else if (ret <= 0) {
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(servconn->tx_buf, ret);
+- servconn_timeout_renew(servconn);
+-}
+-
+-gssize
+-msn_servconn_write(MsnServConn *servconn, const char *buf, size_t len)
+-{
+- gssize ret = 0;
+-
+- g_return_val_if_fail(servconn != NULL, 0);
+-
+- if (!servconn->session->http_method)
+- {
+- if (servconn->tx_handler == 0) {
+- switch (servconn->type)
+- {
+- case MSN_SERVCONN_NS:
+- case MSN_SERVCONN_SB:
+- ret = write(servconn->fd, buf, len);
+- break;
+-#if 0
+- case MSN_SERVCONN_DC:
+- ret = write(servconn->fd, &buf, sizeof(len));
+- ret = write(servconn->fd, buf, len);
+- break;
+-#endif
+- default:
+- ret = write(servconn->fd, buf, len);
+- break;
+- }
+- } else {
+- ret = -1;
+- errno = EAGAIN;
+- }
+-
+- if (ret < 0 && errno == EAGAIN)
+- ret = 0;
+- if (ret >= 0 && ret < len) {
+- if (servconn->tx_handler == 0)
+- servconn->tx_handler = purple_input_add(
+- servconn->fd, PURPLE_INPUT_WRITE,
+- servconn_write_cb, servconn);
+- purple_circ_buffer_append(servconn->tx_buf, buf + ret,
+- len - ret);
+- }
+- }
+- else
+- {
+- ret = msn_httpconn_write(servconn->httpconn, buf, len);
+- }
+-
+- if (ret == -1)
+- {
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_WRITE, NULL);
+- }
+-
+- servconn_timeout_renew(servconn);
+- return ret;
+-}
+-
+-static void
+-read_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- MsnServConn *servconn;
+- char buf[MSN_BUF_LEN];
+- gssize len;
+-
+- servconn = data;
+-
+- if (servconn->type == MSN_SERVCONN_NS)
+- servconn->session->account->gc->last_received = time(NULL);
+-
+- len = read(servconn->fd, buf, sizeof(buf) - 1);
+- if (len < 0 && errno == EAGAIN)
+- return;
+- if (len <= 0) {
+- purple_debug_error("msn", "servconn %03d read error, "
+- "len: %" G_GSSIZE_FORMAT ", errno: %d, error: %s\n",
+- servconn->num, len, errno, g_strerror(errno));
+- msn_servconn_got_error(servconn, MSN_SERVCONN_ERROR_READ, NULL);
+-
+- return;
+- }
+-
+- buf[len] = '\0';
+-
+- servconn->rx_buf = g_realloc(servconn->rx_buf, len + servconn->rx_len + 1);
+- memcpy(servconn->rx_buf + servconn->rx_len, buf, len + 1);
+- servconn->rx_len += len;
+-
+- servconn = msn_servconn_process_data(servconn);
+- if (servconn)
+- servconn_timeout_renew(servconn);
+-}
+-
+-MsnServConn *msn_servconn_process_data(MsnServConn *servconn)
+-{
+- char *cur, *end, *old_rx_buf;
+- int cur_len;
+-
+- end = old_rx_buf = servconn->rx_buf;
+-
+- servconn->processing = TRUE;
+-
+- do
+- {
+- cur = end;
+-
+- if (servconn->payload_len)
+- {
+- if (servconn->payload_len > servconn->rx_len)
+- /* The payload is still not complete. */
+- break;
+-
+- cur_len = servconn->payload_len;
+- end += cur_len;
+- }
+- else
+- {
+- end = strstr(cur, "\r\n");
+-
+- if (end == NULL)
+- /* The command is still not complete. */
+- break;
+-
+- *end = '\0';
+- end += 2;
+- cur_len = end - cur;
+- }
+-
+- servconn->rx_len -= cur_len;
+-
+- if (servconn->payload_len)
+- {
+- msn_cmdproc_process_payload(servconn->cmdproc, cur, cur_len);
+- servconn->payload_len = 0;
+- }
+- else
+- {
+- msn_cmdproc_process_cmd_text(servconn->cmdproc, cur);
+- servconn->payload_len = servconn->cmdproc->last_cmd->payload_len;
+- }
+- } while (servconn->connected && !servconn->wasted && servconn->rx_len > 0);
+-
+- if (servconn->connected && !servconn->wasted)
+- {
+- if (servconn->rx_len > 0)
+- servconn->rx_buf = g_memdup(cur, servconn->rx_len);
+- else
+- servconn->rx_buf = NULL;
+- }
+-
+- servconn->processing = FALSE;
+-
+- if (servconn->wasted) {
+- msn_servconn_destroy(servconn);
+- servconn = NULL;
+- }
+-
+- g_free(old_rx_buf);
+- return servconn;
+-}
+-
+-#if 0
+-static int
+-create_listener(int port)
+-{
+- int fd;
+- int flags;
+- const int on = 1;
+-
+-#if 0
+- struct addrinfo hints;
+- struct addrinfo *c, *res;
+- char port_str[5];
+-
+- snprintf(port_str, sizeof(port_str), "%d", port);
+-
+- memset(&hints, 0, sizeof(hints));
+-
+- hints.ai_flags = AI_PASSIVE;
+- hints.ai_family = AF_UNSPEC;
+- hints.ai_socktype = SOCK_STREAM;
+-
+- if (getaddrinfo(NULL, port_str, &hints, &res) != 0)
+- {
+- purple_debug_error("msn", "Could not get address info: %s.\n",
+- port_str);
+- return -1;
+- }
+-
+- for (c = res; c != NULL; c = c->ai_next)
+- {
+- fd = socket(c->ai_family, c->ai_socktype, c->ai_protocol);
+-
+- if (fd < 0)
+- continue;
+-
+- setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+-
+- if (bind(fd, c->ai_addr, c->ai_addrlen) == 0)
+- break;
+-
+- close(fd);
+- }
+-
+- if (c == NULL)
+- {
+- purple_debug_error("msn", "Could not find socket: %s.\n", port_str);
+- return -1;
+- }
+-
+- freeaddrinfo(res);
+-#else
+- struct sockaddr_in sockin;
+-
+- fd = socket(AF_INET, SOCK_STREAM, 0);
+-
+- if (fd < 0)
+- return -1;
+-
+- if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&on, sizeof(on)) != 0)
+- {
+- close(fd);
+- return -1;
+- }
+-
+- memset(&sockin, 0, sizeof(struct sockaddr_in));
+- sockin.sin_family = AF_INET;
+- sockin.sin_port = htons(port);
+-
+- if (bind(fd, (struct sockaddr *)&sockin, sizeof(struct sockaddr_in)) != 0)
+- {
+- close(fd);
+- return -1;
+- }
+-#endif
+-
+- if (listen (fd, 4) != 0)
+- {
+- close (fd);
+- return -1;
+- }
+-
+- flags = fcntl(fd, F_GETFL);
+- fcntl(fd, F_SETFL, flags | O_NONBLOCK);
+-#ifndef _WIN32
+- fcntl(fd, F_SETFD, FD_CLOEXEC);
+-#endif
+-
+- return fd;
+-}
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/servconn.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.h
+--- pidgin-2.10.7/libpurple/protocols/msn/servconn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/servconn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,193 +0,0 @@
+-/**
+- * @file servconn.h Server connection functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SERVCONN_H
+-#define MSN_SERVCONN_H
+-
+-typedef struct _MsnServConn MsnServConn;
+-
+-/**
+- * Connection error types.
+- */
+-typedef enum
+-{
+- MSN_SERVCONN_ERROR_NONE,
+- MSN_SERVCONN_ERROR_CONNECT,
+- MSN_SERVCONN_ERROR_WRITE,
+- MSN_SERVCONN_ERROR_READ
+-} MsnServConnError;
+-
+-/**
+- * Connection types.
+- */
+-typedef enum
+-{
+- MSN_SERVCONN_NS,
+- MSN_SERVCONN_SB
+-} MsnServConnType;
+-
+-#include "internal.h"
+-#include "proxy.h"
+-
+-#include "cmdproc.h"
+-#include "httpconn.h"
+-#include "session.h"
+-
+-/**
+- * A Connection.
+- */
+-struct _MsnServConn
+-{
+- MsnServConnType type; /**< The type of this connection. */
+- MsnSession *session; /**< The MSN session of this connection. */
+- MsnCmdProc *cmdproc; /**< The command processor of this connection. */
+-
+- PurpleProxyConnectData *connect_data;
+-
+- gboolean connected; /**< A flag that states if it's connected. */
+- gboolean processing; /**< A flag that states if something is working
+- with this connection. */
+- gboolean wasted; /**< A flag that states if it should be destroyed. */
+-
+- char *host; /**< The host this connection is connected or should be
+- connected to. */
+- int num; /**< A number id of this connection. */
+-
+- MsnHttpConn *httpconn; /**< The HTTP connection this connection should use. */
+-
+- int fd; /**< The connection's file descriptor. */
+- int inpa; /**< The connection's input handler. */
+-
+- char *rx_buf; /**< The receive buffer. */
+- int rx_len; /**< The receive buffer lenght. */
+-
+- size_t payload_len; /**< The length of the payload.
+- It's only set when we've received a command that
+- has a payload. */
+-
+- PurpleCircBuffer *tx_buf;
+- guint tx_handler;
+- guint timeout_sec;
+- guint timeout_handle;
+-
+- void (*connect_cb)(MsnServConn *); /**< The callback to call when connecting. */
+- void (*disconnect_cb)(MsnServConn *); /**< The callback to call when disconnecting. */
+- void (*destroy_cb)(MsnServConn *); /**< The callback to call when destroying. */
+-};
+-
+-/**
+- * Creates a new connection object.
+- *
+- * @param session The session.
+- * @param type The type of the connection.
+- */
+-MsnServConn *msn_servconn_new(MsnSession *session, MsnServConnType type);
+-
+-/**
+- * Destroys a connection object.
+- *
+- * @param servconn The connection.
+- */
+-void msn_servconn_destroy(MsnServConn *servconn);
+-
+-/**
+- * Connects to a host.
+- *
+- * @param servconn The connection.
+- * @param host The host.
+- * @param port The port.
+- * @param force Force this servconn to connect to a new server.
+- */
+-gboolean msn_servconn_connect(MsnServConn *servconn, const char *host, int port,
+- gboolean force);
+-
+-/**
+- * Disconnects.
+- *
+- * @param servconn The connection.
+- */
+-void msn_servconn_disconnect(MsnServConn *servconn);
+-
+-/**
+- * Sets the connect callback.
+- *
+- * @param servconn The servconn.
+- * @param connect_cb The connect callback.
+- */
+-void msn_servconn_set_connect_cb(MsnServConn *servconn,
+- void (*connect_cb)(MsnServConn *));
+-/**
+- * Sets the disconnect callback.
+- *
+- * @param servconn The servconn.
+- * @param disconnect_cb The disconnect callback.
+- */
+-void msn_servconn_set_disconnect_cb(MsnServConn *servconn,
+- void (*disconnect_cb)(MsnServConn *));
+-/**
+- * Sets the destroy callback.
+- *
+- * @param servconn The servconn that's being destroyed.
+- * @param destroy_cb The destroy callback.
+- */
+-void msn_servconn_set_destroy_cb(MsnServConn *servconn,
+- void (*destroy_cb)(MsnServConn *));
+-
+-/**
+- * Writes a chunck of data to the servconn.
+- *
+- * @param servconn The servconn.
+- * @param buf The data to write.
+- * @param size The size of the data.
+- */
+-gssize msn_servconn_write(MsnServConn *servconn, const char *buf,
+- size_t size);
+-
+-/**
+- * Function to call whenever an error related to a switchboard occurs.
+- *
+- * @param servconn The servconn.
+- * @param error The error that happened.
+- */
+-void msn_servconn_got_error(MsnServConn *servconn, MsnServConnError error,
+- const char *reason);
+-
+-/**
+- * Process the data in servconn->rx_buf. This is called after reading
+- * data from the socket.
+- *
+- * @param servconn The servconn.
+- *
+- * @return @c NULL if servconn was destroyed, 'servconn' otherwise.
+- */
+-MsnServConn *msn_servconn_process_data(MsnServConn *servconn);
+-
+-/**
+- * Set a idle timeout fot this servconn
+- *
+- * @param servconn The servconn
+- * @param seconds The idle timeout in seconds
+- */
+-void msn_servconn_set_idle_timeout(MsnServConn *servconn, guint seconds);
+-
+-#endif /* MSN_SERVCONN_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/session.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.c
+--- pidgin-2.10.7/libpurple/protocols/msn/session.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,500 +0,0 @@
+-/**
+- * @file session.c MSN session functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "error.h"
+-#include "msnutils.h"
+-#include "session.h"
+-#include "notification.h"
+-#include "oim.h"
+-
+-MsnSession *
+-msn_session_new(PurpleAccount *account)
+-{
+- MsnSession *session;
+-
+- g_return_val_if_fail(account != NULL, NULL);
+-
+- session = g_new0(MsnSession, 1);
+-
+- session->account = account;
+- session->notification = msn_notification_new(session);
+- session->userlist = msn_userlist_new(session);
+-
+- session->user = msn_user_new(session->userlist,
+- purple_account_get_username(account), NULL);
+- msn_userlist_add_user(session->userlist, session->user);
+- session->oim = msn_oim_new(session);
+-
+- session->protocol_ver = 0;
+- session->enable_mpop = TRUE; /* Default only */
+-
+- session->guid = rand_guid();
+-
+- return session;
+-}
+-
+-void
+-msn_session_destroy(MsnSession *session)
+-{
+- g_return_if_fail(session != NULL);
+-
+- session->destroying = TRUE;
+-
+- while (session->url_datas) {
+- purple_util_fetch_url_cancel(session->url_datas->data);
+- session->url_datas = g_slist_delete_link(session->url_datas, session->url_datas);
+- }
+-
+- if (session->connected)
+- msn_session_disconnect(session);
+-
+- if (session->soap_cleanup_handle)
+- purple_timeout_remove(session->soap_cleanup_handle);
+-
+- if (session->soap_table != NULL)
+- g_hash_table_destroy(session->soap_table);
+-
+- while (session->slplinks != NULL)
+- msn_slplink_unref(session->slplinks->data);
+-
+- while (session->switches != NULL)
+- msn_switchboard_destroy(session->switches->data);
+-
+- if (session->oim != NULL)
+- msn_oim_destroy(session->oim);
+-
+- if (session->nexus != NULL)
+- msn_nexus_destroy(session->nexus);
+-
+- if (session->user != NULL)
+- msn_user_unref(session->user);
+-
+- if (session->notification != NULL)
+- msn_notification_destroy(session->notification);
+-
+- msn_userlist_destroy(session->userlist);
+-
+- g_free(session->psm);
+- g_free(session->guid);
+- g_free(session->abch_cachekey);
+-#if 0
+- g_free(session->blocked_text);
+-#endif
+-
+- g_free(session->passport_info.sid);
+- g_free(session->passport_info.mspauth);
+- g_free(session->passport_info.client_ip);
+- g_free(session->passport_info.mail_url);
+-
+- g_free(session);
+-}
+-
+-gboolean
+-msn_session_connect(MsnSession *session, const char *host, int port,
+- gboolean http_method)
+-{
+- g_return_val_if_fail(session != NULL, FALSE);
+- g_return_val_if_fail(!session->connected, TRUE);
+-
+- session->connected = TRUE;
+- session->http_method = http_method;
+-
+- if (session->notification == NULL)
+- {
+- purple_debug_error("msn", "This shouldn't happen\n");
+- g_return_val_if_reached(FALSE);
+- }
+-
+- return msn_notification_connect(session->notification, host, port);
+-}
+-
+-void
+-msn_session_disconnect(MsnSession *session)
+-{
+- g_return_if_fail(session != NULL);
+-
+- if (!session->connected)
+- return;
+-
+- if (session->login_timeout) {
+- purple_timeout_remove(session->login_timeout);
+- session->login_timeout = 0;
+- }
+-
+- session->connected = FALSE;
+-
+- while (session->switches != NULL)
+- msn_switchboard_close(session->switches->data);
+-
+- if (session->notification != NULL)
+- msn_notification_close(session->notification);
+-}
+-
+-/* TODO: This must go away when conversation is redesigned */
+-MsnSwitchBoard *
+-msn_session_find_swboard(MsnSession *session, const char *username)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+- g_return_val_if_fail(username != NULL, NULL);
+-
+- for (l = session->switches; l != NULL; l = l->next)
+- {
+- MsnSwitchBoard *swboard;
+-
+- swboard = l->data;
+-
+- if ((swboard->im_user != NULL) && !strcmp(username, swboard->im_user))
+- return swboard;
+- }
+-
+- return NULL;
+-}
+-
+-static PurpleConversation *
+-msn_session_get_conv(MsnSession *session,const char *passport)
+-{
+- PurpleAccount *account;
+- PurpleConversation * conv;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+- account = session->account;
+-
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- passport, account);
+- if(conv == NULL){
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, passport);
+- }
+- return conv;
+-}
+-
+-/* put Message to User Conversation
+- *
+- * passport - the one want to talk to you
+- */
+-void
+-msn_session_report_user(MsnSession *session,const char *passport,const char *msg,PurpleMessageFlags flags)
+-{
+- PurpleConversation * conv;
+-
+- if ((conv = msn_session_get_conv(session,passport)) != NULL){
+- purple_conversation_write(conv, NULL, msg, flags, time(NULL));
+- }
+-}
+-
+-MsnSwitchBoard *
+-msn_session_find_swboard_with_conv(MsnSession *session, PurpleConversation *conv)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+- g_return_val_if_fail(conv != NULL, NULL);
+-
+- for (l = session->switches; l != NULL; l = l->next)
+- {
+- MsnSwitchBoard *swboard;
+-
+- swboard = l->data;
+-
+- if (swboard->conv == conv)
+- return swboard;
+- }
+-
+- return NULL;
+-}
+-
+-MsnSwitchBoard *
+-msn_session_find_swboard_with_id(const MsnSession *session, int chat_id)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+- g_return_val_if_fail(chat_id >= 0, NULL);
+-
+- for (l = session->switches; l != NULL; l = l->next)
+- {
+- MsnSwitchBoard *swboard;
+-
+- swboard = l->data;
+-
+- if (swboard->chat_id == chat_id)
+- return swboard;
+- }
+-
+- return NULL;
+-}
+-
+-MsnSwitchBoard *
+-msn_session_get_swboard(MsnSession *session, const char *username,
+- MsnSBFlag flag)
+-{
+- MsnSwitchBoard *swboard;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- swboard = msn_session_find_swboard(session, username);
+-
+- if (swboard == NULL)
+- {
+- swboard = msn_switchboard_new(session);
+- swboard->im_user = g_strdup(username);
+- if (msn_switchboard_request(swboard))
+- msn_switchboard_request_add_user(swboard, username);
+- else
+- return NULL;
+- }
+-
+- swboard->flag |= flag;
+-
+- return swboard;
+-}
+-
+-static gboolean
+-msn_login_timeout_cb(gpointer data)
+-{
+- MsnSession *session = data;
+- /* This forces the login process to finish, even though we haven't heard
+- a response for our FQY requests yet. We'll at least end up online to the
+- people we've already added. The rest will follow later. */
+- msn_session_finish_login(session);
+- session->login_timeout = 0;
+- return FALSE;
+-}
+-
+-void
+-msn_session_activate_login_timeout(MsnSession *session)
+-{
+- if (!session->logged_in && session->connected) {
+- if (session->login_timeout)
+- purple_timeout_remove(session->login_timeout);
+- session->login_timeout =
+- purple_timeout_add_seconds(MSN_LOGIN_FQY_TIMEOUT,
+- msn_login_timeout_cb, session);
+- }
+-}
+-
+-static void
+-msn_session_sync_users(MsnSession *session)
+-{
+- PurpleConnection *gc = purple_account_get_connection(session->account);
+- GList *to_remove = NULL;
+- GSList *buddies;
+-
+- g_return_if_fail(gc != NULL);
+-
+- /* The core used to use msn_add_buddy to add all buddies before
+- * being logged in. This no longer happens, so we manually iterate
+- * over the whole buddy list to identify sync issues.
+- */
+- for (buddies = purple_find_buddies(session->account, NULL); buddies;
+- buddies = g_slist_delete_link(buddies, buddies)) {
+- PurpleBuddy *buddy = buddies->data;
+- const gchar *buddy_name = purple_buddy_get_name(buddy);
+- const gchar *group_name = purple_group_get_name(purple_buddy_get_group(buddy));
+- MsnUser *remote_user;
+- gboolean found = FALSE;
+-
+- remote_user = msn_userlist_find_user(session->userlist, buddy_name);
+- if (remote_user && remote_user->list_op & MSN_LIST_FL_OP) {
+- GList *l;
+- for (l = remote_user->group_ids; l; l = l->next) {
+- const char *name = msn_userlist_find_group_name(remote_user->userlist, l->data);
+- if (name && !g_ascii_strcasecmp(group_name, name)) {
+- found = TRUE;
+- break;
+- }
+- }
+-
+- /* We don't care if they're in a different group, as long as they're on the
+- * list somewhere. If we check for the group, we cause pain, agony and
+- * suffering for people who decide to re-arrange their buddy list elsewhere.
+- */
+- if (!found) {
+- if ((remote_user == NULL) || !(remote_user->list_op & MSN_LIST_FL_OP)) {
+- /* The user is not on the server list */
+- msn_error_sync_issue(session, buddy_name, group_name);
+- } else {
+- /* The user is not in that group on the server list */
+- to_remove = g_list_prepend(to_remove, buddy);
+- }
+- }
+- }
+- }
+-
+- if (to_remove != NULL) {
+- g_list_foreach(to_remove, (GFunc)purple_blist_remove_buddy, NULL);
+- g_list_free(to_remove);
+- }
+-}
+-
+-void
+-msn_session_set_error(MsnSession *session, MsnErrorType error,
+- const char *info)
+-{
+- PurpleConnection *gc;
+- PurpleConnectionError reason;
+- char *msg;
+-
+- if (session->destroying)
+- return;
+-
+- gc = purple_account_get_connection(session->account);
+-
+- switch (error)
+- {
+- case MSN_ERROR_SERVCONN:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(info);
+- break;
+- case MSN_ERROR_UNSUPPORTED_PROTOCOL:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("Our protocol is not supported by the "
+- "server"));
+- break;
+- case MSN_ERROR_HTTP_MALFORMED:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("Error parsing HTTP"));
+- break;
+- case MSN_ERROR_SIGN_OTHER:
+- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
+- msg = g_strdup(_("You have signed on from another location"));
+- if (!purple_account_get_remember_password(session->account))
+- purple_account_set_password(session->account, NULL);
+- break;
+- case MSN_ERROR_SERV_UNAVAILABLE:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("The MSN servers are temporarily "
+- "unavailable. Please wait and try "
+- "again."));
+- break;
+- case MSN_ERROR_SERV_DOWN:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("The MSN servers are going down "
+- "temporarily"));
+- break;
+- case MSN_ERROR_AUTH:
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- msg = g_strdup_printf(_("Unable to authenticate: %s"),
+- (info == NULL ) ?
+- _("Unknown error") : info);
+- /* Clear the password if it isn't being saved */
+- if (!purple_account_get_remember_password(session->account))
+- purple_account_set_password(session->account, NULL);
+- break;
+- case MSN_ERROR_BAD_BLIST:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("Your MSN buddy list is temporarily "
+- "unavailable. Please wait and try "
+- "again."));
+- break;
+- default:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- msg = g_strdup(_("Unknown error"));
+- break;
+- }
+-
+- msn_session_disconnect(session);
+-
+- purple_connection_error_reason(gc, reason, msg);
+-
+- g_free(msg);
+-}
+-
+-static const char *
+-get_login_step_text(MsnSession *session)
+-{
+- const char *steps_text[] = {
+- _("Connecting"),
+- _("Handshaking"),
+- _("Transferring"),
+- _("Handshaking"),
+- _("Starting authentication"),
+- _("Getting cookie"),
+- _("Authenticating"),
+- _("Sending cookie"),
+- _("Retrieving buddy list")
+- };
+-
+- return steps_text[session->login_step];
+-}
+-
+-void
+-msn_session_set_login_step(MsnSession *session, MsnLoginStep step)
+-{
+- PurpleConnection *gc;
+-
+- /* Prevent the connection progress going backwards, eg. if we get
+- * transferred several times during login */
+- if (session->login_step >= step)
+- return;
+-
+- /* If we're already logged in, we're probably here because of a
+- * mid-session XFR from the notification server, so we don't want to
+- * popup the connection progress dialog */
+- if (session->logged_in)
+- return;
+-
+- gc = session->account->gc;
+-
+- session->login_step = step;
+-
+- purple_connection_update_progress(gc, get_login_step_text(session), step,
+- MSN_LOGIN_STEPS);
+-}
+-
+-void
+-msn_session_finish_login(MsnSession *session)
+-{
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- PurpleStoredImage *img;
+-
+- if (!session->logged_in) {
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- img = purple_buddy_icons_find_account_icon(session->account);
+- /* TODO: Do we really want to call this if img is NULL? */
+- msn_user_set_buddy_icon(session->user, img);
+- if (img != NULL)
+- purple_imgstore_unref(img);
+-
+- session->logged_in = TRUE;
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+-
+- /* Sync users */
+- msn_session_sync_users(session);
+- }
+-
+- /* TODO: Send this when updating status instead? */
+- msn_notification_send_uux_endpointdata(session);
+- msn_notification_send_uux_private_endpointdata(session);
+-
+- msn_change_status(session);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/session.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.h
+--- pidgin-2.10.7/libpurple/protocols/msn/session.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/session.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,245 +0,0 @@
+-/**
+- * @file session.h MSN session functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SESSION_H
+-#define MSN_SESSION_H
+-
+-typedef struct _MsnSession MsnSession;
+-
+-/**
+- * Types of errors.
+- */
+-typedef enum
+-{
+- MSN_ERROR_SERVCONN,
+- MSN_ERROR_UNSUPPORTED_PROTOCOL,
+- MSN_ERROR_HTTP_MALFORMED,
+- MSN_ERROR_AUTH,
+- MSN_ERROR_BAD_BLIST,
+- MSN_ERROR_SIGN_OTHER,
+- MSN_ERROR_SERV_DOWN,
+- MSN_ERROR_SERV_UNAVAILABLE
+-} MsnErrorType;
+-
+-/**
+- * Login steps.
+- */
+-typedef enum
+-{
+- MSN_LOGIN_STEP_START,
+- MSN_LOGIN_STEP_HANDSHAKE,
+- MSN_LOGIN_STEP_TRANSFER,
+- MSN_LOGIN_STEP_HANDSHAKE2,
+- MSN_LOGIN_STEP_AUTH_START,
+- MSN_LOGIN_STEP_GET_COOKIE,
+- MSN_LOGIN_STEP_AUTH_END,
+- MSN_LOGIN_STEP_SYN,
+- MSN_LOGIN_STEP_END
+-} MsnLoginStep;
+-
+-#define MSN_LOGIN_STEPS MSN_LOGIN_STEP_END
+-
+-#define MSN_LOGIN_FQY_TIMEOUT 30
+-
+-#define MSN_LOGIN_FQY_TIMEOUT 30
+-
+-#include "nexus.h"
+-#include "notification.h"
+-#include "oim.h"
+-#include "switchboard.h"
+-#include "user.h"
+-#include "userlist.h"
+-
+-struct _MsnSession
+-{
+- PurpleAccount *account;
+- MsnUser *user;
+-
+- guint protocol_ver;
+-
+- MsnLoginStep login_step; /**< The current step in the login process. */
+-
+- gboolean connected:1;
+- gboolean logged_in:1; /**< A temporal flag to ignore local buddy list adds. */
+- gboolean destroying:1; /**< A flag that states if the session is being destroyed. */
+- gboolean http_method:1;
+- gboolean enable_mpop:1; /**< Use Multiple Points of Presence? */
+- int adl_fqy; /**< A count of ADL/FQY so status is only changed once. */
+- guint login_timeout; /**< Timeout to force status change if ADL/FQY fail. */
+-
+- MsnNotification *notification;
+- MsnNexus *nexus;
+- MsnOim *oim;
+- MsnUserList *userlist;
+- char *abch_cachekey;
+-
+- int servconns_count; /**< The count of server connections. */
+- GList *switches; /**< The list of all the switchboards. */
+- GList *slplinks; /**< The list of all the slplinks. */
+-
+- /*psm info*/
+- char *psm;
+-
+-#if 0
+- char *blocked_text;
+-#endif
+-
+- struct
+- {
+- char *sid;
+- char *mspauth;
+- unsigned long sl;
+- char *client_ip;
+- int client_port;
+- char *mail_url;
+- gulong mail_timestamp;
+- gboolean email_enabled;
+- } passport_info;
+-
+- GHashTable *soap_table;
+- guint soap_cleanup_handle;
+- char *guid;
+-
+- GSList *url_datas; /**< PurpleUtilFetchUrlData to be cancelled on exit */
+-};
+-
+-/**
+- * Creates an MSN session.
+- *
+- * @param account The account.
+- *
+- * @return The new MSN session.
+- */
+-MsnSession *msn_session_new(PurpleAccount *account);
+-
+-/**
+- * Destroys an MSN session.
+- *
+- * @param session The MSN session to destroy.
+- */
+-void msn_session_destroy(MsnSession *session);
+-
+-/**
+- * Connects to and initiates an MSN session.
+- *
+- * @param session The MSN session.
+- * @param host The dispatch server host.
+- * @param port The dispatch server port.
+- * @param http_method Whether to use or not http_method.
+- *
+- * @return @c TRUE on success, @c FALSE on failure.
+- */
+-gboolean msn_session_connect(MsnSession *session,
+- const char *host, int port,
+- gboolean http_method);
+-
+-/**
+- * Disconnects from an MSN session.
+- *
+- * @param session The MSN session.
+- */
+-void msn_session_disconnect(MsnSession *session);
+-
+- /**
+- * Finds a switchboard with the given username.
+- *
+- * @param session The MSN session.
+- * @param username The username to search for.
+- *
+- * @return The switchboard, if found.
+- */
+-MsnSwitchBoard *msn_session_find_swboard(MsnSession *session,
+- const char *username);
+-
+- /**
+- * Finds a switchboard with the given conversation.
+- *
+- * @param session The MSN session.
+- * @param conv The conversation to search for.
+- *
+- * @return The switchboard, if found.
+- */
+-MsnSwitchBoard *msn_session_find_swboard_with_conv(MsnSession *session,
+- PurpleConversation *conv);
+-/**
+- * Finds a switchboard with the given chat ID.
+- *
+- * @param session The MSN session.
+- * @param chat_id The chat ID to search for.
+- *
+- * @return The switchboard, if found.
+- */
+-MsnSwitchBoard *msn_session_find_swboard_with_id(const MsnSession *session,
+- int chat_id);
+-
+-/**
+- * Returns a switchboard to communicate with certain username.
+- *
+- * @param session The MSN session.
+- * @param username The username to search for.
+- * @param flag The flag of the switchboard
+- *
+- * @return The switchboard.
+- */
+-MsnSwitchBoard *msn_session_get_swboard(MsnSession *session,
+- const char *username, MsnSBFlag flag);
+-
+-/**
+- * Sets an error for the MSN session.
+- *
+- * @param session The MSN session.
+- * @param error The error.
+- * @param info Extra information.
+- */
+-void msn_session_set_error(MsnSession *session, MsnErrorType error,
+- const char *info);
+-
+-/**
+- * Starts a timeout to initiate finishing login. Sometimes the server ignores
+- * our FQY requests, so this forces ourselves online eventually.
+- *
+- * @param session The MSN session.
+- */
+-void
+-msn_session_activate_login_timeout(MsnSession *session);
+-
+-/**
+- * Sets the current step in the login process.
+- *
+- * @param session The MSN session.
+- * @param step The current step.
+- */
+-void msn_session_set_login_step(MsnSession *session, MsnLoginStep step);
+-
+-/**
+- * Finish the login proccess.
+- *
+- * @param session The MSN session.
+- */
+-void msn_session_finish_login(MsnSession *session);
+-
+-/*post message to User*/
+-void msn_session_report_user(MsnSession *session,const char *passport,
+- const char *msg,PurpleMessageFlags flags);
+-
+-#endif /* MSN_SESSION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slp.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.c
+--- pidgin-2.10.7/libpurple/protocols/msn/slp.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,396 +0,0 @@
+-/**
+- * @file msnslp.c MSNSLP support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "slp.h"
+-#include "slpcall.h"
+-#include "slpmsg.h"
+-#include "msnutils.h"
+-
+-#include "object.h"
+-#include "user.h"
+-#include "sbconn.h"
+-#include "directconn.h"
+-#include "p2p.h"
+-#include "xfer.h"
+-
+-/* seconds to delay between sending buddy icon requests to the server. */
+-#define BUDDY_ICON_DELAY 20
+-
+-typedef struct {
+- MsnSession *session;
+- const char *remote_user;
+- const char *sha1;
+-} MsnFetchUserDisplayData;
+-
+-/**************************************************************************
+- * SLP Control
+- **************************************************************************/
+-
+-void
+-msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
+- const char *type, const char *content)
+-{
+- MsnSlpLink *slplink;
+- MsnSlpMessage *slpmsg;
+-
+- slplink = slpcall->slplink;
+-
+- /* 200 OK */
+- slpmsg = msn_slpmsg_sip_new(slpcall, 1,
+- "MSNSLP/1.0 200 OK",
+- branch, type, content);
+-
+- slpmsg->info = "SLP 200 OK";
+- slpmsg->text_body = TRUE;
+-
+- msn_slplink_queue_slpmsg(slplink, slpmsg);
+-}
+-
+-void
+-msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
+- const char *type, const char *content)
+-{
+- MsnSlpLink *slplink;
+- MsnSlpMessage *slpmsg;
+-
+- slplink = slpcall->slplink;
+-
+- /* 603 Decline */
+- slpmsg = msn_slpmsg_sip_new(slpcall, 1,
+- "MSNSLP/1.0 603 Decline",
+- branch, type, content);
+-
+- slpmsg->info = "SLP 603 Decline";
+- slpmsg->text_body = TRUE;
+-
+- msn_slplink_queue_slpmsg(slplink, slpmsg);
+-}
+-
+-/**************************************************************************
+- * Msg Callbacks
+- **************************************************************************/
+-
+-/*
+- * Called on a timeout from end_user_display(). Frees a buddy icon window slow and dequeues the next
+- * buddy icon request if there is one.
+- */
+-static gboolean
+-msn_release_buddy_icon_request_timeout(gpointer data)
+-{
+- MsnUserList *userlist = (MsnUserList *)data;
+-
+- /* Free one window slot */
+- userlist->buddy_icon_window++;
+-
+- /* Clear the tag for our former request timer */
+- userlist->buddy_icon_request_timer = 0;
+-
+- msn_release_buddy_icon_request(userlist);
+-
+- return FALSE;
+-}
+-
+-static void
+-got_user_display(MsnSlpCall *slpcall,
+- const guchar *data, gsize size)
+-{
+- const char *info;
+- PurpleAccount *account;
+-
+- g_return_if_fail(slpcall != NULL);
+-
+- info = slpcall->data_info;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Got User Display: %s\n", slpcall->slplink->remote_user);
+-
+- account = slpcall->slplink->session->account;
+-
+- purple_buddy_icons_set_for_user(account, slpcall->slplink->remote_user,
+- g_memdup(data, size), size, info);
+-}
+-
+-static void
+-end_user_display(MsnSlpCall *slpcall, MsnSession *session)
+-{
+- MsnUserList *userlist;
+-
+- g_return_if_fail(session != NULL);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "End User Display\n");
+-
+- userlist = session->userlist;
+-
+- /* If the session is being destroyed we better stop doing anything. */
+- if (session->destroying)
+- return;
+-
+- /* Delay before freeing a buddy icon window slot and requesting the next icon, if appropriate.
+- * If we don't delay, we'll rapidly hit the MSN equivalent of AIM's rate limiting; the server will
+- * send us an error 800 like so:
+- *
+- * C: NS 000: XFR 21 SB
+- * S: NS 000: 800 21
+- */
+- if (userlist->buddy_icon_request_timer) {
+- /* Free the window slot used by this previous request */
+- userlist->buddy_icon_window++;
+-
+- /* Clear our pending timeout */
+- purple_timeout_remove(userlist->buddy_icon_request_timer);
+- }
+-
+- /* Wait BUDDY_ICON_DELAY s before freeing our window slot and requesting the next icon. */
+- userlist->buddy_icon_request_timer = purple_timeout_add_seconds(BUDDY_ICON_DELAY,
+- msn_release_buddy_icon_request_timeout, userlist);
+-}
+-
+-static void
+-fetched_user_display(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *url_text, gsize len, const gchar *error_message)
+-{
+- MsnFetchUserDisplayData *data = user_data;
+- MsnSession *session = data->session;
+-
+- session->url_datas = g_slist_remove(session->url_datas, url_data);
+-
+- if (url_text) {
+- purple_buddy_icons_set_for_user(session->account, data->remote_user,
+- g_memdup(url_text, len), len,
+- data->sha1);
+- }
+-
+- end_user_display(NULL, session);
+-
+- g_free(user_data);
+-}
+-
+-static void
+-request_own_user_display(MsnUser *user)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- MsnObject *my_obj = NULL;
+- gconstpointer data = NULL;
+- const char *info = NULL;
+- size_t len = 0;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Requesting our own user display\n");
+-
+- session = user->userlist->session;
+- account = session->account;
+- my_obj = msn_user_get_object(user);
+-
+- if (my_obj != NULL) {
+- PurpleStoredImage *img = msn_object_get_image(my_obj);
+- data = purple_imgstore_get_data(img);
+- len = purple_imgstore_get_size(img);
+- info = msn_object_get_sha1(my_obj);
+- }
+-
+- purple_buddy_icons_set_for_user(account, user->passport, g_memdup(data, len), len, info);
+-
+- /* Free one window slot */
+- session->userlist->buddy_icon_window++;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "msn_request_user_display(): buddy_icon_window++ yields =%d\n",
+- session->userlist->buddy_icon_window);
+-
+- msn_release_buddy_icon_request(session->userlist);
+-}
+-
+-void
+-msn_request_user_display(MsnUser *user)
+-{
+- PurpleAccount *account;
+- MsnSession *session;
+- MsnSlpLink *slplink;
+- MsnObject *obj;
+- const char *info;
+-
+- session = user->userlist->session;
+- account = session->account;
+-
+- slplink = msn_session_get_slplink(session, user->passport);
+-
+- obj = msn_user_get_object(user);
+-
+- info = msn_object_get_sha1(obj);
+-
+- if (g_ascii_strcasecmp(user->passport,
+- purple_account_get_username(account)))
+- {
+- const char *url = msn_object_get_url1(obj);
+- if (url) {
+- MsnFetchUserDisplayData *data = g_new0(MsnFetchUserDisplayData, 1);
+- PurpleUtilFetchUrlData *url_data;
+- data->session = session;
+- data->remote_user = user->passport;
+- data->sha1 = info;
+- url_data = purple_util_fetch_url_len(url, TRUE, NULL, TRUE, 200*1024,
+- fetched_user_display, data);
+- session->url_datas = g_slist_prepend(session->url_datas, url_data);
+- } else {
+- msn_slplink_request_object(slplink, info, got_user_display,
+- end_user_display, obj);
+- }
+- }
+- else
+- request_own_user_display(user);
+-}
+-
+-static void
+-send_file_cb(MsnSlpCall *slpcall)
+-{
+- MsnSlpMessage *slpmsg;
+- PurpleXfer *xfer;
+-
+- xfer = (PurpleXfer *)slpcall->xfer;
+- if (purple_xfer_get_status(xfer) >= PURPLE_XFER_STATUS_STARTED)
+- return;
+-
+- purple_xfer_ref(xfer);
+- purple_xfer_start(xfer, -1, NULL, 0);
+- if (purple_xfer_get_status(xfer) != PURPLE_XFER_STATUS_STARTED) {
+- purple_xfer_unref(xfer);
+- return;
+- }
+- purple_xfer_unref(xfer);
+-
+- slpmsg = msn_slpmsg_file_new(slpcall, purple_xfer_get_size(xfer));
+-
+- msn_slplink_send_slpmsg(slpcall->slplink, slpmsg);
+-}
+-
+-static gchar *
+-gen_context(PurpleXfer *xfer, const char *file_name, const char *file_path)
+-{
+- gsize size = 0;
+- MsnFileContext context;
+- gchar *u8 = NULL;
+- gchar *ret;
+- gunichar2 *uni = NULL;
+- glong currentChar = 0;
+- glong len = 0;
+- const char *preview;
+- gsize preview_len;
+-
+- size = purple_xfer_get_size(xfer);
+-
+- purple_xfer_prepare_thumbnail(xfer, "png");
+-
+- if (!file_name) {
+- gchar *basename = g_path_get_basename(file_path);
+- u8 = purple_utf8_try_convert(basename);
+- g_free(basename);
+- file_name = u8;
+- }
+-
+- uni = g_utf8_to_utf16(file_name, -1, NULL, &len, NULL);
+-
+- if (u8) {
+- g_free(u8);
+- file_name = NULL;
+- u8 = NULL;
+- }
+-
+- preview = purple_xfer_get_thumbnail(xfer, &preview_len);
+-
+- context.length = MSN_FILE_CONTEXT_SIZE;
+- context.version = 2; /* V.3 contains additional unnecessary data */
+- context.file_size = size;
+- if (preview)
+- context.type = 0;
+- else
+- context.type = 1;
+-
+- len = MIN(len, MAX_FILE_NAME_LEN);
+- for (currentChar = 0; currentChar < len; currentChar++) {
+- context.file_name[currentChar] = GUINT16_TO_LE(uni[currentChar]);
+- }
+- memset(&context.file_name[currentChar], 0x00, (MAX_FILE_NAME_LEN - currentChar) * 2);
+-
+- memset(&context.unknown1, 0, sizeof(context.unknown1));
+- context.unknown2 = 0xffffffff;
+-
+- /* Mind the cast, as in, don't free it after! */
+- context.preview = (char *)preview;
+- context.preview_len = preview_len;
+-
+- u8 = msn_file_context_to_wire(&context);
+- ret = purple_base64_encode((const guchar *)u8, MSN_FILE_CONTEXT_SIZE + preview_len);
+-
+- g_free(uni);
+- g_free(u8);
+-
+- return ret;
+-}
+-
+-void
+-msn_request_ft(PurpleXfer *xfer)
+-{
+- MsnSlpCall *slpcall;
+- MsnSlpLink *slplink;
+- char *context;
+- const char *fn;
+- const char *fp;
+-
+- fn = purple_xfer_get_filename(xfer);
+- fp = purple_xfer_get_local_filename(xfer);
+-
+- slplink = xfer->data;
+-
+- g_return_if_fail(slplink != NULL);
+- g_return_if_fail(fp != NULL);
+-
+- slpcall = msn_slpcall_new(slplink);
+- msn_slpcall_init(slpcall, MSN_SLPCALL_DC);
+-
+- slpcall->session_init_cb = send_file_cb;
+- slpcall->end_cb = msn_xfer_end_cb;
+- slpcall->cb = msn_xfer_completed_cb;
+- slpcall->xfer = xfer;
+- purple_xfer_ref(slpcall->xfer);
+-
+- slpcall->pending = TRUE;
+-
+- purple_xfer_set_cancel_send_fnc(xfer, msn_xfer_cancel);
+- purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+- purple_xfer_set_write_fnc(xfer, msn_xfer_write);
+-
+- xfer->data = slpcall;
+-
+- context = gen_context(xfer, fn, fp);
+-
+- msn_slpcall_invite(slpcall, MSN_FT_GUID, P2P_APPID_FILE, context);
+- msn_slplink_unref(slplink);
+-
+- g_free(context);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpcall.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.c
+--- pidgin-2.10.7/libpurple/protocols/msn/slpcall.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1157 +0,0 @@
+-/**
+- * @file slpcall.c SLP Call Functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "smiley.h"
+-
+-#include "msnutils.h"
+-#include "slpcall.h"
+-
+-#include "slp.h"
+-#include "p2p.h"
+-#include "xfer.h"
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-static gboolean
+-msn_slpcall_timeout(gpointer data)
+-{
+- MsnSlpCall *slpcall;
+-
+- slpcall = data;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpcall_timeout: slpcall(%p)\n", slpcall);
+-
+- if (!slpcall->pending && !slpcall->progress)
+- {
+- msn_slpcall_destroy(slpcall);
+- return TRUE;
+- }
+-
+- slpcall->progress = FALSE;
+-
+- return TRUE;
+-}
+-
+-MsnSlpCall *
+-msn_slpcall_new(MsnSlpLink *slplink)
+-{
+- MsnSlpCall *slpcall;
+-
+- g_return_val_if_fail(slplink != NULL, NULL);
+-
+- slpcall = g_new0(MsnSlpCall, 1);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpcall_new: slpcall(%p)\n", slpcall);
+-
+- slpcall->slplink = slplink;
+-
+- msn_slplink_add_slpcall(slplink, slpcall);
+-
+- slpcall->timer = purple_timeout_add_seconds(MSN_SLPCALL_TIMEOUT, msn_slpcall_timeout, slpcall);
+-
+- return slpcall;
+-}
+-
+-void
+-msn_slpcall_destroy(MsnSlpCall *slpcall)
+-{
+- GList *e;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpcall_destroy: slpcall(%p)\n", slpcall);
+-
+- g_return_if_fail(slpcall != NULL);
+-
+- if (slpcall->timer)
+- purple_timeout_remove(slpcall->timer);
+-
+- for (e = slpcall->slplink->slp_msgs; e != NULL; )
+- {
+- MsnSlpMessage *slpmsg = e->data;
+- e = e->next;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpcall_destroy: trying slpmsg(%p)\n",
+- slpmsg);
+-
+- if (slpmsg->slpcall == slpcall)
+- {
+- msn_slpmsg_destroy(slpmsg);
+- }
+- }
+-
+- if (slpcall->end_cb != NULL)
+- slpcall->end_cb(slpcall, slpcall->slplink->session);
+-
+- if (slpcall->xfer != NULL) {
+- if (purple_xfer_get_type(slpcall->xfer) == PURPLE_XFER_RECEIVE)
+- g_byte_array_free(slpcall->u.incoming_data, TRUE);
+- slpcall->xfer->data = NULL;
+- purple_xfer_unref(slpcall->xfer);
+- }
+-
+-
+- msn_slplink_remove_slpcall(slpcall->slplink, slpcall);
+-
+- g_free(slpcall->id);
+- g_free(slpcall->branch);
+- g_free(slpcall->data_info);
+-
+- g_free(slpcall);
+-}
+-
+-void
+-msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type)
+-{
+- slpcall->session_id = rand() % 0xFFFFFF00 + 4;
+- slpcall->id = rand_guid();
+- slpcall->type = type;
+-}
+-
+-void
+-msn_slpcall_session_init(MsnSlpCall *slpcall)
+-{
+- if (slpcall->session_init_cb)
+- slpcall->session_init_cb(slpcall);
+-
+- slpcall->started = TRUE;
+-}
+-
+-void
+-msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
+- MsnP2PAppId app_id, const char *context)
+-{
+- MsnSlpLink *slplink;
+- MsnSlpMessage *slpmsg;
+- char *header;
+- char *content;
+-
+- g_return_if_fail(slpcall != NULL);
+- g_return_if_fail(context != NULL);
+-
+- slplink = slpcall->slplink;
+-
+- slpcall->branch = rand_guid();
+-
+- content = g_strdup_printf(
+- "EUF-GUID: {%s}\r\n"
+- "SessionID: %lu\r\n"
+- "AppID: %d\r\n"
+- "Context: %s\r\n\r\n",
+- euf_guid,
+- slpcall->session_id,
+- app_id,
+- context);
+-
+- header = g_strdup_printf("INVITE MSNMSGR:%s MSNSLP/1.0",
+- slplink->remote_user);
+-
+- slpmsg = msn_slpmsg_sip_new(slpcall, 0, header, slpcall->branch,
+- "application/x-msnmsgr-sessionreqbody", content);
+-
+- slpmsg->info = "SLP INVITE";
+- slpmsg->text_body = TRUE;
+-
+- msn_slplink_send_slpmsg(slplink, slpmsg);
+-
+- g_free(header);
+- g_free(content);
+-}
+-
+-void
+-msn_slpcall_close(MsnSlpCall *slpcall)
+-{
+- g_return_if_fail(slpcall != NULL);
+- g_return_if_fail(slpcall->slplink != NULL);
+-
+- send_bye(slpcall, "application/x-msnmsgr-sessionclosebody");
+- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
+- msn_slpcall_destroy(slpcall);
+-}
+-
+-/*****************************************************************************
+- * Parse received SLP messages
+- ****************************************************************************/
+-
+-/**************************************************************************
+- *** Util
+- **************************************************************************/
+-
+-static char *
+-get_token(const char *str, const char *start, const char *end)
+-{
+- const char *c, *c2;
+-
+- if ((c = strstr(str, start)) == NULL)
+- return NULL;
+-
+- c += strlen(start);
+-
+- if (end != NULL)
+- {
+- if ((c2 = strstr(c, end)) == NULL)
+- return NULL;
+-
+- return g_strndup(c, c2 - c);
+- }
+- else
+- {
+- /* This has to be changed */
+- return g_strdup(c);
+- }
+-
+-}
+-
+-/* XXX: this could be improved if we tracked custom smileys
+- * per-protocol, per-account, per-session or (ideally) per-conversation
+- */
+-static PurpleStoredImage *
+-find_valid_emoticon(PurpleAccount *account, const char *path)
+-{
+- GList *smileys;
+-
+- if (!purple_account_get_bool(account, "custom_smileys", TRUE))
+- return NULL;
+-
+- smileys = purple_smileys_get_all();
+-
+- for (; smileys; smileys = g_list_delete_link(smileys, smileys)) {
+- PurpleSmiley *smiley;
+- PurpleStoredImage *img;
+-
+- smiley = smileys->data;
+- img = purple_smiley_get_stored_image(smiley);
+-
+- if (purple_strequal(path, purple_imgstore_get_filename(img))) {
+- g_list_free(smileys);
+- return img;
+- }
+-
+- purple_imgstore_unref(img);
+- }
+-
+- purple_debug_error("msn", "Received illegal request for file %s\n", path);
+- return NULL;
+-}
+-
+-static char *
+-parse_dc_nonce(const char *content, MsnDirectConnNonceType *ntype)
+-{
+- char *nonce;
+-
+- *ntype = DC_NONCE_UNKNOWN;
+-
+- nonce = get_token(content, "Hashed-Nonce: {", "}\r\n");
+- if (nonce) {
+- *ntype = DC_NONCE_SHA1;
+- } else {
+- guint32 n1, n6;
+- guint16 n2, n3, n4, n5;
+- nonce = get_token(content, "Nonce: {", "}\r\n");
+- if (nonce
+- && sscanf(nonce, "%08x-%04hx-%04hx-%04hx-%04hx%08x",
+- &n1, &n2, &n3, &n4, &n5, &n6) == 6) {
+- *ntype = DC_NONCE_PLAIN;
+- g_free(nonce);
+- nonce = g_malloc(16);
+- *(guint32 *)(nonce + 0) = GUINT32_TO_LE(n1);
+- *(guint16 *)(nonce + 4) = GUINT16_TO_LE(n2);
+- *(guint16 *)(nonce + 6) = GUINT16_TO_LE(n3);
+- *(guint16 *)(nonce + 8) = GUINT16_TO_BE(n4);
+- *(guint16 *)(nonce + 10) = GUINT16_TO_BE(n5);
+- *(guint32 *)(nonce + 12) = GUINT32_TO_BE(n6);
+- } else {
+- /* Invalid nonce, so ignore request */
+- g_free(nonce);
+- nonce = NULL;
+- }
+- }
+-
+- return nonce;
+-}
+-
+-static void
+-msn_slp_process_transresp(MsnSlpCall *slpcall, const char *content)
+-{
+- /* A direct connection negotiation response */
+- char *bridge;
+- char *nonce;
+- char *listening;
+- MsnDirectConn *dc = slpcall->slplink->dc;
+- MsnDirectConnNonceType ntype;
+-
+- purple_debug_info("msn", "process_transresp\n");
+-
+- /* Direct connections are disabled. */
+- if (!purple_account_get_bool(slpcall->slplink->session->account, "direct_connect", TRUE))
+- return;
+-
+- g_return_if_fail(dc != NULL);
+- g_return_if_fail(dc->state == DC_STATE_CLOSED);
+-
+- bridge = get_token(content, "Bridge: ", "\r\n");
+- nonce = parse_dc_nonce(content, &ntype);
+- listening = get_token(content, "Listening: ", "\r\n");
+- if (listening && bridge && !strcmp(bridge, "TCPv1")) {
+- /* Ok, the client supports direct TCP connection */
+-
+- /* We always need this. */
+- if (ntype == DC_NONCE_SHA1) {
+- strncpy(dc->remote_nonce, nonce, 36);
+- dc->remote_nonce[36] = '\0';
+- }
+-
+- if (!strcasecmp(listening, "false")) {
+- if (dc->listen_data != NULL) {
+- /*
+- * We'll listen for incoming connections but
+- * the listening socket isn't ready yet so we cannot
+- * send the INVITE packet now. Put the slpcall into waiting mode
+- * and let the callback send the invite.
+- */
+- slpcall->wait_for_socket = TRUE;
+-
+- } else if (dc->listenfd != -1) {
+- /* The listening socket is ready. Send the INVITE here. */
+- msn_dc_send_invite(dc);
+-
+- } else {
+- /* We weren't able to create a listener either. Use SB. */
+- msn_dc_fallback_to_sb(dc);
+- }
+-
+- } else {
+- /*
+- * We should connect to the client so parse
+- * IP/port from response.
+- */
+- char *ip, *port_str;
+- int port = 0;
+-
+- if (ntype == DC_NONCE_PLAIN) {
+- /* Only needed for listening side. */
+- memcpy(dc->nonce, nonce, 16);
+- }
+-
+- /* Cancel any listen attempts because we don't need them. */
+- if (dc->listenfd_handle != 0) {
+- purple_input_remove(dc->listenfd_handle);
+- dc->listenfd_handle = 0;
+- }
+- if (dc->connect_timeout_handle != 0) {
+- purple_timeout_remove(dc->connect_timeout_handle);
+- dc->connect_timeout_handle = 0;
+- }
+- if (dc->listenfd != -1) {
+- purple_network_remove_port_mapping(dc->listenfd);
+- close(dc->listenfd);
+- dc->listenfd = -1;
+- }
+- if (dc->listen_data != NULL) {
+- purple_network_listen_cancel(dc->listen_data);
+- dc->listen_data = NULL;
+- }
+-
+- /* Save external IP/port for later use. We'll try local connection first. */
+- dc->ext_ip = get_token(content, "IPv4External-Addrs: ", "\r\n");
+- port_str = get_token(content, "IPv4External-Port: ", "\r\n");
+- if (port_str) {
+- dc->ext_port = atoi(port_str);
+- g_free(port_str);
+- }
+-
+- ip = get_token(content, "IPv4Internal-Addrs: ", "\r\n");
+- port_str = get_token(content, "IPv4Internal-Port: ", "\r\n");
+- if (port_str) {
+- port = atoi(port_str);
+- g_free(port_str);
+- }
+-
+- if (ip && port) {
+- /* Try internal address first */
+- dc->connect_data = purple_proxy_connect(
+- NULL,
+- slpcall->slplink->session->account,
+- ip,
+- port,
+- msn_dc_connected_to_peer_cb,
+- dc
+- );
+-
+- if (dc->connect_data) {
+- /* Add connect timeout handle */
+- dc->connect_timeout_handle = purple_timeout_add_seconds(
+- DC_OUTGOING_TIMEOUT,
+- msn_dc_outgoing_connection_timeout_cb,
+- dc
+- );
+- } else {
+- /*
+- * Connection failed
+- * Try external IP/port (if specified)
+- */
+- msn_dc_outgoing_connection_timeout_cb(dc);
+- }
+-
+- } else {
+- /*
+- * Omitted or invalid internal IP address / port
+- * Try external IP/port (if specified)
+- */
+- msn_dc_outgoing_connection_timeout_cb(dc);
+- }
+-
+- g_free(ip);
+- }
+-
+- } else {
+- /*
+- * Invalid direct connect invitation or
+- * TCP connection is not supported
+- */
+- }
+-
+- g_free(listening);
+- g_free(nonce);
+- g_free(bridge);
+-
+- return;
+-}
+-
+-static void
+-got_sessionreq(MsnSlpCall *slpcall, const char *branch,
+- const char *euf_guid, const char *context)
+-{
+- gboolean accepted = FALSE;
+-
+- if (!strcmp(euf_guid, MSN_OBJ_GUID))
+- {
+- /* Emoticon or UserDisplay */
+- char *content;
+- gsize len;
+- MsnSlpLink *slplink;
+- MsnSlpMessage *slpmsg;
+- MsnObject *obj;
+- char *msnobj_data;
+- PurpleStoredImage *img = NULL;
+- int type;
+-
+- /* Send Ok */
+- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
+- slpcall->session_id);
+-
+- msn_slp_send_ok(slpcall, branch, "application/x-msnmsgr-sessionreqbody",
+- content);
+-
+- g_free(content);
+-
+- slplink = slpcall->slplink;
+-
+- msnobj_data = (char *)purple_base64_decode(context, &len);
+- obj = msn_object_new_from_string(msnobj_data);
+- type = msn_object_get_type(obj);
+- g_free(msnobj_data);
+- if (type == MSN_OBJECT_EMOTICON) {
+- img = find_valid_emoticon(slplink->session->account, obj->location);
+- } else if (type == MSN_OBJECT_USERTILE) {
+- img = msn_object_get_image(obj);
+- if (img)
+- purple_imgstore_ref(img);
+- }
+- msn_object_destroy(obj);
+-
+- if (img != NULL) {
+- /* DATA PREP */
+- slpmsg = msn_slpmsg_dataprep_new(slpcall);
+- msn_slplink_queue_slpmsg(slplink, slpmsg);
+-
+- /* DATA */
+- slpmsg = msn_slpmsg_obj_new(slpcall, img);
+- msn_slplink_queue_slpmsg(slplink, slpmsg);
+- purple_imgstore_unref(img);
+-
+- accepted = TRUE;
+-
+- } else {
+- purple_debug_error("msn", "Wrong object.\n");
+- }
+- }
+-
+- else if (!strcmp(euf_guid, MSN_FT_GUID))
+- {
+- /* File Transfer */
+- PurpleAccount *account;
+- PurpleXfer *xfer;
+- MsnFileContext *file_context;
+- char *buf;
+- gsize bin_len;
+- guint32 file_size;
+- char *file_name;
+-
+- account = slpcall->slplink->session->account;
+-
+- slpcall->end_cb = msn_xfer_end_cb;
+- slpcall->branch = g_strdup(branch);
+-
+- slpcall->pending = TRUE;
+-
+- xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE,
+- slpcall->slplink->remote_user);
+-
+- buf = (char *)purple_base64_decode(context, &bin_len);
+- file_context = msn_file_context_from_wire(buf, bin_len);
+-
+- if (file_context != NULL) {
+- file_size = file_context->file_size;
+-
+- file_name = g_convert((const gchar *)&file_context->file_name,
+- MAX_FILE_NAME_LEN * 2,
+- "UTF-8", "UTF-16LE",
+- NULL, NULL, NULL);
+-
+- purple_xfer_set_filename(xfer, file_name ? file_name : "");
+- g_free(file_name);
+- purple_xfer_set_size(xfer, file_size);
+- purple_xfer_set_init_fnc(xfer, msn_xfer_init);
+- purple_xfer_set_request_denied_fnc(xfer, msn_xfer_cancel);
+- purple_xfer_set_cancel_recv_fnc(xfer, msn_xfer_cancel);
+- purple_xfer_set_read_fnc(xfer, msn_xfer_read);
+- purple_xfer_set_write_fnc(xfer, msn_xfer_write);
+-
+- slpcall->u.incoming_data = g_byte_array_new();
+-
+- slpcall->xfer = xfer;
+- purple_xfer_ref(slpcall->xfer);
+-
+- xfer->data = slpcall;
+-
+- if (file_context->preview) {
+- purple_xfer_set_thumbnail(xfer, file_context->preview,
+- file_context->preview_len,
+- "image/png");
+- g_free(file_context->preview);
+- }
+-
+- purple_xfer_request(xfer);
+- }
+- g_free(file_context);
+- g_free(buf);
+-
+- accepted = TRUE;
+-
+- } else if (!strcmp(euf_guid, MSN_CAM_REQUEST_GUID)) {
+- purple_debug_info("msn", "Cam request.\n");
+- if (slpcall->slplink && slpcall->slplink->session) {
+- PurpleConversation *conv;
+- gchar *from = slpcall->slplink->remote_user;
+- conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, from,
+- slpcall->slplink->session->account);
+- if (conv) {
+- char *buf;
+- buf = g_strdup_printf(
+- _("%s requests to view your "
+- "webcam, but this request is "
+- "not yet supported."), from);
+- purple_conversation_write(conv, NULL, buf,
+- PURPLE_MESSAGE_SYSTEM |
+- PURPLE_MESSAGE_NOTIFY,
+- time(NULL));
+- g_free(buf);
+- }
+- }
+-
+- } else if (!strcmp(euf_guid, MSN_CAM_GUID)) {
+- purple_debug_info("msn", "Cam invite.\n");
+- if (slpcall->slplink && slpcall->slplink->session) {
+- PurpleConversation *conv;
+- gchar *from = slpcall->slplink->remote_user;
+- conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, from,
+- slpcall->slplink->session->account);
+- if (conv) {
+- char *buf;
+- buf = g_strdup_printf(
+- _("%s invited you to view his/her webcam, but "
+- "this is not yet supported."), from);
+- purple_conversation_write(conv, NULL, buf,
+- PURPLE_MESSAGE_SYSTEM |
+- PURPLE_MESSAGE_NOTIFY,
+- time(NULL));
+- g_free(buf);
+- }
+- }
+-
+- } else
+- purple_debug_warning("msn", "SLP SessionReq with unknown EUF-GUID: %s\n", euf_guid);
+-
+- if (!accepted) {
+- char *content = g_strdup_printf("SessionID: %lu\r\n\r\n",
+- slpcall->session_id);
+- msn_slp_send_decline(slpcall, branch, "application/x-msnmsgr-sessionreqbody", content);
+- g_free(content);
+- }
+-}
+-
+-void
+-send_bye(MsnSlpCall *slpcall, const char *type)
+-{
+- MsnSlpLink *slplink;
+- PurpleAccount *account;
+- MsnSlpMessage *slpmsg;
+- char *header;
+-
+- slplink = slpcall->slplink;
+-
+- g_return_if_fail(slplink != NULL);
+-
+- account = slplink->session->account;
+-
+- header = g_strdup_printf("BYE MSNMSGR:%s MSNSLP/1.0",
+- purple_account_get_username(account));
+-
+- slpmsg = msn_slpmsg_sip_new(slpcall, 0, header,
+- "A0D624A6-6C0C-4283-A9E0-BC97B4B46D32",
+- type,
+- "\r\n");
+- g_free(header);
+-
+- slpmsg->info = "SLP BYE";
+- slpmsg->text_body = TRUE;
+-
+- msn_slplink_queue_slpmsg(slplink, slpmsg);
+-}
+-
+-static void
+-got_invite(MsnSlpCall *slpcall,
+- const char *branch, const char *type, const char *content)
+-{
+- MsnSlpLink *slplink;
+-
+- slplink = slpcall->slplink;
+-
+- if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
+- {
+- char *euf_guid, *context;
+- char *temp;
+-
+- euf_guid = get_token(content, "EUF-GUID: {", "}\r\n");
+-
+- temp = get_token(content, "SessionID: ", "\r\n");
+- if (temp != NULL)
+- slpcall->session_id = atoi(temp);
+- g_free(temp);
+-
+- temp = get_token(content, "AppID: ", "\r\n");
+- if (temp != NULL)
+- slpcall->app_id = atoi(temp);
+- g_free(temp);
+-
+- context = get_token(content, "Context: ", "\r\n");
+-
+- if (context != NULL)
+- got_sessionreq(slpcall, branch, euf_guid, context);
+-
+- g_free(context);
+- g_free(euf_guid);
+- }
+- else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
+- {
+- /* A direct connection negotiation request */
+- char *bridges;
+- char *nonce;
+- MsnDirectConnNonceType ntype;
+-
+- purple_debug_info("msn", "got_invite: transreqbody received\n");
+-
+- /* Direct connections may be disabled. */
+- if (!purple_account_get_bool(slplink->session->account, "direct_connect", TRUE)) {
+- msn_slp_send_ok(slpcall, branch,
+- "application/x-msnmsgr-transrespbody",
+- "Bridge: TCPv1\r\n"
+- "Listening: false\r\n"
+- "Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
+- "\r\n");
+- msn_slpcall_session_init(slpcall);
+-
+- return;
+- }
+-
+- /* Don't do anything if we already have a direct connection */
+- if (slplink->dc != NULL)
+- return;
+-
+- bridges = get_token(content, "Bridges: ", "\r\n");
+- nonce = parse_dc_nonce(content, &ntype);
+- if (bridges && strstr(bridges, "TCPv1") != NULL) {
+- /*
+- * Ok, the client supports direct TCP connection
+- * Try to create a listening port
+- */
+- MsnDirectConn *dc;
+-
+- dc = msn_dc_new(slpcall);
+- if (ntype == DC_NONCE_PLAIN) {
+- /* There is only one nonce for plain auth. */
+- dc->nonce_type = ntype;
+- memcpy(dc->nonce, nonce, 16);
+- } else if (ntype == DC_NONCE_SHA1) {
+- /* Each side has a nonce in SHA1 auth. */
+- dc->nonce_type = ntype;
+- strncpy(dc->remote_nonce, nonce, 36);
+- dc->remote_nonce[36] = '\0';
+- }
+-
+- dc->listen_data = purple_network_listen_range(
+- 0, 0,
+- SOCK_STREAM,
+- msn_dc_listen_socket_created_cb,
+- dc
+- );
+-
+- if (dc->listen_data == NULL) {
+- /* Listen socket creation failed */
+-
+- purple_debug_info("msn", "got_invite: listening failed\n");
+-
+- if (dc->nonce_type != DC_NONCE_PLAIN)
+- msn_slp_send_ok(slpcall, branch,
+- "application/x-msnmsgr-transrespbody",
+- "Bridge: TCPv1\r\n"
+- "Listening: false\r\n"
+- "Hashed-Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
+- "\r\n");
+- else
+- msn_slp_send_ok(slpcall, branch,
+- "application/x-msnmsgr-transrespbody",
+- "Bridge: TCPv1\r\n"
+- "Listening: false\r\n"
+- "Nonce: {00000000-0000-0000-0000-000000000000}\r\n"
+- "\r\n");
+-
+- } else {
+- /*
+- * Listen socket created successfully.
+- * Don't send anything here because we don't know the parameters
+- * of the created socket yet. msn_dc_send_ok will be called from
+- * the callback function: dc_listen_socket_created_cb
+- */
+- purple_debug_info("msn", "got_invite: listening socket created\n");
+-
+- dc->send_connection_info_msg_cb = msn_dc_send_ok;
+- slpcall->wait_for_socket = TRUE;
+- }
+-
+- } else {
+- /*
+- * Invalid direct connect invitation or
+- * TCP connection is not supported.
+- */
+- }
+-
+- g_free(nonce);
+- g_free(bridges);
+- }
+- else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
+- {
+- /* A direct connection negotiation response */
+- msn_slp_process_transresp(slpcall, content);
+- }
+-}
+-
+-static void
+-got_ok(MsnSlpCall *slpcall,
+- const char *type, const char *content)
+-{
+- g_return_if_fail(slpcall != NULL);
+- g_return_if_fail(type != NULL);
+-
+- if (!strcmp(type, "application/x-msnmsgr-sessionreqbody"))
+- {
+- char *content;
+- char *header;
+- char *nonce = NULL;
+- MsnSession *session = slpcall->slplink->session;
+- MsnSlpMessage *msg;
+- MsnDirectConn *dc;
+- MsnUser *user;
+-
+- if (!purple_account_get_bool(session->account, "direct_connect", TRUE)) {
+- /* Don't attempt a direct connection if disabled. */
+- msn_slpcall_session_init(slpcall);
+- return;
+- }
+-
+- if (slpcall->slplink->dc != NULL) {
+- /* If we already have an established direct connection
+- * then just start the transfer.
+- */
+- msn_slpcall_session_init(slpcall);
+- return;
+- }
+-
+- user = msn_userlist_find_user(session->userlist,
+- slpcall->slplink->remote_user);
+- if (!user || !(user->clientid & 0xF0000000)) {
+- /* Just start a normal SB transfer. */
+- msn_slpcall_session_init(slpcall);
+- return;
+- }
+-
+- /* Try direct file transfer by sending a second INVITE */
+- dc = msn_dc_new(slpcall);
+- g_free(slpcall->branch);
+- slpcall->branch = rand_guid();
+-
+- dc->listen_data = purple_network_listen_range(
+- 0, 0,
+- SOCK_STREAM,
+- msn_dc_listen_socket_created_cb,
+- dc
+- );
+-
+- header = g_strdup_printf(
+- "INVITE MSNMSGR:%s MSNSLP/1.0",
+- slpcall->slplink->remote_user
+- );
+-
+- if (dc->nonce_type == DC_NONCE_SHA1)
+- nonce = g_strdup_printf("Hashed-Nonce: {%s}\r\n", dc->nonce_hash);
+-
+- if (dc->listen_data == NULL) {
+- /* Listen socket creation failed */
+- purple_debug_info("msn", "got_ok: listening failed\n");
+-
+- content = g_strdup_printf(
+- "Bridges: TCPv1\r\n"
+- "NetID: %u\r\n"
+- "Conn-Type: IP-Restrict-NAT\r\n"
+- "UPnPNat: false\r\n"
+- "ICF: false\r\n"
+- "%s"
+- "\r\n",
+-
+- rand() % G_MAXUINT32,
+- nonce ? nonce : ""
+- );
+-
+- } else {
+- /* Listen socket created successfully. */
+- purple_debug_info("msn", "got_ok: listening socket created\n");
+-
+- content = g_strdup_printf(
+- "Bridges: TCPv1\r\n"
+- "NetID: 0\r\n"
+- "Conn-Type: Direct-Connect\r\n"
+- "UPnPNat: false\r\n"
+- "ICF: false\r\n"
+- "%s"
+- "\r\n",
+-
+- nonce ? nonce : ""
+- );
+- }
+-
+- msg = msn_slpmsg_sip_new(
+- slpcall,
+- 0,
+- header,
+- slpcall->branch,
+- "application/x-msnmsgr-transreqbody",
+- content
+- );
+- msg->info = "DC INVITE";
+- msg->text_body = TRUE;
+- g_free(nonce);
+- g_free(header);
+- g_free(content);
+-
+- msn_slplink_queue_slpmsg(slpcall->slplink, msg);
+- }
+- else if (!strcmp(type, "application/x-msnmsgr-transreqbody"))
+- {
+- /* Do we get this? */
+- purple_debug_info("msn", "OK with transreqbody\n");
+- }
+- else if (!strcmp(type, "application/x-msnmsgr-transrespbody"))
+- {
+- msn_slp_process_transresp(slpcall, content);
+- }
+-}
+-
+-static void
+-got_error(MsnSlpCall *slpcall,
+- const char *error, const char *type, const char *content)
+-{
+- /* It's not valid. Kill this off. */
+- purple_debug_error("msn", "Received non-OK result: %s\n",
+- error ? error : "Unknown");
+-
+- if (type && !strcmp(type, "application/x-msnmsgr-transreqbody")) {
+- MsnDirectConn *dc = slpcall->slplink->dc;
+- if (dc) {
+- msn_dc_fallback_to_sb(dc);
+- return;
+- }
+- }
+-
+- slpcall->wasted = TRUE;
+-}
+-
+-static MsnSlpCall *
+-msn_slp_sip_recv(MsnSlpLink *slplink, const char *body)
+-{
+- MsnSlpCall *slpcall;
+-
+- if (body == NULL)
+- {
+- purple_debug_warning("msn", "received bogus message\n");
+- return NULL;
+- }
+-
+- if (!strncmp(body, "INVITE", strlen("INVITE")))
+- {
+- /* This is an INVITE request */
+- char *branch;
+- char *call_id;
+- char *content;
+- char *content_type;
+-
+- /* From: <msnmsgr:buddy@hotmail.com> */
+-#if 0
+- slpcall->remote_user = get_token(body, "From: <msnmsgr:", ">\r\n");
+-#endif
+-
+- branch = get_token(body, ";branch={", "}");
+-
+- call_id = get_token(body, "Call-ID: {", "}");
+-
+-#if 0
+- long content_len = -1;
+-
+- temp = get_token(body, "Content-Length: ", "\r\n");
+- if (temp != NULL)
+- content_len = atoi(temp);
+- g_free(temp);
+-#endif
+- content_type = get_token(body, "Content-Type: ", "\r\n");
+-
+- content = get_token(body, "\r\n\r\n", NULL);
+-
+- slpcall = NULL;
+- if (branch && call_id)
+- {
+- slpcall = msn_slplink_find_slp_call(slplink, call_id);
+- if (slpcall)
+- {
+- g_free(slpcall->branch);
+- slpcall->branch = g_strdup(branch);
+- got_invite(slpcall, branch, content_type, content);
+- }
+- else if (content_type && content)
+- {
+- slpcall = msn_slpcall_new(slplink);
+- slpcall->id = g_strdup(call_id);
+- got_invite(slpcall, branch, content_type, content);
+- }
+- }
+-
+- g_free(call_id);
+- g_free(branch);
+- g_free(content_type);
+- g_free(content);
+- }
+- else if (!strncmp(body, "MSNSLP/1.0 ", strlen("MSNSLP/1.0 ")))
+- {
+- /* This is a response */
+- char *content;
+- char *content_type;
+- /* Make sure this is "OK" */
+- const char *status = body + strlen("MSNSLP/1.0 ");
+- char *call_id;
+-
+- call_id = get_token(body, "Call-ID: {", "}");
+- slpcall = msn_slplink_find_slp_call(slplink, call_id);
+- g_free(call_id);
+-
+- g_return_val_if_fail(slpcall != NULL, NULL);
+-
+- content_type = get_token(body, "Content-Type: ", "\r\n");
+-
+- content = get_token(body, "\r\n\r\n", NULL);
+-
+- if (strncmp(status, "200 OK", 6))
+- {
+- char *error = NULL;
+- const char *c;
+-
+- /* Eww */
+- if ((c = strchr(status, '\r')) || (c = strchr(status, '\n')) ||
+- (c = strchr(status, '\0')))
+- {
+- size_t len = c - status;
+- error = g_strndup(status, len);
+- }
+-
+- got_error(slpcall, error, content_type, content);
+- g_free(error);
+-
+- } else {
+- /* Everything's just dandy */
+- got_ok(slpcall, content_type, content);
+- }
+-
+- g_free(content_type);
+- g_free(content);
+- }
+- else if (!strncmp(body, "BYE", strlen("BYE")))
+- {
+- /* This is a BYE request */
+- char *call_id;
+-
+- call_id = get_token(body, "Call-ID: {", "}");
+- slpcall = msn_slplink_find_slp_call(slplink, call_id);
+- g_free(call_id);
+-
+- if (slpcall != NULL)
+- slpcall->wasted = TRUE;
+-
+- /* msn_slpcall_destroy(slpcall); */
+- }
+- else
+- slpcall = NULL;
+-
+- return slpcall;
+-}
+-
+-MsnSlpCall *
+-msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+-{
+- MsnSlpCall *slpcall;
+- const guchar *body;
+- gsize body_len;
+- guint32 session_id;
+- guint32 flags;
+-
+- slpcall = NULL;
+- body = slpmsg->buffer;
+- body_len = msn_p2p_info_get_offset(slpmsg->p2p_info);
+-
+- session_id = msn_p2p_info_get_session_id(slpmsg->p2p_info);
+- flags = msn_p2p_info_get_flags(slpmsg->p2p_info);
+-
+- if (flags == P2P_NO_FLAG || flags == P2P_WLM2009_COMP)
+- {
+- char *body_str;
+-
+- if (session_id == 64)
+- {
+- /* This is for handwritten messages (Ink) */
+- GError *error = NULL;
+- gsize bytes_read, bytes_written;
+-
+- body_str = g_convert((const gchar *)body, body_len / 2,
+- "UTF-8", "UTF-16LE",
+- &bytes_read, &bytes_written, &error);
+- body_len -= bytes_read + 2;
+- body += bytes_read + 2;
+- if (body_str == NULL
+- || body_len <= 0
+- || strstr(body_str, "image/gif") == NULL)
+- {
+- if (error != NULL) {
+- purple_debug_error("msn",
+- "Unable to convert Ink header from UTF-16 to UTF-8: %s\n",
+- error->message);
+- g_error_free(error);
+- }
+- else
+- purple_debug_error("msn",
+- "Received Ink in unknown format\n");
+- g_free(body_str);
+- return NULL;
+- }
+- g_free(body_str);
+-
+- body_str = g_convert((const gchar *)body, body_len / 2,
+- "UTF-8", "UTF-16LE",
+- &bytes_read, &bytes_written, &error);
+- if (!body_str)
+- {
+- if (error != NULL) {
+- purple_debug_error("msn",
+- "Unable to convert Ink body from UTF-16 to UTF-8: %s\n",
+- error->message);
+- g_error_free(error);
+- }
+- else
+- purple_debug_error("msn",
+- "Received Ink in unknown format\n");
+- return NULL;
+- }
+-
+- msn_switchboard_show_ink(slpmsg->slplink->swboard,
+- slplink->remote_user,
+- body_str);
+- }
+- else
+- {
+- body_str = g_strndup((const char *)body, body_len);
+- slpcall = msn_slp_sip_recv(slplink, body_str);
+- }
+- g_free(body_str);
+- }
+- else if (msn_p2p_msg_is_data(slpmsg->p2p_info))
+- {
+- slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
+-
+- if (slpcall != NULL)
+- {
+- if (slpcall->timer) {
+- purple_timeout_remove(slpcall->timer);
+- slpcall->timer = 0;
+- }
+-
+- if (slpcall->cb)
+- slpcall->cb(slpcall, body, body_len);
+-
+- slpcall->wasted = TRUE;
+- }
+- }
+- else if (msn_p2p_info_is_ack(slpmsg->p2p_info))
+- {
+- /* Acknowledgement of previous message. Don't do anything currently. */
+- }
+- else
+- purple_debug_warning("msn", "Unprocessed SLP message with flags 0x%04x\n",
+- flags);
+-
+- return slpcall;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpcall.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.h
+--- pidgin-2.10.7/libpurple/protocols/msn/slpcall.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpcall.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,98 +0,0 @@
+-/**
+- * @file slpcall.h SLP Call functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SLPCALL_H
+-#define MSN_SLPCALL_H
+-
+-typedef struct _MsnSlpCall MsnSlpCall;
+-
+-typedef enum
+-{
+- MSN_SLPCALL_ANY,
+- MSN_SLPCALL_DC
+-} MsnSlpCallType;
+-
+-#include "internal.h"
+-
+-#include "slplink.h"
+-
+-/* The official client seems to timeout slp calls after 5 minutes */
+-#define MSN_SLPCALL_TIMEOUT 300
+-
+-struct _MsnSlpCall
+-{
+- /* Our parent slplink */
+- MsnSlpLink *slplink;
+-
+- MsnSlpCallType type;
+-
+- /* Call-ID */
+- char *id;
+- char *branch;
+-
+- long session_id;
+- long app_id;
+-
+- gboolean pending; /**< A flag that states if we should wait for this
+- slpcall to start and do not time out. */
+- gboolean progress; /**< A flag that states if there has been progress since
+- the last time out. */
+- gboolean wasted; /**< A flag that states if this slpcall is going to be
+- destroyed. */
+- gboolean started; /**< A flag that states if this slpcall's session has
+- been initiated. */
+-
+- gboolean wait_for_socket;
+-
+- void (*progress_cb)(MsnSlpCall *slpcall,
+- gsize total_length, gsize len);
+- void (*session_init_cb)(MsnSlpCall *slpcall);
+-
+- /* Can be checksum, or smile */
+- char *data_info;
+-
+- PurpleXfer *xfer;
+- union {
+- GByteArray *incoming_data;
+- struct {
+- gsize len;
+- const guchar *data;
+- } outgoing;
+- } u;
+- MsnSlpMessage *xfer_msg; /* A dirty hack */
+-
+- MsnSlpCb cb;
+- void (*end_cb)(MsnSlpCall *slpcall, MsnSession *session);
+-
+- guint timer;
+-};
+-
+-MsnSlpCall *msn_slpcall_new(MsnSlpLink *slplink);
+-void msn_slpcall_init(MsnSlpCall *slpcall, MsnSlpCallType type);
+-void msn_slpcall_session_init(MsnSlpCall *slpcall);
+-void msn_slpcall_destroy(MsnSlpCall *slpcall);
+-void msn_slpcall_invite(MsnSlpCall *slpcall, const char *euf_guid,
+- MsnP2PAppId app_id, const char *context);
+-void msn_slpcall_close(MsnSlpCall *slpcall);
+-
+-#endif /* MSN_SLPCALL_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slp.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.h
+--- pidgin-2.10.7/libpurple/protocols/msn/slp.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slp.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,51 +0,0 @@
+-/**
+- * @file slp.h MSNSLP support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SLP_H
+-#define MSN_SLP_H
+-
+-#include "internal.h"
+-#include "ft.h"
+-
+-#include "session.h"
+-#include "slpcall.h"
+-#include "slplink.h"
+-#include "user.h"
+-
+-void
+-msn_slp_send_ok(MsnSlpCall *slpcall, const char *branch,
+- const char *type, const char *content);
+-
+-void
+-msn_slp_send_decline(MsnSlpCall *slpcall, const char *branch,
+- const char *type, const char *content);
+-
+-
+-void send_bye(MsnSlpCall *slpcall, const char *type);
+-
+-
+-void msn_request_user_display(MsnUser *user);
+-
+-void msn_request_ft(PurpleXfer *xfer);
+-
+-#endif /* MSN_SLP_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slplink.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.c
+--- pidgin-2.10.7/libpurple/protocols/msn/slplink.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,646 +0,0 @@
+-/**
+- * @file slplink.c MSNSLP Link support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msn.h"
+-#include "slplink.h"
+-#include "slpmsg_part.h"
+-
+-#include "sbconn.h"
+-#include "switchboard.h"
+-#include "slp.h"
+-#include "p2p.h"
+-
+-#ifdef MSN_DEBUG_SLP_FILES
+-static int m_sc = 0;
+-static int m_rc = 0;
+-
+-static void
+-debug_part_to_file(MsnSlpMessage *msg, gboolean send)
+-{
+- char *tmp;
+- char *dir;
+- char *data;
+- int c;
+- gsize data_size;
+-
+- dir = send ? "send" : "recv";
+- c = send ? m_sc++ : m_rc++;
+- tmp = g_strdup_printf("%s/msntest/%s/%03d", purple_user_dir(), dir, c);
+- data = msn_slpmsg_serialize(msg, &data_size);
+- if (!purple_util_write_data_to_file_absolute(tmp, data, data_size))
+- {
+- purple_debug_error("msn", "could not save debug file\n");
+- }
+- g_free(tmp);
+-}
+-#endif
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-static MsnSlpLink *
+-msn_slplink_new(MsnSession *session, const char *username)
+-{
+- MsnSlpLink *slplink;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- slplink = g_new0(MsnSlpLink, 1);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slplink_new: slplink(%p)\n", slplink);
+-
+- slplink->session = session;
+- slplink->slp_seq_id = rand() % 0xFFFFFF00 + 4;
+-
+- slplink->remote_user = g_strdup(username);
+- slplink->p2p_version = MSN_P2P_VERSION_ONE;
+-
+- slplink->slp_msg_queue = g_queue_new();
+-
+- session->slplinks =
+- g_list_append(session->slplinks, slplink);
+-
+- return msn_slplink_ref(slplink);
+-}
+-
+-static void
+-msn_slplink_destroy(MsnSlpLink *slplink)
+-{
+- MsnSession *session;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slplink_destroy: slplink(%p)\n", slplink);
+-
+- if (slplink->swboard != NULL) {
+- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
+- slplink->swboard = NULL;
+- }
+-
+- session = slplink->session;
+-
+- if (slplink->dc != NULL) {
+- slplink->dc->slplink = NULL;
+- msn_dc_destroy(slplink->dc);
+- slplink->dc = NULL;
+- }
+-
+- while (slplink->slp_calls != NULL)
+- msn_slpcall_destroy(slplink->slp_calls->data);
+-
+- g_queue_free(slplink->slp_msg_queue);
+-
+- session->slplinks =
+- g_list_remove(session->slplinks, slplink);
+-
+- g_free(slplink->remote_user);
+-
+- g_free(slplink);
+-}
+-
+-MsnSlpLink *
+-msn_slplink_ref(MsnSlpLink *slplink)
+-{
+- g_return_val_if_fail(slplink != NULL, NULL);
+-
+- slplink->refs++;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slplink ref (%p)[%d]\n", slplink, slplink->refs);
+-
+- return slplink;
+-}
+-
+-void
+-msn_slplink_unref(MsnSlpLink *slplink)
+-{
+- g_return_if_fail(slplink != NULL);
+-
+- slplink->refs--;
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slplink unref (%p)[%d]\n", slplink, slplink->refs);
+-
+- if (slplink->refs == 0)
+- msn_slplink_destroy(slplink);
+-}
+-
+-MsnSlpLink *
+-msn_session_find_slplink(MsnSession *session, const char *who)
+-{
+- GList *l;
+-
+- for (l = session->slplinks; l != NULL; l = l->next)
+- {
+- MsnSlpLink *slplink;
+-
+- slplink = l->data;
+-
+- if (!strcmp(slplink->remote_user, who))
+- return slplink;
+- }
+-
+- return NULL;
+-}
+-
+-MsnSlpLink *
+-msn_session_get_slplink(MsnSession *session, const char *username)
+-{
+- MsnSlpLink *slplink;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+- g_return_val_if_fail(username != NULL, NULL);
+-
+- slplink = msn_session_find_slplink(session, username);
+-
+- if (slplink == NULL)
+- slplink = msn_slplink_new(session, username);
+-
+- return slplink;
+-}
+-
+-void
+-msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
+-{
+- if (slplink->swboard != NULL)
+- slplink->swboard->flag |= MSN_SB_FLAG_FT;
+-
+- slplink->slp_calls = g_list_append(slplink->slp_calls, slpcall);
+-
+- /*
+- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
+- msn_dc_ref(slplink->dc);
+- */
+-}
+-
+-void
+-msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall)
+-{
+- /*
+- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
+- msn_dc_unref(slplink->dc);
+- */
+-
+- slplink->slp_calls = g_list_remove(slplink->slp_calls, slpcall);
+-
+- /* The slplink has no slpcalls in it, release it from MSN_SB_FLAG_FT.
+- * If nothing else is using it then this might cause swboard to be
+- * destroyed. */
+- if (slplink->slp_calls == NULL && slplink->swboard != NULL) {
+- slplink->swboard->slplinks = g_list_remove(slplink->swboard->slplinks, slplink);
+- msn_switchboard_release(slplink->swboard, MSN_SB_FLAG_FT);
+- slplink->swboard = NULL;
+- }
+-
+- if (slplink->dc != NULL) {
+- if ((slplink->dc->state != DC_STATE_ESTABLISHED && slplink->dc->slpcall == slpcall)
+- || (slplink->slp_calls == NULL)) {
+- /* The DC is not established and its corresponding slpcall is dead,
+- * or the slplink has no slpcalls in it and no longer needs the DC.
+- */
+- slplink->dc->slplink = NULL;
+- msn_dc_destroy(slplink->dc);
+- slplink->dc = NULL;
+- }
+- }
+-}
+-
+-MsnSlpCall *
+-msn_slplink_find_slp_call(MsnSlpLink *slplink, const char *id)
+-{
+- GList *l;
+- MsnSlpCall *slpcall;
+-
+- if (!id)
+- return NULL;
+-
+- for (l = slplink->slp_calls; l != NULL; l = l->next)
+- {
+- slpcall = l->data;
+-
+- if (slpcall->id && !strcmp(slpcall->id, id))
+- return slpcall;
+- }
+-
+- return NULL;
+-}
+-
+-MsnSlpCall *
+-msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id)
+-{
+- GList *l;
+- MsnSlpCall *slpcall;
+-
+- for (l = slplink->slp_calls; l != NULL; l = l->next)
+- {
+- slpcall = l->data;
+-
+- if (slpcall->session_id == id)
+- return slpcall;
+- }
+-
+- return NULL;
+-}
+-
+-MsnP2PVersion
+-msn_slplink_get_p2p_version(MsnSlpLink *slplink)
+-{
+- return slplink->p2p_version;
+-}
+-
+-static void
+-msn_slplink_send_part(MsnSlpLink *slplink, MsnSlpMessagePart *part)
+-{
+- if (slplink->dc != NULL && slplink->dc->state == DC_STATE_ESTABLISHED)
+- {
+- msn_dc_enqueue_part(slplink->dc, part);
+- }
+- else
+- {
+- msn_sbconn_send_part(slplink, part);
+- }
+-}
+-
+-void
+-msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+-{
+- MsnSlpMessagePart *part;
+- MsnP2PInfo *info;
+- long long real_size;
+- size_t len = 0;
+- guint64 offset;
+-
+- /* Maybe we will want to create a new msg for this slpmsg instead of
+- * reusing the same one all the time. */
+- info = slpmsg->p2p_info;
+- part = msn_slpmsgpart_new(msn_p2p_info_dup(info));
+- part->ack_data = slpmsg;
+-
+- real_size = msn_p2p_info_is_ack(info) ? 0 : slpmsg->size;
+-
+- offset = msn_p2p_info_get_offset(info);
+- if (offset < real_size)
+- {
+- if (slpmsg->slpcall && slpmsg->slpcall->xfer && purple_xfer_get_type(slpmsg->slpcall->xfer) == PURPLE_XFER_SEND &&
+- purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
+- {
+- len = MIN(MSN_SBCONN_MAX_SIZE, slpmsg->slpcall->u.outgoing.len);
+- msn_slpmsgpart_set_bin_data(part, slpmsg->slpcall->u.outgoing.data, len);
+- }
+- else
+- {
+- len = slpmsg->size - offset;
+-
+- if (len > MSN_SBCONN_MAX_SIZE)
+- len = MSN_SBCONN_MAX_SIZE;
+-
+- msn_slpmsgpart_set_bin_data(part, slpmsg->buffer + offset, len);
+- }
+-
+- msn_p2p_info_set_length(slpmsg->p2p_info, len);
+- }
+-
+-#if 0
+- /* TODO: port this function to SlpMessageParts */
+- if (purple_debug_is_verbose())
+- msn_message_show_readable(msg, slpmsg->info, slpmsg->text_body);
+-#endif
+-
+-#ifdef MSN_DEBUG_SLP_FILES
+- debug_part_to_file(slpmsg, TRUE);
+-#endif
+-
+- slpmsg->parts = g_list_append(slpmsg->parts, part);
+- msn_slplink_send_part(slplink, part);
+-
+-
+- if (msn_p2p_msg_is_data(info) && slpmsg->slpcall != NULL)
+- {
+- slpmsg->slpcall->progress = TRUE;
+-
+- if (slpmsg->slpcall->progress_cb != NULL)
+- {
+- slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
+- len);
+- }
+- }
+-
+- /* slpmsg->offset += len; */
+-}
+-
+-static void
+-msn_slplink_release_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+-{
+- MsnP2PInfo *info;
+- guint32 flags;
+-
+- info = slpmsg->p2p_info;
+-
+- flags = msn_p2p_info_get_flags(info);
+- if (flags == P2P_NO_FLAG)
+- {
+- msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
+- }
+- else if (msn_p2p_msg_is_data(info))
+- {
+- MsnSlpCall *slpcall;
+- slpcall = slpmsg->slpcall;
+-
+- g_return_if_fail(slpcall != NULL);
+- msn_p2p_info_set_session_id(info, slpcall->session_id);
+- msn_p2p_info_set_app_id(info, slpcall->app_id);
+- msn_p2p_info_set_ack_id(info, rand() % 0xFFFFFF00);
+- }
+-
+- msn_p2p_info_set_id(info, slpmsg->id);
+-
+- msn_p2p_info_set_total_size(info, slpmsg->size);
+-
+- msn_slplink_send_msgpart(slplink, slpmsg);
+-}
+-
+-void
+-msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+-{
+- g_return_if_fail(slpmsg != NULL);
+-
+- slpmsg->id = slplink->slp_seq_id++;
+-
+- g_queue_push_tail(slplink->slp_msg_queue, slpmsg);
+-}
+-
+-void
+-msn_slplink_send_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg)
+-{
+- slpmsg->id = slplink->slp_seq_id++;
+-
+- msn_slplink_release_slpmsg(slplink, slpmsg);
+-}
+-
+-void
+-msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink)
+-{
+- MsnSlpMessage *slpmsg;
+-
+- /* Send the queued msgs in the order they were created */
+- while ((slpmsg = g_queue_pop_head(slplink->slp_msg_queue)) != NULL)
+- {
+- msn_slplink_release_slpmsg(slplink, slpmsg);
+- }
+-}
+-
+-static void
+-msn_slplink_send_ack(MsnSlpLink *slplink, MsnP2PInfo *info)
+-{
+- MsnSlpMessage *slpmsg = msn_slpmsg_ack_new(slplink, info);
+-
+- msn_slplink_send_slpmsg(slplink, slpmsg);
+- msn_slpmsg_destroy(slpmsg);
+-}
+-
+-static MsnSlpMessage *
+-msn_slplink_message_find(MsnSlpLink *slplink, long session_id, long id)
+-{
+- GList *e;
+-
+- for (e = slplink->slp_msgs; e != NULL; e = e->next)
+- {
+- MsnSlpMessage *slpmsg = e->data;
+-
+- if ((msn_p2p_info_get_session_id(slpmsg->p2p_info) == session_id) && (slpmsg->id == id))
+- return slpmsg;
+- }
+-
+- return NULL;
+-}
+-
+-static MsnSlpMessage *
+-init_first_msg(MsnSlpLink *slplink, MsnP2PInfo *info)
+-{
+- MsnSlpMessage *slpmsg;
+- guint32 session_id;
+-
+- slpmsg = msn_slpmsg_new(slplink, NULL);
+- slpmsg->id = msn_p2p_info_get_id(info);
+- session_id = msn_p2p_info_get_session_id(info);
+- slpmsg->size = msn_p2p_info_get_total_size(info);
+- msn_p2p_info_init_first(slpmsg->p2p_info, info);
+-
+- if (session_id)
+- {
+- slpmsg->slpcall = msn_slplink_find_slp_call_with_session_id(slplink, session_id);
+- if (slpmsg->slpcall != NULL)
+- {
+- if (msn_p2p_msg_is_data(info))
+- {
+- PurpleXfer *xfer = slpmsg->slpcall->xfer;
+- if (xfer != NULL)
+- {
+- slpmsg->ft = TRUE;
+- slpmsg->slpcall->xfer_msg = slpmsg;
+-
+- purple_xfer_ref(xfer);
+- purple_xfer_start(xfer, -1, NULL, 0);
+-
+- if (xfer->data == NULL) {
+- purple_xfer_unref(xfer);
+- msn_slpmsg_destroy(slpmsg);
+- g_return_val_if_reached(NULL);
+- } else {
+- purple_xfer_unref(xfer);
+- }
+- }
+- }
+- }
+- }
+- if (!slpmsg->ft && slpmsg->size)
+- {
+- slpmsg->buffer = g_try_malloc(slpmsg->size);
+- if (slpmsg->buffer == NULL)
+- {
+- purple_debug_error("msn", "Failed to allocate buffer for slpmsg\n");
+- msn_slpmsg_destroy(slpmsg);
+- return NULL;
+- }
+- }
+-
+- return slpmsg;
+-}
+-
+-static void
+-process_complete_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg, MsnP2PInfo *info)
+-{
+- MsnSlpCall *slpcall;
+-
+- slpcall = msn_slp_process_msg(slplink, slpmsg);
+-
+- if (slpcall == NULL) {
+- msn_slpmsg_destroy(slpmsg);
+- return;
+- }
+-
+- purple_debug_info("msn", "msn_slplink_process_msg: slpmsg complete\n");
+-
+- if (msn_p2p_info_require_ack(slpmsg->p2p_info))
+- {
+- /* Release all the messages and send the ACK */
+-
+- if (slpcall->wait_for_socket) {
+- /*
+- * Save ack for later because we have to send
+- * a 200 OK message to the previous direct connect
+- * invitation before ACK but the listening socket isn't
+- * created yet.
+- */
+- purple_debug_info("msn", "msn_slplink_process_msg: save ACK\n");
+-
+- slpcall->slplink->dc->prev_ack = msn_slpmsg_ack_new(slplink, info);
+- } else if (!slpcall->wasted) {
+- purple_debug_info("msn", "msn_slplink_process_msg: send ACK\n");
+-
+- msn_slplink_send_ack(slplink, info);
+- msn_slplink_send_queued_slpmsgs(slplink);
+- }
+- }
+-
+- msn_slpmsg_destroy(slpmsg);
+-
+- if (!slpcall->wait_for_socket && slpcall->wasted)
+- msn_slpcall_destroy(slpcall);
+-}
+-
+-static void
+-slpmsg_add_part(MsnSlpMessage *slpmsg, MsnSlpMessagePart *part)
+-{
+- if (slpmsg->ft) {
+- slpmsg->slpcall->u.incoming_data =
+- g_byte_array_append(slpmsg->slpcall->u.incoming_data, (const guchar *)part->buffer, part->size);
+- purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+- }
+- else if (slpmsg->size && slpmsg->buffer) {
+- guint64 offset = msn_p2p_info_get_offset(part->info);
+- if (G_MAXSIZE - part->size < offset
+- || (offset + part->size) > slpmsg->size
+- || msn_p2p_info_get_offset(slpmsg->p2p_info) != offset) {
+- purple_debug_error("msn",
+- "Oversized slpmsg - msgsize=%lld offset=%" G_GUINT64_FORMAT " len=%" G_GSIZE_FORMAT "\n",
+- slpmsg->size, offset, part->size);
+- g_return_if_reached();
+- } else {
+- memcpy(slpmsg->buffer + offset, part->buffer, part->size);
+- msn_p2p_info_set_offset(slpmsg->p2p_info, offset + part->size);
+- }
+- }
+-}
+-
+-void
+-msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part)
+-{
+- MsnSlpMessage *slpmsg;
+- MsnP2PInfo *info;
+-
+- info = part->info;
+-
+- if (!msn_p2p_info_is_valid(info))
+- {
+- /* We seem to have received a bad header */
+- purple_debug_warning("msn", "Total size listed in SLP binary header "
+- "was less than length of this particular message. This "
+- "should not happen. Dropping message.\n");
+- return;
+- }
+-
+- if (msn_p2p_info_is_first(info))
+- slpmsg = init_first_msg(slplink, info);
+- else {
+- guint32 session_id, id;
+- session_id = msn_p2p_info_get_session_id(info);
+- id = msn_p2p_info_get_id(info);
+- slpmsg = msn_slplink_message_find(slplink, session_id, id);
+- if (slpmsg == NULL)
+- {
+- /* Probably the transfer was cancelled */
+- purple_debug_error("msn", "Couldn't find slpmsg\n");
+- return;
+- }
+- }
+-
+- slpmsg_add_part(slpmsg, part);
+-
+- if (msn_p2p_msg_is_data(slpmsg->p2p_info) && slpmsg->slpcall != NULL)
+- {
+- slpmsg->slpcall->progress = TRUE;
+-
+- if (slpmsg->slpcall->progress_cb != NULL)
+- {
+- slpmsg->slpcall->progress_cb(slpmsg->slpcall, slpmsg->size,
+- part->size);
+- }
+- }
+-
+-#if 0
+- if (slpmsg->buffer == NULL)
+- return;
+-#endif
+-
+- /* All the pieces of the slpmsg have been received */
+- if (msn_p2p_info_is_final(info))
+- process_complete_msg(slplink, slpmsg, info);
+-
+- /* NOTE: The slpmsg will be destroyed in process_complete_msg or left in
+- the slplink until fully received. Don't free it here!
+- */
+-}
+-
+-void
+-msn_slplink_request_object(MsnSlpLink *slplink,
+- const char *info,
+- MsnSlpCb cb,
+- MsnSlpEndCb end_cb,
+- const MsnObject *obj)
+-{
+- MsnSlpCall *slpcall;
+- char *msnobj_data;
+- char *msnobj_base64;
+-
+- g_return_if_fail(slplink != NULL);
+- g_return_if_fail(obj != NULL);
+-
+- msnobj_data = msn_object_to_string(obj);
+- msnobj_base64 = purple_base64_encode((const guchar *)msnobj_data, strlen(msnobj_data));
+- g_free(msnobj_data);
+-
+- slpcall = msn_slpcall_new(slplink);
+- msn_slpcall_init(slpcall, MSN_SLPCALL_ANY);
+-
+- slpcall->data_info = g_strdup(info);
+- slpcall->cb = cb;
+- slpcall->end_cb = end_cb;
+-
+- msn_slpcall_invite(slpcall, MSN_OBJ_GUID, P2P_APPID_OBJ, msnobj_base64);
+-
+- g_free(msnobj_base64);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slplink.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.h
+--- pidgin-2.10.7/libpurple/protocols/msn/slplink.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slplink.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,98 +0,0 @@
+-/**
+- * @file slplink.h MSNSLP Link support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SLPLINK_H
+-#define MSN_SLPLINK_H
+-
+-typedef struct _MsnSlpLink MsnSlpLink;
+-
+-#include "directconn.h"
+-#include "session.h"
+-#include "slpcall.h"
+-#include "slpmsg.h"
+-#include "switchboard.h"
+-
+-typedef void (*MsnSlpCb)(MsnSlpCall *slpcall,
+- const guchar *data, gsize size);
+-typedef void (*MsnSlpEndCb)(MsnSlpCall *slpcall, MsnSession *session);
+-
+-struct _MsnSlpLink
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- MsnDirectConn *dc;
+-
+- guint refs;
+-
+- char *remote_user;
+- MsnP2PVersion p2p_version;
+-
+- int slp_seq_id;
+-
+- GList *slp_calls;
+- GList *slp_msgs;
+-
+- GQueue *slp_msg_queue;
+-};
+-
+-MsnSlpLink *msn_slplink_ref(MsnSlpLink *slplink);
+-void msn_slplink_unref(MsnSlpLink *slplink);
+-
+-/**
+- * @return An MsnSlpLink for the given user, or NULL if there is no
+- * existing MsnSlpLink.
+- */
+-MsnSlpLink *msn_session_find_slplink(MsnSession *session,
+- const char *who);
+-
+-/**
+- * @return An MsnSlpLink for the given user. One will be created if
+- * it does not already exist.
+- */
+-MsnSlpLink *msn_session_get_slplink(MsnSession *session, const char *username);
+-
+-void msn_slplink_add_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
+-void msn_slplink_remove_slpcall(MsnSlpLink *slplink, MsnSlpCall *slpcall);
+-MsnSlpCall *msn_slplink_find_slp_call(MsnSlpLink *slplink,
+- const char *id);
+-MsnSlpCall *msn_slplink_find_slp_call_with_session_id(MsnSlpLink *slplink, long id);
+-MsnP2PVersion msn_slplink_get_p2p_version(MsnSlpLink *slplink);
+-
+-void msn_slplink_queue_slpmsg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+-void msn_slplink_send_slpmsg(MsnSlpLink *slplink,
+- MsnSlpMessage *slpmsg);
+-void msn_slplink_send_queued_slpmsgs(MsnSlpLink *slplink);
+-void msn_slplink_process_msg(MsnSlpLink *slplink, MsnSlpMessagePart *part);
+-
+-/* Only exported for msn_xfer_write */
+-void msn_slplink_send_msgpart(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+-
+-void msn_slplink_request_object(MsnSlpLink *slplink,
+- const char *info,
+- MsnSlpCb cb,
+- MsnSlpEndCb end_cb,
+- const MsnObject *obj);
+-
+-MsnSlpCall *msn_slp_process_msg(MsnSlpLink *slplink, MsnSlpMessage *slpmsg);
+-
+-#endif /* MSN_SLPLINK_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.c
+--- pidgin-2.10.7/libpurple/protocols/msn/slpmsg.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,309 +0,0 @@
+-/**
+- * @file slpmsg.c SLP Message functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "slpmsg.h"
+-#include "slpmsg_part.h"
+-#include "slplink.h"
+-
+-/**************************************************************************
+- * SLP Message
+- **************************************************************************/
+-
+-MsnSlpMessage *
+-msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall)
+-{
+- MsnSlpMessage *slpmsg;
+- MsnP2PVersion p2p;
+-
+- g_return_val_if_fail(slplink != NULL, NULL);
+-
+- slpmsg = g_new0(MsnSlpMessage, 1);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpmsg new (%p)\n", slpmsg);
+-
+- msn_slpmsg_set_slplink(slpmsg, slplink);
+- slpmsg->slpcall = slpcall;
+-
+- p2p = msn_slplink_get_p2p_version(slplink);
+- slpmsg->p2p_info = msn_p2p_info_new(p2p);
+-
+- return slpmsg;
+-}
+-
+-void
+-msn_slpmsg_destroy(MsnSlpMessage *slpmsg)
+-{
+- MsnSlpLink *slplink;
+- GList *cur;
+-
+- g_return_if_fail(slpmsg != NULL);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "slpmsg destroy (%p)\n", slpmsg);
+-
+- slplink = slpmsg->slplink;
+-
+- purple_imgstore_unref(slpmsg->img);
+-
+- /* We don't want to free the data of the PurpleStoredImage,
+- * but to avoid code duplication, it's sharing buffer. */
+- if (slpmsg->img == NULL)
+- g_free(slpmsg->buffer);
+-
+- for (cur = slpmsg->parts; cur != NULL; cur = g_list_delete_link(cur, cur))
+- {
+- /* Something is pointing to this slpmsg, so we should remove that
+- * pointer to prevent a crash. */
+- /* Ex: a user goes offline and after that we receive an ACK */
+-
+- MsnSlpMessagePart *part = cur->data;
+-
+- part->ack_cb = NULL;
+- part->nak_cb = NULL;
+- part->ack_data = NULL;
+- msn_slpmsgpart_unref(part);
+- }
+-
+- slplink->slp_msgs = g_list_remove(slplink->slp_msgs, slpmsg);
+-
+- msn_p2p_info_free(slpmsg->p2p_info);
+-
+- g_free(slpmsg);
+-}
+-
+-void
+-msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink)
+-{
+- g_return_if_fail(slplink != NULL);
+-
+- slpmsg->slplink = slplink;
+-
+- slplink->slp_msgs =
+- g_list_append(slplink->slp_msgs, slpmsg);
+-}
+-
+-void
+-msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
+- long long size)
+-{
+- /* We can only have one data source at a time. */
+- g_return_if_fail(slpmsg->buffer == NULL);
+- g_return_if_fail(slpmsg->img == NULL);
+- g_return_if_fail(slpmsg->ft == FALSE);
+-
+- if (body != NULL)
+- slpmsg->buffer = g_memdup(body, size);
+- else
+- slpmsg->buffer = g_new0(guchar, size);
+-
+- slpmsg->size = size;
+-}
+-
+-void
+-msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img)
+-{
+- /* We can only have one data source at a time. */
+- g_return_if_fail(slpmsg->buffer == NULL);
+- g_return_if_fail(slpmsg->img == NULL);
+- g_return_if_fail(slpmsg->ft == FALSE);
+-
+- slpmsg->img = purple_imgstore_ref(img);
+- slpmsg->buffer = (guchar *)purple_imgstore_get_data(img);
+- slpmsg->size = purple_imgstore_get_size(img);
+-}
+-
+-
+-MsnSlpMessage *
+-msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
+- const char *header, const char *branch,
+- const char *content_type, const char *content)
+-{
+- MsnSlpLink *slplink;
+- PurpleAccount *account;
+- MsnSlpMessage *slpmsg;
+- char *body;
+- gsize body_len;
+- gsize content_len;
+-
+- g_return_val_if_fail(slpcall != NULL, NULL);
+- g_return_val_if_fail(header != NULL, NULL);
+-
+- slplink = slpcall->slplink;
+- account = slplink->session->account;
+-
+- /* Let's remember that "content" should end with a 0x00 */
+-
+- content_len = (content != NULL) ? strlen(content) + 1 : 0;
+-
+- body = g_strdup_printf(
+- "%s\r\n"
+- "To: <msnmsgr:%s>\r\n"
+- "From: <msnmsgr:%s>\r\n"
+- "Via: MSNSLP/1.0/TLP ;branch={%s}\r\n"
+- "CSeq: %d\r\n"
+- "Call-ID: {%s}\r\n"
+- "Max-Forwards: 0\r\n"
+- "Content-Type: %s\r\n"
+- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
+- "\r\n",
+- header,
+- slplink->remote_user,
+- purple_account_get_username(account),
+- branch,
+- cseq,
+- slpcall->id,
+- content_type,
+- content_len);
+-
+- body_len = strlen(body);
+-
+- if (content_len > 0)
+- {
+- body_len += content_len;
+- body = g_realloc(body, body_len);
+- g_strlcat(body, content, body_len);
+- }
+-
+- slpmsg = msn_slpmsg_new(slplink, slpcall);
+- msn_slpmsg_set_body(slpmsg, body, body_len);
+-
+- g_free(body);
+-
+- return slpmsg;
+-}
+-
+-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *ack_info)
+-{
+- MsnSlpMessage *slpmsg;
+- MsnP2PInfo *new_info;
+-
+- slpmsg = msn_slpmsg_new(slplink, NULL);
+-
+- new_info = slpmsg->p2p_info;
+- msn_p2p_info_create_ack(ack_info, new_info);
+- slpmsg->size = msn_p2p_info_get_total_size(ack_info);
+- slpmsg->info = "SLP ACK";
+-
+- return slpmsg;
+-}
+-
+-MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img)
+-{
+- MsnSlpMessage *slpmsg;
+-
+- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+- msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_MSN_OBJ_DATA);
+- slpmsg->info = "SLP DATA";
+-
+- msn_slpmsg_set_image(slpmsg, img);
+-
+- return slpmsg;
+-}
+-
+-MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall)
+-{
+- MsnSlpMessage *slpmsg;
+-
+- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+-
+- msn_p2p_info_set_session_id(slpmsg->p2p_info, slpcall->session_id);
+- msn_slpmsg_set_body(slpmsg, NULL, 4);
+- slpmsg->info = "SLP DATA PREP";
+-
+- return slpmsg;
+-
+-}
+-
+-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size)
+-{
+- MsnSlpMessage *slpmsg;
+-
+- slpmsg = msn_slpmsg_new(slpcall->slplink, slpcall);
+-
+- msn_p2p_info_set_flags(slpmsg->p2p_info, P2P_FILE_DATA);
+- slpmsg->info = "SLP FILE";
+- slpmsg->size = size;
+-
+- return slpmsg;
+-}
+-
+-char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size)
+-{
+- char *header;
+- char *footer;
+- char *base;
+- char *tmp;
+- size_t header_size, footer_size;
+-
+- header = msn_p2p_header_to_wire(slpmsg->p2p_info, &header_size);
+- footer = msn_p2p_footer_to_wire(slpmsg->p2p_info, &footer_size);
+-
+- base = g_malloc(header_size + slpmsg->size + footer_size);
+- tmp = base;
+-
+- /* Copy header */
+- memcpy(tmp, header, header_size);
+- tmp += header_size;
+-
+- /* Copy body */
+- memcpy(tmp, slpmsg->buffer, slpmsg->size);
+- tmp += slpmsg->size;
+-
+- /* Copy footer */
+- memcpy(tmp, footer, footer_size);
+- tmp += footer_size;
+-
+- *ret_size = tmp - base;
+-
+- g_free(header);
+- g_free(footer);
+-
+- return base;
+-}
+-
+-void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg)
+-{
+- GString *str;
+-
+- str = g_string_new(NULL);
+-
+- msn_p2p_info_to_string(slpmsg->p2p_info, str);
+-
+- if (purple_debug_is_verbose() && slpmsg->buffer != NULL) {
+- g_string_append_len(str, (gchar*)slpmsg->buffer, slpmsg->size);
+-
+- if (slpmsg->buffer[slpmsg->size - 1] == '\0') {
+- str->len--;
+- g_string_append(str, " 0x00");
+- }
+- g_string_append(str, "\r\n");
+-
+- }
+-
+- purple_debug_info("msn", "SlpMessage %s:\n{%s}\n", slpmsg->info, str->str);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.h
+--- pidgin-2.10.7/libpurple/protocols/msn/slpmsg.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,150 +0,0 @@
+-/**
+- * @file slpmsg.h SLP Message functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef _MSN_SLPMSG_H_
+-#define _MSN_SLPMSG_H_
+-
+-typedef struct _MsnSlpMessage MsnSlpMessage;
+-
+-#include "imgstore.h"
+-
+-#include "slpcall.h"
+-#include "slplink.h"
+-#include "session.h"
+-#include "p2p.h"
+-
+-#include "slp.h"
+-
+-/**
+- * A SLP Message This contains everything that we will need to send a SLP
+- * Message even if has to be sent in several parts.
+- */
+-struct _MsnSlpMessage
+-{
+- MsnSlpCall *slpcall; /**< The slpcall to which this slp message belongs (if applicable). */
+- MsnSlpLink *slplink; /**< The slplink through which this slp message is being sent. */
+- MsnSession *session;
+-
+- MsnP2PInfo *p2p_info;
+-
+- long id;
+-
+- gboolean ft;
+- PurpleStoredImage *img;
+- guchar *buffer;
+-
+- /**
+- * This is the size of buffer, unless this is an outgoing file transfer,
+- * in which case this is the size of the file.
+- */
+- long long size;
+-
+- GList *parts; /**< A list with the SlpMsgParts */
+-
+- const char *info;
+- gboolean text_body;
+-};
+-
+-/**
+- * Creates a new slp message
+- *
+- * @param slplink The slplink through which this slp message will be sent.
+- * If it's set to NULL, it is a temporary SlpMessage.
+- * @return The created slp message.
+- */
+-MsnSlpMessage *msn_slpmsg_new(MsnSlpLink *slplink, MsnSlpCall *slpcall);
+-
+-/**
+- * Destroys a slp message
+- *
+- * @param slpmsg The slp message to destory.
+- */
+-void msn_slpmsg_destroy(MsnSlpMessage *slpmsg);
+-
+-/**
+- * Relate this SlpMessage with an existing SlpLink
+- *
+- * @param slplink The SlpLink that will send this message.
+- */
+-void msn_slpmsg_set_slplink(MsnSlpMessage *slpmsg, MsnSlpLink *slplink);
+-
+-void msn_slpmsg_set_body(MsnSlpMessage *slpmsg, const char *body,
+- long long size);
+-void msn_slpmsg_set_image(MsnSlpMessage *slpmsg, PurpleStoredImage *img);
+-MsnSlpMessage * msn_slpmsg_sip_new(MsnSlpCall *slpcall, int cseq,
+- const char *header,
+- const char *branch,
+- const char *content_type,
+- const char *content);
+-
+-/**
+- * Create a new SLP Ack message
+- *
+- * @param header the value of the header in this slpmsg.
+- *
+- * @return A new SlpMessage with ACK headers
+- */
+-MsnSlpMessage *msn_slpmsg_ack_new(MsnSlpLink *slplink, MsnP2PInfo *info);
+-
+-/**
+- * Create a new SLP message for MsnObject data.
+- *
+- * @param slpcall The slpcall that manages this message.
+- * @param img The image to be sent in this message.
+- *
+- * @return A new SlpMessage with MsnObject info.
+- */
+-MsnSlpMessage *msn_slpmsg_obj_new(MsnSlpCall *slpcall, PurpleStoredImage *img);
+-
+-/**
+- * Create a new SLP message for data preparation.
+- *
+- * @param slpcall The slpcall that manages this message.
+- *
+- * @return A new SlpMessage with data preparation info.
+- */
+-MsnSlpMessage *msn_slpmsg_dataprep_new(MsnSlpCall *slpcall);
+-
+-/**
+- * Create a new SLP message for File transfer.
+- *
+- * @param slpcall The slpcall that manages this message.
+- * @param size The size of the file being transsmited.
+- *
+- * @return A new SlpMessage with the file transfer info.
+- */
+-MsnSlpMessage *msn_slpmsg_file_new(MsnSlpCall *slpcall, size_t size);
+-
+-/**
+- * Serialize the MsnSlpMessage in a way it can be used to be transmited
+- *
+- * @param slpmsg The MsnSlpMessage.
+- * @param ret_size The size of the buffer cointaining the message.
+- *
+- * @return a buffer with the serialized data.
+- */
+-char *msn_slpmsg_serialize(MsnSlpMessage *slpmsg, size_t *ret_size);
+-
+-void msn_slpmsg_show_readable(MsnSlpMessage *slpmsg);
+-
+-#endif /* _MSN_SLPMSG_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.c
+--- pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,232 +0,0 @@
+-/**
+- * @file slpmsg_part.c MSNSLP Parts
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "slpmsg.h"
+-#include "slpmsg_part.h"
+-
+-MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info)
+-{
+- MsnSlpMessagePart *part;
+-
+- part = g_new0(MsnSlpMessagePart, 1);
+-
+- part->info = info;
+-
+- part->ack_cb = msn_slpmsgpart_ack;
+- part->nak_cb = msn_slpmsgpart_nak;
+-
+- return msn_slpmsgpart_ref(part);
+-}
+-
+-MsnSlpMessagePart *
+-msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len)
+-{
+- MsnSlpMessagePart *part;
+- MsnP2PInfo *info;
+- size_t len;
+- int body_len;
+-
+- info = msn_p2p_info_new(p2p);
+-
+- /* Extract the binary SLP header */
+- len = msn_p2p_header_from_wire(info, data, data_len);
+- if (len == 0) {
+- msn_p2p_info_free(info);
+- return NULL;
+- }
+- data += len;
+- part = msn_slpmsgpart_new(info);
+-
+- /* Extract the body */
+- body_len = data_len - len - P2P_PACKET_FOOTER_SIZE;
+- /* msg->body_len = msg->msnslp_header.length; */
+-
+- if (body_len > 0) {
+- part->size = body_len;
+- part->buffer = g_malloc(body_len);
+- memcpy(part->buffer, data, body_len);
+- data += body_len;
+- }
+-
+- /* Extract the footer */
+- if (body_len >= 0)
+- msn_p2p_footer_from_wire(part->info, data);
+-
+- return part;
+-}
+-
+-static void msn_slpmsgpart_destroy(MsnSlpMessagePart *part)
+-{
+- g_free(part->info);
+- g_free(part->buffer);
+-
+- g_free(part);
+-
+-}
+-
+-MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part)
+-{
+- g_return_val_if_fail(part != NULL, NULL);
+- part->ref_count++;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "part ref (%p)[%u]\n", part, part->ref_count);
+-
+- return part;
+-}
+-
+-void msn_slpmsgpart_unref(MsnSlpMessagePart *part)
+-{
+- g_return_if_fail(part != NULL);
+- g_return_if_fail(part->ref_count > 0);
+-
+- part->ref_count--;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "part unref (%p)[%u]\n", part, part->ref_count);
+-
+- if (part->ref_count == 0) {
+- msn_slpmsgpart_destroy(part);
+- }
+-}
+-
+-void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len)
+-{
+- g_return_if_fail(part != NULL);
+-
+- g_free(part->buffer);
+-
+- if (data != NULL && len > 0) {
+- part->buffer = g_malloc(len + 1);
+- memcpy(part->buffer, data, len);
+- part->buffer[len] = '\0';
+- part->size = len;
+- } else {
+- part->buffer = NULL;
+- part->size = 0;
+- }
+-
+-}
+-
+-char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size)
+-{
+- char *header;
+- char *footer;
+- char *base;
+- char *tmp;
+- size_t header_size, footer_size;
+-
+- header = msn_p2p_header_to_wire(part->info, &header_size);
+- footer = msn_p2p_footer_to_wire(part->info, &footer_size);
+-
+- base = g_malloc(header_size + part->size + footer_size);
+- tmp = base;
+-
+- /* Copy header */
+- memcpy(tmp, header, header_size);
+- tmp += header_size;
+-
+- /* Copy body */
+- memcpy(tmp, part->buffer, part->size);
+- tmp += part->size;
+-
+- /* Copy footer */
+- memcpy(tmp, footer, footer_size);
+- tmp += footer_size;
+-
+- *ret_size = tmp - base;
+-
+- g_free(header);
+- g_free(footer);
+-
+- return base;
+-}
+-
+-/* We have received the message ack */
+-void
+-msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data)
+-{
+- MsnSlpMessage *slpmsg;
+- guint64 offset;
+- long long real_size;
+-
+- slpmsg = data;
+-
+- real_size = msn_p2p_info_is_ack(slpmsg->p2p_info) ? 0 : slpmsg->size;
+-
+- offset = msn_p2p_info_get_offset(slpmsg->p2p_info);
+- offset += msn_p2p_info_get_length(part->info);
+- msn_p2p_info_set_offset(slpmsg->p2p_info, offset);
+-
+- slpmsg->parts = g_list_remove(slpmsg->parts, part);
+- msn_slpmsgpart_unref(part);
+-
+- if (offset < real_size)
+- {
+- if (slpmsg->slpcall->xfer && purple_xfer_get_status(slpmsg->slpcall->xfer) == PURPLE_XFER_STATUS_STARTED)
+- {
+- slpmsg->slpcall->xfer_msg = slpmsg;
+- purple_xfer_prpl_ready(slpmsg->slpcall->xfer);
+- }
+- else
+- msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+- }
+- else
+- {
+- /* The whole message has been sent */
+- if (msn_p2p_msg_is_data(slpmsg->p2p_info))
+- {
+- if (slpmsg->slpcall != NULL)
+- {
+- if (slpmsg->slpcall->cb)
+- slpmsg->slpcall->cb(slpmsg->slpcall,
+- NULL, 0);
+- }
+- }
+- }
+-}
+-
+-/* We have received the message nak. */
+-void
+-msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data)
+-{
+- MsnSlpMessage *slpmsg;
+-
+- slpmsg = data;
+-
+- msn_slplink_send_msgpart(slpmsg->slplink, slpmsg);
+-
+- slpmsg->parts = g_list_remove(slpmsg->parts, part);
+- msn_slpmsgpart_unref(part);
+-}
+-
+-void
+-msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str)
+-{
+- msn_p2p_info_to_string(part->info, str);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.h
+--- pidgin-2.10.7/libpurple/protocols/msn/slpmsg_part.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/slpmsg_part.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,66 +0,0 @@
+-/**
+- * @file slpmsg_part.h MSNSLP Parts
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef MSN_SLPMSG_PART_H
+-#define MSN_SLPMSG_PART_H
+-
+-#include "p2p.h"
+-
+-typedef struct _MsnSlpMessagePart MsnSlpMessagePart;
+-typedef void (*MsnSlpPartCb)(MsnSlpMessagePart *part, void *data);
+-
+-struct _MsnSlpMessagePart
+-{
+- guint ref_count;
+-
+- MsnP2PInfo *info;
+-
+- MsnSlpPartCb ack_cb;
+- MsnSlpPartCb nak_cb;
+- void *ack_data;
+-
+- guchar *buffer;
+- size_t size;
+-};
+-
+-MsnSlpMessagePart *msn_slpmsgpart_new(MsnP2PInfo *info);
+-
+-MsnSlpMessagePart *msn_slpmsgpart_new_from_data(MsnP2PVersion p2p, const char *data, size_t data_len);
+-
+-MsnSlpMessagePart *msn_slpmsgpart_ref(MsnSlpMessagePart *part);
+-
+-void msn_slpmsgpart_unref(MsnSlpMessagePart *part);
+-
+-void msn_slpmsgpart_set_bin_data(MsnSlpMessagePart *part, const void *data, size_t len);
+-
+-char *msn_slpmsgpart_serialize(MsnSlpMessagePart *part, size_t *ret_size);
+-
+-void msn_slpmsgpart_ack(MsnSlpMessagePart *part, void *data);
+-
+-void msn_slpmsgpart_nak(MsnSlpMessagePart *part, void *data);
+-
+-void msn_slpmsgpart_to_string(MsnSlpMessagePart *part, GString *str);
+-
+-#endif /* MSN_SLPMSG_PART_H */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/soap.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.c
+--- pidgin-2.10.7/libpurple/protocols/msn/soap.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,683 +0,0 @@
+-/**
+- * @file soap.c
+- * Functions relating to SOAP connections.
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-
+-#include "internal.h"
+-
+-#include "soap.h"
+-
+-#include "session.h"
+-
+-#include "debug.h"
+-#include "xmlnode.h"
+-
+-#include <glib.h>
+-#if !defined(_WIN32) || !defined(_WINERROR_)
+-#include <error.h>
+-#endif
+-
+-#define SOAP_TIMEOUT (5 * 60)
+-
+-typedef struct _MsnSoapRequest {
+- char *path;
+- MsnSoapMessage *message;
+- gboolean secure;
+- MsnSoapCallback cb;
+- gpointer cb_data;
+-} MsnSoapRequest;
+-
+-typedef struct _MsnSoapConnection {
+- MsnSession *session;
+- char *host;
+-
+- time_t last_used;
+- PurpleSslConnection *ssl;
+- gboolean connected;
+-
+- guint event_handle;
+- guint run_timer;
+- GString *buf;
+- gsize handled_len;
+- gsize body_len;
+- int response_code;
+- gboolean headers_done;
+- gboolean close_when_done;
+-
+- MsnSoapMessage *message;
+-
+- GQueue *queue;
+- MsnSoapRequest *current_request;
+-} MsnSoapConnection;
+-
+-static gboolean msn_soap_connection_run(gpointer data);
+-
+-static MsnSoapConnection *
+-msn_soap_connection_new(MsnSession *session, const char *host)
+-{
+- MsnSoapConnection *conn = g_new0(MsnSoapConnection, 1);
+- conn->session = session;
+- conn->host = g_strdup(host);
+- conn->queue = g_queue_new();
+- return conn;
+-}
+-
+-static void
+-msn_soap_message_destroy(MsnSoapMessage *message)
+-{
+- g_slist_foreach(message->headers, (GFunc)g_free, NULL);
+- g_slist_free(message->headers);
+- g_free(message->action);
+- if (message->xml)
+- xmlnode_free(message->xml);
+- g_free(message);
+-}
+-
+-static void
+-msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message)
+-{
+- g_free(req->path);
+- if (!keep_message)
+- msn_soap_message_destroy(req->message);
+- g_free(req);
+-}
+-
+-static void
+-msn_soap_connection_sanitize(MsnSoapConnection *conn, gboolean disconnect)
+-{
+- if (conn->event_handle) {
+- purple_input_remove(conn->event_handle);
+- conn->event_handle = 0;
+- }
+-
+- if (conn->run_timer) {
+- purple_timeout_remove(conn->run_timer);
+- conn->run_timer = 0;
+- }
+-
+- if (conn->message) {
+- msn_soap_message_destroy(conn->message);
+- conn->message = NULL;
+- }
+-
+- if (conn->buf) {
+- g_string_free(conn->buf, TRUE);
+- conn->buf = NULL;
+- }
+-
+- if (conn->ssl && (disconnect || conn->close_when_done)) {
+- purple_ssl_close(conn->ssl);
+- conn->ssl = NULL;
+- }
+-
+- if (conn->current_request) {
+- msn_soap_request_destroy(conn->current_request, FALSE);
+- conn->current_request = NULL;
+- }
+-}
+-
+-static void
+-msn_soap_connection_destroy_foreach_cb(gpointer item, gpointer data)
+-{
+- MsnSoapRequest *req = item;
+-
+- req->cb(req->message, NULL, req->cb_data);
+-
+- msn_soap_request_destroy(req, FALSE);
+-}
+-
+-static void
+-msn_soap_connection_destroy(MsnSoapConnection *conn)
+-{
+- if (conn->current_request) {
+- MsnSoapRequest *req = conn->current_request;
+- conn->current_request = NULL;
+- msn_soap_connection_destroy_foreach_cb(req, conn);
+- }
+-
+- msn_soap_connection_sanitize(conn, TRUE);
+- g_queue_foreach(conn->queue, msn_soap_connection_destroy_foreach_cb, conn);
+- g_queue_free(conn->queue);
+-
+- g_free(conn->host);
+- g_free(conn);
+-}
+-
+-static gboolean
+-msn_soap_cleanup_each(gpointer key, gpointer value, gpointer data)
+-{
+- MsnSoapConnection *conn = value;
+- time_t *t = data;
+-
+- if ((*t - conn->last_used) > SOAP_TIMEOUT * 2) {
+- purple_debug_info("soap", "cleaning up soap conn %p\n", conn);
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-static gboolean
+-msn_soap_cleanup_for_session(gpointer data)
+-{
+- MsnSession *sess = data;
+- time_t t = time(NULL);
+-
+- purple_debug_info("soap", "session cleanup timeout\n");
+-
+- if (sess->soap_table) {
+- g_hash_table_foreach_remove(sess->soap_table, msn_soap_cleanup_each,
+- &t);
+-
+- if (g_hash_table_size(sess->soap_table) != 0)
+- return TRUE;
+- }
+-
+- sess->soap_cleanup_handle = 0;
+- return FALSE;
+-}
+-
+-static MsnSoapConnection *
+-msn_soap_get_connection(MsnSession *session, const char *host)
+-{
+- MsnSoapConnection *conn = NULL;
+-
+- if (session->soap_table) {
+- conn = g_hash_table_lookup(session->soap_table, host);
+- } else {
+- session->soap_table = g_hash_table_new_full(g_str_hash, g_str_equal,
+- NULL, (GDestroyNotify)msn_soap_connection_destroy);
+- }
+-
+- if (session->soap_cleanup_handle == 0)
+- session->soap_cleanup_handle = purple_timeout_add_seconds(SOAP_TIMEOUT,
+- msn_soap_cleanup_for_session, session);
+-
+- if (conn == NULL) {
+- conn = msn_soap_connection_new(session, host);
+- g_hash_table_insert(session->soap_table, conn->host, conn);
+- }
+-
+- conn->last_used = time(NULL);
+-
+- return conn;
+-}
+-
+-static void
+-msn_soap_connection_handle_next(MsnSoapConnection *conn)
+-{
+- msn_soap_connection_sanitize(conn, FALSE);
+-
+- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
+-}
+-
+-static void
+-msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
+- const char *host, const char *path, gboolean secure,
+- MsnSoapCallback cb, gpointer cb_data, gboolean first)
+-{
+- MsnSoapConnection *conn = msn_soap_get_connection(session, host);
+- MsnSoapRequest *req = g_new0(MsnSoapRequest, 1);
+-
+- req->path = g_strdup(path);
+- req->message = message;
+- req->secure = secure;
+- req->cb = cb;
+- req->cb_data = cb_data;
+-
+- if (first) {
+- g_queue_push_head(conn->queue, req);
+- } else {
+- g_queue_push_tail(conn->queue, req);
+- }
+-
+- if (conn->run_timer == 0)
+- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run,
+- conn);
+-}
+-
+-void
+-msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
+- const char *host, const char *path, gboolean secure,
+- MsnSoapCallback cb, gpointer cb_data)
+-{
+- g_return_if_fail(message != NULL);
+- g_return_if_fail(cb != NULL);
+-
+- msn_soap_message_send_internal(session, message, host, path, secure,
+- cb, cb_data, FALSE);
+-}
+-
+-static gboolean
+-msn_soap_handle_redirect(MsnSoapConnection *conn, const char *url)
+-{
+- char *host;
+- char *path;
+-
+- if (purple_url_parse(url, &host, NULL, &path, NULL, NULL)) {
+- MsnSoapRequest *req = conn->current_request;
+- conn->current_request = NULL;
+-
+- msn_soap_message_send_internal(conn->session, req->message, host, path,
+- req->secure, req->cb, req->cb_data, TRUE);
+-
+- msn_soap_request_destroy(req, TRUE);
+-
+- g_free(host);
+- g_free(path);
+-
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-static gboolean
+-msn_soap_handle_body(MsnSoapConnection *conn, MsnSoapMessage *response)
+-{
+- xmlnode *body = xmlnode_get_child(response->xml, "Body");
+- xmlnode *fault = xmlnode_get_child(response->xml, "Fault");
+-
+- if (fault) {
+- xmlnode *faultcode = xmlnode_get_child(fault, "faultcode");
+-
+- if (faultcode != NULL) {
+- char *faultdata = xmlnode_get_data(faultcode);
+-
+- if (g_str_equal(faultdata, "psf:Redirect")) {
+- xmlnode *url = xmlnode_get_child(fault, "redirectUrl");
+-
+- if (url) {
+- char *urldata = xmlnode_get_data(url);
+- msn_soap_handle_redirect(conn, urldata);
+- g_free(urldata);
+- }
+-
+- g_free(faultdata);
+- msn_soap_message_destroy(response);
+- return TRUE;
+- } else if (g_str_equal(faultdata, "wsse:FailedAuthentication")) {
+- xmlnode *reason = xmlnode_get_child(fault, "faultstring");
+- char *reasondata = xmlnode_get_data(reason);
+-
+- msn_soap_connection_sanitize(conn, TRUE);
+- msn_session_set_error(conn->session, MSN_ERROR_AUTH,
+- reasondata);
+-
+- g_free(reasondata);
+- g_free(faultdata);
+- msn_soap_message_destroy(response);
+- return FALSE;
+- }
+-
+- g_free(faultdata);
+- }
+- }
+-
+- if (fault || body) {
+- if (conn->current_request) {
+- MsnSoapRequest *request = conn->current_request;
+- conn->current_request = NULL;
+- request->cb(request->message, response,
+- request->cb_data);
+- msn_soap_request_destroy(request, FALSE);
+- }
+- msn_soap_message_destroy(response);
+- }
+-
+- return TRUE;
+-}
+-
+-static void
+-msn_soap_message_add_header(MsnSoapMessage *message,
+- const char *name, const char *value)
+-{
+- char *header = g_strdup_printf("%s: %s\r\n", name, value);
+-
+- message->headers = g_slist_prepend(message->headers, header);
+-}
+-
+-static void
+-msn_soap_process(MsnSoapConnection *conn)
+-{
+- gboolean handled = FALSE;
+- char *cursor;
+- char *linebreak;
+-
+- cursor = conn->buf->str + conn->handled_len;
+-
+- if (!conn->headers_done) {
+- while ((linebreak = strstr(cursor, "\r\n")) != NULL) {
+- conn->handled_len = linebreak - conn->buf->str + 2;
+-
+- if (conn->response_code == 0) {
+- if (sscanf(cursor, "HTTP/1.1 %d", &conn->response_code) != 1) {
+- /* something horribly wrong */
+- purple_ssl_close(conn->ssl);
+- conn->ssl = NULL;
+- handled = TRUE;
+- break;
+- } else if (conn->response_code == 503 && conn->session->login_step < MSN_LOGIN_STEP_END) {
+- msn_soap_connection_sanitize(conn, TRUE);
+- msn_session_set_error(conn->session, MSN_ERROR_SERV_UNAVAILABLE, NULL);
+- return;
+- }
+- } else if (cursor == linebreak) {
+- /* blank line */
+- conn->headers_done = TRUE;
+- cursor = conn->buf->str + conn->handled_len;
+- break;
+- } else {
+- char *line = g_strndup(cursor, linebreak - cursor);
+- char *sep = strstr(line, ": ");
+- char *key = line;
+- char *value;
+-
+- if (sep == NULL) {
+- purple_debug_info("soap", "ignoring malformed line: %s\n", line);
+- g_free(line);
+- goto loop_end;
+- }
+-
+- value = sep + 2;
+- *sep = '\0';
+- msn_soap_message_add_header(conn->message, key, value);
+-
+- if ((conn->response_code == 301 || conn->response_code == 300)
+- && strcmp(key, "Location") == 0) {
+-
+- msn_soap_handle_redirect(conn, value);
+-
+- handled = TRUE;
+- g_free(line);
+- break;
+- } else if (conn->response_code == 401 &&
+- strcmp(key, "WWW-Authenticate") == 0) {
+- char *error = strstr(value, "cbtxt=");
+-
+- if (error) {
+- error += strlen("cbtxt=");
+- }
+-
+- msn_soap_connection_sanitize(conn, TRUE);
+- msn_session_set_error(conn->session, MSN_ERROR_AUTH,
+- error ? purple_url_decode(error) : NULL);
+-
+- g_free(line);
+- return;
+- } else if (strcmp(key, "Content-Length") == 0) {
+- sscanf(value, "%" G_GSIZE_FORMAT, &(conn->body_len));
+- } else if (strcmp(key, "Connection") == 0) {
+- if (strcmp(value, "close") == 0) {
+- conn->close_when_done = TRUE;
+- }
+- }
+- g_free(line);
+- }
+-
+- loop_end:
+- cursor = conn->buf->str + conn->handled_len;
+- }
+- }
+-
+- if (!handled && conn->headers_done) {
+- if (conn->buf->len - conn->handled_len >=
+- conn->body_len) {
+- xmlnode *node = xmlnode_from_str(cursor, conn->body_len);
+-
+- if (node == NULL) {
+- purple_debug_info("soap", "Malformed SOAP response: %s\n",
+- cursor);
+- } else {
+- MsnSoapMessage *message = conn->message;
+- conn->message = NULL;
+- message->xml = node;
+-
+- if (!msn_soap_handle_body(conn, message)) {
+- return;
+- }
+- }
+-
+- msn_soap_connection_handle_next(conn);
+- }
+-
+- return;
+- }
+-
+- if (handled) {
+- msn_soap_connection_handle_next(conn);
+- }
+-}
+-
+-static void
+-msn_soap_read_cb(gpointer data, gint fd, PurpleInputCondition cond)
+-{
+- MsnSoapConnection *conn = data;
+- int count = 0, cnt, perrno;
+- /* This buffer needs to be larger than any packets received from
+- login.live.com or Adium will fail to receive the packet
+- (something weird with the login.live.com server). With NSS it works
+- fine, so I believe it's some bug with OS X */
+- char buf[16 * 1024];
+- gsize cursor;
+-
+- if (conn->message == NULL) {
+- conn->message = msn_soap_message_new(NULL, NULL);
+- }
+-
+- if (conn->buf == NULL) {
+- conn->buf = g_string_new_len(buf, 0);
+- }
+-
+- cursor = conn->buf->len;
+- while ((cnt = purple_ssl_read(conn->ssl, buf, sizeof(buf))) > 0) {
+- purple_debug_info("soap", "read %d bytes\n", cnt);
+- count += cnt;
+- g_string_append_len(conn->buf, buf, cnt);
+- }
+-
+- perrno = errno;
+- if (cnt < 0 && perrno != EAGAIN)
+- purple_debug_info("soap", "read: %s\n", g_strerror(perrno));
+-
+- if (conn->current_request && conn->current_request->secure &&
+- !purple_debug_is_unsafe())
+- purple_debug_misc("soap", "Received secure request.\n");
+- else if (count != 0)
+- purple_debug_misc("soap", "current %s\n", conn->buf->str + cursor);
+-
+- /* && count is necessary for Adium, on OS X the last read always
+- return an error, so we want to proceed anyway. See #5212 for
+- discussion on this and the above buffer size issues */
+- if(cnt < 0 && errno == EAGAIN && count == 0)
+- return;
+-
+- /* msn_soap_process could alter errno */
+- msn_soap_process(conn);
+-
+- if ((cnt < 0 && perrno != EAGAIN) || cnt == 0) {
+- /* It's possible msn_soap_process closed the ssl connection */
+- if (conn->ssl) {
+- purple_ssl_close(conn->ssl);
+- conn->ssl = NULL;
+- msn_soap_connection_handle_next(conn);
+- }
+- }
+-}
+-
+-static gboolean
+-msn_soap_write_cb_internal(gpointer data, gint fd, PurpleInputCondition cond,
+- gboolean initial)
+-{
+- MsnSoapConnection *conn = data;
+- int written;
+-
+- if (cond != PURPLE_INPUT_WRITE)
+- return TRUE;
+-
+- written = purple_ssl_write(conn->ssl, conn->buf->str + conn->handled_len,
+- conn->buf->len - conn->handled_len);
+-
+- if (written < 0 && errno == EAGAIN)
+- return TRUE;
+- else if (written <= 0) {
+- purple_ssl_close(conn->ssl);
+- conn->ssl = NULL;
+- if (!initial)
+- msn_soap_connection_handle_next(conn);
+- return FALSE;
+- }
+-
+- conn->handled_len += written;
+-
+- if (conn->handled_len < conn->buf->len)
+- return TRUE;
+-
+- /* we are done! */
+- g_string_free(conn->buf, TRUE);
+- conn->buf = NULL;
+- conn->handled_len = 0;
+- conn->body_len = 0;
+- conn->response_code = 0;
+- conn->headers_done = FALSE;
+- conn->close_when_done = FALSE;
+-
+- purple_input_remove(conn->event_handle);
+- conn->event_handle = purple_input_add(conn->ssl->fd, PURPLE_INPUT_READ,
+- msn_soap_read_cb, conn);
+- return TRUE;
+-}
+-
+-static void
+-msn_soap_write_cb(gpointer data, gint fd, PurpleInputCondition cond)
+-{
+- msn_soap_write_cb_internal(data, fd, cond, FALSE);
+-}
+-
+-static void
+-msn_soap_error_cb(PurpleSslConnection *ssl, PurpleSslErrorType error,
+- gpointer data)
+-{
+- MsnSoapConnection *conn = data;
+-
+- /* sslconn already frees the connection in case of error */
+- conn->ssl = NULL;
+-
+- g_hash_table_remove(conn->session->soap_table, conn->host);
+-}
+-
+-static void
+-msn_soap_connected_cb(gpointer data, PurpleSslConnection *ssl,
+- PurpleInputCondition cond)
+-{
+- MsnSoapConnection *conn = data;
+-
+- conn->connected = TRUE;
+-
+- if (conn->run_timer == 0)
+- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
+-}
+-
+-MsnSoapMessage *
+-msn_soap_message_new(const char *action, xmlnode *xml)
+-{
+- MsnSoapMessage *message = g_new0(MsnSoapMessage, 1);
+-
+- message->action = g_strdup(action);
+- message->xml = xml;
+-
+- return message;
+-}
+-
+-static gboolean
+-msn_soap_connection_run(gpointer data)
+-{
+- MsnSoapConnection *conn = data;
+- MsnSoapRequest *req = g_queue_peek_head(conn->queue);
+-
+- conn->run_timer = 0;
+-
+- if (req) {
+- if (conn->ssl == NULL) {
+- conn->ssl = purple_ssl_connect(conn->session->account, conn->host,
+- 443, msn_soap_connected_cb, msn_soap_error_cb, conn);
+- } else if (conn->connected) {
+- int len = -1;
+- char *body = xmlnode_to_str(req->message->xml, &len);
+- GSList *iter;
+-
+- g_queue_pop_head(conn->queue);
+-
+- conn->buf = g_string_new("");
+-
+- g_string_append_printf(conn->buf,
+- "POST /%s HTTP/1.1\r\n"
+- "SOAPAction: %s\r\n"
+- "Content-Type:text/xml; charset=utf-8\r\n"
+- "User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)\r\n"
+- "Accept: */*\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %d\r\n"
+- "Connection: Keep-Alive\r\n"
+- "Cache-Control: no-cache\r\n",
+- req->path, req->message->action ? req->message->action : "",
+- conn->host, len);
+-
+- for (iter = req->message->headers; iter; iter = iter->next) {
+- g_string_append(conn->buf, (char *)iter->data);
+- g_string_append(conn->buf, "\r\n");
+- }
+-
+- g_string_append(conn->buf, "\r\n");
+- g_string_append(conn->buf, body);
+-
+- if (req->secure && !purple_debug_is_unsafe())
+- purple_debug_misc("soap", "Sending secure request.\n");
+- else
+- purple_debug_misc("soap", "%s\n", conn->buf->str);
+-
+- conn->handled_len = 0;
+- conn->current_request = req;
+-
+- if (conn->event_handle)
+- purple_input_remove(conn->event_handle);
+- conn->event_handle = purple_input_add(conn->ssl->fd,
+- PURPLE_INPUT_WRITE, msn_soap_write_cb, conn);
+- if (!msn_soap_write_cb_internal(conn, conn->ssl->fd, PURPLE_INPUT_WRITE, TRUE)) {
+- /* Not connected => reconnect and retry */
+- purple_debug_info("soap", "not connected, reconnecting\n");
+-
+- conn->connected = FALSE;
+- conn->current_request = NULL;
+- msn_soap_connection_sanitize(conn, FALSE);
+-
+- g_queue_push_head(conn->queue, req);
+- conn->run_timer = purple_timeout_add(0, msn_soap_connection_run, conn);
+- }
+-
+- g_free(body);
+- }
+- }
+-
+- return FALSE;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/soap.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.h
+--- pidgin-2.10.7/libpurple/protocols/msn/soap.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/soap.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,52 +0,0 @@
+-/**
+- * @file soap.h
+- * header file for SOAP connection related process
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
+- */
+-#ifndef MSN_SOAP_H
+-#define MSN_SOAP_H
+-
+-typedef struct _MsnSoapMessage MsnSoapMessage;
+-
+-#include <glib.h>
+-
+-#include "xmlnode.h"
+-
+-#include "session.h"
+-#include "sslconn.h"
+-
+-typedef void (*MsnSoapCallback)(MsnSoapMessage *request,
+- MsnSoapMessage *response, gpointer cb_data);
+-
+-struct _MsnSoapMessage {
+- char *action;
+- xmlnode *xml;
+- GSList *headers;
+-};
+-
+-MsnSoapMessage *msn_soap_message_new(const char *action, xmlnode *xml);
+-
+-void msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
+- const char *host, const char *path, gboolean secure,
+- MsnSoapCallback cb, gpointer cb_data);
+-
+-#endif /* MSN_SOAP_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/state.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.c
+--- pidgin-2.10.7/libpurple/protocols/msn/state.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,315 +0,0 @@
+-/**
+- * @file state.c State functions and definitions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "core.h"
+-
+-#include "notification.h"
+-#include "state.h"
+-
+-static const char *away_text[] =
+-{
+- N_("Available"),
+- N_("Available"),
+- N_("Busy"),
+- N_("Idle"),
+- N_("Be Right Back"),
+- N_("Away From Computer"),
+- N_("On The Phone"),
+- N_("Out To Lunch"),
+- N_("Available"),
+- N_("Available")
+-};
+-
+-/*
+- * WLM media PSM info build prcedure
+- *
+- * Result can like:
+- * <CurrentMedia>\0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0</CurrentMedia>\
+- * <CurrentMedia>\0Games\01\0Playing {0}\0Game Name\0</CurrentMedia>\
+- * <CurrentMedia>\0Office\01\0Office Message\0Office App Name\0</CurrentMedia>"
+- */
+-static char *
+-msn_build_psm(const char *psmstr,const char *mediastr, const char *guidstr, guint protocol_ver)
+-{
+- xmlnode *dataNode,*psmNode,*mediaNode,*guidNode;
+- char *result;
+- int length;
+-
+- dataNode = xmlnode_new("Data");
+-
+- psmNode = xmlnode_new("PSM");
+- if(psmstr != NULL){
+- xmlnode_insert_data(psmNode, psmstr, -1);
+- }
+- xmlnode_insert_child(dataNode, psmNode);
+-
+- mediaNode = xmlnode_new("CurrentMedia");
+- if(mediastr != NULL){
+- xmlnode_insert_data(mediaNode, mediastr, -1);
+- }
+- xmlnode_insert_child(dataNode, mediaNode);
+-
+- guidNode = xmlnode_new("MachineGuid");
+- if(guidstr != NULL){
+- xmlnode_insert_data(guidNode, guidstr, -1);
+- }
+- xmlnode_insert_child(dataNode, guidNode);
+-
+- if (protocol_ver >= 16) {
+- /* TODO: What is this for? */
+- xmlnode *ddpNode = xmlnode_new("DDP");
+- xmlnode_insert_child(dataNode, ddpNode);
+- }
+-
+- result = xmlnode_to_str(dataNode, &length);
+- xmlnode_free(dataNode);
+- return result;
+-}
+-
+-/* get the CurrentMedia info from the XML node */
+-char *
+-msn_get_currentmedia(xmlnode *payloadNode)
+-{
+- xmlnode *currentmediaNode;
+- char *currentmedia;
+-
+- purple_debug_info("msn", "Get CurrentMedia\n");
+- currentmediaNode = xmlnode_get_child(payloadNode, "CurrentMedia");
+- if (currentmediaNode == NULL) {
+- purple_debug_info("msn", "No CurrentMedia Node\n");
+- return NULL;
+- }
+- currentmedia = xmlnode_get_data(currentmediaNode);
+-
+- return currentmedia;
+-}
+-
+-/* Get the PSM info from the XML node */
+-char *
+-msn_get_psm(xmlnode *payloadNode)
+-{
+- xmlnode *psmNode;
+- char *psm;
+-
+- purple_debug_info("msn", "msn get PSM\n");
+- psmNode = xmlnode_get_child(payloadNode, "PSM");
+- if (psmNode == NULL) {
+- purple_debug_info("msn", "No PSM status Node\n");
+- return NULL;
+- }
+- psm = xmlnode_get_data(psmNode);
+-
+- return psm;
+-}
+-
+-static char *
+-create_media_string(PurplePresence *presence)
+-{
+- const char *title, *game, *office;
+- char *ret;
+- PurpleStatus *status = purple_presence_get_status(presence, "tune");
+- if (!status || !purple_status_is_active(status))
+- return NULL;
+-
+- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+- game = purple_status_get_attr_string(status, "game");
+- office = purple_status_get_attr_string(status, "office");
+-
+- if (title && *title) {
+- const char *artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+- const char *album = purple_status_get_attr_string(status, PURPLE_TUNE_ALBUM);
+- ret = g_strdup_printf("WMP\\0Music\\01\\0{0}%s%s\\0%s\\0%s\\0%s\\0",
+- artist ? " - {1}" : "",
+- album ? " ({2})" : "",
+- title,
+- artist ? artist : "",
+- album ? album : "");
+- }
+- else if (game && *game)
+- ret = g_strdup_printf("\\0Games\\01\\0Playing {0}\\0%s\\0", game);
+- else if (office && *office)
+- ret = g_strdup_printf("\\0Office\\01\\0Editing {0}\\0%s\\0", office);
+- else
+- ret = NULL;
+-
+- return ret;
+-}
+-
+-/* set the MSN's PSM info,Currently Read from the status Line
+- * Thanks for Cris Code
+- */
+-static void
+-msn_set_psm(MsnSession *session)
+-{
+- PurpleAccount *account;
+- PurplePresence *presence;
+- PurpleStatus *status;
+- char *payload;
+- const char *statusline;
+- gchar *statusline_stripped, *media = NULL;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->notification != NULL);
+-
+- account = session->account;
+-
+- /* Get the PSM string from Purple's Status Line */
+- presence = purple_account_get_presence(account);
+- status = purple_presence_get_active_status(presence);
+- statusline = purple_status_get_attr_string(status, "message");
+-
+- /* MSN expects plain text, not HTML */
+- statusline_stripped = purple_markup_strip_html(statusline);
+- media = create_media_string(presence);
+- g_free(session->psm);
+- session->psm = msn_build_psm(statusline_stripped, media, session->guid, session->protocol_ver);
+-
+- payload = session->psm;
+-
+- msn_notification_send_uux(session, payload);
+-
+- g_free(statusline_stripped);
+- g_free(media);
+-}
+-
+-void
+-msn_change_status(MsnSession *session)
+-{
+- PurpleAccount *account;
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+- MsnUser *user;
+- MsnObject *msnobj;
+- const char *state_text;
+- GHashTable *ui_info = purple_core_get_ui_info();
+- MsnClientCaps caps = MSN_CLIENT_ID;
+-
+- g_return_if_fail(session != NULL);
+- g_return_if_fail(session->notification != NULL);
+-
+- /* set client caps based on what the UI tells us it is... */
+- if (ui_info) {
+- const gchar *client_type = g_hash_table_lookup(ui_info, "client_type");
+- if (client_type) {
+- if (strcmp(client_type, "phone") == 0 ||
+- strcmp(client_type, "handheld") == 0) {
+- caps |= MSN_CAP_VIA_MOBILE;
+- } else if (strcmp(client_type, "web") == 0) {
+- caps |= MSN_CAP_VIA_WEBIM;
+- } else if (strcmp(client_type, "bot") == 0) {
+- caps |= MSN_CAP_BOT;
+- }
+- /* MSN doesn't a "console" type...
+- What, they have no ncurses UI? :-) */
+- }
+- }
+-
+- account = session->account;
+- cmdproc = session->notification->cmdproc;
+- user = session->user;
+- state_text = msn_state_get_text(msn_state_from_account(account));
+-
+- /* If we're not logged in yet, don't send the status to the server,
+- * it will be sent when login completes
+- */
+- if (!session->logged_in)
+- return;
+-
+- msn_set_psm(session);
+-
+- msnobj = msn_user_get_object(user);
+-
+- if (msnobj == NULL)
+- {
+- trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u 0", state_text,
+- caps, MSN_CLIENT_ID_EXT_CAPS);
+- }
+- else
+- {
+- char *msnobj_str;
+-
+- msnobj_str = msn_object_to_string(msnobj);
+-
+- trans = msn_transaction_new(cmdproc, "CHG", "%s %u:%02u %s", state_text,
+- caps, MSN_CLIENT_ID_EXT_CAPS,
+- purple_url_encode(msnobj_str));
+-
+- g_free(msnobj_str);
+- }
+-
+- msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-const char *
+-msn_away_get_text(MsnAwayType type)
+-{
+- g_return_val_if_fail(type <= MSN_HIDDEN, NULL);
+-
+- return _(away_text[type]);
+-}
+-
+-const char *
+-msn_state_get_text(MsnAwayType state)
+-{
+- static char *status_text[] =
+- { "NLN", "NLN", "BSY", "IDL", "BRB", "AWY", "PHN", "LUN", "HDN", "HDN" };
+-
+- return status_text[state];
+-}
+-
+-MsnAwayType
+-msn_state_from_account(PurpleAccount *account)
+-{
+- MsnAwayType msnstatus;
+- PurplePresence *presence;
+- PurpleStatus *status;
+- const char *status_id;
+-
+- presence = purple_account_get_presence(account);
+- status = purple_presence_get_active_status(presence);
+- status_id = purple_status_get_id(status);
+-
+- if (!strcmp(status_id, "away"))
+- msnstatus = MSN_AWAY;
+- else if (!strcmp(status_id, "brb"))
+- msnstatus = MSN_BRB;
+- else if (!strcmp(status_id, "busy"))
+- msnstatus = MSN_BUSY;
+- else if (!strcmp(status_id, "phone"))
+- msnstatus = MSN_PHONE;
+- else if (!strcmp(status_id, "lunch"))
+- msnstatus = MSN_LUNCH;
+- else if (!strcmp(status_id, "invisible"))
+- msnstatus = MSN_HIDDEN;
+- else
+- msnstatus = MSN_ONLINE;
+-
+- if ((msnstatus == MSN_ONLINE) && purple_presence_is_idle(presence))
+- msnstatus = MSN_IDLE;
+-
+- return msnstatus;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/state.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.h
+--- pidgin-2.10.7/libpurple/protocols/msn/state.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/state.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,69 +0,0 @@
+-/**
+- * @file state.h State functions and definitions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_STATE_H
+-#define MSN_STATE_H
+-
+-/**
+- * Away types.
+- */
+-typedef enum
+-{
+- MSN_ONLINE = 1,
+- MSN_BUSY = 2,
+- MSN_IDLE = 3,
+- MSN_BRB = 4,
+- MSN_AWAY = 5,
+- MSN_PHONE = 6,
+- MSN_LUNCH = 7,
+- MSN_OFFLINE = 8,
+- MSN_HIDDEN = 9
+-} MsnAwayType;
+-
+-/**
+- * Changes the status of the user.
+- *
+- * @param session The MSN session.
+- */
+-void msn_change_status(MsnSession *session);
+-
+-/**
+- * Returns the string representation of an away type.
+- *
+- * @param type The away type.
+- *
+- * @return The string representation of the away type.
+- */
+-const char *msn_away_get_text(MsnAwayType type);
+-
+-const char *msn_state_get_text(MsnAwayType state);
+-
+-/* Get the CurrentMedia info from the XML node */
+-char *msn_get_currentmedia(xmlnode *payloadNode);
+-
+-/* Get the PSM info from the XML node */
+-char *msn_get_psm(xmlnode *payloadNode);
+-
+-MsnAwayType msn_state_from_account(PurpleAccount *account);
+-
+-#endif /* MSN_STATE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/switchboard.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.c
+--- pidgin-2.10.7/libpurple/protocols/msn/switchboard.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1197 +0,0 @@
+-/**
+- * @file switchboard.c MSN switchboard functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msnutils.h"
+-#include "switchboard.h"
+-#include "sbconn.h"
+-#include "slplink.h"
+-#include "user.h"
+-#include "userlist.h"
+-
+-static MsnTable *cbs_table;
+-
+-/**************************************************************************
+- * Main
+- **************************************************************************/
+-
+-MsnSwitchBoard *
+-msn_switchboard_new(MsnSession *session)
+-{
+- MsnSwitchBoard *swboard;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- swboard = g_new0(MsnSwitchBoard, 1);
+-
+- swboard->session = session;
+- swboard->servconn = msn_servconn_new(session, MSN_SERVCONN_SB);
+- msn_servconn_set_idle_timeout(swboard->servconn, 60);
+- swboard->cmdproc = swboard->servconn->cmdproc;
+-
+- swboard->msg_queue = g_queue_new();
+- swboard->empty = TRUE;
+-
+- swboard->cmdproc->data = swboard;
+- swboard->cmdproc->cbs_table = cbs_table;
+-
+- session->switches = g_list_prepend(session->switches, swboard);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "switchboard new: swboard(%p)\n", swboard);
+-
+- return swboard;
+-}
+-
+-void
+-msn_switchboard_destroy(MsnSwitchBoard *swboard)
+-{
+- MsnSession *session;
+- MsnMessage *msg;
+- GList *l;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "switchboard destroy: swboard(%p)\n", swboard);
+-
+- g_return_if_fail(swboard != NULL);
+-
+- if (swboard->destroying)
+- return;
+-
+- swboard->destroying = TRUE;
+-
+- if (swboard->reconn_timeout_h > 0)
+- purple_timeout_remove(swboard->reconn_timeout_h);
+-
+- /* If it linked us is because its looking for trouble */
+- while (swboard->slplinks != NULL) {
+- MsnSlpLink *slplink = swboard->slplinks->data;
+-
+- swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
+-
+- /* Destroy only those slplinks which use the switchboard */
+- if (slplink->dc == NULL)
+- msn_slplink_unref(slplink);
+- else {
+- swboard->slplinks = g_list_remove(swboard->slplinks, slplink);
+- slplink->swboard = NULL;
+- }
+- }
+-
+- /* Destroy the message queue */
+- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL)
+- {
+- if (swboard->error != MSN_SB_ERROR_NONE)
+- {
+- /* The messages could not be sent due to a switchboard error */
+- msg_error_helper(swboard->cmdproc, msg,
+- MSN_MSG_ERROR_SB);
+- }
+- msn_message_unref(msg);
+- }
+-
+- g_queue_free(swboard->msg_queue);
+-
+- /* msg_error_helper will both remove the msg from ack_list and
+- unref it, so we don't need to do either here */
+- while ((l = swboard->ack_list) != NULL)
+- msg_error_helper(swboard->cmdproc, l->data, MSN_MSG_ERROR_SB);
+-
+- g_free(swboard->im_user);
+- g_free(swboard->auth_key);
+- g_free(swboard->session_id);
+-
+- for (; swboard->users; swboard->users = g_list_delete_link(swboard->users, swboard->users))
+- msn_user_unref(swboard->users->data);
+-
+- session = swboard->session;
+- session->switches = g_list_remove(session->switches, swboard);
+-
+- for (l = session->slplinks; l; l = l->next) {
+- MsnSlpLink *slplink = l->data;
+- if (slplink->swboard == swboard) slplink->swboard = NULL;
+- }
+-
+-#if 0
+- /* This should never happen or we are in trouble. */
+- if (swboard->servconn != NULL)
+- msn_servconn_destroy(swboard->servconn);
+-#endif
+-
+- swboard->cmdproc->data = NULL;
+-
+- msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
+-
+- msn_servconn_destroy(swboard->servconn);
+-
+- g_free(swboard);
+-}
+-
+-void
+-msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key)
+-{
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(key != NULL);
+-
+- swboard->auth_key = g_strdup(key);
+-}
+-
+-const char *
+-msn_switchboard_get_auth_key(MsnSwitchBoard *swboard)
+-{
+- g_return_val_if_fail(swboard != NULL, NULL);
+-
+- return swboard->auth_key;
+-}
+-
+-void
+-msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id)
+-{
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(id != NULL);
+-
+- g_free(swboard->session_id);
+- swboard->session_id = g_strdup(id);
+-}
+-
+-const char *
+-msn_switchboard_get_session_id(MsnSwitchBoard *swboard)
+-{
+- g_return_val_if_fail(swboard != NULL, NULL);
+-
+- return swboard->session_id;
+-}
+-
+-int
+-msn_switchboard_get_chat_id(void)
+-{
+- static int chat_id = 1;
+-
+- return chat_id++;
+-}
+-
+-void
+-msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited)
+-{
+- g_return_if_fail(swboard != NULL);
+-
+- swboard->invited = invited;
+-}
+-
+-gboolean
+-msn_switchboard_is_invited(MsnSwitchBoard *swboard)
+-{
+- g_return_val_if_fail(swboard != NULL, FALSE);
+-
+- return swboard->invited;
+-}
+-
+-/**************************************************************************
+- * Utility
+- **************************************************************************/
+-
+-static void
+-send_clientcaps(MsnSwitchBoard *swboard)
+-{
+- MsnMessage *msg;
+-
+- msg = msn_message_new(MSN_MSG_CAPS);
+- msn_message_set_content_type(msg, "text/x-clientcaps");
+- msn_message_set_flag(msg, 'U');
+- msn_message_set_bin_data(msg, MSN_CLIENTINFO, strlen(MSN_CLIENTINFO));
+-
+- msn_switchboard_send_msg(swboard, msg, TRUE);
+-
+- msn_message_unref(msg);
+-}
+-
+-static void
+-msn_switchboard_add_user(MsnSwitchBoard *swboard, const char *user)
+-{
+- MsnCmdProc *cmdproc;
+- PurpleAccount *account;
+- MsnUserList *userlist;
+- MsnUser *msnuser;
+- char *semicolon;
+- char *passport;
+-
+- g_return_if_fail(swboard != NULL);
+-
+- cmdproc = swboard->cmdproc;
+- account = cmdproc->session->account;
+-
+- semicolon = strchr(user, ';');
+- /* We don't really care about the machine ID. */
+- if (semicolon)
+- passport = g_strndup(user, semicolon - user);
+- else
+- passport = g_strdup(user);
+-
+- userlist = swboard->session->userlist;
+- msnuser = msn_userlist_find_user(userlist, passport);
+-
+- /* Don't add multiple endpoints to the conversation. */
+- if (g_list_find_custom(swboard->users, passport, (GCompareFunc)msn_user_passport_cmp)) {
+- g_free(passport);
+- return;
+- }
+-
+- /* Don't add ourselves either... */
+- if (g_str_equal(passport, purple_account_get_username(account))) {
+- g_free(passport);
+- return;
+- }
+-
+- if (!msnuser) {
+- purple_debug_info("msn","User %s is not on our list.\n", passport);
+- msnuser = msn_user_new(userlist, passport, NULL);
+- } else
+- msn_user_ref(msnuser);
+-
+- g_free(passport);
+-
+- swboard->users = g_list_prepend(swboard->users, msnuser);
+- swboard->current_users++;
+- swboard->empty = FALSE;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "user=[%s], total=%d\n",
+- user, swboard->current_users);
+-
+- if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
+- {
+- /* This is a helper switchboard. */
+- purple_debug_error("msn", "switchboard_add_user: conv != NULL\n");
+- return;
+- }
+-
+- if ((swboard->conv != NULL) &&
+- (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+- {
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv), msnuser->passport, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+- msn_servconn_set_idle_timeout(swboard->servconn, 0);
+- }
+- else if (swboard->current_users > 1)
+- {
+- msn_servconn_set_idle_timeout(swboard->servconn, 0);
+- if (swboard->conv == NULL ||
+- purple_conversation_get_type(swboard->conv) != PURPLE_CONV_TYPE_CHAT)
+- {
+- GList *l;
+-
+-#if 0
+- /* this is bad - it causes msn_switchboard_close to be called on the
+- * switchboard we're in the middle of using :( */
+- if (swboard->conv != NULL)
+- purple_conversation_destroy(swboard->conv);
+-#endif
+-
+- swboard->chat_id = msn_switchboard_get_chat_id();
+- swboard->flag |= MSN_SB_FLAG_IM;
+- swboard->conv = serv_got_joined_chat(account->gc,
+- swboard->chat_id,
+- "MSN Chat");
+-
+- for (l = swboard->users; l != NULL; l = l->next)
+- {
+- const char *tmp_user;
+-
+- tmp_user = ((MsnUser*)l->data)->passport;
+-
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
+- tmp_user, NULL, PURPLE_CBFLAGS_NONE, TRUE);
+- }
+-
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(swboard->conv),
+- purple_account_get_username(account),
+- NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-
+- g_free(swboard->im_user);
+- swboard->im_user = NULL;
+- }
+- }
+- else if (swboard->conv == NULL)
+- {
+- swboard->conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- msnuser->passport, account);
+- }
+- else
+- {
+- purple_debug_warning("msn", "switchboard_add_user: This should not happen!\n");
+- }
+-}
+-
+-static PurpleConversation *
+-msn_switchboard_get_conv(MsnSwitchBoard *swboard)
+-{
+- PurpleAccount *account;
+-
+- g_return_val_if_fail(swboard != NULL, NULL);
+-
+- if (swboard->conv != NULL)
+- return swboard->conv;
+-
+- purple_debug_error("msn", "Switchboard with unassigned conversation\n");
+-
+- account = swboard->session->account;
+-
+- return (swboard->conv = purple_conversation_new(PURPLE_CONV_TYPE_IM,
+- account, swboard->im_user));
+-}
+-
+-static void
+-msn_switchboard_report_user(MsnSwitchBoard *swboard, PurpleMessageFlags flags, const char *msg)
+-{
+- PurpleConversation *conv;
+-
+- g_return_if_fail(swboard != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- if ((conv = msn_switchboard_get_conv(swboard)) != NULL)
+- {
+- purple_conversation_write(conv, NULL, msg, flags, time(NULL));
+- }
+-}
+-
+-static void
+-swboard_error_helper(MsnSwitchBoard *swboard, int reason, const char *passport)
+-{
+- g_return_if_fail(swboard != NULL);
+-
+- purple_debug_warning("msn", "Error: Unable to call the user %s for reason %i\n",
+- passport ? passport : "(null)", reason);
+-
+- /* TODO: if current_users > 0, this is probably a chat and an invite failed,
+- * we should report that in the chat or something */
+- if (swboard->current_users == 0)
+- {
+- swboard->error = reason;
+- msn_switchboard_close(swboard);
+- }
+-}
+-
+-static void
+-cal_error_helper(MsnTransaction *trans, int reason)
+-{
+- MsnSwitchBoard *swboard;
+- const char *passport;
+- char **params;
+-
+- params = g_strsplit(trans->params, " ", 0);
+-
+- passport = params[0];
+-
+- swboard = trans->data;
+-
+- purple_debug_warning("msn", "cal_error_helper: command %s failed for reason %i\n",trans->command,reason);
+-
+- swboard_error_helper(swboard, reason, passport);
+-
+- g_strfreev(params);
+-}
+-
+-static gboolean
+-msg_resend_cb(gpointer data)
+-{
+- MsnSwitchBoard *swboard = data;
+-
+- purple_debug_info("msn", "unqueuing unsent message to %s\n", swboard->im_user);
+-
+- if (msn_switchboard_request(swboard)) {
+- msn_switchboard_request_add_user(swboard, swboard->im_user);
+- swboard->reconn_timeout_h = 0;
+- }
+- return FALSE;
+-}
+-
+-void
+-msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error)
+-{
+- MsnSwitchBoard *swboard;
+-
+- g_return_if_fail(cmdproc != NULL);
+- g_return_if_fail(msg != NULL);
+-
+- if ((error != MSN_MSG_ERROR_SB) && (msg->nak_cb != NULL))
+- msg->nak_cb(msg, msg->ack_data);
+-
+- swboard = cmdproc->data;
+-
+- /* This is not good, and should be fixed somewhere else. */
+- g_return_if_fail(swboard != NULL);
+-
+- if (msg->type == MSN_MSG_TEXT)
+- {
+- const char *format, *str_reason;
+- char *body_str, *body_enc, *pre, *post;
+-
+-#if 0
+- if (swboard->conv == NULL)
+- {
+- if (msg->ack_ref)
+- msn_message_unref(msg);
+-
+- return;
+- }
+-#endif
+-
+- if (error == MSN_MSG_ERROR_TIMEOUT)
+- {
+- str_reason = _("Message may have not been sent "
+- "because a timeout occurred:");
+- }
+- else if (error == MSN_MSG_ERROR_SB)
+- {
+- MsnSession *session = swboard->session;
+-
+- if (!session->destroying && msg->retries && swboard->im_user &&
+- (swboard->error == MSN_SB_ERROR_CONNECTION ||
+- swboard->error == MSN_SB_ERROR_UNKNOWN)) {
+- MsnSwitchBoard *new_sw = msn_session_find_swboard(session,
+- swboard->im_user);
+-
+- if (new_sw == NULL || new_sw->reconn_timeout_h == 0) {
+- new_sw = msn_switchboard_new(session);
+- new_sw->im_user = g_strdup(swboard->im_user);
+- new_sw->reconn_timeout_h = purple_timeout_add_seconds(3, msg_resend_cb, new_sw);
+- new_sw->flag |= MSN_SB_FLAG_IM;
+- }
+-
+- body_str = msn_message_to_string(msg);
+- body_enc = g_markup_escape_text(body_str, -1);
+- g_free(body_str);
+-
+- purple_debug_info("msn", "queuing unsent message to %s: %s\n",
+- swboard->im_user, body_enc);
+- g_free(body_enc);
+- msn_send_im_message(session, msg);
+- msg->retries--;
+-
+- return;
+- }
+-
+- switch (swboard->error)
+- {
+- case MSN_SB_ERROR_OFFLINE:
+- str_reason = _("Message could not be sent, "
+- "not allowed while invisible:");
+- break;
+- case MSN_SB_ERROR_USER_OFFLINE:
+- str_reason = _("Message could not be sent "
+- "because the user is offline:");
+- break;
+- case MSN_SB_ERROR_CONNECTION:
+- str_reason = _("Message could not be sent "
+- "because a connection error occurred:");
+- break;
+- case MSN_SB_ERROR_TOO_FAST:
+- str_reason = _("Message could not be sent "
+- "because we are sending too quickly:");
+- break;
+- case MSN_SB_ERROR_AUTHFAILED:
+- str_reason = _("Message could not be sent "
+- "because we were 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 "
+- "the switchboard occurred:");
+- break;
+- }
+- }
+- else
+- {
+- str_reason = _("Message may have not been sent "
+- "because an unknown error occurred:");
+- }
+-
+- body_str = msn_message_to_string(msg);
+- body_enc = g_markup_escape_text(body_str, -1);
+- g_free(body_str);
+-
+- format = msn_message_get_header_value(msg, "X-MMS-IM-Format");
+- msn_parse_format(format, &pre, &post);
+- body_str = g_strdup_printf("%s%s%s", pre ? pre : "",
+- body_enc ? body_enc : "", post ? post : "");
+- g_free(body_enc);
+- g_free(pre);
+- g_free(post);
+-
+- msn_switchboard_report_user(swboard, PURPLE_MESSAGE_ERROR,
+- str_reason);
+- msn_switchboard_report_user(swboard, PURPLE_MESSAGE_RAW,
+- body_str);
+-
+- g_free(body_str);
+- }
+-
+- /* If a timeout occures we will want the msg around just in case we
+- * receive the ACK after the timeout. */
+- if (msg->ack_ref && error != MSN_MSG_ERROR_TIMEOUT)
+- {
+- swboard->ack_list = g_list_remove(swboard->ack_list, msg);
+- msn_message_unref(msg);
+- }
+-}
+-
+-/**************************************************************************
+- * Message Stuff
+- **************************************************************************/
+-
+-/** Called when we receive an error of a message. */
+-static void
+-msg_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- msg_error_helper(cmdproc, trans->data, MSN_MSG_ERROR_UNKNOWN);
+-}
+-
+-gboolean
+-msn_switchboard_can_send(MsnSwitchBoard *swboard)
+-{
+- g_return_val_if_fail(swboard != NULL, FALSE);
+-
+- if (swboard->empty || !g_queue_is_empty(swboard->msg_queue))
+- return FALSE;
+-
+- return TRUE;
+-}
+-
+-/**************************************************************************
+- * Switchboard Commands
+- **************************************************************************/
+-
+-static void
+-ans_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+-
+- swboard = cmdproc->data;
+- swboard->ready = TRUE;
+-}
+-
+-static void
+-bye_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+- const char *user;
+-
+- swboard = cmdproc->data;
+- user = cmd->params[0];
+-
+- /* cmdproc->data is set to NULL when the switchboard is destroyed;
+- * we may get a bye shortly thereafter. */
+- g_return_if_fail(swboard != NULL);
+-
+- if (!(swboard->flag & MSN_SB_FLAG_IM) && (swboard->conv != NULL))
+- purple_debug_error("msn", "bye_cmd: helper bug\n");
+-
+- if (swboard->conv == NULL)
+- {
+- /* This is a helper switchboard */
+- msn_switchboard_destroy(swboard);
+- }
+- else if ((swboard->current_users > 1) ||
+- (purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+- {
+- GList *passport;
+- /* This is a switchboard used for a chat */
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(swboard->conv), user, NULL);
+-
+- passport = g_list_find_custom(swboard->users, user, (GCompareFunc)strcmp);
+- if (passport)
+- g_free(passport->data);
+- else
+- purple_debug_warning("msn", "Can't find user %s in the switchboard\n", user);
+- swboard->users = g_list_delete_link(swboard->users, passport);
+- swboard->current_users--;
+- if (swboard->current_users == 0)
+- msn_switchboard_destroy(swboard);
+- }
+- else
+- {
+- /* This is a switchboard used for a im session */
+- msn_switchboard_destroy(swboard);
+- }
+-}
+-
+-static void
+-iro_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+-
+- swboard = cmdproc->data;
+-
+- swboard->total_users = atoi(cmd->params[2]);
+-
+- msn_switchboard_add_user(swboard, cmd->params[3]);
+-}
+-
+-static void
+-joi_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- const char *passport;
+-
+- passport = cmd->params[0];
+-
+- session = cmdproc->session;
+- swboard = cmdproc->data;
+-
+- msn_switchboard_add_user(swboard, passport);
+-
+- msn_sbconn_process_queue(swboard);
+-
+- if (!session->http_method)
+- send_clientcaps(swboard);
+-
+- if (swboard->closed)
+- msn_switchboard_close(swboard);
+-}
+-
+-static void
+-msg_cmd_post(MsnCmdProc *cmdproc, MsnCommand *cmd, char *payload, size_t len)
+-{
+- MsnMessage *msg;
+-
+- msg = msn_message_new_from_cmd(cmdproc->session, cmd);
+-
+- msn_message_parse_payload(msg, payload, len,
+- MSG_LINE_DEM,MSG_BODY_DEM);
+- if (purple_debug_is_verbose())
+- msn_message_show_readable(msg, "SB RECV", FALSE);
+-
+- g_free (msg->remote_user);
+- msg->remote_user = g_strdup(cmd->params[0]);
+-
+- msn_cmdproc_process_msg(cmdproc, msg);
+-
+- msn_message_unref(msg);
+-}
+-
+-static void
+-msg_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- cmd->payload_len = atoi(cmd->params[2]);
+- cmdproc->last_cmd->payload_cb = msg_cmd_post;
+-}
+-
+-static void
+-ubm_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- purple_debug_misc("msn", "get UBM...\n");
+- cmd->payload_len = atoi(cmd->params[5]);
+- cmdproc->last_cmd->payload_cb = msg_cmd_post;
+-}
+-
+-static void
+-nak_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnMessage *msg;
+-
+- msg = cmd->trans->data;
+- g_return_if_fail(msg != NULL);
+-
+- msg_error_helper(cmdproc, msg, MSN_MSG_ERROR_NAK);
+- cmd->trans->data = NULL;
+-}
+-
+-static void
+-ack_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+- MsnMessage *msg;
+-
+- msg = cmd->trans->data;
+-
+- if (msg->part && msg->part->ack_cb != NULL)
+- msg->part->ack_cb(msg->part, msg->part->ack_data);
+-
+- swboard = cmdproc->data;
+- if (swboard)
+- swboard->ack_list = g_list_remove(swboard->ack_list, msg);
+- msn_message_unref(msg);
+- cmd->trans->data = NULL;
+-}
+-
+-static void
+-out_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- PurpleConnection *gc;
+- MsnSwitchBoard *swboard;
+-
+- gc = cmdproc->session->account->gc;
+- swboard = cmdproc->data;
+-
+- if (swboard->current_users > 1)
+- serv_got_chat_left(gc, swboard->chat_id);
+-
+- msn_switchboard_disconnect(swboard);
+-}
+-
+-static void
+-usr_cmd(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+-
+- swboard = cmdproc->data;
+-
+-#if 0
+- GList *l;
+-
+- for (l = swboard->users; l != NULL; l = l->next)
+- {
+- const char *user;
+- user = l->data;
+-
+- msn_cmdproc_send(cmdproc, "CAL", "%s", user);
+- }
+-#endif
+-
+- swboard->ready = TRUE;
+- msn_cmdproc_process_queue(cmdproc);
+-}
+-
+-/**************************************************************************
+- * Message Handlers
+- **************************************************************************/
+-static void
+-clientcaps_msg(MsnCmdProc *cmdproc, MsnMessage *msg)
+-{
+-#if 0
+- MsnSession *session;
+- MsnSwitchBoard *swboard;
+- MsnUser *user;
+- GHashTable *clientcaps;
+- const char *value;
+-
+- char *passport = msg->sender;
+-
+- session = cmdproc->session;
+- swboard = cmdproc->servconn->swboard;
+-
+- clientcaps = msn_message_get_hashtable_from_body(msg);
+-#endif
+-}
+-
+-void
+-msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+- const char *data)
+-{
+- PurpleConnection *gc;
+- guchar *image_data;
+- size_t image_len;
+- int imgid;
+- char *image_msg;
+-
+- if (!purple_str_has_prefix(data, "base64:"))
+- {
+- purple_debug_error("msn", "Ignoring Ink not in Base64 format.\n");
+- return;
+- }
+-
+- gc = purple_account_get_connection(swboard->session->account);
+-
+- data += sizeof("base64:") - 1;
+- image_data = purple_base64_decode(data, &image_len);
+- if (!image_data || !image_len)
+- {
+- purple_debug_error("msn", "Unable to decode Ink from Base64 format.\n");
+- return;
+- }
+-
+- imgid = purple_imgstore_add_with_id(image_data, image_len, NULL);
+- image_msg = g_strdup_printf("<IMG ID='%d'>", imgid);
+-
+- if (swboard->current_users > 1 ||
+- ((swboard->conv != NULL) &&
+- purple_conversation_get_type(swboard->conv) == PURPLE_CONV_TYPE_CHAT))
+- serv_got_chat_in(gc, swboard->chat_id, passport, 0, image_msg,
+- time(NULL));
+- else
+- serv_got_im(gc, passport, image_msg, 0, time(NULL));
+-
+- purple_imgstore_unref_by_id(imgid);
+- g_free(image_msg);
+-}
+-
+-/**************************************************************************
+- * 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;
+- char *username;
+-
+- cmdproc = servconn->cmdproc;
+- g_return_if_fail(cmdproc != NULL);
+-
+- account = cmdproc->session->account;
+- swboard = cmdproc->data;
+- g_return_if_fail(swboard != NULL);
+-
+- username = g_strdup_printf("%s;{%s}",
+- purple_account_get_username(account),
+- servconn->session->guid);
+-
+- if (msn_switchboard_is_invited(swboard))
+- {
+- swboard->empty = FALSE;
+-
+- trans = msn_transaction_new(cmdproc, "ANS", "%s %s %s",
+- username,
+- swboard->auth_key, swboard->session_id);
+- }
+- else
+- {
+- trans = msn_transaction_new(cmdproc, "USR", "%s %s",
+- username,
+- swboard->auth_key);
+- }
+-
+- msn_transaction_set_error_cb(trans, ans_usr_error);
+- msn_transaction_set_data(trans, swboard);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- g_free(username);
+-}
+-
+-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
+-disconnect_cb(MsnServConn *servconn)
+-{
+- MsnSwitchBoard *swboard;
+-
+- swboard = servconn->cmdproc->data;
+- g_return_if_fail(swboard != NULL);
+-
+- msn_servconn_set_disconnect_cb(swboard->servconn, NULL);
+-
+- msn_switchboard_destroy(swboard);
+-}
+-
+-gboolean
+-msn_switchboard_connect(MsnSwitchBoard *swboard, const char *host, int port)
+-{
+- g_return_val_if_fail(swboard != NULL, FALSE);
+-
+- msn_servconn_set_connect_cb(swboard->servconn, connect_cb);
+- msn_servconn_set_disconnect_cb(swboard->servconn, disconnect_cb);
+-
+- return msn_servconn_connect(swboard->servconn, host, port, FALSE);
+-}
+-
+-void
+-msn_switchboard_disconnect(MsnSwitchBoard *swboard)
+-{
+- g_return_if_fail(swboard != NULL);
+-
+- msn_servconn_disconnect(swboard->servconn);
+-}
+-
+-/**************************************************************************
+- * Call stuff
+- **************************************************************************/
+-static void
+-got_cal(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+-#if 0
+- MsnSwitchBoard *swboard;
+- const char *user;
+-
+- swboard = cmdproc->data;
+-
+- user = cmd->params[0];
+-
+- msn_switchboard_add_user(swboard, user);
+-#endif
+-}
+-
+-static void
+-cal_timeout(MsnCmdProc *cmdproc, MsnTransaction *trans)
+-{
+- purple_debug_warning("msn", "cal_timeout: command %s timed out\n", trans->command);
+-
+- cal_error_helper(trans, MSN_SB_ERROR_UNKNOWN);
+-}
+-
+-static void
+-cal_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- int reason = MSN_SB_ERROR_UNKNOWN;
+- MsnMessage *msg;
+- MsnSwitchBoard *swboard = trans->data;
+-
+- if (error == 215)
+- {
+- purple_debug_info("msn", "Invited user already in switchboard\n");
+- return;
+- }
+- else if (error == 217)
+- {
+- reason = MSN_SB_ERROR_USER_OFFLINE;
+- }
+-
+- purple_debug_warning("msn", "cal_error: command %s gave error %i\n", trans->command, error);
+-
+- while ((msg = g_queue_pop_head(swboard->msg_queue)) != NULL){
+- purple_debug_warning("msn", "Unable to send msg: {%s}\n", msg->body);
+- /* The messages could not be sent due to a switchboard error */
+- swboard->error = MSN_SB_ERROR_USER_OFFLINE;
+- msg_error_helper(swboard->cmdproc, msg,
+- MSN_MSG_ERROR_SB);
+- }
+- cal_error_helper(trans, reason);
+-}
+-
+-void
+-msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user)
+-{
+- MsnTransaction *trans;
+- MsnCmdProc *cmdproc;
+-
+- g_return_if_fail(swboard != NULL);
+-
+- cmdproc = swboard->cmdproc;
+-
+- trans = msn_transaction_new(cmdproc, "CAL", "%s", user);
+- /* this doesn't do anything, but users seem to think that
+- * 'Unhandled command' is some kind of error, so we don't report it */
+- msn_transaction_add_cb(trans, "CAL", got_cal);
+-
+- msn_transaction_set_data(trans, swboard);
+- msn_transaction_set_timeout_cb(trans, cal_timeout);
+-
+- if (swboard->ready)
+- msn_cmdproc_send_trans(cmdproc, trans);
+- else
+- msn_cmdproc_queue_trans(cmdproc, trans);
+-}
+-
+-/**************************************************************************
+- * Create & Transfer stuff
+- **************************************************************************/
+-
+-static void
+-got_swboard(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+- MsnSwitchBoard *swboard;
+- char *host;
+- int port;
+- swboard = cmd->trans->data;
+-
+- if (g_list_find(cmdproc->session->switches, swboard) == NULL)
+- /* The conversation window was closed. */
+- return;
+-
+- purple_debug_info("msn", "Switchboard:auth:{%s} socket:{%s}\n", cmd->params[4], cmd->params[2]);
+- msn_switchboard_set_auth_key(swboard, cmd->params[4]);
+-
+- msn_parse_socket(cmd->params[2], &host, &port);
+-
+- if (!msn_switchboard_connect(swboard, host, port))
+- msn_switchboard_destroy(swboard);
+-
+- g_free(host);
+-}
+-
+-static void
+-xfr_error(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+- MsnSwitchBoard *swboard;
+- int reason = MSN_SB_ERROR_UNKNOWN;
+-
+- if (error == 913)
+- reason = MSN_SB_ERROR_OFFLINE;
+- else if (error == 800)
+- reason = MSN_SB_ERROR_TOO_FAST;
+-
+- swboard = trans->data;
+-
+- purple_debug_info("msn",
+- "xfr_error %i for %s: trans %p, command %s, reason %i\n",
+- error, (swboard->im_user ? swboard->im_user : "(null)"), trans,
+- (trans->command ? trans->command : "(null)"), reason);
+-
+- swboard_error_helper(swboard, reason, swboard->im_user);
+-}
+-
+-gboolean
+-msn_switchboard_request(MsnSwitchBoard *swboard)
+-{
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+-
+- g_return_val_if_fail(swboard != NULL, FALSE);
+-
+- cmdproc = swboard->session->notification->cmdproc;
+-
+- trans = msn_transaction_new(cmdproc, "XFR", "%s", "SB");
+- msn_transaction_add_cb(trans, "XFR", got_swboard);
+-
+- msn_transaction_set_data(trans, swboard);
+- msn_transaction_set_error_cb(trans, xfr_error);
+-
+- return msn_cmdproc_send_trans(cmdproc, trans);
+-}
+-
+-void
+-msn_switchboard_close(MsnSwitchBoard *swboard)
+-{
+- g_return_if_fail(swboard != NULL);
+-
+- if (swboard->error != MSN_SB_ERROR_NONE)
+- {
+- msn_switchboard_destroy(swboard);
+- }
+- else if (g_queue_is_empty(swboard->msg_queue) ||
+- !swboard->session->connected)
+- {
+- MsnCmdProc *cmdproc;
+- MsnTransaction *trans;
+- cmdproc = swboard->cmdproc;
+- trans = msn_transaction_new(cmdproc, "OUT", NULL);
+- msn_transaction_set_saveable(trans, FALSE);
+- msn_cmdproc_send_trans(cmdproc, trans);
+-
+- msn_switchboard_destroy(swboard);
+- }
+- else
+- {
+- swboard->closed = TRUE;
+- }
+-}
+-
+-void
+-msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag)
+-{
+- g_return_if_fail(swboard != NULL);
+-
+- swboard->flag &= ~flag;
+-
+- if (flag == MSN_SB_FLAG_IM)
+- /* Forget any conversation that used to be associated with this
+- * swboard. */
+- swboard->conv = NULL;
+-
+- if (swboard->flag == 0)
+- /* Nothing else is using this switchboard, so close it */
+- msn_switchboard_close(swboard);
+-}
+-
+-/**************************************************************************
+- * Init stuff
+- **************************************************************************/
+-
+-void
+-msn_switchboard_init(void)
+-{
+- cbs_table = msn_table_new();
+-
+- msn_table_add_cmd(cbs_table, "ANS", "ANS", ans_cmd);
+- msn_table_add_cmd(cbs_table, "ANS", "IRO", iro_cmd);
+-
+- msn_table_add_cmd(cbs_table, "MSG", "ACK", ack_cmd);
+- msn_table_add_cmd(cbs_table, "MSG", "NAK", nak_cmd);
+-
+- msn_table_add_cmd(cbs_table, "USR", "USR", usr_cmd);
+-
+- msn_table_add_cmd(cbs_table, NULL, "MSG", msg_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "UBM", ubm_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "JOI", joi_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "BYE", bye_cmd);
+- msn_table_add_cmd(cbs_table, NULL, "OUT", out_cmd);
+-
+-#if 0
+- /* They might skip the history */
+- msn_table_add_cmd(cbs_table, NULL, "ACK", NULL);
+-#endif
+-
+- msn_table_add_error(cbs_table, "MSG", msg_error);
+- msn_table_add_error(cbs_table, "CAL", cal_error);
+-
+- /* Register the message type callbacks. */
+- msn_table_add_msg_type(cbs_table, "text/plain",
+- msn_plain_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-msmsgscontrol",
+- msn_control_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-clientcaps",
+- clientcaps_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-clientinfo",
+- clientcaps_msg);
+- msn_table_add_msg_type(cbs_table, "application/x-msnmsgrp2p",
+- msn_p2p_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-mms-emoticon",
+- msn_emoticon_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-mms-animemoticon",
+- msn_emoticon_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-msnmsgr-datacast",
+- msn_datacast_msg);
+- msn_table_add_msg_type(cbs_table, "text/x-msmsgsinvite",
+- msn_invite_msg);
+- msn_table_add_msg_type(cbs_table, "image/gif",
+- msn_handwritten_msg);
+-}
+-
+-void
+-msn_switchboard_end(void)
+-{
+- msn_table_destroy(cbs_table);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/switchboard.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.h
+--- pidgin-2.10.7/libpurple/protocols/msn/switchboard.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/switchboard.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,266 +0,0 @@
+-/**
+- * @file switchboard.h MSN switchboard functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_SWITCHBOARD_H
+-#define MSN_SWITCHBOARD_H
+-
+-typedef struct _MsnSwitchBoard MsnSwitchBoard;
+-
+-/**
+- * A switchboard error.
+- */
+-typedef enum
+-{
+- MSN_SB_ERROR_NONE, /**< No error. */
+- MSN_SB_ERROR_CAL, /**< The user could not join (answer the call). */
+- MSN_SB_ERROR_OFFLINE, /**< The account is offline. */
+- 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 switchboard flag.
+- */
+-typedef enum
+-{
+- MSN_SB_FLAG_IM = 0x01, /**< This switchboard is being used for a conversation. */
+- MSN_SB_FLAG_FT = 0x02 /**< This switchboard is being used for file transfer. */
+-} MsnSBFlag;
+-
+-#include "cmdproc.h"
+-#include "msg.h"
+-#include "servconn.h"
+-#include "session.h"
+-
+-/**
+- * A switchboard.
+- *
+- * A place where a bunch of users send messages to the rest of the users.
+- */
+-struct _MsnSwitchBoard
+-{
+- MsnSession *session; /**< Our parent session. */
+- MsnServConn *servconn; /**< The physical connection for this switchboard. */
+- MsnCmdProc *cmdproc; /**< Convenience variable for servconn->cmdproc. */
+- char *im_user;
+-
+- MsnSBFlag flag;
+- char *auth_key;
+- char *session_id;
+-
+- PurpleConversation *conv; /**< The conversation that displays the
+- messages of this switchboard, or @c NULL if
+- this is a helper switchboard. */
+-
+- gboolean empty; /**< A flag that states if the swithcboard has no
+- users in it. */
+- gboolean invited; /**< A flag that states if we were invited to the
+- switchboard. */
+- gboolean ready; /**< A flag that states if this switchboard is
+- ready to be used. */
+- gboolean closed; /**< A flag that states if the switchboard has
+- been closed by the user. */
+- gboolean destroying; /**< A flag that states if the switchboard is
+- alredy on the process of destruction. */
+-
+- int current_users;
+- int total_users;
+- GList *users;
+-
+- int chat_id;
+-
+- GQueue *msg_queue; /**< Queue of messages to send. */
+- GList *ack_list; /**< List of messages waiting for an ack. */
+-
+- MsnSBErrorType error; /**< The error that occurred in this switchboard
+- (if applicable). */
+- GList *slplinks; /**< The list of slplinks that are using this switchboard. */
+- guint reconn_timeout_h;
+-};
+-
+-/**
+- * Initialize the variables for switchboard creation.
+- */
+-void msn_switchboard_init(void);
+-
+-/**
+- * Destroy the variables for switchboard creation.
+- */
+-void msn_switchboard_end(void);
+-
+-/**
+- * Creates a new switchboard.
+- *
+- * @param session The MSN session.
+- *
+- * @return The new switchboard.
+- */
+-MsnSwitchBoard *msn_switchboard_new(MsnSession *session);
+-
+-/**
+- * Destroys a switchboard.
+- *
+- * @param swboard The switchboard to destroy.
+- */
+-void msn_switchboard_destroy(MsnSwitchBoard *swboard);
+-
+-/**
+- * Sets the auth key the switchboard must use when connecting.
+- *
+- * @param swboard The switchboard.
+- * @param key The auth key.
+- */
+-void msn_switchboard_set_auth_key(MsnSwitchBoard *swboard, const char *key);
+-
+-/**
+- * Returns the auth key the switchboard must use when connecting.
+- *
+- * @param swboard The switchboard.
+- *
+- * @return The auth key.
+- */
+-const char *msn_switchboard_get_auth_key(MsnSwitchBoard *swboard);
+-
+-/**
+- * Sets the session ID the switchboard must use when connecting.
+- *
+- * @param swboard The switchboard.
+- * @param id The session ID.
+- */
+-void msn_switchboard_set_session_id(MsnSwitchBoard *swboard, const char *id);
+-
+-/**
+- * Returns the session ID the switchboard must use when connecting.
+- *
+- * @param swboard The switchboard.
+- *
+- * @return The session ID.
+- */
+-const char *msn_switchboard_get_session_id(MsnSwitchBoard *swboard);
+-
+-/**
+- * Returns the next chat ID for use by a switchboard.
+- *
+- * @return The chat ID.
+- */
+-int msn_switchboard_get_chat_id(void);
+-
+-/**
+- * Sets whether or not we were invited to this switchboard.
+- *
+- * @param swboard The switchboard.
+- * @param invite @c TRUE if invited, @c FALSE otherwise.
+- */
+-void msn_switchboard_set_invited(MsnSwitchBoard *swboard, gboolean invited);
+-
+-/**
+- * Returns whether or not we were invited to this switchboard.
+- *
+- * @param swboard The switchboard.
+- *
+- * @return @c TRUE if invited, @c FALSE otherwise.
+- */
+-gboolean msn_switchboard_is_invited(MsnSwitchBoard *swboard);
+-
+-/**
+- * Connects to a switchboard.
+- *
+- * @param swboard The switchboard.
+- * @param host The switchboard server host.
+- * @param port The switcbharod server port.
+- *
+- * @return @c TRUE if able to connect, or @c FALSE otherwise.
+- */
+-gboolean msn_switchboard_connect(MsnSwitchBoard *swboard,
+- const char *host, int port);
+-
+-/**
+- * Disconnects from a switchboard.
+- *
+- * @param swboard The switchboard to disconnect from.
+- */
+-void msn_switchboard_disconnect(MsnSwitchBoard *swboard);
+-
+-/**
+- * Closes the switchboard.
+- *
+- * Called when a conversation is closed.
+- *
+- * @param swboard The switchboard to close.
+- */
+-void msn_switchboard_close(MsnSwitchBoard *swboard);
+-
+-/**
+- * Release a switchboard from a certain function.
+- *
+- * @param swboard The switchboard to release.
+- * @param flag The flag that states the function.
+- */
+-void msn_switchboard_release(MsnSwitchBoard *swboard, MsnSBFlag flag);
+-
+-/**
+- * Returns whether or not we currently can send a message through this
+- * switchboard.
+- *
+- * @param swboard The switchboard.
+- *
+- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
+- */
+-gboolean msn_switchboard_can_send(MsnSwitchBoard *swboard);
+-
+-/**
+- * Sends a message through this switchboard.
+- *
+- * @param swboard The switchboard.
+- * @param msg The message.
+- * @param queue A flag that states if we want this message to be queued (in
+- * the case it cannot currently be sent).
+- *
+- * @return @c TRUE if a message can be sent, @c FALSE otherwise.
+- */
+-void msn_switchboard_send_msg(MsnSwitchBoard *swboard, MsnMessage *msg,
+- gboolean queue);
+-
+-void
+-msg_error_helper(MsnCmdProc *cmdproc, MsnMessage *msg, MsnMsgErrorType error);
+-
+-gboolean msn_switchboard_chat_leave(MsnSwitchBoard *swboard);
+-gboolean msn_switchboard_chat_invite(MsnSwitchBoard *swboard, const char *who);
+-
+-gboolean msn_switchboard_request(MsnSwitchBoard *swboard);
+-void msn_switchboard_request_add_user(MsnSwitchBoard *swboard, const char *user);
+-
+-/**
+- * Shows an ink message from this switchboard.
+- *
+- * @param swboard The switchboard.
+- * @param passport The user that sent the ink.
+- * @param data The ink data.
+- */
+-void msn_switchboard_show_ink(MsnSwitchBoard *swboard, const char *passport,
+- const char *data);
+-
+-#endif /* MSN_SWITCHBOARD_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/table.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.c
+--- pidgin-2.10.7/libpurple/protocols/msn/table.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,132 +0,0 @@
+-/**
+- * @file table.c MSN helper structure
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#include "msn.h"
+-#include "table.h"
+-
+-static void
+-null_cmd_cb(MsnCmdProc *cmdproc, MsnCommand *cmd)
+-{
+-}
+-
+-static void
+-null_error_cb(MsnCmdProc *cmdproc, MsnTransaction *trans, int error)
+-{
+-}
+-
+-MsnTable *
+-msn_table_new()
+-{
+- MsnTable *table;
+-
+- table = g_new0(MsnTable, 1);
+-
+- table->cmds = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, (GDestroyNotify)g_hash_table_destroy);
+- table->msgs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+- table->errors = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+-
+- table->async = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+- table->fallback = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+-
+- return table;
+-}
+-
+-void
+-msn_table_destroy(MsnTable *table)
+-{
+- g_return_if_fail(table != NULL);
+-
+- g_hash_table_destroy(table->cmds);
+- g_hash_table_destroy(table->msgs);
+- g_hash_table_destroy(table->errors);
+-
+- g_hash_table_destroy(table->async);
+- g_hash_table_destroy(table->fallback);
+-
+- g_free(table);
+-}
+-
+-void
+-msn_table_add_cmd(MsnTable *table,
+- char *command, char *answer, MsnTransCb cb)
+-{
+- GHashTable *cbs;
+-
+- g_return_if_fail(table != NULL);
+- g_return_if_fail(answer != NULL);
+-
+- cbs = NULL;
+-
+- if (command == NULL)
+- {
+- cbs = table->async;
+- }
+- else if (strcmp(command, "fallback") == 0)
+- {
+- cbs = table->fallback;
+- }
+- else
+- {
+- cbs = g_hash_table_lookup(table->cmds, command);
+-
+- if (cbs == NULL)
+- {
+- cbs = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+- g_hash_table_insert(table->cmds, command, cbs);
+- }
+- }
+-
+- if (cb == NULL)
+- cb = null_cmd_cb;
+-
+- g_hash_table_insert(cbs, answer, cb);
+-}
+-
+-void
+-msn_table_add_error(MsnTable *table,
+- char *answer, MsnErrorCb cb)
+-{
+- g_return_if_fail(table != NULL);
+- g_return_if_fail(answer != NULL);
+-
+- if (cb == NULL)
+- cb = null_error_cb;
+-
+- g_hash_table_insert(table->errors, answer, cb);
+-}
+-
+-void
+-msn_table_add_msg_type(MsnTable *table,
+- char *type, MsnMsgTypeCb cb)
+-{
+- g_return_if_fail(table != NULL);
+- g_return_if_fail(type != NULL);
+- g_return_if_fail(cb != NULL);
+-
+-#if 0
+- if (cb == NULL)
+- cb = null_msg_cb;
+-#endif
+-
+- g_hash_table_insert(table->msgs, type, cb);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/table.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.h
+--- pidgin-2.10.7/libpurple/protocols/msn/table.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/table.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-/**
+- * @file table.h MSN helper structure
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_TABLE_H
+-#define MSN_TABLE_H
+-
+-typedef struct _MsnTable MsnTable;
+-
+-#include "cmdproc.h"
+-#include "transaction.h"
+-#include "msg.h"
+-
+-typedef void (*MsnMsgTypeCb)(MsnCmdProc *cmdproc, MsnMessage *msg);
+-
+-struct _MsnTable
+-{
+- GHashTable *cmds; /**< Callbacks that manage command response. */
+- GHashTable *msgs; /**< Callbacks that manage incoming messages. */
+- GHashTable *errors; /**< Callbacks that manage command errors. */
+-
+- GHashTable *async; /**< Callbacks that manage incoming asyncronous messages. */
+- /* TODO: Does this one is really needed? */
+- GHashTable *fallback; /**< Fallback callback. */
+-};
+-
+-/**
+- * Create a new instance of a MsnTable which map commands, errors and messages
+- * with callbacks that will handle it.
+- *
+- * @return A new MsnTable.
+- */
+-MsnTable *msn_table_new(void);
+-
+-/**
+- * Destroy a MsnTable.
+- *
+- * @param table The MsnTable to be destroyed.
+- */
+-void msn_table_destroy(MsnTable *table);
+-
+-/**
+- * Relate an incomming command from server with a callback able to handle
+- * the event.
+- *
+- * @param table The MsnTable.
+- * @param command If NULL this add an incoming asyncronous command set in answer.
+- * Else, the command sent.
+- * @param answer The server answer to 'command'. If 'command' is NULL,
+- * the asyncronous command sent by the server.
+- * @param cb Callback to handle this event.
+- */
+-void msn_table_add_cmd(MsnTable *table, char *command, char *answer,
+- MsnTransCb cb);
+-
+-/**
+- * Set a callback to handle incoming command errors.
+- *
+- * @param table The MsnTable.
+- * @param answer Incoming command with error.
+- * @param cb Callback to handle this error.
+- */
+-void msn_table_add_error(MsnTable *table, char *answer, MsnErrorCb cb);
+-
+-/**
+- * Relate a message Content-type with a callback able to handle it.
+- *
+- * @param table The MsnTable.
+- * @param type The Message Content-Type.
+- * @param cb Callback to handle this Content-type.
+- */
+-void msn_table_add_msg_type(MsnTable *table, char *type, MsnMsgTypeCb cb);
+-
+-#endif /* MSN_TABLE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/tlv.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.c
+--- pidgin-2.10.7/libpurple/protocols/msn/tlv.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,458 +0,0 @@
+-/**
+- * @file tlv.c MSN TLV functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "tlv.h"
+-#include "msnutils.h"
+-
+-static msn_tlv_t *
+-createtlv(guint8 type, guint8 length, guint8 *value)
+-{
+- msn_tlv_t *ret;
+-
+- ret = g_new(msn_tlv_t, 1);
+- ret->type = type;
+- ret->length = length;
+- ret->value = value;
+-
+- return ret;
+-}
+-
+-static void
+-freetlv(msn_tlv_t *oldtlv)
+-{
+- g_free(oldtlv->value);
+- g_free(oldtlv);
+-}
+-
+-GSList *
+-msn_tlvlist_read(const char *bs, size_t bs_len)
+-{
+- GSList *list = NULL;
+-
+- while (bs_len > 0) {
+- guint8 type, length;
+- msn_tlv_t *tlv;
+-
+- if (bs_len == 3 && *bs == 0) {
+- /* Padding to multiple of 4 */
+- break;
+- } else if (bs_len == 2 && *bs == 0) {
+- /* Padding to multiple of 4 */
+- break;
+- } else if (bs_len == 1) {
+- if (*bs == 0) {
+- /* Padding to multiple of 4 */
+- break;
+- } else {
+- /* TLV is not small enough to fit here */
+- msn_tlvlist_free(list);
+- return NULL;
+- }
+- }
+-
+- type = msn_pop8(bs);
+- length = msn_pop8(bs);
+- bs_len -= 2;
+-
+- if (length > bs_len) {
+- msn_tlvlist_free(list);
+- return NULL;
+- }
+-
+- tlv = createtlv(type, length, NULL);
+- if (length > 0) {
+- tlv->value = g_memdup(bs, length);
+- if (!tlv->value) {
+- freetlv(tlv);
+- msn_tlvlist_free(list);
+- return NULL;
+- }
+- }
+-
+- bs_len -= length;
+- bs += length;
+-
+- list = g_slist_prepend(list, tlv);
+- }
+-
+- return g_slist_reverse(list);
+-}
+-
+-GSList *
+-msn_tlvlist_copy(GSList *orig)
+-{
+- GSList *new = NULL;
+- msn_tlv_t *tlv;
+-
+- while (orig != NULL) {
+- tlv = orig->data;
+- msn_tlvlist_add_raw(&new, tlv->type, tlv->length, (const char *)tlv->value);
+- orig = orig->next;
+- }
+-
+- return new;
+-}
+-
+-gboolean
+-msn_tlvlist_equal(GSList *one, GSList *two)
+-{
+- while (one && two) {
+- msn_tlv_t *a = one->data;
+- msn_tlv_t *b = two->data;
+-
+- if (a->type != b->type)
+- return FALSE;
+- else if (a->length != b->length)
+- return FALSE;
+- else if (!a->value && b->value)
+- return FALSE;
+- else if (a->value && !b->value)
+- return FALSE;
+- else if (a->value && b->value && memcmp(a->value, b->value, a->length) != 0)
+- return FALSE;
+-
+- one = one->next;
+- two = two->next;
+- }
+-
+- return one == two;
+-}
+-
+-void
+-msn_tlvlist_free(GSList *list)
+-{
+- while (list != NULL) {
+- freetlv(list->data);
+- list = g_slist_delete_link(list, list);
+- }
+-}
+-
+-int
+-msn_tlvlist_count(GSList *list)
+-{
+- return g_slist_length(list);
+-}
+-
+-size_t
+-msn_tlvlist_size(GSList *list)
+-{
+- int size;
+-
+- if (list == NULL)
+- return 0;
+-
+- for (size = 0; list; list = list->next)
+- size += (2 + ((msn_tlv_t *)list->data)->length);
+-
+- return size;
+-}
+-
+-int
+-msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
+-{
+- msn_tlv_t *tlv;
+-
+- if (list == NULL)
+- return 0;
+-
+- tlv = createtlv(type, length, NULL);
+- if (length > 0)
+- tlv->value = g_memdup(value, length);
+-
+- *list = g_slist_append(*list, tlv);
+-
+- return tlv->length;
+-}
+-
+-int
+-msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value)
+-{
+- char v8[1];
+-
+- msn_write8(v8, value);
+-
+- return msn_tlvlist_add_raw(list, type, 1, v8);
+-}
+-
+-int
+-msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value)
+-{
+- char v16[2];
+-
+- msn_write16be(v16, value);
+-
+- return msn_tlvlist_add_raw(list, type, 2, v16);
+-}
+-
+-int
+-msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value)
+-{
+- char v32[4];
+-
+- msn_write32be(v32, value);
+-
+- return msn_tlvlist_add_raw(list, type, 4, v32);
+-}
+-
+-int
+-msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value)
+-{
+- return msn_tlvlist_add_raw(list, type, strlen(value), value);
+-}
+-
+-int
+-msn_tlvlist_add_empty(GSList **list, const guint8 type)
+-{
+- return msn_tlvlist_add_raw(list, type, 0, NULL);
+-}
+-
+-int
+-msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv)
+-{
+- return msn_tlvlist_add_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
+-}
+-
+-int
+-msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 length, const char *value)
+-{
+- GSList *cur;
+- msn_tlv_t *tlv;
+-
+- if (list == NULL)
+- return 0;
+-
+- 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 msn_tlvlist_add_raw(list, type, length, value);
+-
+- g_free(tlv->value);
+- tlv->length = length;
+- if (length > 0) {
+- tlv->value = g_memdup(value, length);
+- } else
+- tlv->value = NULL;
+-
+- return length;
+-}
+-
+-int
+-msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str)
+-{
+- return msn_tlvlist_replace_raw(list, type, strlen(str), str);
+-}
+-
+-int
+-msn_tlvlist_replace_empty(GSList **list, const guint8 type)
+-{
+- return msn_tlvlist_replace_raw(list, type, 0, NULL);
+-}
+-
+-int
+-msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value)
+-{
+- char v8[1];
+-
+- msn_write8(v8, value);
+-
+- return msn_tlvlist_replace_raw(list, type, 1, v8);
+-}
+-
+-int
+-msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value)
+-{
+- char v32[4];
+-
+- msn_write32be(v32, value);
+-
+- return msn_tlvlist_replace_raw(list, type, 4, v32);
+-}
+-
+-int
+-msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv)
+-{
+- return msn_tlvlist_replace_raw(list, tlv->type, tlv->length, (const char *)tlv->value);
+-}
+-
+-void
+-msn_tlvlist_remove(GSList **list, const guint8 type)
+-{
+- GSList *cur, *next;
+- msn_tlv_t *tlv;
+-
+- if (list == NULL || *list == NULL)
+- return;
+-
+- 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;
+- }
+-}
+-
+-char *
+-msn_tlvlist_write(GSList *list, size_t *out_len)
+-{
+- char *buf;
+- char *tmp;
+- size_t bytes_left;
+- size_t total_len;
+-
+- tmp = buf = g_malloc(256);
+- bytes_left = total_len = 256;
+-
+- for (; list; list = g_slist_next(list)) {
+- msn_tlv_t *tlv = (msn_tlv_t *)list->data;
+-
+- if (G_UNLIKELY(tlv->length + 2 > bytes_left)) {
+- buf = g_realloc(buf, total_len + 256);
+- bytes_left += 256;
+- total_len += 256;
+- tmp = buf + (total_len - bytes_left);
+- }
+-
+- msn_push8(tmp, tlv->type);
+- msn_push8(tmp, tlv->length);
+- memcpy(tmp, tlv->value, tlv->length);
+- tmp += tlv->length;
+-
+- bytes_left -= (tlv->length + 2);
+- }
+-
+- /* Align length to multiple of 4 */
+- total_len = total_len - bytes_left;
+- bytes_left = 4 - total_len % 4;
+- if (bytes_left != 4)
+- memset(tmp, 0, bytes_left);
+- else
+- bytes_left = 0;
+-
+- *out_len = total_len + bytes_left;
+-
+- return buf;
+-}
+-
+-msn_tlv_t *
+-msn_tlv_gettlv(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+- int i;
+-
+- for (i = 0; list != NULL; list = list->next) {
+- tlv = list->data;
+- if (tlv->type == type)
+- i++;
+- if (i >= nth)
+- return tlv;
+- }
+-
+- return NULL;
+-}
+-
+-int
+-msn_tlv_getlength(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+-
+- tlv = msn_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return -1;
+-
+- return tlv->length;
+-}
+-
+-char *
+-msn_tlv_getvalue_as_string(msn_tlv_t *tlv)
+-{
+- char *ret;
+-
+- ret = g_malloc(tlv->length + 1);
+- memcpy(ret, tlv->value, tlv->length);
+- ret[tlv->length] = '\0';
+-
+- return ret;
+-}
+-
+-char *
+-msn_tlv_getstr(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+-
+- tlv = msn_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return NULL;
+-
+- return msn_tlv_getvalue_as_string(tlv);
+-}
+-
+-guint8
+-msn_tlv_get8(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+-
+- tlv = msn_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return msn_read8((const char *)tlv->value);
+-}
+-
+-guint16
+-msn_tlv_get16(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+-
+- tlv = msn_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return msn_read16be((const char *)tlv->value);
+-}
+-
+-guint32
+-msn_tlv_get32(GSList *list, const guint8 type, const int nth)
+-{
+- msn_tlv_t *tlv;
+-
+- tlv = msn_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return msn_read32be((const char *)tlv->value);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/tlv.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.h
+--- pidgin-2.10.7/libpurple/protocols/msn/tlv.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/tlv.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,77 +0,0 @@
+-/**
+- * @file tlv.h MSN TLV functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef MSN_TLV_H
+-#define MSN_TLV_H
+-
+-#include "msn.h"
+-
+-/* TLV structure */
+-typedef struct msn_tlv_s
+-{
+- guint8 type;
+- guint8 length;
+- guint8 *value;
+-} msn_tlv_t;
+-
+-/* TLV handling functions */
+-char *msn_tlv_getvalue_as_string(msn_tlv_t *tlv);
+-
+-msn_tlv_t *msn_tlv_gettlv(GSList *list, const guint8 type, const int nth);
+-int msn_tlv_getlength(GSList *list, const guint8 type, const int nth);
+-char *msn_tlv_getstr(GSList *list, const guint8 type, const int nth);
+-guint8 msn_tlv_get8(GSList *list, const guint8 type, const int nth);
+-guint16 msn_tlv_get16(GSList *list, const guint8 type, const int nth);
+-guint32 msn_tlv_get32(GSList *list, const guint8 type, const int nth);
+-
+-/* TLV list handling functions */
+-GSList *msn_tlvlist_read(const char *bs, size_t bs_len);
+-GSList *msn_tlvlist_copy(GSList *orig);
+-
+-int msn_tlvlist_count(GSList *list);
+-size_t msn_tlvlist_size(GSList *list);
+-gboolean msn_tlvlist_equal(GSList *one, GSList *two);
+-char *msn_tlvlist_write(GSList *list, size_t *out_len);
+-void msn_tlvlist_free(GSList *list);
+-
+-int msn_tlvlist_add_raw(GSList **list, const guint8 type, const guint8 length, const char *value);
+-int msn_tlvlist_add_empty(GSList **list, const guint8 type);
+-int msn_tlvlist_add_8(GSList **list, const guint8 type, const guint8 value);
+-int msn_tlvlist_add_16(GSList **list, const guint8 type, const guint16 value);
+-int msn_tlvlist_add_32(GSList **list, const guint8 type, const guint32 value);
+-int msn_tlvlist_add_str(GSList **list, const guint8 type, const char *value);
+-int msn_tlvlist_add_tlv(GSList **list, const msn_tlv_t *tlv);
+-
+-int msn_tlvlist_replace_raw(GSList **list, const guint8 type, const guint8 lenth, const char *value);
+-int msn_tlvlist_replace_str(GSList **list, const guint8 type, const char *str);
+-int msn_tlvlist_replace_empty(GSList **list, const guint8 type);
+-int msn_tlvlist_replace_8(GSList **list, const guint8 type, const guint8 value);
+-int msn_tlvlist_replace_16(GSList **list, const guint8 type, const guint16 value);
+-int msn_tlvlist_replace_32(GSList **list, const guint8 type, const guint32 value);
+-int msn_tlvlist_replace_tlv(GSList **list, const msn_tlv_t *tlv);
+-
+-void msn_tlvlist_remove(GSList **list, const guint8 type);
+-
+-#endif /* MSN_TLV_H */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/transaction.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.c
+--- pidgin-2.10.7/libpurple/protocols/msn/transaction.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,247 +0,0 @@
+-/**
+- * @file transaction.c MSN transaction functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msn.h"
+-#include "transaction.h"
+-
+-MsnTransaction *
+-msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
+- const char *format, ...)
+-{
+- MsnTransaction *trans;
+- va_list arg;
+-
+- g_return_val_if_fail(command != NULL, NULL);
+-
+- trans = g_new0(MsnTransaction, 1);
+-
+- trans->cmdproc = cmdproc;
+- trans->command = g_strdup(command);
+- trans->saveable = TRUE;
+-
+- if (format != NULL)
+- {
+- va_start(arg, format);
+- trans->params = g_strdup_vprintf(format, arg);
+- va_end(arg);
+- }
+-
+- /* trans->queue = g_queue_new(); */
+-
+- return trans;
+-}
+-
+-void
+-msn_transaction_destroy(MsnTransaction *trans)
+-{
+- g_return_if_fail(trans != NULL);
+-
+- g_free(trans->command);
+- g_free(trans->params);
+- g_free(trans->payload);
+-
+- if (trans->data_free)
+- trans->data_free(trans->data);
+-
+-#if 0
+- if (trans->pendent_cmd != NULL)
+- msn_message_unref(trans->pendent_msg);
+-#endif
+-
+-#if 0
+- MsnTransaction *elem;
+- if (trans->queue != NULL)
+- {
+- while ((elem = g_queue_pop_head(trans->queue)) != NULL)
+- msn_transaction_destroy(elem);
+-
+- g_queue_free(trans->queue);
+- }
+-#endif
+-
+- if (trans->callbacks != NULL && trans->has_custom_callbacks)
+- g_hash_table_destroy(trans->callbacks);
+-
+- if (trans->timer)
+- purple_timeout_remove(trans->timer);
+-
+- g_free(trans);
+-}
+-
+-char *
+-msn_transaction_to_string(MsnTransaction *trans)
+-{
+- char *str;
+-
+- g_return_val_if_fail(trans != NULL, FALSE);
+-
+- if (trans->params != NULL)
+- str = g_strdup_printf("%s %u %s\r\n", trans->command, trans->trId, trans->params);
+- else if (trans->saveable)
+- str = g_strdup_printf("%s %u\r\n", trans->command, trans->trId);
+- else
+- str = g_strdup_printf("%s\r\n", trans->command);
+-
+- return str;
+-}
+-
+-void
+-msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd)
+-{
+- purple_debug_info("msn", "queueing command.\n");
+- trans->pendent_cmd = cmd;
+- msn_command_ref(cmd);
+-}
+-
+-void
+-msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc)
+-{
+- MsnCommand *cmd;
+-
+- if (!cmdproc->servconn->connected)
+- return;
+-
+- purple_debug_info("msn", "unqueueing command.\n");
+- cmd = trans->pendent_cmd;
+-
+- g_return_if_fail(cmd != NULL);
+-
+- msn_cmdproc_process_cmd(cmdproc, cmd);
+- msn_command_unref(cmd);
+-
+- trans->pendent_cmd = NULL;
+-}
+-
+-#if 0
+-void
+-msn_transaction_queue(MsnTransaction *trans, MsnTransaction *elem)
+-{
+- if (trans->queue == NULL)
+- trans->queue = g_queue_new();
+-
+- g_queue_push_tail(trans->queue, elem);
+-}
+-
+-void
+-msn_transaction_unqueue(MsnTransaction *trans, MsnCmdProc *cmdproc)
+-{
+- MsnTransaction *elem;
+-
+- while ((elem = g_queue_pop_head(trans->queue)) != NULL)
+- msn_cmdproc_send_trans(cmdproc, elem);
+-}
+-#endif
+-
+-void
+-msn_transaction_set_payload(MsnTransaction *trans,
+- const char *payload, int payload_len)
+-{
+- g_return_if_fail(trans != NULL);
+- g_return_if_fail(payload != NULL);
+-
+- trans->payload = g_strdup(payload);
+- trans->payload_len = payload_len ? payload_len : strlen(trans->payload);
+-}
+-
+-void
+-msn_transaction_set_data(MsnTransaction *trans, void *data)
+-{
+- g_return_if_fail(trans != NULL);
+-
+- trans->data = data;
+-}
+-
+-void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn)
+-{
+- g_return_if_fail(trans != NULL);
+- trans->data_free = fn;
+-}
+-
+-void
+-msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable)
+-{
+- g_return_if_fail(trans != NULL);
+-
+- trans->saveable = saveable;
+-}
+-
+-void
+-msn_transaction_add_cb(MsnTransaction *trans, char *answer,
+- MsnTransCb cb)
+-{
+- g_return_if_fail(trans != NULL);
+- g_return_if_fail(answer != NULL);
+-
+- if (trans->callbacks == NULL)
+- {
+- trans->has_custom_callbacks = TRUE;
+- trans->callbacks = g_hash_table_new_full(g_str_hash, g_str_equal, NULL,
+- NULL);
+- }
+- else if (trans->has_custom_callbacks != TRUE)
+- g_return_if_reached ();
+-
+- g_hash_table_insert(trans->callbacks, answer, cb);
+-}
+-
+-static gboolean
+-transaction_timeout(gpointer data)
+-{
+- MsnTransaction *trans;
+-
+- trans = data;
+- g_return_val_if_fail(trans != NULL, FALSE);
+-
+-#if 0
+- purple_debug_info("msn", "timed out: %s %d %s\n", trans->command, trans->trId, trans->params);
+-#endif
+-
+- trans->timer = 0;
+-
+- if (trans->timeout_cb != NULL)
+- trans->timeout_cb(trans->cmdproc, trans);
+-
+- return FALSE;
+-}
+-
+-void
+-msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb)
+-{
+- if (trans->timer)
+- {
+- purple_debug_error("msn", "This shouldn't be happening\n");
+- purple_timeout_remove(trans->timer);
+- }
+- trans->timeout_cb = cb;
+- trans->timer = purple_timeout_add_seconds(60, transaction_timeout, trans);
+-}
+-
+-void
+-msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb)
+-{
+- trans->error_cb = cb;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/transaction.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.h
+--- pidgin-2.10.7/libpurple/protocols/msn/transaction.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/transaction.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,87 +0,0 @@
+-/**
+- * @file transaction.h MSN transaction functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_TRANSACTION_H
+-#define MSN_TRANSACTION_H
+-
+-#include "internal.h"
+-
+-typedef struct _MsnTransaction MsnTransaction;
+-
+-#include "cmdproc.h"
+-#include "command.h"
+-
+-typedef void (*MsnTransCb)(MsnCmdProc *cmdproc, MsnCommand *cmd);
+-typedef void (*MsnTimeoutCb)(MsnCmdProc *cmdproc, MsnTransaction *trans);
+-typedef void (*MsnErrorCb)(MsnCmdProc *cmdproc, MsnTransaction *trans,
+- int error);
+-
+-/**
+- * A transaction. A sending command that will initiate the transaction.
+- */
+-struct _MsnTransaction
+-{
+- MsnCmdProc *cmdproc;
+-
+- gboolean saveable; /**< Whether to save this transaction in the history */
+- unsigned int trId; /**< The ID of this transaction, if it's being saved */
+-
+- char *command;
+- char *params;
+-
+- guint timer;
+-
+- void *data; /**< The data to be used on the different callbacks. */
+- GDestroyNotify data_free; /**< The function to free 'data', or @c NULL */
+-
+- GHashTable *callbacks;
+- gboolean has_custom_callbacks;
+- MsnErrorCb error_cb;
+- MsnTimeoutCb timeout_cb;
+-
+- char *payload;
+- size_t payload_len;
+-
+- GQueue *queue;
+- MsnCommand *pendent_cmd; /**< The command that is waiting for the result of
+- this transaction. */
+-};
+-
+-MsnTransaction *msn_transaction_new(MsnCmdProc *cmdproc, const char *command,
+- const char *format, ...) G_GNUC_PRINTF(3, 4);
+-void msn_transaction_destroy(MsnTransaction *trans);
+-
+-char *msn_transaction_to_string(MsnTransaction *trans);
+-void msn_transaction_queue_cmd(MsnTransaction *trans, MsnCommand *cmd);
+-void msn_transaction_unqueue_cmd(MsnTransaction *trans, MsnCmdProc *cmdproc);
+-void msn_transaction_set_payload(MsnTransaction *trans,
+- const char *payload, int payload_len);
+-void msn_transaction_set_data(MsnTransaction *trans, void *data);
+-void msn_transaction_set_data_free(MsnTransaction *trans, GDestroyNotify fn);
+-void msn_transaction_set_saveable(MsnTransaction *trans, gboolean saveable);
+-void msn_transaction_add_cb(MsnTransaction *trans, char *answer,
+- MsnTransCb cb);
+-void msn_transaction_set_error_cb(MsnTransaction *trans, MsnErrorCb cb);
+-void msn_transaction_set_timeout_cb(MsnTransaction *trans, MsnTimeoutCb cb);
+-
+-#endif /* MSN_TRANSACTION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/user.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.c
+--- pidgin-2.10.7/libpurple/protocols/msn/user.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,801 +0,0 @@
+-/**
+- * @file user.c User functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "util.h"
+-
+-#include "user.h"
+-#include "slp.h"
+-
+-static void free_user_endpoint(MsnUserEndpoint *data)
+-{
+- g_free(data->id);
+- g_free(data->name);
+- g_free(data);
+-}
+-
+-/*new a user object*/
+-MsnUser *
+-msn_user_new(MsnUserList *userlist, const char *passport,
+- const char *friendly_name)
+-{
+- MsnUser *user;
+-
+- user = g_new0(MsnUser, 1);
+-
+- user->userlist = userlist;
+-
+- msn_user_set_passport(user, passport);
+- msn_user_set_friendly_name(user, friendly_name);
+-
+- return msn_user_ref(user);
+-}
+-
+-/*destroy a user object*/
+-static void
+-msn_user_destroy(MsnUser *user)
+-{
+- while (user->endpoints != NULL) {
+- free_user_endpoint(user->endpoints->data);
+- user->endpoints = g_slist_delete_link(user->endpoints, user->endpoints);
+- }
+-
+- if (user->clientcaps != NULL)
+- g_hash_table_destroy(user->clientcaps);
+-
+- if (user->group_ids != NULL)
+- {
+- GList *l;
+- for (l = user->group_ids; l != NULL; l = l->next)
+- {
+- g_free(l->data);
+- }
+- g_list_free(user->group_ids);
+- }
+-
+- if (user->msnobj != NULL)
+- msn_object_destroy(user->msnobj);
+-
+- g_free(user->passport);
+- g_free(user->friendly_name);
+- g_free(user->uid);
+- if (user->extinfo) {
+- g_free(user->extinfo->media_album);
+- g_free(user->extinfo->media_artist);
+- g_free(user->extinfo->media_title);
+- g_free(user->extinfo->phone_home);
+- g_free(user->extinfo->phone_mobile);
+- g_free(user->extinfo->phone_work);
+- g_free(user->extinfo);
+- }
+- g_free(user->statusline);
+- g_free(user->invite_message);
+-
+- g_free(user);
+-}
+-
+-MsnUser *
+-msn_user_ref(MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- user->refcount++;
+-
+- return user;
+-}
+-
+-void
+-msn_user_unref(MsnUser *user)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->refcount--;
+-
+- if(user->refcount == 0)
+- msn_user_destroy(user);
+-}
+-
+-void
+-msn_user_update(MsnUser *user)
+-{
+- PurpleAccount *account;
+- gboolean offline;
+-
+- g_return_if_fail(user != NULL);
+-
+- account = user->userlist->session->account;
+-
+- offline = (user->status == NULL);
+-
+- if (!offline) {
+- purple_prpl_got_user_status(account, user->passport, user->status,
+- "message", user->statusline, NULL);
+- } else {
+- if (user->mobile) {
+- purple_prpl_got_user_status(account, user->passport, "mobile", NULL);
+- purple_prpl_got_user_status(account, user->passport, "available", NULL);
+- } else {
+- purple_prpl_got_user_status(account, user->passport, "offline", NULL);
+- }
+- }
+-
+- if (!offline || !user->mobile) {
+- purple_prpl_got_user_status_deactive(account, user->passport, "mobile");
+- }
+-
+- if (!offline && user->extinfo && user->extinfo->media_type != CURRENT_MEDIA_UNKNOWN) {
+- if (user->extinfo->media_type == CURRENT_MEDIA_MUSIC) {
+- purple_prpl_got_user_status(account, user->passport, "tune",
+- PURPLE_TUNE_ARTIST, user->extinfo->media_artist,
+- PURPLE_TUNE_ALBUM, user->extinfo->media_album,
+- PURPLE_TUNE_TITLE, user->extinfo->media_title,
+- NULL);
+- } else if (user->extinfo->media_type == CURRENT_MEDIA_GAMES) {
+- purple_prpl_got_user_status(account, user->passport, "tune",
+- "game", user->extinfo->media_title,
+- NULL);
+- } else if (user->extinfo->media_type == CURRENT_MEDIA_OFFICE) {
+- purple_prpl_got_user_status(account, user->passport, "tune",
+- "office", user->extinfo->media_title,
+- NULL);
+- } else {
+- purple_debug_warning("msn", "Got CurrentMedia with unknown type %d.\n",
+- user->extinfo->media_type);
+- }
+- } else {
+- purple_prpl_got_user_status_deactive(account, user->passport, "tune");
+- }
+-
+- if (user->idle)
+- purple_prpl_got_user_idle(account, user->passport, TRUE, -1);
+- else
+- purple_prpl_got_user_idle(account, user->passport, FALSE, 0);
+-}
+-
+-void
+-msn_user_set_state(MsnUser *user, const char *state)
+-{
+- const char *status;
+-
+- g_return_if_fail(user != NULL);
+-
+- if (state == NULL) {
+- user->status = NULL;
+- return;
+- }
+-
+- if (!g_ascii_strcasecmp(state, "BSY"))
+- status = "busy";
+- else if (!g_ascii_strcasecmp(state, "BRB"))
+- status = "brb";
+- else if (!g_ascii_strcasecmp(state, "AWY"))
+- status = "away";
+- else if (!g_ascii_strcasecmp(state, "PHN"))
+- status = "phone";
+- else if (!g_ascii_strcasecmp(state, "LUN"))
+- status = "lunch";
+- else if (!g_ascii_strcasecmp(state, "HDN"))
+- status = NULL;
+- else
+- status = "available";
+-
+- if (!g_ascii_strcasecmp(state, "IDL"))
+- user->idle = TRUE;
+- else
+- user->idle = FALSE;
+-
+- user->status = status;
+-}
+-
+-void
+-msn_user_set_passport(MsnUser *user, const char *passport)
+-{
+- g_return_if_fail(user != NULL);
+-
+- g_free(user->passport);
+- user->passport = g_strdup(passport);
+-}
+-
+-gboolean
+-msn_user_set_friendly_name(MsnUser *user, const char *name)
+-{
+- g_return_val_if_fail(user != NULL, FALSE);
+-
+- if (!name)
+- return FALSE;
+-
+- if (user->friendly_name && (!strcmp(user->friendly_name, name) ||
+- !strcmp(user->passport, name)))
+- return FALSE;
+-
+- g_free(user->friendly_name);
+- user->friendly_name = g_strdup(name);
+-
+- serv_got_alias(purple_account_get_connection(user->userlist->session->account),
+- user->passport, name);
+- return TRUE;
+-}
+-
+-void
+-msn_user_set_statusline(MsnUser *user, const char *statusline)
+-{
+- g_return_if_fail(user != NULL);
+-
+- g_free(user->statusline);
+- user->statusline = g_strdup(statusline);
+-}
+-
+-void
+-msn_user_set_uid(MsnUser *user, const char *uid)
+-{
+- g_return_if_fail(user != NULL);
+-
+- g_free(user->uid);
+- user->uid = g_strdup(uid);
+-}
+-
+-void
+-msn_user_set_endpoint_data(MsnUser *user, const char *input, MsnUserEndpoint *newep)
+-{
+- MsnUserEndpoint *ep;
+- char *endpoint;
+- GSList *l;
+-
+- g_return_if_fail(user != NULL);
+- g_return_if_fail(input != NULL);
+-
+- endpoint = g_ascii_strdown(input, -1);
+-
+- for (l = user->endpoints; l; l = l->next) {
+- ep = l->data;
+- if (g_str_equal(ep->id, endpoint)) {
+- /* We have info about this endpoint! */
+-
+- g_free(endpoint);
+-
+- if (newep == NULL) {
+- /* Delete it and exit */
+- user->endpoints = g_slist_delete_link(user->endpoints, l);
+- free_user_endpoint(ep);
+- return;
+- }
+-
+- /* Break out of our loop and update it */
+- break;
+- }
+- }
+- if (l == NULL) {
+- /* Need to add a new endpoint */
+- ep = g_new0(MsnUserEndpoint, 1);
+- ep->id = endpoint;
+- user->endpoints = g_slist_prepend(user->endpoints, ep);
+- }
+-
+- ep->clientid = newep->clientid;
+- ep->extcaps = newep->extcaps;
+-}
+-
+-void
+-msn_user_clear_endpoints(MsnUser *user)
+-{
+- MsnUserEndpoint *ep;
+- GSList *l;
+-
+- g_return_if_fail(user != NULL);
+-
+- for (l = user->endpoints; l; l = g_slist_delete_link(l, l)) {
+- ep = l->data;
+- free_user_endpoint(ep);
+- }
+-
+- user->endpoints = NULL;
+-}
+-
+-void
+-msn_user_set_op(MsnUser *user, MsnListOp list_op)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->list_op |= list_op;
+-}
+-
+-void
+-msn_user_unset_op(MsnUser *user, MsnListOp list_op)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->list_op &= ~list_op;
+-}
+-
+-void
+-msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img)
+-{
+- MsnObject *msnobj;
+-
+- g_return_if_fail(user != NULL);
+-
+- msnobj = msn_object_new_from_image(img, "TFR2C2.tmp",
+- user->passport, MSN_OBJECT_USERTILE);
+-
+- if (!msnobj)
+- purple_debug_error("msn", "Unable to open buddy icon from %s!\n", user->passport);
+-
+- msn_user_set_object(user, msnobj);
+-}
+-
+-/*add group id to User object*/
+-void
+-msn_user_add_group_id(MsnUser *user, const char* group_id)
+-{
+- MsnUserList *userlist;
+- PurpleAccount *account;
+- PurpleBuddy *b;
+- PurpleGroup *g;
+- const char *passport;
+- const char *group_name;
+-
+- g_return_if_fail(user != NULL);
+- g_return_if_fail(group_id != NULL);
+-
+- user->group_ids = g_list_append(user->group_ids, g_strdup(group_id));
+-
+- userlist = user->userlist;
+- account = userlist->session->account;
+- passport = msn_user_get_passport(user);
+-
+- group_name = msn_userlist_find_group_name(userlist, group_id);
+-
+- purple_debug_info("msn", "User: group id:%s,name:%s,user:%s\n", group_id, group_name, passport);
+-
+- g = purple_find_group(group_name);
+-
+- if ((group_id == NULL) && (g == NULL))
+- {
+- g = purple_group_new(group_name);
+- purple_blist_add_group(g, NULL);
+- }
+-
+- b = purple_find_buddy_in_group(account, passport, g);
+- if (b == NULL)
+- {
+- b = purple_buddy_new(account, passport, NULL);
+- purple_blist_add_buddy(b, NULL, g, NULL);
+- }
+- purple_buddy_set_protocol_data(b, user);
+- /*Update the blist Node info*/
+-}
+-
+-/*check if the msn user is online*/
+-gboolean
+-msn_user_is_online(PurpleAccount *account, const char *name)
+-{
+- PurpleBuddy *buddy;
+-
+- buddy = purple_find_buddy(account, name);
+- return PURPLE_BUDDY_IS_ONLINE(buddy);
+-}
+-
+-gboolean
+-msn_user_is_yahoo(PurpleAccount *account, const char *name)
+-{
+- MsnSession *session = NULL;
+- MsnUser *user;
+- PurpleConnection *gc;
+-
+- gc = purple_account_get_connection(account);
+- if (gc != NULL)
+- session = gc->proto_data;
+-
+- if ((session != NULL) && (user = msn_userlist_find_user(session->userlist, name)) != NULL)
+- {
+- return (user->networkid == MSN_NETWORK_YAHOO);
+- }
+- return (strstr(name,"@yahoo.") != NULL);
+-}
+-
+-void
+-msn_user_remove_group_id(MsnUser *user, const char *id)
+-{
+- GList *l;
+-
+- g_return_if_fail(user != NULL);
+- g_return_if_fail(id != NULL);
+-
+- l = g_list_find_custom(user->group_ids, id, (GCompareFunc)strcmp);
+-
+- if (l == NULL)
+- return;
+-
+- g_free(l->data);
+- user->group_ids = g_list_delete_link(user->group_ids, l);
+-}
+-
+-void
+-msn_user_set_pending_group(MsnUser *user, const char *group)
+-{
+- user->pending_group = g_strdup(group);
+-}
+-
+-char *
+-msn_user_remove_pending_group(MsnUser *user)
+-{
+- char *group = user->pending_group;
+- user->pending_group = NULL;
+- return group;
+-}
+-
+-void
+-msn_user_set_home_phone(MsnUser *user, const char *number)
+-{
+- g_return_if_fail(user != NULL);
+-
+- if (!number && !user->extinfo)
+- return;
+-
+- if (user->extinfo)
+- g_free(user->extinfo->phone_home);
+- else
+- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+-
+- user->extinfo->phone_home = g_strdup(number);
+-}
+-
+-void
+-msn_user_set_work_phone(MsnUser *user, const char *number)
+-{
+- g_return_if_fail(user != NULL);
+-
+- if (!number && !user->extinfo)
+- return;
+-
+- if (user->extinfo)
+- g_free(user->extinfo->phone_work);
+- else
+- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+-
+- user->extinfo->phone_work = g_strdup(number);
+-}
+-
+-void
+-msn_user_set_mobile_phone(MsnUser *user, const char *number)
+-{
+- g_return_if_fail(user != NULL);
+-
+- if (!number && !user->extinfo)
+- return;
+-
+- if (user->extinfo)
+- g_free(user->extinfo->phone_mobile);
+- else
+- user->extinfo = g_new0(MsnUserExtendedInfo, 1);
+-
+- user->extinfo->phone_mobile = g_strdup(number);
+-}
+-
+-void
+-msn_user_set_clientid(MsnUser *user, guint clientid)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->clientid = clientid;
+-}
+-
+-void
+-msn_user_set_extcaps(MsnUser *user, guint extcaps)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->extcaps = extcaps;
+-}
+-
+-void
+-msn_user_set_network(MsnUser *user, MsnNetwork network)
+-{
+- g_return_if_fail(user != NULL);
+-
+- user->networkid = network;
+-}
+-
+-static gboolean
+-buddy_icon_cached(PurpleConnection *gc, MsnObject *obj)
+-{
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- const char *old;
+- const char *new;
+-
+- g_return_val_if_fail(obj != NULL, FALSE);
+-
+- account = purple_connection_get_account(gc);
+-
+- buddy = purple_find_buddy(account, msn_object_get_creator(obj));
+- if (buddy == NULL)
+- return FALSE;
+-
+- old = purple_buddy_icons_get_checksum_for_user(buddy);
+- new = msn_object_get_sha1(obj);
+-
+- if (new == NULL)
+- return FALSE;
+-
+- /* If the old and new checksums are the same, and the file actually exists,
+- * then return TRUE */
+- if (old != NULL && !strcmp(old, new))
+- return TRUE;
+-
+- return FALSE;
+-}
+-
+-static void
+-queue_buddy_icon_request(MsnUser *user)
+-{
+- PurpleAccount *account;
+- MsnObject *obj;
+- GQueue *queue;
+-
+- g_return_if_fail(user != NULL);
+-
+- account = user->userlist->session->account;
+-
+- obj = msn_user_get_object(user);
+-
+- if (obj == NULL) {
+- purple_buddy_icons_set_for_user(account, user->passport, NULL, 0, NULL);
+- return;
+- }
+-
+- if (!buddy_icon_cached(account->gc, obj)) {
+- MsnUserList *userlist;
+-
+- userlist = user->userlist;
+- queue = userlist->buddy_icon_requests;
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Queueing buddy icon request for %s (buddy_icon_window = %i)\n",
+- user->passport, userlist->buddy_icon_window);
+-
+- g_queue_push_tail(queue, user);
+-
+- if (userlist->buddy_icon_window > 0)
+- msn_release_buddy_icon_request(userlist);
+- }
+-}
+-
+-void
+-msn_user_set_object(MsnUser *user, MsnObject *obj)
+-{
+- g_return_if_fail(user != NULL);
+-
+- if (user->msnobj != NULL && !msn_object_find_local(msn_object_get_sha1(obj)))
+- msn_object_destroy(user->msnobj);
+-
+- user->msnobj = obj;
+-
+- if (user->list_op & MSN_LIST_FL_OP)
+- queue_buddy_icon_request(user);
+-}
+-
+-void
+-msn_user_set_client_caps(MsnUser *user, GHashTable *info)
+-{
+- g_return_if_fail(user != NULL);
+- g_return_if_fail(info != NULL);
+-
+- if (user->clientcaps != NULL)
+- g_hash_table_destroy(user->clientcaps);
+-
+- user->clientcaps = info;
+-}
+-
+-void
+-msn_user_set_invite_message(MsnUser *user, const char *message)
+-{
+- g_return_if_fail(user != NULL);
+-
+- g_free(user->invite_message);
+- user->invite_message = g_strdup(message);
+-}
+-
+-const char *
+-msn_user_get_passport(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->passport;
+-}
+-
+-const char *
+-msn_user_get_friendly_name(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->friendly_name;
+-}
+-
+-const char *
+-msn_user_get_home_phone(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->extinfo ? user->extinfo->phone_home : NULL;
+-}
+-
+-const char *
+-msn_user_get_work_phone(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->extinfo ? user->extinfo->phone_work : NULL;
+-}
+-
+-const char *
+-msn_user_get_mobile_phone(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->extinfo ? user->extinfo->phone_mobile : NULL;
+-}
+-
+-guint
+-msn_user_get_clientid(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, 0);
+-
+- return user->clientid;
+-}
+-
+-guint
+-msn_user_get_extcaps(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, 0);
+-
+- return user->extcaps;
+-}
+-
+-MsnUserEndpoint *
+-msn_user_get_endpoint_data(MsnUser *user, const char *input)
+-{
+- char *endpoint;
+- GSList *l;
+- MsnUserEndpoint *ep;
+-
+- g_return_val_if_fail(user != NULL, NULL);
+- g_return_val_if_fail(input != NULL, NULL);
+-
+- endpoint = g_ascii_strdown(input, -1);
+-
+- for (l = user->endpoints; l; l = l->next) {
+- ep = l->data;
+- if (g_str_equal(ep->id, endpoint)) {
+- g_free(endpoint);
+- return ep;
+- }
+- }
+-
+- g_free(endpoint);
+-
+- return NULL;
+-}
+-
+-MsnNetwork
+-msn_user_get_network(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, MSN_NETWORK_UNKNOWN);
+-
+- return user->networkid;
+-}
+-
+-MsnObject *
+-msn_user_get_object(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->msnobj;
+-}
+-
+-GHashTable *
+-msn_user_get_client_caps(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->clientcaps;
+-}
+-
+-const char *
+-msn_user_get_invite_message(const MsnUser *user)
+-{
+- g_return_val_if_fail(user != NULL, NULL);
+-
+- return user->invite_message;
+-}
+-
+-gboolean
+-msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap)
+-{
+- g_return_val_if_fail(user != NULL, FALSE);
+-
+- if (endpoint != NULL) {
+- MsnUserEndpoint *ep = msn_user_get_endpoint_data(user, endpoint);
+- if (ep != NULL)
+- return (ep->clientid & capability) && (ep->extcaps & extcap);
+- else
+- return FALSE;
+- }
+-
+- return (user->clientid & capability) && (user->extcaps & extcap);
+-}
+-
+-/**************************************************************************
+- * Utility functions
+- **************************************************************************/
+-
+-int
+-msn_user_passport_cmp(MsnUser *user, const char *passport)
+-{
+- const char *str;
+- char *pass;
+- int result;
+-
+- str = purple_normalize_nocase(NULL, msn_user_get_passport(user));
+- pass = g_strdup(str);
+-
+-#if GLIB_CHECK_VERSION(2,16,0)
+- result = g_strcmp0(pass, purple_normalize_nocase(NULL, passport));
+-#else
+- str = purple_normalize_nocase(NULL, passport);
+- if (!pass)
+- result = -(pass != str);
+- else if (!str)
+- result = pass != str;
+- else
+- result = strcmp(pass, str);
+-#endif /* GLIB < 2.16.0 */
+-
+- g_free(pass);
+-
+- return result;
+-}
+-
+-gboolean
+-msn_user_is_in_group(MsnUser *user, const char * group_id)
+-{
+- if (user == NULL)
+- return FALSE;
+-
+- if (group_id == NULL)
+- return FALSE;
+-
+- return (g_list_find_custom(user->group_ids, group_id, (GCompareFunc)strcmp)) != NULL;
+-}
+-
+-gboolean
+-msn_user_is_in_list(MsnUser *user, MsnListId list_id)
+-{
+- if (user == NULL)
+- return FALSE;
+-
+- return (user->list_op & (1 << list_id));
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/user.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.h
+--- pidgin-2.10.7/libpurple/protocols/msn/user.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/user.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,533 +0,0 @@
+-/**
+- * @file user.h User functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_USER_H
+-#define MSN_USER_H
+-
+-typedef struct _MsnUser MsnUser;
+-
+-typedef enum
+-{
+- MSN_NETWORK_UNKNOWN = 0,
+- MSN_NETWORK_PASSPORT = 1,
+- MSN_NETWORK_COMMUNICATOR = 2,
+- MSN_NETWORK_MOBILE = 4,
+- MSN_NETWORK_MNI = 8,
+- MSN_NETWORK_CIRCLE = 9,
+- MSN_NETWORK_TEMP_GROUP = 10,
+- MSN_NETWORK_CID = 11,
+- MSN_NETWORK_CONNECT = 13,
+- MSN_NETWORK_REMOTE = 14,
+- MSN_NETWORK_SMTP = 16,
+- MSN_NETWORK_YAHOO = 32
+-} MsnNetwork;
+-
+-/**
+- * Current media.
+- */
+-typedef enum
+-{
+- CURRENT_MEDIA_UNKNOWN,
+- CURRENT_MEDIA_MUSIC,
+- CURRENT_MEDIA_GAMES,
+- CURRENT_MEDIA_OFFICE
+-} CurrentMediaType;
+-
+-#include "object.h"
+-#include "session.h"
+-#include "userlist.h"
+-
+-/**
+- * Contains optional info about a user that is fairly uncommon. We
+- * put this info in in a separate struct to save memory because we
+- * allocate an MsnUser struct for each buddy, but we generally only
+- * need this information for a small percentage of our buddies
+- * (usually less than 1%). Putting it in a separate struct makes
+- * MsnUser smaller by the size of a few pointers.
+- */
+-typedef struct _MsnUserExtendedInfo
+-{
+- CurrentMediaType media_type; /**< Type of the user's current media. */
+- char *media_title; /**< Title of the user's current media. */
+- char *media_artist; /**< Artist of the user's current media. */
+- char *media_album; /**< Album of the user's current media. */
+-
+- char *phone_home; /**< E.T. uses this. */
+- char *phone_work; /**< Work phone number. */
+- char *phone_mobile; /**< Mobile phone number. */
+-} MsnUserExtendedInfo;
+-
+-/**
+- * A user.
+- */
+-struct _MsnUser
+-{
+- MsnUserList *userlist;
+-
+- guint8 refcount; /**< The reference count of this object */
+-
+- char *passport; /**< The passport account. */
+- char *friendly_name; /**< The friendly name. */
+-
+- char *uid; /*< User ID */
+- GSList *endpoints; /*< Endpoint-specific data */
+-
+- const char *status; /**< The state of the user. */
+- char *statusline; /**< The state of the user. */
+-
+- gboolean idle; /**< The idle state of the user. */
+-
+- MsnUserExtendedInfo *extinfo; /**< Extended info for the user. */
+-
+- gboolean authorized; /**< Authorized to add this user. */
+- gboolean mobile; /**< Signed up with MSN Mobile. */
+-
+- GList *group_ids; /**< The group IDs. */
+- char *pending_group; /**< A pending group to add. */
+-
+- MsnObject *msnobj; /**< The user's MSN Object. */
+-
+- GHashTable *clientcaps; /**< The client's capabilities. */
+-
+- guint clientid; /**< The client's ID */
+- guint extcaps; /**< The client's extended capabilities */
+-
+- MsnNetwork networkid; /**< The user's network */
+-
+- MsnListOp list_op; /**< Which lists the user is in */
+-
+- /**
+- * The membershipId for this buddy on our pending list. Sent by
+- * the contact's server
+- */
+- guint member_id_on_pending_list;
+-
+- char *invite_message; /**< Invite message of user request */
+-};
+-
+-/**
+- * A specific user endpoint.
+- */
+-typedef struct MsnUserEndpoint {
+- char *id; /**< The client's endpoint ID */
+- char *name; /**< The client's endpoint's name */
+- int type; /**< The client's endpoint type */
+- guint clientid; /**< The client's ID */
+- guint extcaps; /**< The client's extended capabilites */
+-
+-} MsnUserEndpoint;
+-
+-/**************************************************************************
+- ** @name User API *
+- **************************************************************************/
+-/*@{*/
+-
+-/**
+- * Creates a new user structure.
+- *
+- * @param session The MSN session.
+- * @param passport The initial passport.
+- * @param stored_name The initial stored name.
+- *
+- * @return A new user structure. It will have a reference count of 1.
+- */
+-MsnUser *msn_user_new(MsnUserList *userlist, const char *passport,
+- const char *friendly_name);
+-
+-/**
+- * Increment the reference count.
+- *
+- * @param user The user.
+- *
+- * @return user.
+- */
+-MsnUser *msn_user_ref(MsnUser *user);
+-
+-/**
+- * Decrement the reference count. When the count reaches 0 the object is
+- * automatically freed.
+- *
+- * @param user The user
+- */
+-void msn_user_unref(MsnUser *user);
+-
+-/**
+- * Updates the user.
+- *
+- * Communicates with the core to update the ui, etc.
+- *
+- * @param user The user to update.
+- */
+-void msn_user_update(MsnUser *user);
+-
+- /**
+- * Sets the new statusline of user.
+- *
+- * @param user The user.
+- * @param state The statusline string.
+- */
+-void msn_user_set_statusline(MsnUser *user, const char *statusline);
+-
+-/**
+- * Sets the new state of user.
+- *
+- * @param user The user.
+- * @param state The state string.
+- */
+-void msn_user_set_state(MsnUser *user, const char *state);
+-
+-/**
+- * Sets the passport account for a user.
+- *
+- * @param user The user.
+- * @param passport The passport account.
+- */
+-void msn_user_set_passport(MsnUser *user, const char *passport);
+-
+-/**
+- * Sets the friendly name for a user.
+- *
+- * @param user The user.
+- * @param name The friendly name.
+- *
+- * @returns TRUE is name actually changed, FALSE otherwise.
+- */
+-gboolean msn_user_set_friendly_name(MsnUser *user, const char *name);
+-
+-/**
+- * Sets the buddy icon for a local user.
+- *
+- * @param user The user.
+- * @param img The buddy icon image
+- */
+-void msn_user_set_buddy_icon(MsnUser *user, PurpleStoredImage *img);
+-
+-/**
+- * Sets the group ID list for a user.
+- *
+- * @param user The user.
+- * @param ids The group ID list.
+- */
+-void msn_user_set_group_ids(MsnUser *user, GList *ids);
+-
+-/**
+- * Adds the group ID for a user.
+- *
+- * @param user The user.
+- * @param id The group ID.
+- */
+-void msn_user_add_group_id(MsnUser *user, const char * id);
+-
+-/**
+- * Removes the group ID from a user.
+- *
+- * @param user The user.
+- * @param id The group ID.
+- */
+-void msn_user_remove_group_id(MsnUser *user, const char * id);
+-
+-/**
+- * Sets the pending group for a user.
+- *
+- * @param user The user.
+- * @param group The group name.
+- */
+-void msn_user_set_pending_group(MsnUser *user, const char *group);
+-
+-/**
+- * Removes the pending group from a user.
+- *
+- * @param user The user.
+- *
+- * @return Returns the pending group name.
+- */
+-char *msn_user_remove_pending_group(MsnUser *user);
+-
+-/**
+- * Sets the home phone number for a user.
+- *
+- * @param user The user.
+- * @param number The home phone number.
+- */
+-void msn_user_set_home_phone(MsnUser *user, const char *number);
+-
+-/**
+- * Sets the work phone number for a user.
+- *
+- * @param user The user.
+- * @param number The work phone number.
+- */
+-void msn_user_set_work_phone(MsnUser *user, const char *number);
+-
+-void msn_user_set_uid(MsnUser *user, const char *uid);
+-
+-/**
+- * Sets endpoint data for a user.
+- *
+- * @param user The user.
+- * @param endpoint The endpoint.
+- * @param data The endpoint data.
+- */
+-void
+-msn_user_set_endpoint_data(MsnUser *user, const char *endpoint, MsnUserEndpoint *data);
+-
+-/**
+- * Clears all endpoint data for a user.
+- *
+- * @param user The user.
+- */
+-void
+-msn_user_clear_endpoints(MsnUser *user);
+-
+-/**
+- * Sets the client id for a user.
+- *
+- * @param user The user.
+- * @param clientid The client id.
+- */
+-void msn_user_set_clientid(MsnUser *user, guint clientid);
+-
+-/**
+- * Sets the client id for a user.
+- *
+- * @param user The user.
+- * @param extcaps The client's extended capabilities.
+- */
+-void msn_user_set_extcaps(MsnUser *user, guint extcaps);
+-
+-/**
+- * Sets the network id for a user.
+- *
+- * @param user The user.
+- * @param network The network id.
+- */
+-void msn_user_set_network(MsnUser *user, MsnNetwork network);
+-
+-/**
+- * Sets the mobile phone number for a user.
+- *
+- * @param user The user.
+- * @param number The mobile phone number.
+- */
+-void msn_user_set_mobile_phone(MsnUser *user, const char *number);
+-
+-/**
+- * Sets the MSNObject for a user.
+- *
+- * @param user The user.
+- * @param obj The MSNObject.
+- */
+-void msn_user_set_object(MsnUser *user, MsnObject *obj);
+-
+-/**
+- * Sets the client information for a user.
+- *
+- * @param user The user.
+- * @param info The client information.
+- */
+-void msn_user_set_client_caps(MsnUser *user, GHashTable *info);
+-
+-/**
+- * Sets the invite message for a user.
+- *
+- * @param user The user.
+- * @param message The invite message for a user.
+- */
+-void msn_user_set_invite_message(MsnUser *user, const char *message);
+-
+-
+-/**
+- * Returns the passport account for a user.
+- *
+- * @param user The user.
+- *
+- * @return The passport account.
+- */
+-const char *msn_user_get_passport(const MsnUser *user);
+-
+-/**
+- * Returns the friendly name for a user.
+- *
+- * @param user The user.
+- *
+- * @return The friendly name.
+- */
+-const char *msn_user_get_friendly_name(const MsnUser *user);
+-
+-/**
+- * Returns the home phone number for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's home phone number.
+- */
+-const char *msn_user_get_home_phone(const MsnUser *user);
+-
+-/**
+- * Returns the work phone number for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's work phone number.
+- */
+-const char *msn_user_get_work_phone(const MsnUser *user);
+-
+-/**
+- * Returns the mobile phone number for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's mobile phone number.
+- */
+-const char *msn_user_get_mobile_phone(const MsnUser *user);
+-
+-/**
+- * Gets endpoint data for a user.
+- *
+- * @param user The user.
+- * @param endpoint The endpoint.
+- *
+- * @return The user's endpoint data.
+- */
+-MsnUserEndpoint *
+-msn_user_get_endpoint_data(MsnUser *user, const char *endpoint);
+-
+-/**
+- * Returns the client id for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's client id.
+- */
+-guint msn_user_get_clientid(const MsnUser *user);
+-
+-/**
+- * Returns the extended capabilities for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's extended capabilities.
+- */
+-guint msn_user_get_extcaps(const MsnUser *user);
+-
+-/**************************************************************************
+- * Utility functions
+- **************************************************************************/
+-
+-
+-/**
+- * Check if the user is part of the group.
+- *
+- * @param user The user we are asking group membership.
+- * @param group_id The group where the user may be in.
+- *
+- * @return TRUE if user is part of the group. Otherwise, FALSE.
+- */
+-gboolean msn_user_is_in_group(MsnUser *user, const char * group_id);
+-
+-/**
+- * Check if user is on list.
+- *
+- * @param user The user we are asking list membership.
+- * @param list_id The list where the user may be in.
+- *
+- * @return TRUE if the user is on the list, else FALSE.
+- */
+-gboolean msn_user_is_in_list(MsnUser *user, MsnListId list_id);
+-/**
+- * Returns the network id for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's network id.
+- */
+-MsnNetwork msn_user_get_network(const MsnUser *user);
+-
+-/**
+- * Returns the MSNObject for a user.
+- *
+- * @param user The user.
+- *
+- * @return The MSNObject.
+- */
+-MsnObject *msn_user_get_object(const MsnUser *user);
+-
+-/**
+- * Returns the client information for a user.
+- *
+- * @param user The user.
+- *
+- * @return The client information.
+- */
+-GHashTable *msn_user_get_client_caps(const MsnUser *user);
+-
+-/**
+- * Returns the invite message for a user.
+- *
+- * @param user The user.
+- *
+- * @return The user's invite message.
+- */
+-const char *msn_user_get_invite_message(const MsnUser *user);
+-
+-/**
+- * check to see if user is online
+- */
+-gboolean msn_user_is_online(PurpleAccount *account, const char *name);
+-
+-/**
+- * check to see if user is Yahoo User
+- */
+-gboolean msn_user_is_yahoo(PurpleAccount *account, const char *name);
+-
+-void msn_user_set_op(MsnUser *user, MsnListOp list_op);
+-void msn_user_unset_op(MsnUser *user, MsnListOp list_op);
+-
+-/**
+- * Compare the given passport with the one of the user
+- *
+- * @param user User to compare.
+- * @oaran passport Passport to compare.
+- *
+- * @return Zero if the passport match with the one of the user, otherwise
+- * a positive integer if the user passport is greather than the one given
+- * and a negative integer if it is less.
+- */
+-int msn_user_passport_cmp(MsnUser *user, const char *passport);
+-
+-/**
+- * Checks whether a user is capable of some task.
+- *
+- * @param user The user.
+- * @param endpoint The endpoint. Can be @NULL to check overall capabilities.
+- * @param capability The capability (including client version).
+- * @param extcap The extended capability.
+- *
+- * @return Whether the user supports the capability.
+- */
+-gboolean
+-msn_user_is_capable(MsnUser *user, char *endpoint, guint capability, guint extcap);
+-
+-/*@}*/
+-
+-#endif /* MSN_USER_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/userlist.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.c
+--- pidgin-2.10.7/libpurple/protocols/msn/userlist.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,759 +0,0 @@
+-/**
+- * @file userlist.c MSN user list support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "request.h"
+-
+-#include "msn.h"
+-#include "msnutils.h"
+-#include "userlist.h"
+-
+-#include "contact.h"
+-
+-const char *lists[] = { "FL", "AL", "BL", "RL" };
+-
+-typedef struct
+-{
+- PurpleConnection *gc;
+- char *who;
+- char *friendly;
+-
+-} MsnPermitAdd;
+-
+-/**************************************************************************
+- * Callbacks
+- **************************************************************************/
+-static void
+-msn_accept_add_cb(gpointer data)
+-{
+- MsnPermitAdd *pa = data;
+-
+- purple_debug_misc("msn", "Accepted the new buddy: %s\n", pa->who);
+-
+- if (PURPLE_CONNECTION_IS_VALID(pa->gc))
+- {
+- MsnSession *session = pa->gc->proto_data;
+- MsnUserList *userlist = session->userlist;
+- PurpleAccount *account = purple_connection_get_account(pa->gc);
+-
+- msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_AL);
+- purple_privacy_deny_remove(account, pa->who, TRUE);
+- purple_privacy_permit_add(account, pa->who, TRUE);
+-
+- msn_del_contact_from_list(session, NULL, pa->who, MSN_LIST_PL);
+- }
+-
+- g_free(pa->who);
+- g_free(pa->friendly);
+- g_free(pa);
+-}
+-
+-static void
+-msn_cancel_add_cb(gpointer data)
+-{
+- MsnPermitAdd *pa = data;
+-
+- purple_debug_misc("msn", "Denied the new buddy: %s\n", pa->who);
+-
+- if (PURPLE_CONNECTION_IS_VALID(pa->gc))
+- {
+- MsnSession *session = pa->gc->proto_data;
+- MsnUserList *userlist = session->userlist;
+- MsnCallbackState *state = msn_callback_state_new(session);
+-
+- msn_callback_state_set_action(state, MSN_DENIED_BUDDY);
+-
+- msn_userlist_add_buddy_to_list(userlist, pa->who, MSN_LIST_BL);
+- msn_del_contact_from_list(session, state, pa->who, MSN_LIST_PL);
+- }
+-
+- g_free(pa->who);
+- g_free(pa->friendly);
+- g_free(pa);
+-}
+-
+-static void
+-got_new_entry(PurpleConnection *gc, const char *passport, const char *friendly, const char *message)
+-{
+- PurpleAccount *acct;
+- MsnPermitAdd *pa;
+-
+- pa = g_new0(MsnPermitAdd, 1);
+- pa->who = g_strdup(passport);
+- pa->friendly = g_strdup(friendly);
+- pa->gc = gc;
+-
+- acct = purple_connection_get_account(gc);
+- purple_account_request_authorization(acct, passport, NULL, friendly, message,
+- purple_find_buddy(acct, passport) != NULL,
+- msn_accept_add_cb, msn_cancel_add_cb, pa);
+-
+-}
+-
+-/**************************************************************************
+- * Server functions
+- **************************************************************************/
+-
+-void
+-msn_got_lst_user(MsnSession *session, MsnUser *user,
+- MsnListOp list_op, GSList *group_ids)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- const char *passport;
+- const char *store;
+- const char *message;
+-
+- account = session->account;
+- gc = purple_account_get_connection(account);
+-
+- passport = msn_user_get_passport(user);
+- store = msn_user_get_friendly_name(user);
+- message = msn_user_get_invite_message(user);
+-
+- msn_user_set_op(user, list_op);
+-
+- if (list_op & MSN_LIST_FL_OP)
+- {
+- GSList *c;
+- for (c = group_ids; c != NULL; c = g_slist_next(c))
+- {
+- char *group_id = c->data;
+- msn_user_add_group_id(user, group_id);
+- }
+-
+- /* FIXME: It might be a real alias */
+- /* Umm, what? This might fix bug #1385130 */
+- serv_got_alias(gc, passport, store);
+- }
+-
+- if (list_op & MSN_LIST_AL_OP)
+- {
+- /* These are users who are allowed to see our status. */
+- purple_privacy_deny_remove(account, passport, TRUE);
+- purple_privacy_permit_add(account, passport, TRUE);
+- }
+-
+- if (list_op & MSN_LIST_BL_OP)
+- {
+- /* These are users who are not allowed to see our status. */
+- purple_privacy_permit_remove(account, passport, TRUE);
+- purple_privacy_deny_add(account, passport, TRUE);
+- }
+-
+- if (list_op & MSN_LIST_RL_OP)
+- {
+- /* These are users who have us on their buddy list. */
+- /*
+- * TODO: What is store name set to when this happens?
+- * For one of my accounts "something@hotmail.com"
+- * the store name was "something." Maybe we
+- * should use the friendly name, instead? --KingAnt
+- */
+-
+- if (!(list_op & (MSN_LIST_AL_OP | MSN_LIST_BL_OP)))
+- {
+-/* got_new_entry(gc, passport, store, NULL); */
+- }
+- }
+-
+- if (list_op & MSN_LIST_PL_OP)
+- {
+- user->authorized = TRUE;
+- got_new_entry(gc, passport, store, message);
+- }
+-}
+-
+-/**************************************************************************
+- * UserList functions
+- **************************************************************************/
+-
+-MsnUserList*
+-msn_userlist_new(MsnSession *session)
+-{
+- MsnUserList *userlist;
+-
+- userlist = g_new0(MsnUserList, 1);
+-
+- userlist->session = session;
+- userlist->buddy_icon_requests = g_queue_new();
+-
+- /* buddy_icon_window is the number of allowed simultaneous buddy icon requests.
+- * XXX With smarter rate limiting code, we could allow more at once... 5 was the limit set when
+- * we weren't retrieiving any more than 5 per MSN session. */
+- userlist->buddy_icon_window = 1;
+-
+- return userlist;
+-}
+-
+-void
+-msn_userlist_destroy(MsnUserList *userlist)
+-{
+- GList *l;
+-
+- /*destroy userlist*/
+- for (l = userlist->users; l != NULL; l = l->next)
+- {
+- msn_user_unref(l->data);
+- }
+- g_list_free(userlist->users);
+-
+- /*destroy group list*/
+- for (l = userlist->groups; l != NULL; l = l->next)
+- {
+- msn_group_destroy(l->data);
+- }
+- g_list_free(userlist->groups);
+-
+- g_queue_free(userlist->buddy_icon_requests);
+-
+- if (userlist->buddy_icon_request_timer)
+- purple_timeout_remove(userlist->buddy_icon_request_timer);
+-
+- g_free(userlist);
+-}
+-
+-MsnUser *
+-msn_userlist_find_add_user(MsnUserList *userlist, const char *passport, const char *friendly_name)
+-{
+- MsnUser *user;
+-
+- user = msn_userlist_find_user(userlist, passport);
+- if (user == NULL)
+- {
+- user = msn_user_new(userlist, passport, friendly_name);
+- msn_userlist_add_user(userlist, user);
+- msn_user_unref(user);
+- } else {
+- msn_user_set_friendly_name(user, friendly_name);
+- }
+- return user;
+-}
+-
+-void
+-msn_userlist_add_user(MsnUserList *userlist, MsnUser *user)
+-{
+- msn_user_ref(user);
+- userlist->users = g_list_prepend(userlist->users, user);
+-}
+-
+-void
+-msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user)
+-{
+- userlist->users = g_list_remove(userlist->users, user);
+- g_queue_remove(userlist->buddy_icon_requests, user);
+- msn_user_unref(user);
+-}
+-
+-MsnUser *
+-msn_userlist_find_user(MsnUserList *userlist, const char *passport)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(passport != NULL, NULL);
+-
+- for (l = userlist->users; l != NULL; l = l->next)
+- {
+- MsnUser *user = (MsnUser *)l->data;
+-
+- g_return_val_if_fail(user->passport != NULL, NULL);
+-
+- if (!g_ascii_strcasecmp(passport, user->passport)){
+- return user;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-MsnUser *
+-msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(uid != NULL, NULL);
+-
+- for (l = userlist->users; l != NULL; l = l->next) {
+- MsnUser *user = (MsnUser *)l->data;
+-
+- if (user->uid == NULL) {
+- continue;
+- }
+-
+- if ( !g_ascii_strcasecmp(uid, user->uid) ) {
+- return user;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-MsnUser *
+-msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(number != NULL, NULL);
+-
+- for (l = userlist->users; l != NULL; l = l->next) {
+- MsnUser *user = (MsnUser *)l->data;
+- const char *user_number = msn_user_get_mobile_phone(user);
+-
+- if (user_number && !g_ascii_strcasecmp(number, user_number))
+- return user;
+- }
+-
+- return NULL;
+-}
+-
+-void
+-msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group)
+-{
+- userlist->groups = g_list_append(userlist->groups, group);
+-}
+-
+-void
+-msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group)
+-{
+- userlist->groups = g_list_remove(userlist->groups, group);
+-}
+-
+-MsnGroup *
+-msn_userlist_find_group_with_id(MsnUserList *userlist, const char * id)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(userlist != NULL, NULL);
+- g_return_val_if_fail(id != NULL, NULL);
+-
+- for (l = userlist->groups; l != NULL; l = l->next)
+- {
+- MsnGroup *group = l->data;
+-
+- if (!g_ascii_strcasecmp(group->id,id))
+- return group;
+- }
+-
+- return NULL;
+-}
+-
+-MsnGroup *
+-msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name)
+-{
+- GList *l;
+-
+- g_return_val_if_fail(userlist != NULL, NULL);
+- g_return_val_if_fail(name != NULL, NULL);
+-
+- for (l = userlist->groups; l != NULL; l = l->next)
+- {
+- MsnGroup *group = l->data;
+-
+- if ((group->name != NULL) && !g_ascii_strcasecmp(name, group->name))
+- return group;
+- }
+-
+- return NULL;
+-}
+-
+-const char *
+-msn_userlist_find_group_id(MsnUserList *userlist, const char *group_name)
+-{
+- MsnGroup *group;
+-
+- group = msn_userlist_find_group_with_name(userlist, group_name);
+-
+- if (group != NULL)
+- return msn_group_get_id(group);
+- else
+- return NULL;
+-}
+-
+-const char *
+-msn_userlist_find_group_name(MsnUserList *userlist, const char * group_id)
+-{
+- MsnGroup *group;
+-
+- group = msn_userlist_find_group_with_id(userlist, group_id);
+-
+- if (group != NULL)
+- return msn_group_get_name(group);
+- else
+- return NULL;
+-}
+-
+-void
+-msn_userlist_rename_group_id(MsnUserList *userlist, const char * group_id,
+- const char *new_name)
+-{
+- MsnGroup *group;
+-
+- group = msn_userlist_find_group_with_id(userlist, group_id);
+-
+- if (group != NULL)
+- msn_group_set_name(group, new_name);
+-}
+-
+-void
+-msn_userlist_remove_group_id(MsnUserList *userlist, const char * group_id)
+-{
+- MsnGroup *group;
+-
+- group = msn_userlist_find_group_with_id(userlist, group_id);
+-
+- if (group != NULL)
+- {
+- msn_userlist_remove_group(userlist, group);
+- msn_group_destroy(group);
+- }
+-}
+-
+-typedef struct {
+- MsnSession *session;
+- char *uid;
+-} MsnUserlistABData;
+-
+-static void
+-userlist_ab_delete_cb(void *data, int choice)
+-{
+- MsnUserlistABData *ab = (MsnUserlistABData *)data;
+-
+- /* msn_delete_contact(ab->session, ab->uid, (gboolean)choice); */
+-
+- g_free(ab->uid);
+- g_free(ab);
+-}
+-
+-void
+-msn_userlist_rem_buddy(MsnUserList *userlist, const char *who)
+-{
+- MsnUser *user = NULL;
+-
+- g_return_if_fail(userlist != NULL);
+- g_return_if_fail(userlist->session != NULL);
+- g_return_if_fail(who != NULL);
+-
+- user = msn_userlist_find_user(userlist, who);
+-
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_FL);
+-
+- /* delete the contact from address book via soap action */
+- if (user != NULL) {
+- if (0 /*not ready yet*/ && userlist->session->passport_info.email_enabled) {
+- MsnUserlistABData *ab = g_new0(MsnUserlistABData, 1);
+- ab->session = userlist->session;
+- ab->uid = g_strdup(user->uid); /* Not necessary? */
+- purple_request_yes_no(userlist->session->account,
+- _("Delete Buddy from Address Book?"),
+- _("Do you want to delete this buddy from your address book as well?"),
+- user->passport, 0, userlist->session->account, user->passport,
+- NULL, ab,
+- G_CALLBACK(userlist_ab_delete_cb), G_CALLBACK(userlist_ab_delete_cb));
+- } else
+- msn_delete_contact(userlist->session, user);
+- }
+-}
+-
+-void
+-msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
+- MsnListId list_id)
+-{
+- MsnUser *user;
+- const gchar *list;
+- MsnListOp list_op = 1 << list_id;
+-
+- user = msn_userlist_find_user(userlist, who);
+-
+- g_return_if_fail(user != NULL);
+-
+- if ( !msn_user_is_in_list(user, list_id)) {
+- list = lists[list_id];
+- purple_debug_info("msn", "User %s is not in list %s, not removing.\n", who, list);
+- return;
+- }
+-
+- msn_user_unset_op(user, list_op);
+-
+- msn_notification_rem_buddy_from_list(userlist->session->notification, list_id, user);
+-}
+-
+-/*add buddy*/
+-void
+-msn_userlist_add_buddy(MsnUserList *userlist, const char *who, const char *group_name)
+-{
+- MsnUser *user;
+- MsnCallbackState *state = NULL;
+- const char *group_id = NULL, *new_group_name;
+-
+- new_group_name = group_name == NULL ? MSN_INDIVIDUALS_GROUP_NAME : group_name;
+-
+- g_return_if_fail(userlist != NULL);
+- g_return_if_fail(userlist->session != NULL);
+-
+- purple_debug_info("msn", "Add user: %s to group: %s\n", who, new_group_name);
+-
+- if (!msn_email_is_valid(who))
+- {
+- /* only notify the user about problems adding to the friends list
+- * maybe we should do something else for other lists, but it probably
+- * won't cause too many problems if we just ignore it */
+-
+- char *str = g_strdup_printf(_("Unable to add \"%s\"."), who);
+-
+- purple_notify_error(NULL, NULL, str,
+- _("The username specified is invalid."));
+- g_free(str);
+-
+- return;
+- }
+-
+- state = msn_callback_state_new(userlist->session);
+- msn_callback_state_set_who(state, who);
+- msn_callback_state_set_new_group_name(state, new_group_name);
+-
+- group_id = msn_userlist_find_group_id(userlist, new_group_name);
+-
+- if (group_id == NULL)
+- {
+- /* Whoa, we must add that group first. */
+- purple_debug_info("msn", "Adding user %s to a new group, creating group %s first\n", who, new_group_name);
+-
+- msn_callback_state_set_action(state, MSN_ADD_BUDDY);
+-
+- msn_add_group(userlist->session, state, new_group_name);
+- return;
+- } else {
+- msn_callback_state_set_guid(state, group_id);
+- }
+-
+- /* XXX: adding user here may not be correct (should add them in the
+- * ACK to the ADL command), but for now we need to make sure they exist
+- * early enough that the ILN command doesn't screw us up */
+-
+- user = msn_userlist_find_add_user(userlist, who, who);
+-
+- if ( msn_user_is_in_list(user, MSN_LIST_FL) ) {
+-
+- purple_debug_info("msn", "User %s already exists\n", who);
+-
+- msn_userlist_rem_buddy_from_list(userlist, who, MSN_LIST_BL);
+-
+- if (msn_user_is_in_group(user, group_id)) {
+- purple_debug_info("msn", "User %s is already in group %s, returning\n", who, new_group_name);
+- msn_callback_state_free(state);
+- return;
+- }
+- }
+-
+- purple_debug_info("msn", "Adding user: %s to group id: %s\n", who, group_id);
+-
+- msn_callback_state_set_action(state, MSN_ADD_BUDDY);
+-
+- /* Add contact in the Contact server with a SOAP request and if
+- successful, send ADL with MSN_LIST_AL and MSN_LIST_FL and a FQY */
+- msn_add_contact_to_group(userlist->session, state, who, group_id);
+-}
+-
+-void
+-msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
+- MsnListId list_id)
+-{
+- MsnUser *user = NULL;
+- const gchar *list;
+- MsnListOp list_op = 1 << list_id;
+-
+- g_return_if_fail(userlist != NULL);
+-
+- user = msn_userlist_find_add_user(userlist, who, who);
+-
+- /* First we're going to check if it's already there. */
+- if (msn_user_is_in_list(user, list_id))
+- {
+- list = lists[list_id];
+- purple_debug_info("msn", "User '%s' is already in list: %s\n", who, list);
+- return;
+- }
+-
+- /* XXX: see XXX above, this should really be done when we get the response from
+- the server */
+-
+- msn_user_set_op(user, list_op);
+-
+- msn_notification_add_buddy_to_list(userlist->session->notification, list_id, user);
+-}
+-
+-gboolean
+-msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
+- const char *group_name)
+-{
+- MsnUser *user;
+- gchar * group_id;
+-
+- g_return_val_if_fail(userlist != NULL, FALSE);
+- g_return_val_if_fail(group_name != NULL, FALSE);
+- g_return_val_if_fail(who != NULL, FALSE);
+-
+- purple_debug_info("msn", "Adding buddy with passport %s to group %s\n", who, group_name);
+-
+- if ( (group_id = (gchar *)msn_userlist_find_group_id(userlist, group_name)) == NULL) {
+- purple_debug_error("msn", "Group %s has no guid!\n", group_name);
+- return FALSE;
+- }
+-
+- if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
+- purple_debug_error("msn", "User %s not found!\n", who);
+- return FALSE;
+- }
+-
+- msn_user_add_group_id(user, group_id);
+-
+- return TRUE;
+-}
+-
+-
+-gboolean
+-msn_userlist_rem_buddy_from_group(MsnUserList *userlist, const char *who,
+- const char *group_name)
+-{
+- const gchar * group_id;
+- MsnUser *user;
+-
+- g_return_val_if_fail(userlist != NULL, FALSE);
+- g_return_val_if_fail(group_name != NULL, FALSE);
+- g_return_val_if_fail(who != NULL, FALSE);
+-
+- purple_debug_info("msn", "Removing buddy with passport %s from group %s\n", who, group_name);
+-
+- if ( (group_id = msn_userlist_find_group_id(userlist, group_name)) == NULL) {
+- purple_debug_error("msn", "Group %s has no guid!\n", group_name);
+- return FALSE;
+- }
+-
+- if ( (user = msn_userlist_find_user(userlist, who)) == NULL) {
+- purple_debug_error("msn", "User %s not found!\n", who);
+- return FALSE;
+- }
+-
+- msn_user_remove_group_id(user, group_id);
+-
+- return TRUE;
+-}
+-
+-void
+-msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
+- const char *old_group_name, const char *new_group_name)
+-{
+- const char *new_group_id;
+- MsnCallbackState *state;
+-
+- g_return_if_fail(userlist != NULL);
+- g_return_if_fail(userlist->session != NULL);
+-
+- state = msn_callback_state_new(userlist->session);
+- msn_callback_state_set_who(state, who);
+- msn_callback_state_set_action(state, MSN_MOVE_BUDDY);
+- msn_callback_state_set_old_group_name(state, old_group_name);
+- msn_callback_state_set_new_group_name(state, new_group_name);
+-
+- new_group_id = msn_userlist_find_group_id(userlist, new_group_name);
+-
+- if (new_group_id == NULL)
+- {
+- msn_add_group(userlist->session, state, new_group_name);
+- return;
+- }
+-
+- /* add the contact to the new group, and remove it from the old one in
+- * the callback
+- */
+- msn_add_contact_to_group(userlist->session, state, who, new_group_id);
+-}
+-
+-void
+-msn_release_buddy_icon_request(MsnUserList *userlist)
+-{
+- MsnUser *user;
+-
+- g_return_if_fail(userlist != NULL);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn", "Releasing buddy icon request\n");
+-
+- if (userlist->buddy_icon_window > 0) {
+- GQueue *queue;
+-
+- queue = userlist->buddy_icon_requests;
+-
+- if (g_queue_is_empty(userlist->buddy_icon_requests))
+- return;
+-
+- user = g_queue_pop_head(queue);
+-
+- userlist->buddy_icon_window--;
+-
+- msn_request_user_display(user);
+-
+- if (purple_debug_is_verbose())
+- purple_debug_info("msn",
+- "msn_release_buddy_icon_request(): buddy_icon_window-- yields =%d\n",
+- userlist->buddy_icon_window);
+- }
+-}
+-
+-/*load userlist from the Blist file cache*/
+-void
+-msn_userlist_load(MsnSession *session)
+-{
+- PurpleAccount *account = session->account;
+- PurpleConnection *gc = purple_account_get_connection(account);
+- GSList *l;
+- MsnUser * user;
+-
+- g_return_if_fail(gc != NULL);
+-
+- for (l = purple_find_buddies(account, NULL); l != NULL;
+- l = g_slist_delete_link(l, l)) {
+- PurpleBuddy *buddy = l->data;
+-
+- user = msn_userlist_find_add_user(session->userlist,
+- purple_buddy_get_name(buddy), NULL);
+- purple_buddy_set_protocol_data(buddy, user);
+- msn_user_set_op(user, MSN_LIST_FL_OP);
+- }
+- for (l = session->account->permit; l != NULL; l = l->next)
+- {
+- user = msn_userlist_find_add_user(session->userlist,
+- (char *)l->data,NULL);
+- msn_user_set_op(user, MSN_LIST_AL_OP);
+- }
+- for (l = session->account->deny; l != NULL; l = l->next)
+- {
+- user = msn_userlist_find_add_user(session->userlist,
+- (char *)l->data,NULL);
+- msn_user_set_op(user, MSN_LIST_BL_OP);
+- }
+-
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/userlist.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.h
+--- pidgin-2.10.7/libpurple/protocols/msn/userlist.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/userlist.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,112 +0,0 @@
+-/**
+- * @file userlist.h MSN user list support
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef MSN_USERLIST_H
+-#define MSN_USERLIST_H
+-
+-typedef struct _MsnUserList MsnUserList;
+-
+-typedef enum
+-{
+- MSN_LIST_FL, /**< Forward list */
+- MSN_LIST_AL, /**< Allow list */
+- MSN_LIST_BL, /**< Block list */
+- MSN_LIST_RL, /**< Reverse list */
+- MSN_LIST_PL /**< Pending list */
+-} MsnListId;
+-
+-typedef enum
+-{
+- MSN_LIST_FL_OP = 0x01,
+- MSN_LIST_AL_OP = 0x02,
+- MSN_LIST_BL_OP = 0x04,
+- MSN_LIST_RL_OP = 0x08,
+- MSN_LIST_PL_OP = 0x10
+-} MsnListOp;
+-#define MSN_LIST_OP_MASK 0x07
+-
+-#include "group.h"
+-#include "msn.h"
+-#include "user.h"
+-
+-struct _MsnUserList
+-{
+- MsnSession *session;
+-
+- GList *users; /* Contains MsnUsers */
+- GList *groups; /* Contains MsnGroups */
+-
+- GQueue *buddy_icon_requests;
+- int buddy_icon_window;
+- guint buddy_icon_request_timer;
+-
+-};
+-
+-void msn_got_lst_user(MsnSession *session, MsnUser *user,
+- MsnListOp list_op, GSList *group_ids);
+-
+-MsnUserList *msn_userlist_new(MsnSession *session);
+-void msn_userlist_destroy(MsnUserList *userlist);
+-
+-void msn_userlist_add_user(MsnUserList *userlist, MsnUser *user);
+-void msn_userlist_remove_user(MsnUserList *userlist, MsnUser *user);
+-
+-MsnUser * msn_userlist_find_user(MsnUserList *userlist, const char *passport);
+-MsnUser * msn_userlist_find_add_user(MsnUserList *userlist,
+- const char *passport, const char *friendly_name);
+-MsnUser * msn_userlist_find_user_with_id(MsnUserList *userlist, const char *uid);
+-MsnUser * msn_userlist_find_user_with_mobile_phone(MsnUserList *userlist, const char *number);
+-
+-void msn_userlist_add_group(MsnUserList *userlist, MsnGroup *group);
+-void msn_userlist_remove_group(MsnUserList *userlist, MsnGroup *group);
+-MsnGroup *msn_userlist_find_group_with_id(MsnUserList *userlist, const char *id);
+-MsnGroup *msn_userlist_find_group_with_name(MsnUserList *userlist, const char *name);
+-const char * msn_userlist_find_group_id(MsnUserList *userlist,
+- const char *group_name);
+-const char *msn_userlist_find_group_name(MsnUserList *userlist, const char *group_id);
+-void msn_userlist_rename_group_id(MsnUserList *userlist, const char *group_id,
+- const char *new_name);
+-void msn_userlist_remove_group_id(MsnUserList *userlist, const char *group_id);
+-
+-void msn_userlist_rem_buddy(MsnUserList *userlist, const char *who);
+-void msn_userlist_add_buddy(MsnUserList *userlist,
+- const char *who, const char *group_name);
+-void msn_userlist_move_buddy(MsnUserList *userlist, const char *who,
+- const char *old_group_name,
+- const char *new_group_name);
+-
+-gboolean msn_userlist_add_buddy_to_group(MsnUserList *userlist, const char *who,
+- const char *group_name);
+-gboolean msn_userlist_rem_buddy_from_group(MsnUserList *userlist,
+- const char *who,
+- const char *group_name);
+-
+-void msn_userlist_add_buddy_to_list(MsnUserList *userlist, const char *who,
+- MsnListId list_id);
+-void msn_userlist_rem_buddy_from_list(MsnUserList *userlist, const char *who,
+- MsnListId list_id);
+-void msn_release_buddy_icon_request(MsnUserList *userlist);
+-
+-void msn_userlist_load(MsnSession *session);
+-
+-#endif /* MSN_USERLIST_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/xfer.c pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.c
+--- pidgin-2.10.7/libpurple/protocols/msn/xfer.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,235 +0,0 @@
+-/**
+- * @file xfer.c MSN File Transfer functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "msnutils.h"
+-#include "sbconn.h"
+-#include "xfer.h"
+-
+-/**************************************************************************
+- * Xfer
+- **************************************************************************/
+-
+-void
+-msn_xfer_init(PurpleXfer *xfer)
+-{
+- MsnSlpCall *slpcall;
+- /* MsnSlpLink *slplink; */
+- char *content;
+-
+- purple_debug_info("msn", "xfer_init\n");
+-
+- slpcall = xfer->data;
+-
+- /* Send Ok */
+- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
+- slpcall->session_id);
+-
+- msn_slp_send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
+- content);
+-
+- g_free(content);
+- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
+-}
+-
+-void
+-msn_xfer_cancel(PurpleXfer *xfer)
+-{
+- MsnSlpCall *slpcall;
+- char *content;
+-
+- g_return_if_fail(xfer != NULL);
+- g_return_if_fail(xfer->data != NULL);
+-
+- slpcall = xfer->data;
+-
+- if (purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL)
+- {
+- if (slpcall->started)
+- {
+- msn_slpcall_close(slpcall);
+- }
+- else
+- {
+- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
+- slpcall->session_id);
+-
+- msn_slp_send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
+- content);
+-
+- g_free(content);
+- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
+-
+- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND)
+- slpcall->wasted = TRUE;
+- else
+- msn_slpcall_destroy(slpcall);
+- }
+- }
+-}
+-
+-gssize
+-msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
+-{
+- MsnSlpCall *slpcall;
+-
+- g_return_val_if_fail(xfer != NULL, -1);
+- g_return_val_if_fail(data != NULL, -1);
+- g_return_val_if_fail(len > 0, -1);
+-
+- g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND, -1);
+-
+- slpcall = xfer->data;
+- /* Not sure I trust it'll be there */
+- g_return_val_if_fail(slpcall != NULL, -1);
+-
+- g_return_val_if_fail(slpcall->xfer_msg != NULL, -1);
+-
+- slpcall->u.outgoing.len = len;
+- slpcall->u.outgoing.data = data;
+- msn_slplink_send_msgpart(slpcall->slplink, slpcall->xfer_msg);
+-
+- return MIN(MSN_SBCONN_MAX_SIZE, len);
+-}
+-
+-gssize
+-msn_xfer_read(guchar **data, PurpleXfer *xfer)
+-{
+- MsnSlpCall *slpcall;
+- gsize len;
+-
+- g_return_val_if_fail(xfer != NULL, -1);
+- g_return_val_if_fail(data != NULL, -1);
+-
+- g_return_val_if_fail(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE, -1);
+-
+- slpcall = xfer->data;
+- /* Not sure I trust it'll be there */
+- g_return_val_if_fail(slpcall != NULL, -1);
+-
+- /* Just pass up the whole GByteArray. We'll make another. */
+- *data = slpcall->u.incoming_data->data;
+- len = slpcall->u.incoming_data->len;
+-
+- g_byte_array_free(slpcall->u.incoming_data, FALSE);
+- slpcall->u.incoming_data = g_byte_array_new();
+-
+- return len;
+-}
+-
+-void
+-msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session)
+-{
+- if ((purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_DONE) &&
+- (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_REMOTE) &&
+- (purple_xfer_get_status(slpcall->xfer) != PURPLE_XFER_STATUS_CANCEL_LOCAL))
+- {
+- purple_xfer_cancel_remote(slpcall->xfer);
+- }
+-}
+-
+-void
+-msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body,
+- gsize size)
+-{
+- PurpleXfer *xfer = slpcall->xfer;
+-
+- purple_xfer_set_completed(xfer, TRUE);
+- purple_xfer_end(xfer);
+-}
+-
+-gchar *
+-msn_file_context_to_wire(MsnFileContext *context)
+-{
+- gchar *ret, *tmp;
+-
+- tmp = ret = g_new(gchar, MSN_FILE_CONTEXT_SIZE + context->preview_len + 1);
+-
+- msn_push32le(tmp, context->length);
+- msn_push32le(tmp, context->version);
+- msn_push64le(tmp, context->file_size);
+- msn_push32le(tmp, context->type);
+- memcpy(tmp, context->file_name, MAX_FILE_NAME_LEN * 2);
+- tmp += MAX_FILE_NAME_LEN * 2;
+- memcpy(tmp, context->unknown1, sizeof(context->unknown1));
+- tmp += sizeof(context->unknown1);
+- msn_push32le(tmp, context->unknown2);
+- if (context->preview) {
+- memcpy(tmp, context->preview, context->preview_len);
+- }
+- tmp[context->preview_len] = '\0';
+-
+- return ret;
+-}
+-
+-MsnFileContext *
+-msn_file_context_from_wire(const char *buf, gsize len)
+-{
+- MsnFileContext *context;
+-
+- if (!buf || len < MSN_FILE_CONTEXT_SIZE)
+- return NULL;
+-
+- context = g_new(MsnFileContext, 1);
+-
+- context->length = msn_pop32le(buf);
+- context->version = msn_pop32le(buf);
+- if (context->version == 2) {
+- /* The length field is broken for this version. No check. */
+- context->length = MSN_FILE_CONTEXT_SIZE;
+- } else if (context->version == 3) {
+- if (context->length != MSN_FILE_CONTEXT_SIZE + 63) {
+- g_free(context);
+- return NULL;
+- } else if (len < MSN_FILE_CONTEXT_SIZE + 63) {
+- g_free(context);
+- return NULL;
+- }
+- } else {
+- purple_debug_warning("msn", "Received MsnFileContext with unknown version: %d\n", context->version);
+- g_free(context);
+- return NULL;
+- }
+-
+- context->file_size = msn_pop64le(buf);
+- context->type = msn_pop32le(buf);
+- memcpy(context->file_name, buf, MAX_FILE_NAME_LEN * 2);
+- buf += MAX_FILE_NAME_LEN * 2;
+- memcpy(context->unknown1, buf, sizeof(context->unknown1));
+- buf += sizeof(context->unknown1);
+- context->unknown2 = msn_pop32le(buf);
+-
+- if (context->type == 0 && len > context->length) {
+- context->preview_len = len - context->length;
+- context->preview = g_memdup(buf, context->preview_len);
+- } else {
+- context->preview_len = 0;
+- context->preview = NULL;
+- }
+-
+- return context;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/msn/xfer.h pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.h
+--- pidgin-2.10.7/libpurple/protocols/msn/xfer.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/msn/xfer.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,67 +0,0 @@
+-/**
+- * @file xfer.h MSN File Transfer functions
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef MSN_XFER_H
+-#define MSN_XFER_H
+-
+-#include "slpcall.h"
+-
+-#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
+-
+-/**
+- * The context data for a file transfer request
+- */
+-typedef struct
+-{
+- guint32 length; /*< Length of header */
+- guint32 version; /*< MSN version */
+- guint64 file_size; /*< Size of file */
+- guint32 type; /*< Transfer type */
+- gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
+- gchar unknown1[30]; /*< Used somehow for background sharing */
+- guint32 unknown2; /*< Possibly for background sharing as well */
+- gchar *preview; /*< File preview data, 96x96 PNG */
+- gsize preview_len;
+-} MsnFileContext;
+-
+-#define MSN_FILE_CONTEXT_SIZE (4*4 + 1*8 + 2*MAX_FILE_NAME_LEN + 30)
+-
+-void msn_xfer_init(PurpleXfer *xfer);
+-void msn_xfer_cancel(PurpleXfer *xfer);
+-
+-gssize msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer);
+-gssize msn_xfer_read(guchar **data, PurpleXfer *xfer);
+-
+-void msn_xfer_completed_cb(MsnSlpCall *slpcall,
+- const guchar *body, gsize size);
+-void msn_xfer_end_cb(MsnSlpCall *slpcall, MsnSession *session);
+-
+-gchar *
+-msn_file_context_to_wire(MsnFileContext *context);
+-
+-MsnFileContext *
+-msn_file_context_from_wire(const char *buf, gsize len);
+-
+-#endif /* MSN_XFER_H */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/actions.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/actions.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,544 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- handle MXit plugin actions --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "roster.h"
+-#include "actions.h"
+-#include "splashscreen.h"
+-#include "cipher.h"
+-#include "profile.h"
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has selected to change their profile.
+- *
+- * @param gc The connection object
+- * @param fields The fields from the request pop-up
+- */
+-static void mxit_profile_cb( PurpleConnection* gc, PurpleRequestFields* fields )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleRequestField* field = NULL;
+- const char* name = NULL;
+- const char* bday = NULL;
+- const char* err = NULL;
+- GList* entry = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_cb\n" );
+-
+- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Unable to update profile; account offline.\n" );
+- return;
+- }
+-
+- /* validate name */
+- name = purple_request_fields_get_string( fields, "name" );
+- if ( ( !name ) || ( strlen( name ) < 3 ) ) {
+- err = _( "The Display Name you entered is invalid." );
+- goto out;
+- }
+-
+- /* validate birthdate */
+- bday = purple_request_fields_get_string( fields, "bday" );
+- if ( ( !bday ) || ( strlen( bday ) < 10 ) || ( !validateDate( bday ) ) ) {
+- err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
+- goto out;
+- }
+-
+-out:
+- if ( !err ) {
+- struct MXitProfile* profile = session->profile;
+- GString* attributes = g_string_sized_new( 128 );
+- char attrib[512];
+- unsigned int acount = 0;
+-
+-
+- /* update name */
+- g_strlcpy( profile->nickname, name, sizeof( profile->nickname ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FULLNAME, CP_PROFILE_TYPE_UTF8, profile->nickname );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update birthday */
+- g_strlcpy( profile->birthday, bday, sizeof( profile->birthday ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_BIRTHDATE, CP_PROFILE_TYPE_UTF8, profile->birthday );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update gender */
+- profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_GENDER, CP_PROFILE_TYPE_BOOL, ( profile->male ) ? "1" : "0" );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update title */
+- name = purple_request_fields_get_string( fields, "title" );
+- if ( !name )
+- profile->title[0] = '\0';
+- else
+- g_strlcpy( profile->title, name, sizeof( profile->title ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_TITLE, CP_PROFILE_TYPE_UTF8, profile->title );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update firstname */
+- name = purple_request_fields_get_string( fields, "firstname" );
+- if ( !name )
+- profile->firstname[0] = '\0';
+- else
+- g_strlcpy( profile->firstname, name, sizeof( profile->firstname ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_FIRSTNAME, CP_PROFILE_TYPE_UTF8, profile->firstname );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update lastname */
+- name = purple_request_fields_get_string( fields, "lastname" );
+- if ( !name )
+- profile->lastname[0] = '\0';
+- else
+- g_strlcpy( profile->lastname, name, sizeof( profile->lastname ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_LASTNAME, CP_PROFILE_TYPE_UTF8, profile->lastname );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update email address */
+- name = purple_request_fields_get_string( fields, "email" );
+- if ( !name )
+- profile->email[0] = '\0';
+- else
+- g_strlcpy( profile->email, name, sizeof( profile->email ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_EMAIL, CP_PROFILE_TYPE_UTF8, profile->email );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update mobile number */
+- name = purple_request_fields_get_string( fields, "mobilenumber" );
+- if ( !name )
+- profile->mobilenr[0] = '\0';
+- else
+- g_strlcpy( profile->mobilenr, name, sizeof( profile->mobilenr ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_MOBILENR, CP_PROFILE_TYPE_UTF8, profile->mobilenr );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update about me */
+- name = purple_request_fields_get_string( fields, "aboutme" );
+- if ( !name )
+- profile->aboutme[0] = '\0';
+- else
+- g_strlcpy( profile->aboutme, name, sizeof( profile->aboutme ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_ABOUTME, CP_PROFILE_TYPE_UTF8, profile->aboutme );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update where am i */
+- name = purple_request_fields_get_string( fields, "whereami" );
+- if ( !name)
+- profile->whereami[0] = '\0';
+- else
+- g_strlcpy( profile->whereami, name, sizeof( profile->whereami ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%s", CP_PROFILE_WHEREAMI, CP_PROFILE_TYPE_UTF8, profile->whereami );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* relationship status */
+- field = purple_request_fields_get_field( fields, "relationship" );
+- entry = g_list_first( purple_request_field_list_get_selected( field ) );
+- profile->relationship = atoi( purple_request_field_list_get_data( field, entry->data ) );
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_RELATIONSHIP, CP_PROFILE_TYPE_SHORT, profile->relationship );
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* update flags */
+- field = purple_request_fields_get_field( fields, "searchable" );
+- if ( purple_request_field_bool_get_value( field ) ) /* is searchable -> clear not-searchable flag */
+- profile->flags &= ~CP_PROF_NOT_SEARCHABLE;
+- else
+- profile->flags |= CP_PROF_NOT_SEARCHABLE;
+- field = purple_request_fields_get_field( fields, "suggestable" );
+- if ( purple_request_field_bool_get_value( field ) ) /* is suggestable -> clear not-suggestable flag */
+- profile->flags &= ~CP_PROF_NOT_SUGGESTABLE;
+- else
+- profile->flags |= CP_PROF_NOT_SUGGESTABLE;
+- g_snprintf( attrib, sizeof( attrib ), "\01%s\01%i\01%i", CP_PROFILE_FLAGS, CP_PROFILE_TYPE_LONG, profile->flags);
+- g_string_append( attributes, attrib );
+- acount++;
+-
+- /* send the profile update to MXit */
+- mxit_send_extprofile_update( session, NULL, acount, attributes->str );
+- g_string_free( attributes, TRUE );
+- }
+- else {
+- /* show error to user */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Profile Update Error" ), err );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display and update the user's profile.
+- *
+- * @param action The action object
+- */
+-static void mxit_profile_action( PurplePluginAction* action )
+-{
+- PurpleConnection* gc = (PurpleConnection*) action->context;
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- struct MXitProfile* profile = session->profile;
+-
+- PurpleRequestFields* fields = NULL;
+- PurpleRequestField* field = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_profile_action\n" );
+-
+- /* ensure that we actually have the user's profile information */
+- if ( !profile ) {
+- /* no profile information yet, so we cannot update */
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile" ), _( "Your profile information is not yet retrieved. Please try again later." ) );
+- return;
+- }
+-
+- fields = purple_request_fields_new();
+-
+- /* Public information - what other users can see */
+- {
+- PurpleRequestFieldGroup* public_group = purple_request_field_group_new( "Public information" );
+-
+- /* display name */
+- field = purple_request_field_string_new( "name", _( "Display Name" ), profile->nickname, FALSE );
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* birthday */
+- field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
+- purple_request_field_group_add_field( public_group, field );
+- if ( profile->flags & CP_PROF_DOBLOCKED )
+- purple_request_field_string_set_editable( field, FALSE );
+-
+- /* gender */
+- field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
+- purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */
+- purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* first name */
+- field = purple_request_field_string_new( "firstname", _( "First Name" ), profile->firstname, FALSE );
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* last name */
+- field = purple_request_field_string_new( "lastname", _( "Last Name" ), profile->lastname, FALSE );
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* about me */
+- field = purple_request_field_string_new( "aboutme", _( "About Me" ), profile->aboutme, FALSE);
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* where I live */
+- field = purple_request_field_string_new( "whereami", _( "Where I Live" ), profile->whereami, FALSE);
+- purple_request_field_group_add_field( public_group, field );
+-
+- /* relationship status */
+- field = purple_request_field_list_new( "relationship", _( "Relationship Status" ) );
+- purple_request_field_list_set_multi_select( field, FALSE );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_UNKNOWN ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_UNKNOWN ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DONTSAY ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DONTSAY ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SINGLE ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SINGLE ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_INVOLVED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_INVOLVED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_ENGAGED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_ENGAGED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_MARRIED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_MARRIED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_COMPLICATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_COMPLICATED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_WIDOWED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_WIDOWED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_SEPARATED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_SEPARATED ) );
+- purple_request_field_list_add_icon( field, mxit_relationship_to_name( MXIT_RELATIONSHIP_DIVORCED ), NULL, g_strdup_printf( "%i", MXIT_RELATIONSHIP_DIVORCED ) );
+- purple_request_field_list_add_selected( field, mxit_relationship_to_name( profile->relationship ) );
+- purple_request_field_group_add_field( public_group, field );
+-
+- purple_request_fields_add_group( fields, public_group );
+- }
+-
+- /* Private information - what only MXit can see */
+- {
+- PurpleRequestFieldGroup* private_group = purple_request_field_group_new( "Private information" );
+-
+- /* title */
+- field = purple_request_field_string_new( "title", _( "Title" ), profile->title, FALSE );
+- purple_request_field_group_add_field( private_group, field );
+-
+- /* email */
+- field = purple_request_field_string_new( "email", _( "Email" ), profile->email, FALSE );
+- purple_request_field_group_add_field( private_group, field );
+-
+- /* mobile number */
+- field = purple_request_field_string_new( "mobilenumber", _( "Mobile Number" ), profile->mobilenr, FALSE );
+- purple_request_field_group_add_field( private_group, field );
+-
+- /* is searchable */
+- field = purple_request_field_bool_new( "searchable", _( "Can be searched" ), ( ( profile->flags & CP_PROF_NOT_SEARCHABLE ) == 0) );
+- purple_request_field_group_add_field( private_group, field );
+-
+- /* is suggestable */
+- field = purple_request_field_bool_new( "suggestable", _( "Can be suggested" ), ( ( profile->flags & CP_PROF_NOT_SUGGESTABLE ) == 0 ) );
+- purple_request_field_group_add_field( private_group, field );
+-
+- purple_request_fields_add_group( fields, private_group );
+- }
+-
+- /* (reference: "libpurple/request.h") */
+- purple_request_fields( gc, _( "Profile" ), _( "Update your MXit Profile" ), NULL, fields, _( "Set" ),
+- G_CALLBACK( mxit_profile_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has selected to change their PIN.
+- *
+- * @param gc The connection object
+- * @param fields The fields from the request pop-up
+- */
+-static void mxit_change_pin_cb( PurpleConnection* gc, PurpleRequestFields* fields )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const char* pin = NULL;
+- const char* pin2 = NULL;
+- const char* err = NULL;
+- int len;
+- int i;
+-
+- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Unable to update PIN; account offline.\n" );
+- return;
+- }
+-
+- /* validate pin */
+- pin = purple_request_fields_get_string( fields, "pin" );
+- if ( !pin ) {
+- err = _( "The PIN you entered is invalid." );
+- goto out;
+- }
+- len = strlen( pin );
+- if ( ( len < 4 ) || ( len > 10 ) ) {
+- err = _( "The PIN you entered has an invalid length [4-10]." );
+- goto out;
+- }
+- for ( i = 0; i < len; i++ ) {
+- if ( !g_ascii_isdigit( pin[i] ) ) {
+- err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
+- goto out;
+- }
+- }
+- pin2 = purple_request_fields_get_string( fields, "pin2" );
+- if ( ( !pin2 ) || ( strcmp( pin, pin2 ) != 0 ) ) {
+- err = _( "The two PINs you entered do not match." );
+- goto out;
+- }
+-
+-out:
+- if ( !err ) {
+- /* update PIN in account */
+- purple_account_set_password( session->acc, pin );
+-
+- /* update session object */
+- g_free( session->encpwd );
+- session->encpwd = mxit_encrypt_password( session );
+-
+- /* send the update request to MXit */
+- mxit_send_extprofile_update( session, session->encpwd, 0, NULL );
+- }
+- else {
+- /* show error to user */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "PIN Update Error" ), err );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Enable the user to change their PIN.
+- *
+- * @param action The action object
+- */
+-static void mxit_change_pin_action( PurplePluginAction* action )
+-{
+- PurpleConnection* gc = (PurpleConnection*) action->context;
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- PurpleRequestFields* fields = NULL;
+- PurpleRequestFieldGroup* group = NULL;
+- PurpleRequestField* field = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_change_pin_action\n" );
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- /* pin */
+- field = purple_request_field_string_new( "pin", _( "PIN" ), session->acc->password, FALSE );
+- purple_request_field_string_set_masked( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* verify pin */
+- field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), session->acc->password, FALSE );
+- purple_request_field_string_set_masked( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* (reference: "libpurple/request.h") */
+- purple_request_fields( gc, _( "Change PIN" ), _( "Change MXit PIN" ), NULL, fields, _( "Set" ),
+- G_CALLBACK( mxit_change_pin_cb ), _( "Cancel" ), NULL, purple_connection_get_account( gc ), NULL, NULL, gc );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the current splash-screen, or a notification pop-up if one is not available.
+- *
+- * @param action The action object
+- */
+-static void mxit_splash_action( PurplePluginAction* action )
+-{
+- PurpleConnection* gc = (PurpleConnection*) action->context;
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- if ( splash_current( session ) != NULL )
+- splash_display( session );
+- else
+- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "View Splash" ), _( "There is no splash-screen currently available" ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display info about the plugin.
+- *
+- * @param action The action object
+- */
+-static void mxit_about_action( PurplePluginAction* action )
+-{
+- char version[256];
+-
+- g_snprintf( version, sizeof( version ),
+- "MXit Client Protocol v%i.%i\n\n"
+- "Author:\nPieter Loubser\n\n"
+- "Contributors:\nAndrew Victor\n\n"
+- "Testers:\nBraeme Le Roux\n\n",
+- ( MXIT_CP_PROTO_VESION / 10 ), ( MXIT_CP_PROTO_VESION % 10 ) );
+-
+- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "About" ), version );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Request list of suggested friends.
+- *
+- * @param action The action object
+- */
+-static void mxit_suggested_friends_action( PurplePluginAction* action )
+-{
+- PurpleConnection* gc = (PurpleConnection*) action->context;
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const char* profilelist[] = {
+- CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
+- CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
+- CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
+-
+- mxit_send_suggest_friends( session, MXIT_SEARCHRESULTS_MAX, ARRAY_SIZE( profilelist ), profilelist );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Perform contact search.
+- *
+- * @param action The action object
+- */
+-static void mxit_user_search_cb( PurpleConnection *gc, const char *input )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const char* profilelist[] = {
+- CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME, CP_PROFILE_FIRSTNAME,
+- CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_STATUS, CP_PROFILE_AVATAR,
+- CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME };
+-
+- mxit_send_suggest_search( session, MXIT_SEARCHRESULTS_MAX, input, ARRAY_SIZE( profilelist ), profilelist );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the search input form.
+- *
+- * @param action The action object
+- */
+-static void mxit_user_search_action( PurplePluginAction* action )
+-{
+- PurpleConnection* gc = (PurpleConnection*) action->context;
+-
+- purple_request_input( gc, _( "Search for user" ),
+- _( "Search for a MXit contact" ),
+- _( "Type search information" ),
+- NULL, FALSE, FALSE, NULL,
+- _("_Search"), G_CALLBACK( mxit_user_search_cb ),
+- _("_Cancel"), NULL,
+- purple_connection_get_account( gc ), NULL, NULL,
+- gc);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Associate actions with the MXit plugin.
+- *
+- * @param plugin The MXit protocol plugin
+- * @param context The connection context (if available)
+- * @return The list of plugin actions
+- */
+-GList* mxit_actions( PurplePlugin* plugin, gpointer context )
+-{
+- PurplePluginAction* action = NULL;
+- GList* m = NULL;
+-
+- /* display / change profile */
+- action = purple_plugin_action_new( _( "Change Profile..." ), mxit_profile_action );
+- m = g_list_append( m, action );
+-
+- /* change PIN */
+- action = purple_plugin_action_new( _( "Change PIN..." ), mxit_change_pin_action );
+- m = g_list_append( m, action );
+-
+- /* suggested friends */
+- action = purple_plugin_action_new( _( "Suggested friends..." ), mxit_suggested_friends_action );
+- m = g_list_append( m, action );
+-
+- /* search for contacts */
+- action = purple_plugin_action_new( _( "Search for contacts..." ), mxit_user_search_action );
+- m = g_list_append( m, action );
+-
+- /* display splash-screen */
+- action = purple_plugin_action_new( _( "View Splash..." ), mxit_splash_action );
+- m = g_list_append( m, action );
+-
+- /* display plugin version */
+- action = purple_plugin_action_new( _( "About..." ), mxit_about_action );
+- m = g_list_append( m, action );
+-
+- return m;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/actions.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/actions.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/actions.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,34 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- handle MXit plugin actions --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_ACTIONS_H_
+-#define _MXIT_ACTIONS_H_
+-
+-
+-/* callbacks */
+-GList* mxit_actions( PurplePlugin* plugin, gpointer context );
+-
+-
+-#endif /* _MXIT_ACTIONS_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/aes.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/aes.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,405 +0,0 @@
+-
+-// advanced encryption standard
+-// author: karl malbrain, malbrain@yahoo.com
+-
+-/*
+-This work, including the source code, documentation
+-and related data, is placed into the public domain.
+-
+-The orginal author is Karl Malbrain.
+-
+-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+-RESULTING FROM THE USE, MODIFICATION, OR
+-REDISTRIBUTION OF THIS SOFTWARE.
+-*/
+-
+-#include <string.h>
+-#include <memory.h>
+-
+-#include "aes.h"
+-
+-// AES only supports Nb=4
+-#define Nb 4 // number of columns in the state & expanded key
+-
+-#define Nk 4 // number of columns in a key
+-#define Nr 10 // number of rounds in encryption
+-
+-static uchar Sbox[256] = { // forward s-box
+-0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b, 0xfe, 0xd7, 0xab, 0x76,
+-0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0, 0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0,
+-0xb7, 0xfd, 0x93, 0x26, 0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
+-0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2, 0xeb, 0x27, 0xb2, 0x75,
+-0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0, 0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84,
+-0x53, 0xd1, 0x00, 0xed, 0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
+-0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f, 0x50, 0x3c, 0x9f, 0xa8,
+-0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5, 0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2,
+-0xcd, 0x0c, 0x13, 0xec, 0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
+-0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14, 0xde, 0x5e, 0x0b, 0xdb,
+-0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c, 0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79,
+-0xe7, 0xc8, 0x37, 0x6d, 0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
+-0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f, 0x4b, 0xbd, 0x8b, 0x8a,
+-0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e, 0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e,
+-0xe1, 0xf8, 0x98, 0x11, 0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
+-0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f, 0xb0, 0x54, 0xbb, 0x16};
+-
+-static uchar InvSbox[256] = { // inverse s-box
+-0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e, 0x81, 0xf3, 0xd7, 0xfb,
+-0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87, 0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb,
+-0x54, 0x7b, 0x94, 0x32, 0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
+-0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49, 0x6d, 0x8b, 0xd1, 0x25,
+-0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92,
+-0x6c, 0x70, 0x48, 0x50, 0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
+-0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05, 0xb8, 0xb3, 0x45, 0x06,
+-0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02, 0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b,
+-0x3a, 0x91, 0x11, 0x41, 0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
+-0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8, 0x1c, 0x75, 0xdf, 0x6e,
+-0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89, 0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b,
+-0xfc, 0x56, 0x3e, 0x4b, 0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
+-0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xec, 0x5f,
+-0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d, 0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef,
+-0xa0, 0xe0, 0x3b, 0x4d, 0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
+-0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0c, 0x7d};
+-
+-// combined Xtimes2[Sbox[]]
+-static uchar Xtime2Sbox[256] = {
+-0xc6, 0xf8, 0xee, 0xf6, 0xff, 0xd6, 0xde, 0x91, 0x60, 0x02, 0xce, 0x56, 0xe7, 0xb5, 0x4d, 0xec,
+-0x8f, 0x1f, 0x89, 0xfa, 0xef, 0xb2, 0x8e, 0xfb, 0x41, 0xb3, 0x5f, 0x45, 0x23, 0x53, 0xe4, 0x9b,
+-0x75, 0xe1, 0x3d, 0x4c, 0x6c, 0x7e, 0xf5, 0x83, 0x68, 0x51, 0xd1, 0xf9, 0xe2, 0xab, 0x62, 0x2a,
+-0x08, 0x95, 0x46, 0x9d, 0x30, 0x37, 0x0a, 0x2f, 0x0e, 0x24, 0x1b, 0xdf, 0xcd, 0x4e, 0x7f, 0xea,
+-0x12, 0x1d, 0x58, 0x34, 0x36, 0xdc, 0xb4, 0x5b, 0xa4, 0x76, 0xb7, 0x7d, 0x52, 0xdd, 0x5e, 0x13,
+-0xa6, 0xb9, 0x00, 0xc1, 0x40, 0xe3, 0x79, 0xb6, 0xd4, 0x8d, 0x67, 0x72, 0x94, 0x98, 0xb0, 0x85,
+-0xbb, 0xc5, 0x4f, 0xed, 0x86, 0x9a, 0x66, 0x11, 0x8a, 0xe9, 0x04, 0xfe, 0xa0, 0x78, 0x25, 0x4b,
+-0xa2, 0x5d, 0x80, 0x05, 0x3f, 0x21, 0x70, 0xf1, 0x63, 0x77, 0xaf, 0x42, 0x20, 0xe5, 0xfd, 0xbf,
+-0x81, 0x18, 0x26, 0xc3, 0xbe, 0x35, 0x88, 0x2e, 0x93, 0x55, 0xfc, 0x7a, 0xc8, 0xba, 0x32, 0xe6,
+-0xc0, 0x19, 0x9e, 0xa3, 0x44, 0x54, 0x3b, 0x0b, 0x8c, 0xc7, 0x6b, 0x28, 0xa7, 0xbc, 0x16, 0xad,
+-0xdb, 0x64, 0x74, 0x14, 0x92, 0x0c, 0x48, 0xb8, 0x9f, 0xbd, 0x43, 0xc4, 0x39, 0x31, 0xd3, 0xf2,
+-0xd5, 0x8b, 0x6e, 0xda, 0x01, 0xb1, 0x9c, 0x49, 0xd8, 0xac, 0xf3, 0xcf, 0xca, 0xf4, 0x47, 0x10,
+-0x6f, 0xf0, 0x4a, 0x5c, 0x38, 0x57, 0x73, 0x97, 0xcb, 0xa1, 0xe8, 0x3e, 0x96, 0x61, 0x0d, 0x0f,
+-0xe0, 0x7c, 0x71, 0xcc, 0x90, 0x06, 0xf7, 0x1c, 0xc2, 0x6a, 0xae, 0x69, 0x17, 0x99, 0x3a, 0x27,
+-0xd9, 0xeb, 0x2b, 0x22, 0xd2, 0xa9, 0x07, 0x33, 0x2d, 0x3c, 0x15, 0xc9, 0x87, 0xaa, 0x50, 0xa5,
+-0x03, 0x59, 0x09, 0x1a, 0x65, 0xd7, 0x84, 0xd0, 0x82, 0x29, 0x5a, 0x1e, 0x7b, 0xa8, 0x6d, 0x2c
+-};
+-
+-// combined Xtimes3[Sbox[]]
+-static uchar Xtime3Sbox[256] = {
+-0xa5, 0x84, 0x99, 0x8d, 0x0d, 0xbd, 0xb1, 0x54, 0x50, 0x03, 0xa9, 0x7d, 0x19, 0x62, 0xe6, 0x9a,
+-0x45, 0x9d, 0x40, 0x87, 0x15, 0xeb, 0xc9, 0x0b, 0xec, 0x67, 0xfd, 0xea, 0xbf, 0xf7, 0x96, 0x5b,
+-0xc2, 0x1c, 0xae, 0x6a, 0x5a, 0x41, 0x02, 0x4f, 0x5c, 0xf4, 0x34, 0x08, 0x93, 0x73, 0x53, 0x3f,
+-0x0c, 0x52, 0x65, 0x5e, 0x28, 0xa1, 0x0f, 0xb5, 0x09, 0x36, 0x9b, 0x3d, 0x26, 0x69, 0xcd, 0x9f,
+-0x1b, 0x9e, 0x74, 0x2e, 0x2d, 0xb2, 0xee, 0xfb, 0xf6, 0x4d, 0x61, 0xce, 0x7b, 0x3e, 0x71, 0x97,
+-0xf5, 0x68, 0x00, 0x2c, 0x60, 0x1f, 0xc8, 0xed, 0xbe, 0x46, 0xd9, 0x4b, 0xde, 0xd4, 0xe8, 0x4a,
+-0x6b, 0x2a, 0xe5, 0x16, 0xc5, 0xd7, 0x55, 0x94, 0xcf, 0x10, 0x06, 0x81, 0xf0, 0x44, 0xba, 0xe3,
+-0xf3, 0xfe, 0xc0, 0x8a, 0xad, 0xbc, 0x48, 0x04, 0xdf, 0xc1, 0x75, 0x63, 0x30, 0x1a, 0x0e, 0x6d,
+-0x4c, 0x14, 0x35, 0x2f, 0xe1, 0xa2, 0xcc, 0x39, 0x57, 0xf2, 0x82, 0x47, 0xac, 0xe7, 0x2b, 0x95,
+-0xa0, 0x98, 0xd1, 0x7f, 0x66, 0x7e, 0xab, 0x83, 0xca, 0x29, 0xd3, 0x3c, 0x79, 0xe2, 0x1d, 0x76,
+-0x3b, 0x56, 0x4e, 0x1e, 0xdb, 0x0a, 0x6c, 0xe4, 0x5d, 0x6e, 0xef, 0xa6, 0xa8, 0xa4, 0x37, 0x8b,
+-0x32, 0x43, 0x59, 0xb7, 0x8c, 0x64, 0xd2, 0xe0, 0xb4, 0xfa, 0x07, 0x25, 0xaf, 0x8e, 0xe9, 0x18,
+-0xd5, 0x88, 0x6f, 0x72, 0x24, 0xf1, 0xc7, 0x51, 0x23, 0x7c, 0x9c, 0x21, 0xdd, 0xdc, 0x86, 0x85,
+-0x90, 0x42, 0xc4, 0xaa, 0xd8, 0x05, 0x01, 0x12, 0xa3, 0x5f, 0xf9, 0xd0, 0x91, 0x58, 0x27, 0xb9,
+-0x38, 0x13, 0xb3, 0x33, 0xbb, 0x70, 0x89, 0xa7, 0xb6, 0x22, 0x92, 0x20, 0x49, 0xff, 0x78, 0x7a,
+-0x8f, 0xf8, 0x80, 0x17, 0xda, 0x31, 0xc6, 0xb8, 0xc3, 0xb0, 0x77, 0x11, 0xcb, 0xfc, 0xd6, 0x3a
+-};
+-
+-// modular multiplication tables
+-// based on:
+-
+-// Xtime2[x] = (x & 0x80 ? 0x1b : 0) ^ (x + x)
+-// Xtime3[x] = x^Xtime2[x];
+-
+-#if 0
+-static uchar Xtime2[256] = {
+-0x00, 0x02, 0x04, 0x06, 0x08, 0x0a, 0x0c, 0x0e, 0x10, 0x12, 0x14, 0x16, 0x18, 0x1a, 0x1c, 0x1e,
+-0x20, 0x22, 0x24, 0x26, 0x28, 0x2a, 0x2c, 0x2e, 0x30, 0x32, 0x34, 0x36, 0x38, 0x3a, 0x3c, 0x3e,
+-0x40, 0x42, 0x44, 0x46, 0x48, 0x4a, 0x4c, 0x4e, 0x50, 0x52, 0x54, 0x56, 0x58, 0x5a, 0x5c, 0x5e,
+-0x60, 0x62, 0x64, 0x66, 0x68, 0x6a, 0x6c, 0x6e, 0x70, 0x72, 0x74, 0x76, 0x78, 0x7a, 0x7c, 0x7e,
+-0x80, 0x82, 0x84, 0x86, 0x88, 0x8a, 0x8c, 0x8e, 0x90, 0x92, 0x94, 0x96, 0x98, 0x9a, 0x9c, 0x9e,
+-0xa0, 0xa2, 0xa4, 0xa6, 0xa8, 0xaa, 0xac, 0xae, 0xb0, 0xb2, 0xb4, 0xb6, 0xb8, 0xba, 0xbc, 0xbe,
+-0xc0, 0xc2, 0xc4, 0xc6, 0xc8, 0xca, 0xcc, 0xce, 0xd0, 0xd2, 0xd4, 0xd6, 0xd8, 0xda, 0xdc, 0xde,
+-0xe0, 0xe2, 0xe4, 0xe6, 0xe8, 0xea, 0xec, 0xee, 0xf0, 0xf2, 0xf4, 0xf6, 0xf8, 0xfa, 0xfc, 0xfe,
+-0x1b, 0x19, 0x1f, 0x1d, 0x13, 0x11, 0x17, 0x15, 0x0b, 0x09, 0x0f, 0x0d, 0x03, 0x01, 0x07, 0x05,
+-0x3b, 0x39, 0x3f, 0x3d, 0x33, 0x31, 0x37, 0x35, 0x2b, 0x29, 0x2f, 0x2d, 0x23, 0x21, 0x27, 0x25,
+-0x5b, 0x59, 0x5f, 0x5d, 0x53, 0x51, 0x57, 0x55, 0x4b, 0x49, 0x4f, 0x4d, 0x43, 0x41, 0x47, 0x45,
+-0x7b, 0x79, 0x7f, 0x7d, 0x73, 0x71, 0x77, 0x75, 0x6b, 0x69, 0x6f, 0x6d, 0x63, 0x61, 0x67, 0x65,
+-0x9b, 0x99, 0x9f, 0x9d, 0x93, 0x91, 0x97, 0x95, 0x8b, 0x89, 0x8f, 0x8d, 0x83, 0x81, 0x87, 0x85,
+-0xbb, 0xb9, 0xbf, 0xbd, 0xb3, 0xb1, 0xb7, 0xb5, 0xab, 0xa9, 0xaf, 0xad, 0xa3, 0xa1, 0xa7, 0xa5,
+-0xdb, 0xd9, 0xdf, 0xdd, 0xd3, 0xd1, 0xd7, 0xd5, 0xcb, 0xc9, 0xcf, 0xcd, 0xc3, 0xc1, 0xc7, 0xc5,
+-0xfb, 0xf9, 0xff, 0xfd, 0xf3, 0xf1, 0xf7, 0xf5, 0xeb, 0xe9, 0xef, 0xed, 0xe3, 0xe1, 0xe7, 0xe5};
+-#endif
+-
+-static uchar Xtime9[256] = {
+-0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f, 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+-0x90, 0x99, 0x82, 0x8b, 0xb4, 0xbd, 0xa6, 0xaf, 0xd8, 0xd1, 0xca, 0xc3, 0xfc, 0xf5, 0xee, 0xe7,
+-0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04, 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+-0xab, 0xa2, 0xb9, 0xb0, 0x8f, 0x86, 0x9d, 0x94, 0xe3, 0xea, 0xf1, 0xf8, 0xc7, 0xce, 0xd5, 0xdc,
+-0x76, 0x7f, 0x64, 0x6d, 0x52, 0x5b, 0x40, 0x49, 0x3e, 0x37, 0x2c, 0x25, 0x1a, 0x13, 0x08, 0x01,
+-0xe6, 0xef, 0xf4, 0xfd, 0xc2, 0xcb, 0xd0, 0xd9, 0xae, 0xa7, 0xbc, 0xb5, 0x8a, 0x83, 0x98, 0x91,
+-0x4d, 0x44, 0x5f, 0x56, 0x69, 0x60, 0x7b, 0x72, 0x05, 0x0c, 0x17, 0x1e, 0x21, 0x28, 0x33, 0x3a,
+-0xdd, 0xd4, 0xcf, 0xc6, 0xf9, 0xf0, 0xeb, 0xe2, 0x95, 0x9c, 0x87, 0x8e, 0xb1, 0xb8, 0xa3, 0xaa,
+-0xec, 0xe5, 0xfe, 0xf7, 0xc8, 0xc1, 0xda, 0xd3, 0xa4, 0xad, 0xb6, 0xbf, 0x80, 0x89, 0x92, 0x9b,
+-0x7c, 0x75, 0x6e, 0x67, 0x58, 0x51, 0x4a, 0x43, 0x34, 0x3d, 0x26, 0x2f, 0x10, 0x19, 0x02, 0x0b,
+-0xd7, 0xde, 0xc5, 0xcc, 0xf3, 0xfa, 0xe1, 0xe8, 0x9f, 0x96, 0x8d, 0x84, 0xbb, 0xb2, 0xa9, 0xa0,
+-0x47, 0x4e, 0x55, 0x5c, 0x63, 0x6a, 0x71, 0x78, 0x0f, 0x06, 0x1d, 0x14, 0x2b, 0x22, 0x39, 0x30,
+-0x9a, 0x93, 0x88, 0x81, 0xbe, 0xb7, 0xac, 0xa5, 0xd2, 0xdb, 0xc0, 0xc9, 0xf6, 0xff, 0xe4, 0xed,
+-0x0a, 0x03, 0x18, 0x11, 0x2e, 0x27, 0x3c, 0x35, 0x42, 0x4b, 0x50, 0x59, 0x66, 0x6f, 0x74, 0x7d,
+-0xa1, 0xa8, 0xb3, 0xba, 0x85, 0x8c, 0x97, 0x9e, 0xe9, 0xe0, 0xfb, 0xf2, 0xcd, 0xc4, 0xdf, 0xd6,
+-0x31, 0x38, 0x23, 0x2a, 0x15, 0x1c, 0x07, 0x0e, 0x79, 0x70, 0x6b, 0x62, 0x5d, 0x54, 0x4f, 0x46};
+-
+-static uchar XtimeB[256] = {
+-0x00, 0x0b, 0x16, 0x1d, 0x2c, 0x27, 0x3a, 0x31, 0x58, 0x53, 0x4e, 0x45, 0x74, 0x7f, 0x62, 0x69,
+-0xb0, 0xbb, 0xa6, 0xad, 0x9c, 0x97, 0x8a, 0x81, 0xe8, 0xe3, 0xfe, 0xf5, 0xc4, 0xcf, 0xd2, 0xd9,
+-0x7b, 0x70, 0x6d, 0x66, 0x57, 0x5c, 0x41, 0x4a, 0x23, 0x28, 0x35, 0x3e, 0x0f, 0x04, 0x19, 0x12,
+-0xcb, 0xc0, 0xdd, 0xd6, 0xe7, 0xec, 0xf1, 0xfa, 0x93, 0x98, 0x85, 0x8e, 0xbf, 0xb4, 0xa9, 0xa2,
+-0xf6, 0xfd, 0xe0, 0xeb, 0xda, 0xd1, 0xcc, 0xc7, 0xae, 0xa5, 0xb8, 0xb3, 0x82, 0x89, 0x94, 0x9f,
+-0x46, 0x4d, 0x50, 0x5b, 0x6a, 0x61, 0x7c, 0x77, 0x1e, 0x15, 0x08, 0x03, 0x32, 0x39, 0x24, 0x2f,
+-0x8d, 0x86, 0x9b, 0x90, 0xa1, 0xaa, 0xb7, 0xbc, 0xd5, 0xde, 0xc3, 0xc8, 0xf9, 0xf2, 0xef, 0xe4,
+-0x3d, 0x36, 0x2b, 0x20, 0x11, 0x1a, 0x07, 0x0c, 0x65, 0x6e, 0x73, 0x78, 0x49, 0x42, 0x5f, 0x54,
+-0xf7, 0xfc, 0xe1, 0xea, 0xdb, 0xd0, 0xcd, 0xc6, 0xaf, 0xa4, 0xb9, 0xb2, 0x83, 0x88, 0x95, 0x9e,
+-0x47, 0x4c, 0x51, 0x5a, 0x6b, 0x60, 0x7d, 0x76, 0x1f, 0x14, 0x09, 0x02, 0x33, 0x38, 0x25, 0x2e,
+-0x8c, 0x87, 0x9a, 0x91, 0xa0, 0xab, 0xb6, 0xbd, 0xd4, 0xdf, 0xc2, 0xc9, 0xf8, 0xf3, 0xee, 0xe5,
+-0x3c, 0x37, 0x2a, 0x21, 0x10, 0x1b, 0x06, 0x0d, 0x64, 0x6f, 0x72, 0x79, 0x48, 0x43, 0x5e, 0x55,
+-0x01, 0x0a, 0x17, 0x1c, 0x2d, 0x26, 0x3b, 0x30, 0x59, 0x52, 0x4f, 0x44, 0x75, 0x7e, 0x63, 0x68,
+-0xb1, 0xba, 0xa7, 0xac, 0x9d, 0x96, 0x8b, 0x80, 0xe9, 0xe2, 0xff, 0xf4, 0xc5, 0xce, 0xd3, 0xd8,
+-0x7a, 0x71, 0x6c, 0x67, 0x56, 0x5d, 0x40, 0x4b, 0x22, 0x29, 0x34, 0x3f, 0x0e, 0x05, 0x18, 0x13,
+-0xca, 0xc1, 0xdc, 0xd7, 0xe6, 0xed, 0xf0, 0xfb, 0x92, 0x99, 0x84, 0x8f, 0xbe, 0xb5, 0xa8, 0xa3};
+-
+-static uchar XtimeD[256] = {
+-0x00, 0x0d, 0x1a, 0x17, 0x34, 0x39, 0x2e, 0x23, 0x68, 0x65, 0x72, 0x7f, 0x5c, 0x51, 0x46, 0x4b,
+-0xd0, 0xdd, 0xca, 0xc7, 0xe4, 0xe9, 0xfe, 0xf3, 0xb8, 0xb5, 0xa2, 0xaf, 0x8c, 0x81, 0x96, 0x9b,
+-0xbb, 0xb6, 0xa1, 0xac, 0x8f, 0x82, 0x95, 0x98, 0xd3, 0xde, 0xc9, 0xc4, 0xe7, 0xea, 0xfd, 0xf0,
+-0x6b, 0x66, 0x71, 0x7c, 0x5f, 0x52, 0x45, 0x48, 0x03, 0x0e, 0x19, 0x14, 0x37, 0x3a, 0x2d, 0x20,
+-0x6d, 0x60, 0x77, 0x7a, 0x59, 0x54, 0x43, 0x4e, 0x05, 0x08, 0x1f, 0x12, 0x31, 0x3c, 0x2b, 0x26,
+-0xbd, 0xb0, 0xa7, 0xaa, 0x89, 0x84, 0x93, 0x9e, 0xd5, 0xd8, 0xcf, 0xc2, 0xe1, 0xec, 0xfb, 0xf6,
+-0xd6, 0xdb, 0xcc, 0xc1, 0xe2, 0xef, 0xf8, 0xf5, 0xbe, 0xb3, 0xa4, 0xa9, 0x8a, 0x87, 0x90, 0x9d,
+-0x06, 0x0b, 0x1c, 0x11, 0x32, 0x3f, 0x28, 0x25, 0x6e, 0x63, 0x74, 0x79, 0x5a, 0x57, 0x40, 0x4d,
+-0xda, 0xd7, 0xc0, 0xcd, 0xee, 0xe3, 0xf4, 0xf9, 0xb2, 0xbf, 0xa8, 0xa5, 0x86, 0x8b, 0x9c, 0x91,
+-0x0a, 0x07, 0x10, 0x1d, 0x3e, 0x33, 0x24, 0x29, 0x62, 0x6f, 0x78, 0x75, 0x56, 0x5b, 0x4c, 0x41,
+-0x61, 0x6c, 0x7b, 0x76, 0x55, 0x58, 0x4f, 0x42, 0x09, 0x04, 0x13, 0x1e, 0x3d, 0x30, 0x27, 0x2a,
+-0xb1, 0xbc, 0xab, 0xa6, 0x85, 0x88, 0x9f, 0x92, 0xd9, 0xd4, 0xc3, 0xce, 0xed, 0xe0, 0xf7, 0xfa,
+-0xb7, 0xba, 0xad, 0xa0, 0x83, 0x8e, 0x99, 0x94, 0xdf, 0xd2, 0xc5, 0xc8, 0xeb, 0xe6, 0xf1, 0xfc,
+-0x67, 0x6a, 0x7d, 0x70, 0x53, 0x5e, 0x49, 0x44, 0x0f, 0x02, 0x15, 0x18, 0x3b, 0x36, 0x21, 0x2c,
+-0x0c, 0x01, 0x16, 0x1b, 0x38, 0x35, 0x22, 0x2f, 0x64, 0x69, 0x7e, 0x73, 0x50, 0x5d, 0x4a, 0x47,
+-0xdc, 0xd1, 0xc6, 0xcb, 0xe8, 0xe5, 0xf2, 0xff, 0xb4, 0xb9, 0xae, 0xa3, 0x80, 0x8d, 0x9a, 0x97};
+-
+-static uchar XtimeE[256] = {
+-0x00, 0x0e, 0x1c, 0x12, 0x38, 0x36, 0x24, 0x2a, 0x70, 0x7e, 0x6c, 0x62, 0x48, 0x46, 0x54, 0x5a,
+-0xe0, 0xee, 0xfc, 0xf2, 0xd8, 0xd6, 0xc4, 0xca, 0x90, 0x9e, 0x8c, 0x82, 0xa8, 0xa6, 0xb4, 0xba,
+-0xdb, 0xd5, 0xc7, 0xc9, 0xe3, 0xed, 0xff, 0xf1, 0xab, 0xa5, 0xb7, 0xb9, 0x93, 0x9d, 0x8f, 0x81,
+-0x3b, 0x35, 0x27, 0x29, 0x03, 0x0d, 0x1f, 0x11, 0x4b, 0x45, 0x57, 0x59, 0x73, 0x7d, 0x6f, 0x61,
+-0xad, 0xa3, 0xb1, 0xbf, 0x95, 0x9b, 0x89, 0x87, 0xdd, 0xd3, 0xc1, 0xcf, 0xe5, 0xeb, 0xf9, 0xf7,
+-0x4d, 0x43, 0x51, 0x5f, 0x75, 0x7b, 0x69, 0x67, 0x3d, 0x33, 0x21, 0x2f, 0x05, 0x0b, 0x19, 0x17,
+-0x76, 0x78, 0x6a, 0x64, 0x4e, 0x40, 0x52, 0x5c, 0x06, 0x08, 0x1a, 0x14, 0x3e, 0x30, 0x22, 0x2c,
+-0x96, 0x98, 0x8a, 0x84, 0xae, 0xa0, 0xb2, 0xbc, 0xe6, 0xe8, 0xfa, 0xf4, 0xde, 0xd0, 0xc2, 0xcc,
+-0x41, 0x4f, 0x5d, 0x53, 0x79, 0x77, 0x65, 0x6b, 0x31, 0x3f, 0x2d, 0x23, 0x09, 0x07, 0x15, 0x1b,
+-0xa1, 0xaf, 0xbd, 0xb3, 0x99, 0x97, 0x85, 0x8b, 0xd1, 0xdf, 0xcd, 0xc3, 0xe9, 0xe7, 0xf5, 0xfb,
+-0x9a, 0x94, 0x86, 0x88, 0xa2, 0xac, 0xbe, 0xb0, 0xea, 0xe4, 0xf6, 0xf8, 0xd2, 0xdc, 0xce, 0xc0,
+-0x7a, 0x74, 0x66, 0x68, 0x42, 0x4c, 0x5e, 0x50, 0x0a, 0x04, 0x16, 0x18, 0x32, 0x3c, 0x2e, 0x20,
+-0xec, 0xe2, 0xf0, 0xfe, 0xd4, 0xda, 0xc8, 0xc6, 0x9c, 0x92, 0x80, 0x8e, 0xa4, 0xaa, 0xb8, 0xb6,
+-0x0c, 0x02, 0x10, 0x1e, 0x34, 0x3a, 0x28, 0x26, 0x7c, 0x72, 0x60, 0x6e, 0x44, 0x4a, 0x58, 0x56,
+-0x37, 0x39, 0x2b, 0x25, 0x0f, 0x01, 0x13, 0x1d, 0x47, 0x49, 0x5b, 0x55, 0x7f, 0x71, 0x63, 0x6d,
+-0xd7, 0xd9, 0xcb, 0xc5, 0xef, 0xe1, 0xf3, 0xfd, 0xa7, 0xa9, 0xbb, 0xb5, 0x9f, 0x91, 0x83, 0x8d};
+-
+-// exchanges columns in each of 4 rows
+-// row0 - unchanged, row1- shifted left 1,
+-// row2 - shifted left 2 and row3 - shifted left 3
+-static void ShiftRows (uchar *state)
+-{
+-uchar tmp;
+-
+- // just substitute row 0
+- state[0] = Sbox[state[0]], state[4] = Sbox[state[4]];
+- state[8] = Sbox[state[8]], state[12] = Sbox[state[12]];
+-
+- // rotate row 1
+- tmp = Sbox[state[1]], state[1] = Sbox[state[5]];
+- state[5] = Sbox[state[9]], state[9] = Sbox[state[13]], state[13] = tmp;
+-
+- // rotate row 2
+- tmp = Sbox[state[2]], state[2] = Sbox[state[10]], state[10] = tmp;
+- tmp = Sbox[state[6]], state[6] = Sbox[state[14]], state[14] = tmp;
+-
+- // rotate row 3
+- tmp = Sbox[state[15]], state[15] = Sbox[state[11]];
+- state[11] = Sbox[state[7]], state[7] = Sbox[state[3]], state[3] = tmp;
+-}
+-
+-// restores columns in each of 4 rows
+-// row0 - unchanged, row1- shifted right 1,
+-// row2 - shifted right 2 and row3 - shifted right 3
+-static void InvShiftRows (uchar *state)
+-{
+-uchar tmp;
+-
+- // restore row 0
+- state[0] = InvSbox[state[0]], state[4] = InvSbox[state[4]];
+- state[8] = InvSbox[state[8]], state[12] = InvSbox[state[12]];
+-
+- // restore row 1
+- tmp = InvSbox[state[13]], state[13] = InvSbox[state[9]];
+- state[9] = InvSbox[state[5]], state[5] = InvSbox[state[1]], state[1] = tmp;
+-
+- // restore row 2
+- tmp = InvSbox[state[2]], state[2] = InvSbox[state[10]], state[10] = tmp;
+- tmp = InvSbox[state[6]], state[6] = InvSbox[state[14]], state[14] = tmp;
+-
+- // restore row 3
+- tmp = InvSbox[state[3]], state[3] = InvSbox[state[7]];
+- state[7] = InvSbox[state[11]], state[11] = InvSbox[state[15]], state[15] = tmp;
+-}
+-
+-// recombine and mix each row in a column
+-static void MixSubColumns (uchar *state)
+-{
+-uchar tmp[4 * Nb];
+-
+- // mixing column 0
+- tmp[0] = Xtime2Sbox[state[0]] ^ Xtime3Sbox[state[5]] ^ Sbox[state[10]] ^ Sbox[state[15]];
+- tmp[1] = Sbox[state[0]] ^ Xtime2Sbox[state[5]] ^ Xtime3Sbox[state[10]] ^ Sbox[state[15]];
+- tmp[2] = Sbox[state[0]] ^ Sbox[state[5]] ^ Xtime2Sbox[state[10]] ^ Xtime3Sbox[state[15]];
+- tmp[3] = Xtime3Sbox[state[0]] ^ Sbox[state[5]] ^ Sbox[state[10]] ^ Xtime2Sbox[state[15]];
+-
+- // mixing column 1
+- tmp[4] = Xtime2Sbox[state[4]] ^ Xtime3Sbox[state[9]] ^ Sbox[state[14]] ^ Sbox[state[3]];
+- tmp[5] = Sbox[state[4]] ^ Xtime2Sbox[state[9]] ^ Xtime3Sbox[state[14]] ^ Sbox[state[3]];
+- tmp[6] = Sbox[state[4]] ^ Sbox[state[9]] ^ Xtime2Sbox[state[14]] ^ Xtime3Sbox[state[3]];
+- tmp[7] = Xtime3Sbox[state[4]] ^ Sbox[state[9]] ^ Sbox[state[14]] ^ Xtime2Sbox[state[3]];
+-
+- // mixing column 2
+- tmp[8] = Xtime2Sbox[state[8]] ^ Xtime3Sbox[state[13]] ^ Sbox[state[2]] ^ Sbox[state[7]];
+- tmp[9] = Sbox[state[8]] ^ Xtime2Sbox[state[13]] ^ Xtime3Sbox[state[2]] ^ Sbox[state[7]];
+- tmp[10] = Sbox[state[8]] ^ Sbox[state[13]] ^ Xtime2Sbox[state[2]] ^ Xtime3Sbox[state[7]];
+- tmp[11] = Xtime3Sbox[state[8]] ^ Sbox[state[13]] ^ Sbox[state[2]] ^ Xtime2Sbox[state[7]];
+-
+- // mixing column 3
+- tmp[12] = Xtime2Sbox[state[12]] ^ Xtime3Sbox[state[1]] ^ Sbox[state[6]] ^ Sbox[state[11]];
+- tmp[13] = Sbox[state[12]] ^ Xtime2Sbox[state[1]] ^ Xtime3Sbox[state[6]] ^ Sbox[state[11]];
+- tmp[14] = Sbox[state[12]] ^ Sbox[state[1]] ^ Xtime2Sbox[state[6]] ^ Xtime3Sbox[state[11]];
+- tmp[15] = Xtime3Sbox[state[12]] ^ Sbox[state[1]] ^ Sbox[state[6]] ^ Xtime2Sbox[state[11]];
+-
+- memcpy (state, tmp, sizeof(tmp));
+-}
+-
+-// restore and un-mix each row in a column
+-static void InvMixSubColumns (uchar *state)
+-{
+-uchar tmp[4 * Nb];
+-int i;
+-
+- // restore column 0
+- tmp[0] = XtimeE[state[0]] ^ XtimeB[state[1]] ^ XtimeD[state[2]] ^ Xtime9[state[3]];
+- tmp[5] = Xtime9[state[0]] ^ XtimeE[state[1]] ^ XtimeB[state[2]] ^ XtimeD[state[3]];
+- tmp[10] = XtimeD[state[0]] ^ Xtime9[state[1]] ^ XtimeE[state[2]] ^ XtimeB[state[3]];
+- tmp[15] = XtimeB[state[0]] ^ XtimeD[state[1]] ^ Xtime9[state[2]] ^ XtimeE[state[3]];
+-
+- // restore column 1
+- tmp[4] = XtimeE[state[4]] ^ XtimeB[state[5]] ^ XtimeD[state[6]] ^ Xtime9[state[7]];
+- tmp[9] = Xtime9[state[4]] ^ XtimeE[state[5]] ^ XtimeB[state[6]] ^ XtimeD[state[7]];
+- tmp[14] = XtimeD[state[4]] ^ Xtime9[state[5]] ^ XtimeE[state[6]] ^ XtimeB[state[7]];
+- tmp[3] = XtimeB[state[4]] ^ XtimeD[state[5]] ^ Xtime9[state[6]] ^ XtimeE[state[7]];
+-
+- // restore column 2
+- tmp[8] = XtimeE[state[8]] ^ XtimeB[state[9]] ^ XtimeD[state[10]] ^ Xtime9[state[11]];
+- tmp[13] = Xtime9[state[8]] ^ XtimeE[state[9]] ^ XtimeB[state[10]] ^ XtimeD[state[11]];
+- tmp[2] = XtimeD[state[8]] ^ Xtime9[state[9]] ^ XtimeE[state[10]] ^ XtimeB[state[11]];
+- tmp[7] = XtimeB[state[8]] ^ XtimeD[state[9]] ^ Xtime9[state[10]] ^ XtimeE[state[11]];
+-
+- // restore column 3
+- tmp[12] = XtimeE[state[12]] ^ XtimeB[state[13]] ^ XtimeD[state[14]] ^ Xtime9[state[15]];
+- tmp[1] = Xtime9[state[12]] ^ XtimeE[state[13]] ^ XtimeB[state[14]] ^ XtimeD[state[15]];
+- tmp[6] = XtimeD[state[12]] ^ Xtime9[state[13]] ^ XtimeE[state[14]] ^ XtimeB[state[15]];
+- tmp[11] = XtimeB[state[12]] ^ XtimeD[state[13]] ^ Xtime9[state[14]] ^ XtimeE[state[15]];
+-
+- for( i=0; i < 4 * Nb; i++ )
+- state[i] = InvSbox[tmp[i]];
+-}
+-
+-// encrypt/decrypt columns of the key
+-// n.b. you can replace this with
+-// byte-wise xor if you wish.
+-
+-static void AddRoundKey (unsigned *state, unsigned *key)
+-{
+-int idx;
+-
+- for( idx = 0; idx < 4; idx++ )
+- state[idx] ^= key[idx];
+-}
+-
+-static uchar Rcon[11] = {
+-0x00, 0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, 0x80, 0x1b, 0x36};
+-
+-// produce Nb bytes for each round
+-void ExpandKey (uchar *key, uchar *expkey)
+-{
+-uchar tmp0, tmp1, tmp2, tmp3, tmp4;
+-unsigned idx;
+-
+- memcpy (expkey, key, Nk * 4);
+-
+- for( idx = Nk; idx < Nb * (Nr + 1); idx++ ) {
+- tmp0 = expkey[4*idx - 4];
+- tmp1 = expkey[4*idx - 3];
+- tmp2 = expkey[4*idx - 2];
+- tmp3 = expkey[4*idx - 1];
+- if( !(idx % Nk) ) {
+- tmp4 = tmp3;
+- tmp3 = Sbox[tmp0];
+- tmp0 = Sbox[tmp1] ^ Rcon[idx/Nk];
+- tmp1 = Sbox[tmp2];
+- tmp2 = Sbox[tmp4];
+- } else if( Nk > 6 && idx % Nk == 4 ) {
+- tmp0 = Sbox[tmp0];
+- tmp1 = Sbox[tmp1];
+- tmp2 = Sbox[tmp2];
+- tmp3 = Sbox[tmp3];
+- }
+-
+- expkey[4*idx+0] = expkey[4*idx - 4*Nk + 0] ^ tmp0;
+- expkey[4*idx+1] = expkey[4*idx - 4*Nk + 1] ^ tmp1;
+- expkey[4*idx+2] = expkey[4*idx - 4*Nk + 2] ^ tmp2;
+- expkey[4*idx+3] = expkey[4*idx - 4*Nk + 3] ^ tmp3;
+- }
+-}
+-
+-// encrypt one 128 bit block
+-void Encrypt (uchar *in, uchar *expkey, uchar *out)
+-{
+-uchar state[Nb * 4];
+-unsigned round;
+-
+- memcpy (state, in, Nb * 4);
+- AddRoundKey ((unsigned *)state, (unsigned *)expkey);
+-
+- for( round = 1; round < Nr + 1; round++ ) {
+- if( round < Nr )
+- MixSubColumns (state);
+- else
+- ShiftRows (state);
+-
+- AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
+- }
+-
+- memcpy (out, state, sizeof(state));
+-}
+-
+-void Decrypt (uchar *in, uchar *expkey, uchar *out)
+-{
+-uchar state[Nb * 4];
+-unsigned round;
+-
+- memcpy (state, in, sizeof(state));
+-
+- AddRoundKey ((unsigned *)state, (unsigned *)expkey + Nr * Nb);
+- InvShiftRows(state);
+-
+- for( round = Nr; round--; )
+- {
+- AddRoundKey ((unsigned *)state, (unsigned *)expkey + round * Nb);
+- if( round )
+- InvMixSubColumns (state);
+- }
+-
+- memcpy (out, state, sizeof(state));
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/aes.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/aes.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/aes.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,39 +0,0 @@
+-// advanced encryption standard
+-// author: karl malbrain, malbrain@yahoo.com
+-
+-/*
+-This work, including the source code, documentation
+-and related data, is placed into the public domain.
+-
+-The orginal author is Karl Malbrain.
+-
+-THIS SOFTWARE IS PROVIDED AS-IS WITHOUT WARRANTY
+-OF ANY KIND, NOT EVEN THE IMPLIED WARRANTY OF
+-MERCHANTABILITY. THE AUTHOR OF THIS SOFTWARE,
+-ASSUMES _NO_ RESPONSIBILITY FOR ANY CONSEQUENCE
+-RESULTING FROM THE USE, MODIFICATION, OR
+-REDISTRIBUTION OF THIS SOFTWARE.
+-*/
+-
+-
+-#ifndef AES_MALBRAIN
+-#define AES_MALBRAIN
+-
+-
+-// AES only supports Nb=4
+-#define Nb 4 // number of columns in the state & expanded key
+-
+-#define Nk 4 // number of columns in a key
+-#define Nr 10 // number of rounds in encryption
+-
+-
+-typedef unsigned char uchar;
+-
+-
+-void ExpandKey (uchar *key, uchar *expkey);
+-void Encrypt (uchar *in, uchar *expkey, uchar *out);
+-void Decrypt (uchar *in, uchar *expkey, uchar *out);
+-
+-
+-#endif /* AES_MALBRAIN */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/chunk.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/chunk.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,686 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- handle chunked data (multimedia messages) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "chunk.h"
+-#include "filexfer.h"
+-
+-
+-/*========================================================================================================================
+- * Data-Type encoding
+- */
+-
+-#if 0
+-#include <byteswap.h>
+-#if (__BYTE_ORDER == __BIG_ENDIAN)
+-#define SWAP_64(x) (x)
+-#else
+-#define SWAP_64(x) bswap_64(x)
+-#endif
+-#endif
+-
+-/*------------------------------------------------------------------------
+- * Encode a single byte in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The byte
+- * @return The number of bytes added.
+- */
+-static int add_int8( char* chunkdata, char value )
+-{
+- *chunkdata = value;
+-
+- return sizeof( char );
+-}
+-
+-/*------------------------------------------------------------------------
+- * Encode a 16-bit value in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 16-bit value
+- * @return The number of bytes added.
+- */
+-static int add_int16( char* chunkdata, short value )
+-{
+- value = htons( value ); /* network byte-order */
+- memcpy( chunkdata, &value, sizeof( short ) );
+-
+- return sizeof( short );
+-}
+-
+-/*------------------------------------------------------------------------
+- * Encode a 32-bit value in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 32-bit value
+- * @return The number of bytes added.
+- */
+-static int add_int32( char* chunkdata, int value )
+-{
+- value = htonl( value ); /* network byte-order */
+- memcpy( chunkdata, &value, sizeof( int ) );
+-
+- return sizeof( int );
+-}
+-
+-#if 0
+-/*------------------------------------------------------------------------
+- * Encode a 64-bit value in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 64-bit value
+- * @return The number of bytes added.
+- */
+-static int add_int64( char* chunkdata, int64_t value )
+-{
+- value = SWAP_64( value ); /* network byte-order */
+- memcpy( chunkdata, &value, sizeof( int64_t ) );
+-
+- return sizeof( int64_t );
+-}
+-#endif
+-
+-/*------------------------------------------------------------------------
+- * Encode a block of data in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param data The data to add
+- * @param datalen The length of the data to add
+- * @return The number of bytes added.
+- */
+-static int add_data( char* chunkdata, const char* data, int datalen )
+-{
+- memcpy( chunkdata, data, datalen );
+-
+- return datalen;
+-}
+-
+-/*------------------------------------------------------------------------
+- * Encode a string as UTF-8 in the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param str The string to encode
+- * @return The number of bytes in the string
+- */
+-static int add_utf8_string( char* chunkdata, const char* str )
+-{
+- int pos = 0;
+- size_t len = strlen( str );
+-
+- /* utf8 string length [2 bytes] */
+- pos += add_int16( &chunkdata[pos], len );
+-
+- /* utf8 string */
+- pos += add_data( &chunkdata[pos], str, len );
+-
+- return pos;
+-}
+-
+-
+-/*========================================================================================================================
+- * Data-Type decoding
+- */
+-
+-/*------------------------------------------------------------------------
+- * Extract a single byte from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The byte
+- * @return The number of bytes extracted.
+- */
+-static int get_int8( const char* chunkdata, char* value )
+-{
+- *value = *chunkdata;
+-
+- return sizeof( char );
+-}
+-
+-/*------------------------------------------------------------------------
+- * Extract a 16-bit value from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 16-bit value
+- * @return The number of bytes extracted
+- */
+-static int get_int16( const char* chunkdata, short* value )
+-{
+- *value = ntohs( *( (const short*) chunkdata ) ); /* host byte-order */
+-
+- return sizeof( short );
+-}
+-
+-/*------------------------------------------------------------------------
+- * Extract a 32-bit value from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 32-bit value
+- * @return The number of bytes extracted
+- */
+-static int get_int32( const char* chunkdata, int* value )
+-{
+- *value = ntohl( *( (const int*) chunkdata ) ); /* host byte-order */
+-
+- return sizeof( int );
+-}
+-
+-#if 0
+-/*------------------------------------------------------------------------
+- * Extract a 64-bit value from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param value The 64-bit value
+- * @return The number of bytes extracted
+- */
+-static int get_int64( const char* chunkdata, int64_t* value )
+-{
+- *value = SWAP_64( *( (const int64_t*) chunkdata ) ); /* host byte-order */
+-
+- return sizeof( int64_t );
+-}
+-#endif
+-
+-/*------------------------------------------------------------------------
+- * Copy a block of data from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param dest Where to store the extract data
+- * @param datalen The length of the data to extract
+- * @return The number of bytes extracted
+- */
+-static int get_data( const char* chunkdata, char* dest, int datalen )
+-{
+- memcpy( dest, chunkdata, datalen );
+-
+- return datalen;
+-}
+-
+-/*------------------------------------------------------------------------
+- * Extract a UTF-8 encoded string from the chunked data.
+- *
+- * @param chunkdata The chunked-data buffer
+- * @param str A pointer to extracted string. Must be g_free()'d.
+- * @param maxstrlen Maximum size of destination buffer.
+- * @return The number of bytes consumed
+- */
+-static int get_utf8_string( const char* chunkdata, char* str, int maxstrlen )
+-{
+- int pos = 0;
+- short len;
+- int skip = 0;
+-
+- /* string length [2 bytes] */
+- pos += get_int16( &chunkdata[pos], &len );
+-
+- if ( len > maxstrlen ) {
+- /* possible buffer overflow */
+- purple_debug_error( MXIT_PLUGIN_ID, "Buffer overflow detected (get_utf8_string)\n" );
+- skip = len - maxstrlen;
+- len = maxstrlen;
+- }
+-
+- /* string data */
+- pos += get_data( &chunkdata[pos], str, len );
+- str[len] = '\0'; /* terminate string */
+-
+- return pos + skip;
+-}
+-
+-
+-/*========================================================================================================================
+- * Chunked Data encoding
+- */
+-
+-/*------------------------------------------------------------------------
+- * Encode a "reject file" chunk. (Chunk type 7)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param fileid A unique ID that identifies this file
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_reject( char* chunkdata, const char* fileid )
+-{
+- int pos = 0;
+-
+- /* file id [8 bytes] */
+- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+-
+- /* rejection reason [1 byte] */
+- pos += add_int8( &chunkdata[pos], REJECT_BY_USER );
+-
+- /* rejection description [UTF-8 (optional)] */
+- pos += add_utf8_string( &chunkdata[pos], "" );
+-
+- return pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encode a "get file" request chunk. (Chunk type 8)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param fileid A unique ID that identifies this file
+- * @param filesize The number of bytes to retrieve
+- * @param offset The start offset in the file
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset )
+-{
+- int pos = 0;
+-
+- /* file id [8 bytes] */
+- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+-
+- /* offset [4 bytes] */
+- pos += add_int32( &chunkdata[pos], offset );
+-
+- /* length [4 bytes] */
+- pos += add_int32( &chunkdata[pos], filesize );
+-
+- return pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encode a "received file" chunk. (Chunk type 9)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param fileid A unique ID that identifies this file
+- * @param status The status of the file transfer (see chunk.h)
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status )
+-{
+- int pos = 0;
+-
+- /* file id [8 bytes] */
+- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+-
+- /* status [1 byte] */
+- pos += add_int8( &chunkdata[pos], status );
+-
+- return pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encode a "send file direct" chunk. (Chunk type 10)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param username The username of the recipient
+- * @param filename The name of the file being sent
+- * @param data The file contents
+- * @param datalen The size of the file contents
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen )
+-{
+- int pos = 0;
+- const char* mime = NULL;
+-
+- /* data length [4 bytes] */
+- pos += add_int32( &chunkdata[pos], datalen );
+-
+- /* number of username(s) [2 bytes] */
+- pos += add_int16( &chunkdata[pos], 1 );
+-
+- /* username(s) [UTF-8] */
+- pos += add_utf8_string( &chunkdata[pos], username );
+-
+- /* filename [UTF-8] */
+- pos += add_utf8_string( &chunkdata[pos], filename );
+-
+- /* file mime type [UTF-8] */
+- mime = file_mime_type( filename, (const char*) data, datalen );
+- pos += add_utf8_string( &chunkdata[pos], mime );
+-
+- /* human readable description [UTF-8 (optional)] */
+- pos += add_utf8_string( &chunkdata[pos], "" );
+-
+- /* crc [4 bytes] (0 = optional) */
+- pos += add_int32( &chunkdata[pos], 0 );
+-
+- /* the actual file data */
+- pos += add_data( &chunkdata[pos], (const char *) data, datalen );
+-
+- return pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encode a "set avatar" chunk. (Chunk type 13)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param data The avatar data
+- * @param datalen The size of the avatar data
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen )
+-{
+- const char fileid[MXIT_CHUNK_FILEID_LEN];
+- int pos = 0;
+-
+- /* id [8 bytes] */
+- memset( &fileid, 0, sizeof( fileid ) ); /* set to 0 for file upload */
+- pos += add_data( &chunkdata[pos], fileid, MXIT_CHUNK_FILEID_LEN );
+-
+- /* size [4 bytes] */
+- pos += add_int32( &chunkdata[pos], datalen );
+-
+- /* crc [4 bytes] (0 = optional) */
+- pos += add_int32( &chunkdata[pos], 0 );
+-
+- /* the actual file data */
+- pos += add_data( &chunkdata[pos], (const char *) data, datalen );
+-
+- return pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encode a "get avatar" chunk. (Chunk type 14)
+- *
+- * @param chunkdata Chunked-data buffer
+- * @param mxitId The username who's avatar to download
+- * @param avatarId The Id of the avatar image (as string)
+- * @return The number of bytes encoded in the buffer
+- */
+-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId )
+-{
+- int pos = 0;
+-
+- /* number of avatars [4 bytes] */
+- pos += add_int32( &chunkdata[pos], 1 );
+-
+- /* username [UTF-8] */
+- pos += add_utf8_string( &chunkdata[pos], mxitId );
+-
+- /* avatar id [UTF-8] */
+- pos += add_utf8_string( &chunkdata[pos], avatarId );
+-
+- /* avatar format [UTF-8] */
+- pos += add_utf8_string( &chunkdata[pos], MXIT_AVATAR_TYPE );
+-
+- /* avatar bit depth [1 byte] */
+- pos += add_int8( &chunkdata[pos], MXIT_AVATAR_BITDEPT );
+-
+- /* number of sizes [2 bytes] */
+- pos += add_int16( &chunkdata[pos], 1 );
+-
+- /* image size [4 bytes] */
+- pos += add_int32( &chunkdata[pos], MXIT_AVATAR_SIZE );
+-
+- return pos;
+-}
+-
+-
+-/*========================================================================================================================
+- * Chunked Data decoding
+- */
+-
+-/*------------------------------------------------------------------------
+- * Parse a received "offer file" chunk. (Chunk 6)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param offer Decoded offerfile information
+- */
+-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer )
+-{
+- int pos = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_offer (%i bytes)\n", datalen );
+-
+- /* id [8 bytes] */
+- pos += get_data( &chunkdata[pos], offer->fileid, 8);
+-
+- /* from username [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->username, sizeof( offer->username ) );
+- mxit_strip_domain( offer->username );
+-
+- /* file size [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(offer->filesize) );
+-
+- /* filename [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->filename, sizeof( offer->filename ) );
+-
+- /* mime type [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], offer->mimetype, sizeof( offer->mimetype ) );
+-
+- /* timestamp [8 bytes] */
+- /* not used by libPurple */
+-
+- /* file description [UTF-8] */
+- /* not used by libPurple */
+-
+- /* file alternative [UTF-8] */
+- /* not used by libPurple */
+-
+- /* flags [4 bytes] */
+- /* not used by libPurple */
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a received "get file" response chunk. (Chunk 8)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param offer Decoded getfile information
+- */
+-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile )
+-{
+- int pos = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_file (%i bytes)\n", datalen );
+-
+- /* id [8 bytes] */
+- pos += get_data( &chunkdata[pos], getfile->fileid, 8 );
+-
+- /* offset [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->offset) );
+-
+- /* file length [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->length) );
+-
+- /* crc [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(getfile->crc) );
+-
+- /* file data */
+- getfile->data = &chunkdata[pos];
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a received splash screen chunk. (Chunk 2)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param splash Decoded splash image information
+- */
+-static void mxit_chunk_parse_splash( char* chunkdata, int datalen, struct splash_chunk* splash )
+-{
+- int pos = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_splash (%i bytes)\n", datalen );
+-
+- /* anchor [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(splash->anchor) );
+-
+- /* time to show [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(splash->showtime) );
+-
+- /* background color [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(splash->bgcolor) );
+-
+- /* file data */
+- splash->data = &chunkdata[pos];
+-
+- /* data length */
+- splash->datalen = datalen - pos;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a received "custom resource" chunk. (Chunk 1)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param offer Decoded custom resource
+- */
+-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr )
+-{
+- int pos = 0;
+- int chunklen = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_cr (%i bytes)\n", datalen );
+-
+- /* id [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], cr->id, sizeof( cr->id ) );
+-
+- /* handle [UTF-8] */
+- pos += get_utf8_string( &chunkdata[pos], cr->handle, sizeof( cr->handle ) );
+-
+- /* operation [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(cr->operation) );
+-
+- /* chunk size [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &chunklen );
+-
+- /* parse the resource chunks */
+- while ( chunklen > 0 ) {
+- gchar* chunk = &chunkdata[pos];
+-
+- /* start of chunk data */
+- pos += MXIT_CHUNK_HEADER_SIZE;
+-
+- switch ( chunk_type( chunk ) ) {
+- case CP_CHUNK_SPLASH : /* splash image */
+- {
+- struct splash_chunk* splash = g_new0( struct splash_chunk, 1 );
+-
+- mxit_chunk_parse_splash( &chunkdata[pos], chunk_length( chunk ), splash );
+-
+- cr->resources = g_list_append( cr->resources, splash );
+- break;
+- }
+- case CP_CHUNK_CLICK : /* splash click */
+- {
+- struct splash_click_chunk* click = g_new0( struct splash_click_chunk, 1 );
+-
+- cr->resources = g_list_append( cr->resources, click );
+- break;
+- }
+- default:
+- purple_debug_info( MXIT_PLUGIN_ID, "Unsupported custom resource chunk received (%i)\n", chunk_type( chunk) );
+- }
+-
+- /* skip over data to next resource chunk */
+- pos += chunk_length( chunk );
+- chunklen -= ( MXIT_CHUNK_HEADER_SIZE + chunk_length( chunk ) );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a received "send file direct" response chunk. (Chunk 10)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param sendfile Decoded sendfile information
+- */
+-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile )
+-{
+- int pos = 0;
+- short entries = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_sendfile (%i bytes)\n", datalen );
+-
+- /* number of entries [2 bytes] */
+- pos += get_int16( &chunkdata[pos], &entries );
+-
+- if ( entries < 1 ) /* no data */
+- return;
+-
+- /* contactAddress [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], sendfile->username, sizeof( sendfile->username ) );
+-
+- /* status [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(sendfile->status) );
+-
+- /* status message [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], sendfile->statusmsg, sizeof( sendfile->statusmsg ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a received "get avatar" response chunk. (Chunk 14)
+- *
+- * @param chunkdata Chunked data buffer
+- * @param datalen The length of the chunked data
+- * @param avatar Decoded avatar information
+- */
+-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar )
+-{
+- int pos = 0;
+- int numfiles = 0;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_chunk_parse_get_avatar (%i bytes)\n", datalen );
+-
+- /* number of files [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &numfiles );
+-
+- if ( numfiles < 1 ) /* no data */
+- return;
+-
+- /* mxitId [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->mxitid, sizeof( avatar->mxitid ) );
+-
+- /* avatar id [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->avatarid, sizeof( avatar->avatarid ) );
+-
+- /* format [UTF-8 string] */
+- pos += get_utf8_string( &chunkdata[pos], avatar->format, sizeof( avatar->format ) );
+-
+- /* bit depth [1 byte] */
+- pos += get_int8( &chunkdata[pos], &(avatar->bitdepth) );
+-
+- /* crc [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->crc) );
+-
+- /* width [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->width) );
+-
+- /* height [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->height) );
+-
+- /* file length [4 bytes] */
+- pos += get_int32( &chunkdata[pos], &(avatar->length) );
+-
+- /* file data */
+- avatar->data = &chunkdata[pos];
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/chunk.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/chunk.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/chunk.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,192 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- handle chunked data (multimedia messages) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_CHUNK_H_
+-#define _MXIT_CHUNK_H_
+-
+-
+-#include "roster.h"
+-
+-
+-#define MXIT_CHUNK_FILEID_LEN 8 /* bytes */
+-#define MXIT_CHUNK_HEADER_SIZE 5 /* type (1 byte) + length (4 bytes) */
+-
+-
+-/* Multimedia chunk types */
+-#define CP_CHUNK_NONE 0x00 /* (0) no chunk */
+-#define CP_CHUNK_CUSTOM 0x01 /* (1) custom resource */
+-#define CP_CHUNK_SPLASH 0x02 /* (2) splash image */
+-#define CP_CHUNK_CLICK 0x03 /* (3) splash click through */
+-#define CP_CHUNK_OFFER 0x06 /* (6) offer file */
+-#define CP_CHUNK_REJECT 0x07 /* (7) reject file */
+-#define CP_CHUNK_GET 0x08 /* (8) get file */
+-#define CP_CHUNK_RECEIVED 0x09 /* (9) received file */
+-#define CP_CHUNK_DIRECT_SND 0x0A /* (10) send file direct */
+-#define CP_CHUNK_DIRECT_FWD 0x0B /* (11) forward file direct */
+-#define CP_CHUNK_SKIN 0x0C /* (12) MXit client skin */
+-#define CP_CHUNK_SET_AVATAR 0x0D /* (13) set avatar */
+-#define CP_CHUNK_GET_AVATAR 0x0E /* (14) get avatar */
+-#define CP_CHUNK_END 0x7E /* (126) end */
+-#define CP_CHUNK_EXT 0x7F /* (127) extended type */
+-
+-
+-/* Custom Resource operations */
+-#define CR_OP_UPDATE 0
+-#define CR_OP_REMOVE 1
+-
+-/* File Received status */
+-#define RECV_STATUS_SUCCESS 0
+-#define RECV_STATUS_PARSE_FAIL 1
+-#define RECV_STATUS_CANNOT_OPEN 8
+-#define RECV_STATUS_BAD_CRC 9
+-#define RECV_STATUS_BAD_ID 10
+-
+-/* File Reject status */
+-#define REJECT_BY_USER 1
+-#define REJECT_FILETYPE 2
+-#define REJECT_NO_RESOURCES 3
+-#define REJECT_BAD_RECIPIENT 4
+-
+-/*
+- * Chunk header manipulation functions
+- */
+-static inline guint chunk_type( gchar* chunkheader )
+-{
+- return *chunkheader;
+-}
+-
+-static inline void set_chunk_type( gchar* chunkheader, guint type )
+-{
+- *chunkheader = type;
+-}
+-
+-static inline guint32 chunk_length( gchar* chunkheader )
+-{
+- guint32 length = *( (const guint32*) &chunkheader[1] );
+- return htonl( length );
+-}
+-
+-static inline void set_chunk_length( gchar* chunkheader, guint32 size )
+-{
+- size = htonl( size );
+- memcpy( &chunkheader[1], &size, sizeof( guint32 ) );
+-}
+-
+-static inline gchar* chunk_data( gchar* chunkheader )
+-{
+- return &chunkheader[MXIT_CHUNK_HEADER_SIZE];
+-}
+-
+-/*
+- * Offer File chunk (6).
+- */
+-struct offerfile_chunk {
+- char fileid[MXIT_CHUNK_FILEID_LEN];
+- char username[MXIT_CP_MAX_JID_LEN + 1];
+- int filesize;
+- char filename[FILENAME_MAX];
+- char mimetype[64];
+-};
+-
+-/*
+- * Get File chunk (8) response.
+- */
+-struct getfile_chunk {
+- char fileid[MXIT_CHUNK_FILEID_LEN];
+- int offset;
+- int length;
+- int crc;
+- char* data;
+-};
+-
+-/*
+- * Custom Resource chunk (1).
+- */
+-struct cr_chunk {
+- char id[64];
+- char handle[64];
+- char operation;
+- GList* resources;
+-};
+-
+-/*
+- * Splash Image chunk (2)
+- */
+-struct splash_chunk {
+- char anchor;
+- char showtime;
+- int bgcolor;
+- char* data;
+- int datalen;
+-};
+-
+-/*
+- * Splash Click Through chunk (3)
+- */
+-struct splash_click_chunk {
+- char reserved[1];
+-};
+-
+-/*
+- * Get Avatar chunk (14) response.
+- */
+-struct getavatar_chunk {
+- char mxitid[50];
+- char avatarid[64];
+- char format[16];
+- char bitdepth;
+- int crc;
+- int width;
+- int height;
+- int length;
+- char* data;
+-};
+-
+-/*
+- * Send File Direct chunk (10) response.
+- */
+-struct sendfile_chunk {
+- char username[MXIT_CP_MAX_JID_LEN + 1];
+- int status;
+- char statusmsg[1024];
+-};
+-
+-/* Encode chunk */
+-int mxit_chunk_create_senddirect( char* chunkdata, const char* username, const char* filename, const unsigned char* data, int datalen );
+-int mxit_chunk_create_reject( char* chunkdata, const char* fileid );
+-int mxit_chunk_create_get( char* chunkdata, const char* fileid, int filesize, int offset );
+-int mxit_chunk_create_received( char* chunkdata, const char* fileid, unsigned char status );
+-int mxit_chunk_create_set_avatar( char* chunkdata, const unsigned char* data, int datalen );
+-int mxit_chunk_create_get_avatar( char* chunkdata, const char* mxitId, const char* avatarId );
+-
+-/* Decode chunk */
+-void mxit_chunk_parse_offer( char* chunkdata, int datalen, struct offerfile_chunk* offer );
+-void mxit_chunk_parse_get( char* chunkdata, int datalen, struct getfile_chunk* getfile );
+-void mxit_chunk_parse_cr( char* chunkdata, int datalen, struct cr_chunk* cr );
+-void mxit_chunk_parse_sendfile( char* chunkdata, int datalen, struct sendfile_chunk* sendfile );
+-void mxit_chunk_parse_get_avatar( char* chunkdata, int datalen, struct getavatar_chunk* avatar );
+-
+-#endif /* _MXIT_CHUNK_H_ */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/cipher.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/cipher.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,245 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- encryption --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "mxit.h"
+-#include "cipher.h"
+-#include "aes.h"
+-
+-
+-/* encryption */
+-#define INITIAL_KEY "6170383452343567"
+-#define SECRET_HEADER "<mxit/>"
+-#define ENCRYPT_HEADER "<mxitencrypted ver=\"5.2\"/>"
+-
+-
+-/*------------------------------------------------------------------------
+- * Add ISO10126 Padding to the data.
+- *
+- * @param data The data to pad.
+- */
+-static void padding_add( GString* data )
+-{
+- unsigned int blocks = ( data->len / 16 ) + 1;
+- unsigned int padding = ( blocks * 16 ) - data->len;
+-
+- g_string_set_size( data, blocks * 16 );
+- data->str[data->len - 1] = padding;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Remove ISO10126 Padding from the data.
+- *
+- * @param data The data from which to remove padding.
+- */
+-static void padding_remove( GString* data )
+-{
+- unsigned int padding;
+-
+- if ( data->len == 0 )
+- return;
+-
+- padding = data->str[data->len - 1];
+- g_string_truncate( data, data->len - padding );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Generate the Transport-Layer crypto key.
+- * (Note: this function is not-thread safe)
+- *
+- * @param session The MXit Session object
+- * @return The transport-layer crypto key.
+- */
+-static char* transport_layer_key( struct MXitSession* session )
+-{
+- static char key[16 + 1];
+- const char* password = purple_account_get_password( session->acc );
+- int passlen = strlen( password );
+-
+- /* initialize with initial key */
+- g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
+-
+- /* client key (8 bytes) */
+- memcpy( key, session->clientkey, strlen( session->clientkey ) );
+-
+- /* add last 8 characters of the PIN (no padding if less characters) */
+- if ( passlen <= 8 )
+- memcpy( key + 8, password, passlen );
+- else
+- memcpy( key + 8, password + ( passlen - 8 ), 8 );
+-
+- return key;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encrypt the user's cleartext password using the AES 128-bit (ECB)
+- * encryption algorithm.
+- *
+- * @param session The MXit session object
+- * @return The encrypted & encoded password. Must be g_free'd when no longer needed.
+- */
+-char* mxit_encrypt_password( struct MXitSession* session )
+-{
+- char key[16 + 1];
+- char exkey[512];
+- GString* pass = NULL;
+- GString* encrypted = NULL;
+- char* base64;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_encrypt_password\n" );
+-
+- /* build the AES encryption key */
+- g_strlcpy( key, INITIAL_KEY, sizeof( key ) );
+- memcpy( key, session->clientkey, strlen( session->clientkey ) );
+- ExpandKey( (unsigned char*) key, (unsigned char*) exkey );
+-
+- /* build the secret data to be encrypted: SECRET_HEADER + password */
+- pass = g_string_new( SECRET_HEADER );
+- g_string_append( pass, purple_account_get_password( session->acc) );
+- padding_add( pass ); /* add ISO10126 padding */
+-
+- /* now encrypt the secret. we encrypt each block separately (ECB mode) */
+- encrypted = g_string_sized_new( pass->len );
+- for ( i = 0; i < pass->len; i += 16 ) {
+- char block[16];
+-
+- Encrypt( (unsigned char*) pass->str + i, (unsigned char*) exkey, (unsigned char*) block );
+- g_string_append_len( encrypted, block, 16 );
+- }
+-
+- /* now base64 encode the encrypted password */
+- base64 = purple_base64_encode( (unsigned char*) encrypted->str, encrypted->len );
+- g_string_free( encrypted, TRUE );
+-
+- g_string_free( pass, TRUE );
+-
+- return base64;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Decrypt a message using transport-layer encryption.
+- *
+- * @param session The MXit session object
+- * @param message The encrypted message data (is base64-encoded).
+- * @return The decrypted message. Must be g_free'd when no longer needed.
+- */
+-char* mxit_decrypt_message( struct MXitSession* session, char* message )
+-{
+- guchar* raw_message;
+- gsize raw_len;
+- char exkey[512];
+- GString* decoded = NULL;
+- int i;
+-
+- /* remove optional header: <mxitencrypted ver="5.2"/> */
+- if ( strncmp( message, ENCRYPT_HEADER, strlen( ENCRYPT_HEADER ) ) == 0 )
+- message += strlen( ENCRYPT_HEADER );
+-
+- /* base64 decode the message */
+- raw_message = purple_base64_decode( message, &raw_len );
+-
+- /* AES-encrypted data is always blocks of 16 bytes */
+- if ( ( raw_len == 0 ) || ( raw_len % 16 != 0 ) )
+- return NULL;
+-
+- /* build the AES key */
+- ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
+-
+- /* AES decrypt each block */
+- decoded = g_string_sized_new( raw_len );
+- for ( i = 0; i < raw_len; i += 16 ) {
+- char block[16];
+-
+- Decrypt( (unsigned char*) raw_message + i, (unsigned char*) exkey, (unsigned char*) block );
+- g_string_append_len( decoded, block, 16 );
+- }
+- g_free( raw_message );
+-
+- /* check that the decrypted message starts with header: <mxit/> */
+- if ( strncmp( decoded->str, SECRET_HEADER, strlen( SECRET_HEADER ) != 0 ) ) {
+- g_string_free( decoded, TRUE );
+- return NULL; /* message could not be decrypted */
+- }
+-
+- /* remove ISO10126 padding */
+- padding_remove( decoded );
+-
+- /* remove encryption header */
+- g_string_erase( decoded, 0, strlen( SECRET_HEADER ) );
+-
+- return g_string_free( decoded, FALSE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Encrypt a message using transport-layer encryption.
+- *
+- * @param session The MXit session object
+- * @param message The message data.
+- * @return The encrypted message. Must be g_free'd when no longer needed.
+- */
+-char* mxit_encrypt_message( struct MXitSession* session, char* message )
+-{
+- GString* raw_message = NULL;
+- char exkey[512];
+- GString* encoded = NULL;
+- gchar* base64;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "encrypt message: '%s'\n", message );
+-
+- /* append encryption header to message data */
+- raw_message = g_string_new( SECRET_HEADER );
+- g_string_append( raw_message, message );
+- padding_add( raw_message ); /* add ISO10126 padding */
+-
+- /* build the AES key */
+- ExpandKey( (unsigned char*) transport_layer_key( session ), (unsigned char*) exkey );
+-
+- /* AES encrypt each block */
+- encoded = g_string_sized_new( raw_message->len );
+- for ( i = 0; i < raw_message->len; i += 16 ) {
+- char block[16];
+-
+- Encrypt( (unsigned char*) raw_message->str + i, (unsigned char*) exkey, (unsigned char*) block );
+- g_string_append_len( encoded, block, 16 );
+- }
+- g_string_free( raw_message, TRUE );
+-
+- /* base64 encode the encrypted message */
+- base64 = purple_base64_encode( (unsigned char *) encoded->str, encoded->len );
+- g_string_free( encoded, TRUE );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "encrypted message: '%s'\n", base64 );
+-
+- return base64;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/cipher.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/cipher.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/cipher.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,38 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- encryption --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_CIPHER_H_
+-#define _MXIT_CIPHER_H_
+-
+-
+-struct MXitSession;
+-
+-
+-char* mxit_encrypt_password( struct MXitSession* session );
+-
+-char* mxit_decrypt_message( struct MXitSession* session, char* message );
+-char* mxit_encrypt_message( struct MXitSession* session, char* message );
+-
+-#endif /* _MXIT_CIPHER_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/filexfer.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/filexfer.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,451 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- file transfers (sending and receiving) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "chunk.h"
+-#include "filexfer.h"
+-
+-
+-#define MIME_TYPE_OCTETSTREAM "application/octet-stream"
+-
+-
+-/* supported file mime types */
+-static struct mime_type {
+- const char* magic;
+- const short magic_len;
+- const char* mime;
+-} const mime_types[] = {
+- /* magic length mime */
+- /* images */ { "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8, "image/png" }, /* image png */
+- { "\xFF\xD8", 2, "image/jpeg" }, /* image jpeg */
+- { "\x3C\x3F\x78\x6D\x6C", 5, "image/svg+xml" }, /* image SVGansi */
+- { "\xEF\xBB\xBF", 3, "image/svg+xml" }, /* image SVGutf */
+- { "\xEF\xBB\xBF", 3, "image/svg+xml" }, /* image SVGZ */
+- /* mxit */ { "\x4d\x58\x4d", 3, "application/mxit-msgs" }, /* mxit message */
+- { "\x4d\x58\x44\x01", 4, "application/mxit-mood" }, /* mxit mood */
+- { "\x4d\x58\x45\x01", 4, "application/mxit-emo" }, /* mxit emoticon */
+- { "\x4d\x58\x46\x01", 4, "application/mxit-emof" }, /* mxit emoticon frame */
+- { "\x4d\x58\x53\x01", 4, "application/mxit-skin" }, /* mxit skin */
+- /* audio */ { "\x4d\x54\x68\x64", 4, "audio/midi" }, /* audio midi */
+- { "\x52\x49\x46\x46", 4, "audio/wav" }, /* audio wav */
+- { "\xFF\xF1", 2, "audio/aac" }, /* audio aac1 */
+- { "\xFF\xF9", 2, "audio/aac" }, /* audio aac2 */
+- { "\xFF", 1, "audio/mp3" }, /* audio mp3 */
+- { "\x23\x21\x41\x4D\x52\x0A", 6, "audio/amr" }, /* audio AMR */
+- { "\x23\x21\x41\x4D\x52\x2D\x57\x42", 8, "audio/amr-wb" }, /* audio AMR WB */
+- { "\x00\x00\x00", 3, "audio/mp4" }, /* audio mp4 */
+- { "\x2E\x73\x6E\x64", 4, "audio/au" } /* audio AU */
+-};
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the MIME type matching the data file.
+- *
+- * @param filename The name of file
+- * @param buf The data
+- * @param buflen The length of the data
+- * @return A MIME type string
+- */
+-const char* file_mime_type( const char* filename, const char* buf, int buflen )
+-{
+- unsigned int i;
+-
+- /* check for matching magic headers */
+- for ( i = 0; i < ARRAY_SIZE( mime_types ); i++ ) {
+-
+- if ( buflen < mime_types[i].magic_len ) /* data is shorter than size of magic */
+- continue;
+-
+- if ( memcmp( buf, mime_types[i].magic, mime_types[i].magic_len ) == 0 )
+- return mime_types[i].mime;
+- }
+-
+- /* we did not find the MIME type, so return the default (application/octet-stream) */
+- return MIME_TYPE_OCTETSTREAM;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Cleanup and deallocate a MXit file transfer object
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_free( PurpleXfer* xfer )
+-{
+- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;;
+-
+- if ( mx ) {
+- g_free( mx );
+- xfer->data = NULL;
+- }
+-}
+-
+-
+-/*========================================================================================================================
+- * File Transfer callbacks
+- */
+-
+-/*------------------------------------------------------------------------
+- * Initialise a new file transfer.
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_init( PurpleXfer* xfer )
+-{
+- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_init\n" );
+-
+- if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
+- /* we are trying to send a file to MXit */
+-
+- if ( purple_xfer_get_size( xfer ) > CP_MAX_FILESIZE ) {
+- /* the file is too big */
+- purple_xfer_error( xfer->type, xfer->account, xfer->who, _( "The file you are trying to send is too large!" ) );
+- purple_xfer_cancel_local( xfer );
+- return;
+- }
+-
+- /* start the file transfer */
+- purple_xfer_start( xfer, -1, NULL, 0 );
+- }
+- else {
+- /*
+- * we have just accepted a file transfer request from MXit. send a confirmation
+- * to the MXit server so that can send us the file
+- */
+- mxit_send_file_accept( mx->session, mx->fileid, purple_xfer_get_size( xfer ), 0 );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Start the file transfer.
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_start( PurpleXfer* xfer )
+-{
+- unsigned char* buffer;
+- int size;
+- int wrote;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_start\n" );
+-
+- if ( purple_xfer_get_type( xfer ) == PURPLE_XFER_SEND ) {
+- /*
+- * the user wants to send a file to one of his contacts. we need to create
+- * a buffer and copy the file data into memory and then we can send it to
+- * the contact. we will send the whole file with one go.
+- */
+- buffer = g_malloc( xfer->bytes_remaining );
+- size = fread( buffer, xfer->bytes_remaining, 1, xfer->dest_fp );
+-
+- wrote = purple_xfer_write( xfer, buffer, xfer->bytes_remaining );
+- if ( wrote > 0 )
+- purple_xfer_set_bytes_sent( xfer, wrote );
+-
+- /* free the buffer */
+- g_free( buffer );
+- buffer = NULL;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The file transfer has ended.
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_end( PurpleXfer* xfer )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_end\n" );
+-
+- /* deallocate object */
+- mxit_xfer_free( xfer );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The file transfer (to a user) has been cancelled.
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_cancel_send( PurpleXfer* xfer )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_send\n" );
+-
+- /* deallocate object */
+- mxit_xfer_free( xfer );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send the file data.
+- *
+- * @param buffer The data to sent
+- * @param size The length of the data to send
+- * @param xfer The file transfer object
+- * @return The amount of data actually sent
+- */
+-static gssize mxit_xfer_write( const guchar* buffer, size_t size, PurpleXfer* xfer )
+-{
+- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_write\n" );
+-
+- if ( !mx ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: invalid internal mxit xfer data\n" );
+- return -1;
+- }
+- else if ( purple_xfer_get_type( xfer ) != PURPLE_XFER_SEND ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_xfer_write: wrong xfer type received\n" );
+- return -1;
+- }
+-
+- /* create and send the packet to MXit */
+- mxit_send_file( mx->session, purple_xfer_get_remote_user( xfer ), purple_xfer_get_filename( xfer ), buffer, size );
+-
+- /* the transfer is complete */
+- purple_xfer_set_completed( xfer, TRUE );
+-
+- return size;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has rejected a file offer from MXit.
+- *
+- * @param xfer The file transfer object
+- */
+-static void mxit_xfer_request_denied( PurpleXfer* xfer )
+-{
+- struct mxitxfer* mx = (struct mxitxfer*) xfer->data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_request_denied\n" );
+-
+- /* send file reject packet to MXit server */
+- mxit_send_file_reject( mx->session, mx->fileid );
+-
+- /* deallocate object */
+- mxit_xfer_free( xfer );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The file transfer (from MXit) has been cancelled.
+- */
+-static void mxit_xfer_cancel_recv( PurpleXfer* xfer )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_cancel_recv\n" );
+-
+- /* deallocate object */
+- mxit_xfer_free( xfer );
+-}
+-
+-
+-/*========================================================================================================================
+- * Callbacks from libPurple
+- */
+-
+-/*------------------------------------------------------------------------
+- * Indicate if file transfers are supported to this contact.
+- * For MXit file transfers are always supported.
+- *
+- * @param gc The connection object
+- * @param who The username of the contact
+- * @return TRUE if file transfers are supported
+- */
+-gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who )
+-{
+- return TRUE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Create and initialize a new file transfer to a contact.
+- *
+- * @param gc The connection object
+- * @param who The username of the recipient
+- */
+-PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleXfer* xfer = NULL;
+- struct mxitxfer* mx = NULL;
+-
+- /* (reference: "libpurple/ft.h") */
+- xfer = purple_xfer_new( session->acc, PURPLE_XFER_SEND, who );
+-
+- /* create file info and attach it to the file transfer */
+- mx = g_new0( struct mxitxfer, 1 );
+- mx->session = session;
+- xfer->data = mx;
+-
+- /* configure callbacks (reference: "libpurple/ft.h") */
+- purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
+- purple_xfer_set_start_fnc( xfer, mxit_xfer_start );
+- purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
+- purple_xfer_set_cancel_send_fnc( xfer, mxit_xfer_cancel_send );
+- purple_xfer_set_write_fnc( xfer, mxit_xfer_write );
+-
+- return xfer;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has initiated a file transfer to a contact.
+- *
+- * @param gc The connection object
+- * @param who The username of the contact
+- * @param filename The filename (is NULL if request has not been accepted yet)
+- */
+-void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename )
+-{
+- PurpleXfer *xfer = mxit_xfer_new( gc, who );
+-
+- if ( filename )
+- purple_xfer_request_accepted( xfer, filename );
+- else
+- purple_xfer_request( xfer );
+-}
+-
+-
+-/*========================================================================================================================
+- * Calls from the MXit Protocol layer
+- */
+-
+-/*------------------------------------------------------------------------
+- * A file transfer offer has been received from the MXit server.
+- *
+- * @param session The MXit session object
+- * @param usermame The username of the sender
+- * @param filename The name of the file being offered
+- * @param filesize The size of the file being offered
+- * @param fileid A unique ID that identifies this file
+- */
+-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid )
+-{
+- PurpleXfer* xfer = NULL;
+- struct mxitxfer* mx = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "File Offer: file=%s, from=%s, size=%i\n", filename, username, filesize );
+-
+- xfer = purple_xfer_new( session->acc, PURPLE_XFER_RECEIVE, username );
+- if ( xfer ) {
+- /* create a new mxit xfer struct for internal use */
+- mx = g_new0( struct mxitxfer, 1 );
+- mx->session = session;
+- memcpy( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN );
+- xfer->data = mx;
+-
+- purple_xfer_set_filename( xfer, filename );
+- if( filesize > 0 )
+- purple_xfer_set_size( xfer, filesize );
+-
+- /* register file transfer callback functions */
+- purple_xfer_set_init_fnc( xfer, mxit_xfer_init );
+- purple_xfer_set_request_denied_fnc( xfer, mxit_xfer_request_denied );
+- purple_xfer_set_cancel_recv_fnc( xfer, mxit_xfer_cancel_recv );
+- purple_xfer_set_end_fnc( xfer, mxit_xfer_end );
+-
+- /* give the request to the user to accept/deny */
+- purple_xfer_request( xfer );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the libPurple file-transfer object associated with a MXit transfer
+- *
+- * @param session The MXit session object
+- * @param fileid A unique ID that identifies this file
+- */
+-static PurpleXfer* find_mxit_xfer( struct MXitSession* session, const char* fileid )
+-{
+- GList* item = NULL;
+- PurpleXfer* xfer = NULL;
+-
+- item = purple_xfers_get_all(); /* list of all active transfers */
+- while ( item ) {
+- xfer = item->data;
+-
+- if ( xfer->account == session->acc ) {
+- /* transfer is associated with this MXit account */
+- struct mxitxfer* mx = xfer->data;
+-
+- /* does the fileid match? */
+- if ( ( mx ) && ( memcmp( mx->fileid, fileid, MXIT_CHUNK_FILEID_LEN ) == 0 ) )
+- break;
+- }
+-
+- item = g_list_next( item );
+- }
+-
+- if ( item )
+- return item->data;
+- else
+- return NULL;
+-}
+-
+-/*------------------------------------------------------------------------
+- * A file has been received from the MXit server.
+- *
+- * @param session The MXit session object
+- * @param fileid A unique ID that identifies this file
+- * @param data The file data
+- * @param datalen The size of the data
+- */
+-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen )
+-{
+- PurpleXfer* xfer = NULL;
+- struct mxitxfer* mx = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_xfer_rx_file: (size=%i)\n", datalen );
+-
+- /* find the file-transfer object */
+- xfer = find_mxit_xfer( session, fileid );
+- if ( xfer ) {
+- mx = xfer->data;
+-
+- /* this is the transfer we have been looking for */
+- purple_xfer_ref( xfer );
+- purple_xfer_start( xfer, -1, NULL, 0 );
+- fwrite( data, datalen, 1, xfer->dest_fp );
+- purple_xfer_unref( xfer );
+- purple_xfer_set_completed( xfer, TRUE );
+- purple_xfer_end( xfer );
+-
+- /* inform MXit that file was successfully received */
+- mxit_send_file_received( session, fileid, RECV_STATUS_SUCCESS );
+- }
+- else {
+- /* file transfer not found */
+- mxit_send_file_received( session, fileid, RECV_STATUS_BAD_ID );
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/filexfer.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/filexfer.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/filexfer.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,50 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- file transfers (sending and receiving) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_FILEXFER_H_
+-#define _MXIT_FILEXFER_H_
+-
+-
+-/*
+- * a MXit file transfer
+- */
+-struct mxitxfer {
+- struct MXitSession* session;
+- char fileid[MXIT_CHUNK_FILEID_LEN];
+-};
+-
+-const char* file_mime_type( const char* filename, const char* buf, int buflen );
+-
+-/* libPurple callbacks */
+-gboolean mxit_xfer_enabled( PurpleConnection* gc, const char* who );
+-void mxit_xfer_tx( PurpleConnection* gc, const char* who, const char* filename );
+-PurpleXfer* mxit_xfer_new( PurpleConnection* gc, const char* who );
+-
+-/* MXit Protocol callbacks */
+-void mxit_xfer_rx_offer( struct MXitSession* session, const char* username, const char* filename, int filesize, const char* fileid );
+-void mxit_xfer_rx_file( struct MXitSession* session, const char* fileid, const char* data, int datalen );
+-
+-
+-#endif /* _MXIT_FILEXFER_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/formcmds.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/formcmds.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,624 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit Forms & Commands --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#include "internal.h"
+-#include <glib.h>
+-
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "markup.h"
+-#include "formcmds.h"
+-
+-#undef MXIT_DEBUG_COMMANDS
+-
+-/*
+- * the MXit Command identifiers
+- */
+-typedef enum
+-{
+- MXIT_CMD_UNKNOWN = 0, /* Unknown command */
+- MXIT_CMD_CLEAR, /* Clear (clear) */
+- MXIT_CMD_SENDSMS, /* Send SMS (sendsms) */
+- MXIT_CMD_REPLY, /* Reply (reply) */
+- MXIT_CMD_PLATREQ, /* Platform Request (platreq) */
+- MXIT_CMD_SELECTCONTACT, /* Select Contact (selc) */
+- MXIT_CMD_IMAGE, /* Inline image (img) */
+- MXIT_CMD_SCREENCONFIG, /* Chat-screen config (csc) */
+- MXIT_CMD_SCREENINFO, /* Chat-screen info (csi) */
+- MXIT_CMD_IMAGESTRIP, /* Image Strip (is) */
+- MXIT_CMD_TABLE /* Table (tbl) */
+-} MXitCommandType;
+-
+-/* Chat-screen behaviours (bhvr) */
+-#define SCREEN_NO_HEADINGS 0x01
+-#define SCREEN_FULLSCREEN 0x02
+-#define SCREEN_AUTOCLEAR 0x04
+-#define SCREEN_NO_AUDIO 0x08
+-#define SCREEN_NO_MSGPREFIX 0x10
+-#define SCREEN_NOTIFY 0x20
+-#define SCREEN_PROGRESSBAR 0x40
+-
+-
+-/*
+- * object for an inline image request with an URL
+- */
+-struct ii_url_request
+-{
+- struct RXMsgData* mx;
+- char* url;
+-};
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback function invoked when an inline image request to a web site completes.
+- *
+- * @param url_data
+- * @param user_data The Markup message object
+- * @param url_text The data returned from the WAP site
+- * @param len The length of the data returned
+- * @param error_message Descriptive error message
+- */
+-static void mxit_cb_ii_returned(PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message)
+-{
+- struct ii_url_request* iireq = (struct ii_url_request*) user_data;
+- int* intptr = NULL;
+- int id;
+-
+-#ifdef MXIT_DEBUG_COMMANDS
+- purple_debug_info(MXIT_PLUGIN_ID, "Inline Image returned from %s\n", iireq->url);
+-#endif
+-
+- if (!url_text) {
+- /* no reply from the WAP site */
+- purple_debug_error(MXIT_PLUGIN_ID, "Error downloading Inline Image from %s.\n", iireq->url);
+- goto done;
+- }
+-
+- /* lets first see if we don't have the inline image already in cache */
+- if (g_hash_table_lookup(iireq->mx->session->iimages, iireq->url)) {
+- /* inline image found in the cache, so we just ignore this reply */
+- goto done;
+- }
+-
+- /* we now have the inline image, store a copy in the imagestore */
+- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
+-
+- /* map the inline image id to purple image id */
+- intptr = g_malloc(sizeof(int));
+- *intptr = id;
+- g_hash_table_insert(iireq->mx->session->iimages, iireq->url, intptr);
+-
+- iireq->mx->flags |= PURPLE_MESSAGE_IMAGES;
+-
+-done:
+- iireq->mx->img_count--;
+- if ((iireq->mx->img_count == 0) && (iireq->mx->converted)) {
+- /*
+- * this was the last outstanding emoticon for this message,
+- * so we can now display it to the user.
+- */
+- mxit_show_message(iireq->mx);
+- }
+-
+- g_free(iireq);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the command identifier of this MXit Command.
+- *
+- * @param cmd The MXit command <key,value> map
+- * @return The MXit command identifier
+- */
+-static MXitCommandType command_type(GHashTable* hash)
+-{
+- char* op;
+- char* type;
+-
+- op = g_hash_table_lookup(hash, "op");
+- if (op) {
+- if ( strcmp(op, "cmd") == 0 ) {
+- type = g_hash_table_lookup(hash, "type");
+- if (type == NULL) /* no command provided */
+- return MXIT_CMD_UNKNOWN;
+- else if (strcmp(type, "clear") == 0) /* clear */
+- return MXIT_CMD_CLEAR;
+- else if (strcmp(type, "sendsms") == 0) /* send an SMS */
+- return MXIT_CMD_SENDSMS;
+- else if (strcmp(type, "reply") == 0) /* list of options */
+- return MXIT_CMD_REPLY;
+- else if (strcmp(type, "platreq") == 0) /* platform request */
+- return MXIT_CMD_PLATREQ;
+- else if (strcmp(type, "selc") == 0) /* select contact */
+- return MXIT_CMD_SELECTCONTACT;
+- }
+- else if (strcmp(op, "img") == 0) /* inline image */
+- return MXIT_CMD_IMAGE;
+- else if (strcmp(op, "csc") == 0) /* chat-screen config */
+- return MXIT_CMD_SCREENCONFIG;
+- else if (strcmp(op, "csi") == 0) /* chat-screen info */
+- return MXIT_CMD_SCREENINFO;
+- else if (strcmp(op, "is") == 0) /* image-strip */
+- return MXIT_CMD_IMAGESTRIP;
+- else if (strcmp(op, "tbl") == 0) /* table */
+- return MXIT_CMD_TABLE;
+- }
+-
+- return MXIT_CMD_UNKNOWN;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Tokenize a MXit Command string into a <key,value> map.
+- *
+- * @param cmd The MXit command string
+- * @return The <key,value> hash-map, or NULL on error.
+- */
+-static GHashTable* command_tokenize(char* cmd)
+-{
+- GHashTable* hash = NULL;
+- gchar** parts;
+- int i = 0;
+-
+-#ifdef MXIT_DEBUG_COMMANDS
+- purple_debug_info(MXIT_PLUGIN_ID, "command: '%s'\n", cmd);
+-#endif
+-
+- /* explode the command into parts */
+- parts = g_strsplit(cmd, "|", 0);
+-
+- hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+-
+- /* now break part into a key & value */
+- while (parts[i] != NULL) {
+- char* value;
+-
+- value = strchr(parts[i], '='); /* find start of value */
+- if (value != NULL) {
+- *value = '\0';
+- value++;
+- }
+-
+-#ifdef MXIT_DEBUG_COMMANDS
+- purple_debug_info(MXIT_PLUGIN_ID, " key='%s' value='%s'\n", parts[i], value);
+-#endif
+-
+- g_hash_table_insert(hash, g_strdup(parts[i]), g_strdup(value));
+-
+- i++;
+- }
+-
+- g_strfreev(parts);
+-
+- return hash;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a Clear MXit command.
+- * [::op=cmd|type=clear|clearmsgscreen=true|auto=true|id=12345:]
+- *
+- * @param session The MXit session object
+- * @param from The sender of the message.
+- * @param hash The MXit command <key,value> map
+- */
+-static void command_clear(struct MXitSession* session, const char* from, GHashTable* hash)
+-{
+- PurpleConversation *conv;
+- char* clearmsgscreen;
+-
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, session->acc);
+- if (conv == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, _( "Conversation with '%s' not found\n" ), from);
+- return;
+- }
+-
+- clearmsgscreen = g_hash_table_lookup(hash, "clearmsgscreen");
+- if ( (clearmsgscreen) && (strcmp(clearmsgscreen, "true") == 0) ) {
+- /* this is a command to clear the chat screen */
+- purple_conversation_clear_message_history(conv);
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a Reply MXit command.
+- * [::op=cmd|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
+- * [::op=cmd|nm=rep|type=reply|replymsg=back|selmsg=b) Back|displaymsg=Processing|id=12345:]
+- *
+- * @param mx The received message data object
+- * @param hash The MXit command <key,value> map
+- */
+-static void command_reply(struct RXMsgData* mx, GHashTable* hash)
+-{
+- char* replymsg;
+- char* selmsg;
+- char* nm;
+-
+- selmsg = g_hash_table_lookup(hash, "selmsg"); /* selection message */
+- replymsg = g_hash_table_lookup(hash, "replymsg"); /* reply message */
+- nm = g_hash_table_lookup(hash, "nm"); /* name parameter */
+-
+- if ((selmsg == NULL) || (replymsg == NULL))
+- return; /* these parameters are required */
+-
+- if (nm) { /* indicates response must be a structured response */
+- gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
+- gchar* replycmd = g_strdup_printf("type=reply|nm=%s|res=%s|err=0", nm, replymsg);
+-
+- mxit_add_html_link( mx, replycmd, TRUE, seltext );
+-
+- g_free(seltext);
+- g_free(replycmd);
+- }
+- else {
+- gchar* seltext = g_markup_escape_text(purple_url_decode(selmsg), -1);
+-
+- mxit_add_html_link( mx, purple_url_decode(replymsg), FALSE, seltext );
+-
+- g_free(seltext);
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a PlatformRequest MXit command.
+- * [::op=cmd|type=platreq|selmsg=Upgrade MXit|dest=http%3a//m.mxit.com|id=12345:]
+- *
+- * @param hash The MXit command <key,value> map
+- * @param msg The message to display (as generated so far)
+- */
+-static void command_platformreq(GHashTable* hash, GString* msg)
+-{
+- gchar* text = NULL;
+- char* selmsg;
+- char* dest;
+-
+- selmsg = g_hash_table_lookup(hash, "selmsg"); /* find the selection message */
+- if (selmsg) {
+- text = g_markup_escape_text(purple_url_decode(selmsg), -1);
+- }
+-
+- dest = g_hash_table_lookup(hash, "dest"); /* find the destination */
+- if (dest) {
+- g_string_append_printf(msg, "<a href=\"%s\">%s</a>", purple_url_decode(dest), (text) ? text : _( "Download" )); /* add link to display message */
+- }
+-
+- if (text)
+- g_free(text);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process an inline image MXit command.
+- * [::op=img|dat=ASDF23408asdflkj2309flkjsadf%3d%3d|algn=1|w=120|h=12|t=100|replymsg=text:]
+- *
+- * @param mx The received message data object
+- * @param hash The MXit command <key,value> map
+- * @param msg The message to display (as generated so far)
+- */
+-static void command_image(struct RXMsgData* mx, GHashTable* hash, GString* msg)
+-{
+- const char* img;
+- const char* reply;
+- guchar* rawimg;
+- char link[256];
+- gsize rawimglen;
+- int imgid;
+-
+- img = g_hash_table_lookup(hash, "dat");
+- if (img) {
+- rawimg = purple_base64_decode(img, &rawimglen);
+- //purple_util_write_data_to_file_absolute("/tmp/mxitinline.png", (char*) rawimg, rawimglen);
+- imgid = purple_imgstore_add_with_id(rawimg, rawimglen, NULL);
+- g_snprintf(link, sizeof(link), "<img id=\"%i\">", imgid);
+- g_string_append_printf(msg, "%s", link);
+- mx->flags |= PURPLE_MESSAGE_IMAGES;
+- }
+- else {
+- img = g_hash_table_lookup(hash, "src");
+- if (img) {
+- struct ii_url_request* iireq;
+-
+- iireq = g_new0(struct ii_url_request,1);
+- iireq->url = g_strdup(purple_url_decode(img));
+- iireq->mx = mx;
+-
+- g_string_append_printf(msg, "%s%s>", MXIT_II_TAG, iireq->url);
+- mx->got_img = TRUE;
+-
+- /* lets first see if we don't have the inline image already in cache */
+- if (g_hash_table_lookup(mx->session->iimages, iireq->url)) {
+- /* inline image found in the cache, so we do not have to request it from the web */
+- g_free(iireq);
+- }
+- else {
+- /* send the request for the inline image */
+- purple_debug_info(MXIT_PLUGIN_ID, "sending request for inline image '%s'\n", iireq->url);
+-
+- /* request the image (reference: "libpurple/util.h") */
+- purple_util_fetch_url_request(iireq->url, TRUE, NULL, TRUE, NULL, FALSE, mxit_cb_ii_returned, iireq);
+- mx->img_count++;
+- }
+- }
+- }
+-
+- /* if this is a clickable image, show a click link */
+- reply = g_hash_table_lookup(hash, "replymsg");
+- if (reply) {
+- g_string_append_printf(msg, "\n");
+- mxit_add_html_link(mx, purple_url_decode(reply), FALSE, _( "click here" ));
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process an Imagestrip MXit command.
+- * [::op=is|nm=status|dat=iVBORw0KGgoAAAA%3d%3d|v=63398792426788|fw=8|fh=8|layer=0:]
+- *
+- * @param from The sender of the message.
+- * @param hash The MXit command <key,value> map
+- */
+-static void command_imagestrip(struct MXitSession* session, const char* from, GHashTable* hash)
+-{
+- const char* name;
+- const char* validator;
+- const char* tmp;
+- int width, height, layer;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip received from %s\n", from);
+-
+- /* image strip name */
+- name = g_hash_table_lookup(hash, "nm");
+-
+- /* validator */
+- validator = g_hash_table_lookup(hash, "v");
+-
+- /* image data */
+- tmp = g_hash_table_lookup(hash, "dat");
+- if (tmp) {
+- guchar* rawimg;
+- gsize rawimglen;
+- char* dir;
+- char* escfrom;
+- char* escname;
+- char* escvalidator;
+- char* filename;
+-
+- /* base64 decode the image data */
+- rawimg = purple_base64_decode(tmp, &rawimglen);
+-
+- /* save it to a file */
+- dir = g_build_filename(purple_user_dir(), "mxit", "imagestrips", NULL);
+- purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR); /* ensure directory exists */
+-
+- escfrom = g_strdup(purple_escape_filename(from));
+- escname = g_strdup(purple_escape_filename(name));
+- escvalidator = g_strdup(purple_escape_filename(validator));
+- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s-%s-%s.png", dir, escfrom, escname, escvalidator);
+-
+- purple_util_write_data_to_file_absolute(filename, (char*) rawimg, rawimglen);
+-
+- g_free(dir);
+- g_free(escfrom);
+- g_free(escname);
+- g_free(escvalidator);
+- g_free(filename);
+- }
+-
+- tmp = g_hash_table_lookup(hash, "fw");
+- width = atoi(tmp);
+-
+- tmp = g_hash_table_lookup(hash, "fh");
+- height = atoi(tmp);
+-
+- tmp = g_hash_table_lookup(hash, "layer");
+- layer = atoi(tmp);
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "ImageStrip %s from %s: [w=%i h=%i l=%i validator=%s]\n", name, from, width, height, layer, validator);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a Chat-Screen-Info MXit command.
+- * [::op=csi:]
+- *
+- * @param session The MXit session object
+- * @param from The sender of the message.
+- */
+-static void command_screeninfo(struct MXitSession* session, const char* from)
+-{
+- char* response;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Info received from %s\n", from);
+-
+- // TODO: Determine width, height, colors of chat-screen.
+-
+- response = g_strdup_printf("::type=csi|res=bhvr,0;w,%i;h,%i;col,0.ffffffff,29.ff000000:", 300, 400);
+-
+- /* send response back to MXit */
+- mxit_send_message( session, from, response, FALSE, TRUE );
+-
+- g_free(response);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a Chat-Screen-Configure MXit command.
+- * [::op=csc|bhvr=|menu=<menu>|col=<colors>:]
+- * where:
+- * menu ::= <menuitem> { ";" <menuitem> }
+- * menuitem ::= { type "," <text> "," <name> "," <meta> }
+- * colors ::= <color> { ";" <color> }
+- * color ::= <colorid> "," <ARGB hex color>
+- *
+- * @param session The MXit session object
+- * @param from The sender of the message.
+- * @param hash The MXit command <key,value> map
+- */
+-static void command_screenconfig(struct MXitSession* session, const char* from, GHashTable* hash)
+-{
+- const char* tmp;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Chat Screen Configure received from %s\n", from);
+-
+- /* Behaviour */
+- tmp = g_hash_table_lookup(hash, "bhvr");
+- if (tmp) {
+- purple_debug_info(MXIT_PLUGIN_ID, " behaviour = %s\n", tmp);
+- // TODO: Re-configure conversation screen.
+- }
+-
+- /* Menu */
+- tmp = g_hash_table_lookup(hash, "menu");
+- if (tmp) {
+- purple_debug_info(MXIT_PLUGIN_ID, " menu = %s\n", tmp);
+- // TODO: Implement conversation-specific sub-menu.
+- }
+-
+- /* Colours */
+- tmp = g_hash_table_lookup(hash, "col");
+- if (tmp) {
+- purple_debug_info(MXIT_PLUGIN_ID, " colours = %s\n", tmp);
+- // TODO: Re-configuration conversation colors.
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a Table Markup MXit command.
+- *
+- * @param mx The received message data object
+- * @param hash The MXit command <key,value> map
+- */
+-static void command_table(struct RXMsgData* mx, GHashTable* hash)
+-{
+- const char* tmp;
+- const char* name;
+- int mode;
+- int nr_columns = 0, nr_rows = 0;
+- gchar** coldata;
+- int i, j;
+-
+- /* table name */
+- name = g_hash_table_lookup(hash, "nm");
+-
+- /* number of columns */
+- tmp = g_hash_table_lookup(hash, "col");
+- nr_columns = atoi(tmp);
+-
+- /* number of rows */
+- tmp = g_hash_table_lookup(hash, "row");
+- nr_rows = atoi(tmp);
+-
+- /* mode */
+- tmp = g_hash_table_lookup(hash, "mode");
+- mode = atoi(tmp);
+-
+- /* table data */
+- tmp = g_hash_table_lookup(hash, "d");
+- coldata = g_strsplit(tmp, "~", 0); /* split into entries for each row & column */
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Table %s from %s: [cols=%i rows=%i mode=%i]\n", name, mx->from, nr_columns, nr_rows, mode);
+-
+- for (i = 0; i < nr_rows; i++) {
+- for (j = 0; j < nr_columns; j++) {
+- purple_debug_info(MXIT_PLUGIN_ID, " Row %i Column %i = %s\n", i, j, coldata[i*nr_columns + j]);
+- }
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received MXit Command message.
+- *
+- * @param mx The received message data object
+- * @param message The message text
+- * @return The length of the command
+- */
+-int mxit_parse_command(struct RXMsgData* mx, char* message)
+-{
+- GHashTable* hash = NULL;
+- char* start;
+- char* end;
+-
+- /* ensure that this is really a command */
+- if ( ( message[0] != ':' ) || ( message[1] != ':' ) ) {
+- /* this is not a command */
+- return 0;
+- }
+-
+- start = message + 2;
+- end = strstr(start, ":");
+- if (end) {
+- /* end of a command found */
+- *end = '\0'; /* terminate command string */
+-
+- hash = command_tokenize(start); /* break into <key,value> pairs */
+- if (hash) {
+- MXitCommandType type = command_type(hash);
+-
+- switch (type) {
+- case MXIT_CMD_CLEAR :
+- command_clear(mx->session, mx->from, hash);
+- break;
+- case MXIT_CMD_REPLY :
+- command_reply(mx, hash);
+- break;
+- case MXIT_CMD_PLATREQ :
+- command_platformreq(hash, mx->msg);
+- break;
+- case MXIT_CMD_IMAGE :
+- command_image(mx, hash, mx->msg);
+- break;
+- case MXIT_CMD_SCREENCONFIG :
+- command_screenconfig(mx->session, mx->from, hash);
+- break;
+- case MXIT_CMD_SCREENINFO :
+- command_screeninfo(mx->session, mx->from);
+- break;
+- case MXIT_CMD_IMAGESTRIP :
+- command_imagestrip(mx->session, mx->from, hash);
+- break;
+- case MXIT_CMD_TABLE :
+- command_table(mx, hash);
+- break;
+- default :
+- /* command unknown, or not currently supported */
+- break;
+- }
+- g_hash_table_destroy(hash);
+- }
+- *end = ':';
+-
+- return end - message;
+- }
+- else {
+- return 0;
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/formcmds.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/formcmds.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/formcmds.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,35 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit Forms & Commands --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_FORMCMDS_H_
+-#define _MXIT_FORMCMDS_H_
+-
+-#include "mxit.h"
+-
+-
+-int mxit_parse_command(struct RXMsgData* mx, char* message);
+-
+-
+-#endif /* _MXIT_FORMCMDS_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/http.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/http.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,332 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit client protocol implementation --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "mxit.h"
+-#include "protocol.h"
+-#include "http.h"
+-
+-
+-/* HTTP constants */
+-#define HTTP_11_200_OK "HTTP/1.1 200 OK\r\n"
+-#define HTTP_11_100_CONT "HTTP/1.1 100 Continue\r\n"
+-#define HTTP_11_SEPERATOR "\r\n\r\n"
+-#define HTTP_CONTENT_LEN "Content-Length: "
+-
+-
+-/* define to enable HTTP debugging */
+-#define DEBUG_HTTP
+-
+-
+-/*------------------------------------------------------------------------
+- * This will freeup the memory used by a HTTP request structure
+- *
+- * @param req The HTTP structure's resources should be freed up
+- */
+-static void free_http_request( struct http_request* req )
+-{
+- g_free( req->host );
+- g_free( req->data );
+- g_free( req );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Write the request to the HTTP server.
+- *
+- * @param fd The file descriptor
+- * @param pktdata The packet data
+- * @param pktlen The length of the packet data
+- * @return Return -1 on error, otherwise 0
+- */
+-static int mxit_http_raw_write( int fd, const char* pktdata, int pktlen )
+-{
+- int written;
+- int res;
+-
+- written = 0;
+- while ( written < pktlen ) {
+- res = write( fd, &pktdata[written], pktlen - written );
+- if ( res <= 0 ) {
+- /* error on socket */
+- if ( errno == EAGAIN )
+- continue;
+-
+- purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to HTTP server (%i)\n", res );
+- return -1;
+- }
+- written += res;
+- }
+-
+- return 0;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback when data is received from the HTTP server.
+- *
+- * @param user_data The MXit session object
+- * @param source The file-descriptor on which data was received
+- * @param cond Condition which caused the callback (PURPLE_INPUT_READ)
+- */
+-static void mxit_cb_http_read( gpointer user_data, gint source, PurpleInputCondition cond )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+- char buf[256];
+- int buflen;
+- char* body;
+- int bodylen;
+- char* ch;
+- int len;
+- char* tmp;
+- int res;
+- char* next;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_read\n" );
+-
+- if ( session->rx_state == RX_STATE_RLEN ) {
+- /* we are reading in the HTTP headers */
+-
+- /* copy partial headers if we have any part saved */
+- memcpy( buf, session->rx_dbuf, session->rx_i );
+- buflen = session->rx_i;
+-
+- /* read bytes from the socket */
+- len = read( session->fd, buf + buflen, sizeof( buf ) - ( buflen + 1 ) );
+- if ( len <= 0 ) {
+- /* connection has been terminated, or error occurred */
+- goto done;
+- }
+- buf[buflen+len] = '\0';
+-
+-//nextpacket:
+-
+-#ifdef DEBUG_HTTP
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 1: (%i)\n", len );
+- dump_bytes( session, buf + buflen, len );
+-#endif
+-
+- /* see if we have all the HTTP headers yet */
+- ch = strstr( buf, HTTP_11_SEPERATOR );
+- if ( !ch ) {
+- /* we need to wait for more input, so save what we have */
+- session->rx_i = buflen + len;
+- memcpy( session->rx_dbuf, buf, session->rx_i );
+- return;
+- }
+- buflen += len;
+-
+- /* we have the header's end now skip over the http separator to get the body offset */
+- ch += strlen( HTTP_11_SEPERATOR );
+- *(ch - 1) = '\0';
+- body = ch;
+-
+- res = buflen - ( ch - buf );
+- if ( res > 0 ) {
+- /* we read more bytes than just the header so copy it over */
+- memcpy( session->rx_dbuf, ch, res );
+- session->rx_i = res;
+- }
+- else {
+- session->rx_i = 0;
+- }
+-
+- /* test for a good response */
+- if ( ( strncmp( buf, HTTP_11_200_OK, strlen( HTTP_11_200_OK ) ) != 0 ) && ( strncmp( buf, HTTP_11_100_CONT, strlen( HTTP_11_100_CONT ) ) != 0 ) ) {
+- /* bad result */
+- purple_debug_error( MXIT_PLUGIN_ID, "HTTP error: %s\n", ch );
+- goto done;
+- }
+-
+- /* find the content-length */
+- ch = (char*) purple_strcasestr( buf, HTTP_CONTENT_LEN );
+- if ( !ch ) {
+- /* bad request. it does not contain a content-length header */
+- purple_debug_error( MXIT_PLUGIN_ID, "HTTP reply received without content-length header (ignoring packet)\n" );
+- goto done;
+- }
+-
+- /* parse the content-length */
+- ch += strlen( HTTP_CONTENT_LEN );
+- tmp = strchr( ch, '\r' );
+- if ( !tmp ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Received bad HTTP reply packet (ignoring packet)\n" );
+- goto done;
+- }
+- tmp = g_strndup( ch, tmp - ch );
+- bodylen = atoi( tmp );
+- g_free( tmp );
+- tmp = NULL;
+-
+- if ( buflen + bodylen >= CP_MAX_PACKET ) {
+- /* this packet is way to big */
+- goto done;
+- }
+- else if ( buflen > ( ( body - buf ) + bodylen ) ) {
+- /* we have a second packet here */
+- next = body + bodylen;
+- session->rx_res = 0;
+- }
+- else {
+- session->rx_res = bodylen - session->rx_i;
+- }
+-
+- if ( session->rx_res == 0 ) {
+- /* we have read all the data */
+- session->rx_i = bodylen;
+- session->rx_state = RX_STATE_PROC;
+- }
+- else {
+- /* there is still some data outstanding */
+- session->rx_state = RX_STATE_DATA;
+- }
+- }
+- else if ( session->rx_state == RX_STATE_DATA ) {
+- /* we are reading the HTTP content (body) */
+-
+- /* read bytes from the socket */
+- len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
+- if ( len <= 0 ) {
+- /* connection has been terminated, or error occurred */
+- goto done;
+- }
+-
+-#ifdef DEBUG_HTTP
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST READ 2: (%i)\n", len );
+- dump_bytes( session, &session->rx_dbuf[session->rx_i], len );
+-#endif
+- session->rx_i += len;
+- session->rx_res -= len;
+-
+- if ( session->rx_res == 0 ) {
+- /* ok, so now we have read in the whole packet */
+- session->rx_state = RX_STATE_PROC;
+- }
+- }
+-
+- if ( session->rx_state == RX_STATE_PROC ) {
+- mxit_parse_packet( session );
+-
+-#if 0
+- if ( next ) {
+- /* there is another packet of which we read some data */
+-
+- /* reset input */
+- session->rx_state = RX_STATE_RLEN;
+- session->rx_lbuf[0] = '\0';
+- session->rx_i = 0;
+- session->rx_res = 0;
+-
+- /* move read data */
+- len = next - buf;
+- buflen = len;
+- memcpy( buf, next, len );
+- goto nextpacket;
+- }
+-#endif
+-
+- /* we are done */
+- goto done;
+- }
+-
+- return;
+-done:
+- close( session->fd );
+- purple_input_remove( session->http_handler );
+- session->http_handler = 0;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback invoked once the connection has been established to the HTTP server,
+- * or on connection failure.
+- *
+- * @param user_data The MXit session object
+- * @param source The file-descriptor associated with the connection
+- * @param error_message Message explaining why the connection failed
+- */
+-static void mxit_cb_http_connect( gpointer user_data, gint source, const gchar* error_message )
+-{
+- struct http_request* req = (struct http_request*) user_data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect\n" );
+-
+- /* source is the file descriptor of the new connection */
+- if ( source < 0 ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_http_connect failed: %s\n", error_message );
+- purple_connection_error( req->session->con, _( "Unable to connect to the MXit HTTP server. Please check your server settings." ) );
+- return;
+- }
+-
+- /* we now have an open and active TCP connection to the mxit server */
+- req->session->fd = source;
+-
+- /* reset the receive buffer */
+- req->session->rx_state = RX_STATE_RLEN;
+- req->session->rx_lbuf[0] = '\0';
+- req->session->rx_i = 0;
+- req->session->rx_res = 0;
+-
+- /* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
+- req->session->http_handler = purple_input_add( req->session->fd, PURPLE_INPUT_READ, mxit_cb_http_read, req->session );
+-
+- /* actually send the request to the HTTP server */
+- mxit_http_raw_write( req->session->fd, req->data, req->datalen );
+-
+- /* free up resources */
+- free_http_request( req );
+- req = NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Create HTTP connection for sending a HTTP request
+- *
+- * @param session The MXit session object
+- * @param host The server name to connect to
+- * @param port The port number to connect to
+- * @param data The HTTP request data (including HTTP headers etc.)
+- * @param datalen The HTTP request data length
+- */
+-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen )
+-{
+- PurpleProxyConnectData* con = NULL;
+- struct http_request* req;
+-
+- /* build the http request */
+- req = g_new0( struct http_request, 1 );
+- req->session = session;
+- req->host = host;
+- req->port = port;
+- req->data = g_malloc0( datalen );
+- memcpy( req->data, data, datalen );
+- req->datalen = datalen;
+-
+- /* open connection to the HTTP server */
+- con = purple_proxy_connect( NULL, session->acc, host, port, mxit_cb_http_connect, req );
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/http.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/http.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/http.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,47 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit client protocol implementation --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-
+-#ifndef _MXIT_HTTP_H_
+-#define _MXIT_HTTP_H_
+-
+-
+-
+-struct http_request
+-{
+- struct MXitSession* session;
+- char* host;
+- int port;
+- char* data;
+- int datalen;
+-};
+-
+-
+-void mxit_http_send_request( struct MXitSession* session, char* host, int port, const char* data, int datalen );
+-
+-
+-
+-#endif /* _MXIT_HTTP_H_ */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/login.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/login.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,798 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit user login functionality --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "cipher.h"
+-#include "login.h"
+-#include "profile.h"
+-
+-/* requesting captcha size */
+-#define MXIT_CAPTCHA_HEIGHT 50
+-#define MXIT_CAPTCHA_WIDTH 150
+-
+-
+-/* prototypes */
+-static void mxit_register_view( struct MXitSession* session );
+-static void get_clientinfo( struct MXitSession* session );
+-
+-
+-/*------------------------------------------------------------------------
+- * Create a new mxit session object
+- *
+- * @return The MXit session object
+- */
+-static struct MXitSession* mxit_create_object( PurpleAccount* account )
+-{
+- struct MXitSession* session = NULL;
+- PurpleConnection* con = NULL;
+-
+- /* currently the wapsite does not handle a '+' in front of the username (mxitid) so we just strip it */
+- if ( account->username[0] == '+' ) {
+- char* fixed;
+-
+- /* cut off the '+' */
+- fixed = g_strdup( &account->username[1] );
+- purple_account_set_username( account, fixed );
+- g_free( fixed );
+- }
+-
+- session = g_new0( struct MXitSession, 1 );
+-
+- /* configure the connection (reference: "libpurple/connection.h") */
+- con = purple_account_get_connection( account );
+- con->proto_data = session;
+- con->flags |= PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC | PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_SUPPORT_MOODS;
+- session->con = con;
+-
+- /* add account */
+- session->acc = account;
+-
+- /* configure the session (reference: "libpurple/account.h") */
+- g_strlcpy( session->server, purple_account_get_string( account, MXIT_CONFIG_SERVER_ADDR, DEFAULT_SERVER ), sizeof( session->server ) );
+- g_strlcpy( session->http_server, purple_account_get_string( account, MXIT_CONFIG_HTTPSERVER, DEFAULT_HTTP_SERVER ), sizeof( session->http_server ) );
+- session->port = purple_account_get_int( account, MXIT_CONFIG_SERVER_PORT, DEFAULT_PORT );
+- g_strlcpy( session->distcode, purple_account_get_string( account, MXIT_CONFIG_DISTCODE, "" ), sizeof( session->distcode ) );
+- g_strlcpy( session->clientkey, purple_account_get_string( account, MXIT_CONFIG_CLIENTKEY, "" ), sizeof( session->clientkey ) );
+- g_strlcpy( session->dialcode, purple_account_get_string( account, MXIT_CONFIG_DIALCODE, "" ), sizeof( session->dialcode ) );
+- session->http = purple_account_get_bool( account, MXIT_CONFIG_USE_HTTP, FALSE );
+- session->iimages = g_hash_table_new( g_str_hash, g_str_equal );
+- session->rx_state = RX_STATE_RLEN;
+- session->http_interval = MXIT_HTTP_POLL_MIN;
+- session->http_last_poll = mxit_now_milli();
+-
+- return session;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * We now have a connection established with MXit, so we can start the
+- * login procedure
+- *
+- * @param session The MXit session object
+- */
+-static void mxit_connected( struct MXitSession* session )
+-{
+- int state;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_connected\n" );
+-
+- session->flags |= MXIT_FLAG_CONNECTED;
+- purple_connection_update_progress( session->con, _( "Logging In..." ), 2, 4 );
+-
+- /* create a timer to send a ping packet if the connection is idle */
+- session->last_tx = mxit_now_milli();
+-
+- /* encrypt the user password */
+- session->encpwd = mxit_encrypt_password( session );
+-
+- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+- if ( state == MXIT_STATE_LOGIN ) {
+- /* create and send login packet */
+- mxit_send_login( session );
+- }
+- else {
+- if ( !session->profile ) {
+- /* we have lost the session profile, so ask the user to enter it again */
+- mxit_register_view( session );
+- }
+- else {
+- /* create and send the register packet */
+- mxit_send_register( session );
+- }
+- }
+-
+- /* enable signals */
+- mxit_enable_signals( session );
+-
+-#ifdef MXIT_LINK_CLICK
+- /* register for uri click notification */
+- mxit_register_uri_handler();
+-#endif
+-
+- /* start the polling if this is a HTTP connection */
+- if ( session->http ) {
+- session->http_timer_id = purple_timeout_add_seconds( 2, mxit_manage_polling, session );
+- }
+-
+- /* This timer might already exist if we're registering a new account */
+- if ( session->q_slow_timer_id == 0 ) {
+- /* start the tx queue manager timer */
+- session->q_slow_timer_id = purple_timeout_add_seconds( 2, mxit_manage_queue_slow, session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback invoked once the connection has been established to the MXit server,
+- * or on connection failure.
+- *
+- * @param user_data The MXit session object
+- * @param source The file-descriptor associated with the connection
+- * @param error_message Message explaining why the connection failed
+- */
+-static void mxit_cb_connect( gpointer user_data, gint source, const gchar* error_message )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect\n" );
+-
+- /* source is the file descriptor of the new connection */
+- if ( source < 0 ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_connect failed: %s\n", error_message );
+- purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
+- return;
+- }
+-
+- /* we now have an open and active TCP connection to the mxit server */
+- session->fd = source;
+-
+- /* start listening on the open connection for messages from the server (reference: "libpurple/eventloop.h") */
+- session->con->inpa = purple_input_add( session->fd, PURPLE_INPUT_READ, mxit_cb_rx, session );
+-
+- mxit_connected( session );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Attempt to establish a connection to the MXit server.
+- *
+- * @param session The MXit session object
+- */
+-static void mxit_login_connect( struct MXitSession* session )
+-{
+- PurpleProxyConnectData* data = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_login_connect\n" );
+-
+- purple_connection_update_progress( session->con, _( "Connecting..." ), 1, 4 );
+-
+- /*
+- * at this stage we have all the user's information we require
+- * for logging into MXit. we will now create a new connection to
+- * a MXit server.
+- */
+-
+- if ( !session->http ) {
+- /* socket connection */
+- data = purple_proxy_connect( session->con, session->acc, session->server, session->port, mxit_cb_connect, session );
+- if ( !data ) {
+- purple_connection_error( session->con, _( "Unable to connect to the MXit server. Please check your server settings." ) );
+- return;
+- }
+- }
+- else {
+- /* http connection */
+- mxit_connected( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Register a new account with MXit
+- *
+- * @param gc The connection object
+- * @param fields This is the fields filled-in by the user
+- */
+-static void mxit_cb_register_ok( PurpleConnection *gc, PurpleRequestFields *fields )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- struct MXitProfile* profile = session->profile;
+- const char* str;
+- const char* pin;
+- const char* err = NULL;
+- int len;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_ok\n" );
+-
+- if ( !PURPLE_CONNECTION_IS_VALID( gc ) ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Unable to register; account offline.\n" );
+- return;
+- }
+-
+- /* nickname */
+- str = purple_request_fields_get_string( fields, "nickname" );
+- if ( ( !str ) || ( strlen( str ) < 3 ) ) {
+- err = _( "The Display Name you entered is too short." );
+- goto out;
+- }
+- g_strlcpy( profile->nickname, str, sizeof( profile->nickname ) );
+-
+- /* birthdate */
+- str = purple_request_fields_get_string( fields, "bday" );
+- if ( ( !str ) || ( strlen( str ) < 10 ) || ( !validateDate( str ) ) ) {
+- err = _( "The birthday you entered is invalid. The correct format is: 'YYYY-MM-DD'." );
+- goto out;
+- }
+- g_strlcpy( profile->birthday, str, sizeof( profile->birthday ) );
+-
+- /* gender */
+- profile->male = ( purple_request_fields_get_choice( fields, "male" ) != 0 );
+-
+- /* pin */
+- pin = purple_request_fields_get_string( fields, "pin" );
+- if ( !pin ) {
+- err = _( "The PIN you entered is invalid." );
+- goto out;
+- }
+- len = strlen( pin );
+- if ( ( len < 7 ) || ( len > 10 ) ) {
+- err = _( "The PIN you entered has an invalid length [7-10]." );
+- goto out;
+- }
+- for ( i = 0; i < len; i++ ) {
+- if ( !g_ascii_isdigit( pin[i] ) ) {
+- err = _( "The PIN is invalid. It should only consist of digits [0-9]." );
+- goto out;
+- }
+- }
+- str = purple_request_fields_get_string( fields, "pin2" );
+- if ( ( !str ) || ( strcmp( pin, str ) != 0 ) ) {
+- err = _( "The two PINs you entered do not match." );
+- goto out;
+- }
+- g_strlcpy( profile->pin, pin, sizeof( profile->pin ) );
+-
+-out:
+- if ( !err ) {
+- purple_account_set_password( session->acc, session->profile->pin );
+- mxit_login_connect( session );
+- }
+- else {
+- /* show error to user */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Registration Error" ), err );
+- mxit_register_view( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Register a new account with MXit
+- *
+- * @param gc The connection object
+- * @param fields This is the fields filled-in by the user
+- */
+-static void mxit_cb_register_cancel( PurpleConnection *gc, PurpleRequestFields *fields )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_register_cancel\n" );
+-
+- /* disconnect */
+- purple_account_disconnect( gc->account );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Show a window to the user so that he can enter his information
+- *
+- * @param session The MXit session object
+- */
+-static void mxit_register_view( struct MXitSession* session )
+-{
+- struct MXitProfile* profile;
+- PurpleRequestFields* fields;
+- PurpleRequestFieldGroup* group;
+- PurpleRequestField* field;
+-
+- if ( !session->profile ) {
+- /* we need to create a profile object here */
+- session->profile = g_new0( struct MXitProfile, 1 );
+- }
+- profile = session->profile;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new( NULL );
+- purple_request_fields_add_group( fields, group );
+-
+- /* mxit login name */
+- field = purple_request_field_string_new( "loginname", _( "MXit ID" ), purple_account_get_username( session->acc ), FALSE );
+- purple_request_field_string_set_editable( field, FALSE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* nick name (required) */
+- field = purple_request_field_string_new( "nickname", _( "Display Name" ), profile->nickname, FALSE );
+- purple_request_field_set_required( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* birthday (required) */
+- field = purple_request_field_string_new( "bday", _( "Birthday" ), profile->birthday, FALSE );
+- purple_request_field_string_set_default_value( field, "YYYY-MM-DD" );
+- purple_request_field_set_required( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* gender */
+- field = purple_request_field_choice_new( "male", _( "Gender" ), ( profile->male ) ? 1 : 0 );
+- purple_request_field_choice_add( field, _( "Female" ) ); /* 0 */
+- purple_request_field_choice_add( field, _( "Male" ) ); /* 1 */
+- purple_request_field_group_add_field( group, field );
+-
+- /* pin (required) */
+- field = purple_request_field_string_new( "pin", _( "PIN" ), profile->pin, FALSE );
+- purple_request_field_string_set_masked( field, TRUE );
+- purple_request_field_set_required( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+- field = purple_request_field_string_new( "pin2", _( "Verify PIN" ), "", FALSE );
+- purple_request_field_string_set_masked( field, TRUE );
+- purple_request_field_set_required( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* show the form to the user to complete */
+- purple_request_fields( session->con, _( "Register New MXit Account" ), _( "Register New MXit Account" ), _( "Please fill in the following fields:" ), fields, _( "OK" ), G_CALLBACK( mxit_cb_register_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_register_cancel ), session->acc, NULL, NULL, session->con );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback function invoked once the Authorization information has been submitted
+- * to the MXit WAP site.
+- *
+- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
+- * @param user_data The MXit session object
+- * @param url_text The data returned from the WAP site
+- * @param len The length of the data returned
+- * @param error_message Descriptive error message
+- */
+-static void mxit_cb_clientinfo2( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+- gchar** parts;
+- gchar** host;
+- int state;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb2\n" );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP RESPONSE: '%s'\n", url_text );
+-#endif
+-
+- if ( !url_text ) {
+- /* no reply from the WAP site */
+- purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
+- return;
+- }
+-
+- /* explode the response from the WAP site into an array */
+- parts = g_strsplit( url_text, ";", 15 );
+-
+- if ( !parts ) {
+- /* wapserver error */
+- purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
+- return;
+- }
+-
+- /* check wapsite return code */
+- switch ( parts[0][0] ) {
+- case '0' :
+- /* valid reply! */
+- break;
+- case '1' :
+- purple_connection_error( session->con, _( "Wrong security code entered. Please try again later." ) );
+- return;
+- case '2' :
+- purple_connection_error( session->con, _( "Your session has expired. Please try again later." ) );
+- return;
+- case '5' :
+- purple_connection_error( session->con, _( "Invalid country selected. Please try again." ) );
+- return;
+- case '6' :
+- purple_connection_error( session->con, _( "The MXit ID you entered is not registered. Please register first." ) );
+- return;
+- case '7' :
+- purple_connection_error( session->con, _( "The MXit ID you entered is already registered. Please choose another." ) );
+- /* this user's account already exists, so we need to change the registration login flag to be login */
+- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+- return;
+- case '3' :
+- case '4' :
+- default :
+- purple_connection_error( session->con, _( "Internal error. Please try again later." ) );
+- return;
+- }
+-
+- /* now parse and split the distribution code and the client key */
+- g_strlcpy( session->distcode, &parts[1][2], 36 + 1 );
+- g_strlcpy( session->clientkey, &parts[1][38], 8 + 1 );
+-
+- /* get the dial code for the client */
+- g_strlcpy( session->dialcode, parts[4], sizeof( session->dialcode ) );
+-
+- /* parse the proxy server address and port number */
+- host = g_strsplit( parts[2], ":", 4 );
+- g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
+- session->port = atoi( &host[2][0] );
+-
+- /* parse the http proxy server address and port number */
+- g_strlcpy( session->http_server, parts[3], sizeof( session->http_server ) );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "distcode='%s', clientkey='%s', dialcode='%s'\n", session->distcode, session->clientkey, session->dialcode );
+- purple_debug_info( MXIT_PLUGIN_ID, "sock_server='%s', http_server='%s', port='%i', cc='%s'\n", session->server, session->http_server, session->port, parts[11] );
+-
+- /* save the information (reference: "libpurple/account.h") */
+- purple_account_set_string( session->acc, MXIT_CONFIG_DISTCODE, session->distcode );
+- purple_account_set_string( session->acc, MXIT_CONFIG_CLIENTKEY, session->clientkey );
+- purple_account_set_string( session->acc, MXIT_CONFIG_DIALCODE, session->dialcode );
+- purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
+- purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
+- purple_account_set_string( session->acc, MXIT_CONFIG_HTTPSERVER, session->http_server );
+-
+- /* update the state */
+- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+- if ( state == MXIT_STATE_REGISTER1 )
+- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER2 );
+-
+- /* freeup the memory */
+- g_strfreev( host );
+- g_strfreev( parts );
+-
+- if ( state == MXIT_STATE_LOGIN ) {
+- /* now we can continue with the login process */
+- mxit_login_connect( session );
+- }
+- else {
+- /* the user is registering so we need to get more information from him/her first to complete the process */
+- mxit_register_view( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free up the data associated with the Authorization process.
+- *
+- * @param data The data object to free
+- */
+-static void free_logindata( struct login_data* data )
+-{
+- if ( !data )
+- return;
+-
+- /* free up the login resources */
+- g_free( data->wapserver );
+- g_free( data->sessionid );
+- g_free( data->captcha );
+- g_free( data->cc );
+- g_free( data->locale );
+- g_free( data );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * This function is called when the user accepts the Authorization form.
+- *
+- * @param gc The connection object
+- * @param fields The list of fields in the accepted form
+- */
+-static void mxit_cb_captcha_ok( PurpleConnection* gc, PurpleRequestFields* fields )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleUtilFetchUrlData* url_data;
+- PurpleRequestField* field;
+- const char* captcha_resp;
+- GList* entries;
+- GList* entry;
+- char* url;
+- int state;
+-
+- /* get the captcha response */
+- captcha_resp = purple_request_fields_get_string( fields, "code" );
+- if ( ( captcha_resp == NULL ) || ( captcha_resp[0] == '\0' ) ) {
+- /* the user did not fill in the captcha */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( "You did not enter the security code" ) );
+- free_logindata( session->logindata );
+- purple_account_disconnect( session->acc );
+- return;
+- }
+-
+- /* get chosen country */
+- field = purple_request_fields_get_field( fields, "country" );
+- entries = purple_request_field_list_get_selected( field );
+- entry = g_list_first( entries );
+- session->logindata->cc = purple_request_field_list_get_data( field, entry->data );
+- purple_account_set_string( session->acc, MXIT_CONFIG_COUNTRYCODE, session->logindata->cc );
+-
+- /* get chosen language */
+- field = purple_request_fields_get_field( fields, "locale" );
+- entries = purple_request_field_list_get_selected( field );
+- entry = g_list_first( entries );
+- session->logindata->locale = purple_request_field_list_get_data( field, entry->data );
+- purple_account_set_string( session->acc, MXIT_CONFIG_LOCALE, session->logindata->locale );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "cc='%s', locale='%s', captcha='%s'\n", session->logindata->cc, session->logindata->locale, captcha_resp );
+-#endif
+-
+- /* get state */
+- state = purple_account_get_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+-
+- url = g_strdup_printf( "%s?type=getpid&sessionid=%s&login=%s&ver=%i.%i.%i&clientid=%s&cat=%s&chalresp=%s&cc=%s&loc=%s&path=%i&brand=%s&model=%s&h=%i&w=%i&ts=%li",
+- session->logindata->wapserver, session->logindata->sessionid, purple_url_encode( session->acc->username ), PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CLIENT_ID, MXIT_CP_ARCH,
+- captcha_resp, session->logindata->cc, session->logindata->locale, ( state == MXIT_STATE_REGISTER1 ) ? 0 : 1, MXIT_CP_PLATFORM, MXIT_CP_OS,
+- MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
+- url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo2, session );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
+-#endif
+- g_free( url );
+-
+- /* free up the login resources */
+- free_logindata( session->logindata );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * This function is called when the user cancels the Authorization form.
+- *
+- * @param gc The connection object
+- * @param fields The list of fields in the cancelled form
+- */
+-static void mxit_cb_captcha_cancel( PurpleConnection* gc, PurpleRequestFields* fields )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- /* free up the login resources */
+- free_logindata( session->logindata );
+-
+- /* we cannot continue, so we disconnect this account */
+- purple_account_disconnect( session->acc );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback function invoked once the client information has been retrieved from
+- * the MXit WAP site. Display page where user can select their authorization information.
+- *
+- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
+- * @param user_data The MXit session object
+- * @param url_text The data returned from the WAP site
+- * @param len The length of the data returned
+- * @param error_message Descriptive error message
+- */
+-static void mxit_cb_clientinfo1( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+- struct login_data* logindata;
+- PurpleRequestFields* fields;
+- PurpleRequestFieldGroup* group = NULL;
+- PurpleRequestField* field = NULL;
+- gchar** parts;
+- gchar** countries;
+- gchar** locales;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_clientinfo_cb1\n" );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "RESPONSE: %s\n", url_text );
+-#endif
+-
+- if ( !url_text ) {
+- /* no reply from the WAP site */
+- purple_connection_error( session->con, _( "Error contacting the MXit WAP site. Please try again later." ) );
+- return;
+- }
+-
+- /* explode the response from the WAP site into an array */
+- parts = g_strsplit( url_text, ";", 15 );
+-
+- if ( ( !parts ) || ( parts[0][0] != '0' ) ) {
+- /* server could not find the user */
+- purple_connection_error( session->con, _( "MXit is currently unable to process the request. Please try again later." ) );
+- return;
+- }
+-
+- /* save received settings */
+- logindata = g_new0( struct login_data, 1 );
+- logindata->wapserver = g_strdup( parts[1] );
+- logindata->sessionid = g_strdup( parts[2] );
+- session->logindata = logindata;
+-
+- /* now generate the popup requesting the user for action */
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new( NULL );
+- purple_request_fields_add_group( fields, group );
+-
+- /* add the captcha */
+- logindata->captcha = purple_base64_decode( parts[3], &logindata->captcha_size );
+- field = purple_request_field_image_new( "captcha", _( "Security Code" ), (gchar*) logindata->captcha, logindata->captcha_size );
+- purple_request_field_group_add_field( group, field );
+-
+- /* ask for input (required) */
+- field = purple_request_field_string_new( "code", _( "Enter Security Code" ), NULL, FALSE );
+- purple_request_field_set_required( field, TRUE );
+- purple_request_field_group_add_field( group, field );
+-
+- /* choose your country, but be careful, we already know your IP! ;-) */
+- countries = g_strsplit( parts[4], ",", 500 );
+- field = purple_request_field_list_new( "country", _( "Your Country" ) );
+- purple_request_field_list_set_multi_select( field, FALSE );
+- for ( i = 0; countries[i]; i++ ) {
+- gchar** country;
+-
+- country = g_strsplit( countries[i], "|", 2 );
+- if ( !country ) {
+- /* oops, this is not good, time to bail */
+- break;
+- }
+- purple_request_field_list_add( field, country[1], g_strdup( country[0] ) );
+- if ( strcmp( country[1], parts[6] ) == 0 ) {
+- /* based on the user's IP, this is his current country code, so we default to it */
+- purple_request_field_list_add_selected( field, country[1] );
+- }
+- g_strfreev( country );
+- }
+- purple_request_field_group_add_field( group, field );
+-
+- /* choose your language */
+- locales = g_strsplit( parts[5], ",", 200 );
+- field = purple_request_field_list_new( "locale", _( "Your Language" ) );
+- purple_request_field_list_set_multi_select( field, FALSE );
+- for ( i = 0; locales[i]; i++ ) {
+- gchar** locale;
+-
+- locale = g_strsplit( locales[i], "|", 2 );
+- if ( !locale ) {
+- /* oops, this is not good, time to bail */
+- break;
+- }
+- purple_request_field_list_add( field, locale[1], g_strdup( locale[0] ) );
+- g_strfreev( locale );
+- }
+- purple_request_field_list_add_selected( field, "English" );
+- purple_request_field_group_add_field( group, field );
+-
+- /* display the form to the user and wait for his/her input */
+- purple_request_fields( session->con, "MXit", _( "MXit Authorization" ), _( "MXit account validation" ), fields,
+- _( "Continue" ), G_CALLBACK( mxit_cb_captcha_ok ), _( "Cancel" ), G_CALLBACK( mxit_cb_captcha_cancel ), session->acc, NULL, NULL, session->con );
+-
+- /* freeup the memory */
+- g_strfreev( parts );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Initiate a request for the client information (distribution code, client key, etc)
+- * required for logging in from the MXit WAP site.
+- *
+- * @param session The MXit session object
+- */
+-static void get_clientinfo( struct MXitSession* session )
+-{
+- PurpleUtilFetchUrlData* url_data;
+- const char* wapserver;
+- char* url;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "get_clientinfo\n" );
+-
+- purple_connection_update_progress( session->con, _( "Retrieving User Information..." ), 0, 4 );
+-
+- /* get the WAP site as was configured by the user in the advanced settings */
+- wapserver = purple_account_get_string( session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
+-
+- /* reference: "libpurple/util.h" */
+- url = g_strdup_printf( "%s/res/?type=challenge&getcountries=true&getlanguage=true&getimage=true&h=%i&w=%i&ts=%li", wapserver, MXIT_CAPTCHA_HEIGHT, MXIT_CAPTCHA_WIDTH, time( NULL ) );
+- url_data = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_clientinfo1, session );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP REQUEST: '%s'\n", url );
+-#endif
+- g_free( url );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Log the user into MXit.
+- *
+- * @param account The account object
+- */
+-void mxit_login( PurpleAccount* account )
+-{
+- struct MXitSession* session = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_login\n" );
+-
+- /* create and save a new mxit session */
+- session = mxit_create_object( account );
+-
+- /*
+- * before we can login we need to have a valid distribution code and client key for authentication.
+- * if we don't have any info saved from a previous login, we need to get it from the MXit WAP site.
+- * we do cache it, so this step is only done on the very first login for each account.
+- */
+- if ( ( session->distcode == NULL ) || ( strlen( session->distcode ) == 0 ) ) {
+- /* this must be the very first login, so we need to retrieve the user information */
+- get_clientinfo( session );
+- }
+- else {
+- /* we can continue with the login */
+- mxit_login_connect( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Perform a reconnect to the MXit server, and maintain same session object.
+- *
+- * @param account The account object
+- */
+-void mxit_reconnect( struct MXitSession* session )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_reconnect\n" );
+-
+- /* remove the input cb function */
+- if ( session->con->inpa ) {
+- purple_input_remove( session->con->inpa );
+- session->con->inpa = 0;
+- }
+-
+- /* close existing connection */
+- session->flags &= ~MXIT_FLAG_CONNECTED;
+- purple_proxy_connect_cancel_with_handle( session->con );
+-
+- /* perform the re-connect */
+- mxit_login_connect( session );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Register a new account with MXit
+- *
+- * @param acc The account object
+- */
+-void mxit_register( PurpleAccount* account )
+-{
+- struct MXitSession* session = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_register\n" );
+-
+- /* create and save a new mxit session */
+- session = mxit_create_object( account );
+- purple_account_set_int( account, MXIT_CONFIG_STATE, MXIT_STATE_REGISTER1 );
+-
+- get_clientinfo( session );
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/login.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/login.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/login.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,45 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit user login functionality --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_LOGIN_H_
+-#define _MXIT_LOGIN_H_
+-
+-
+-struct login_data {
+- char* wapserver; /* direct WAP server for postback */
+- char* sessionid; /* unique session id */
+- guchar* captcha; /* actual captcha (PNG) */
+- gsize captcha_size; /* captcha size */
+- char* cc; /* country code */
+- char* locale; /* locale (language) */
+-};
+-
+-
+-void mxit_login( PurpleAccount* account );
+-void mxit_register( PurpleAccount* account );
+-void mxit_reconnect( struct MXitSession* session );
+-
+-
+-#endif /* _MXIT_LOGIN_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,65 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-MXITSOURCES = \
+- actions.c \
+- actions.h \
+- aes.c \
+- aes.h \
+- chunk.c \
+- chunk.h \
+- cipher.c \
+- cipher.h \
+- filexfer.c \
+- filexfer.h \
+- formcmds.c \
+- formcmds.h \
+- http.c \
+- http.h \
+- login.c \
+- login.h \
+- markup.c \
+- markup.h \
+- multimx.c \
+- multimx.h \
+- mxit.c \
+- mxit.h \
+- profile.c \
+- profile.h \
+- protocol.c \
+- protocol.h \
+- roster.c \
+- roster.h \
+- splashscreen.c \
+- splashscreen.h \
+- voicevideo.c \
+- voicevideo.h
+-
+-
+-AM_CFLAGS = $(st)
+-
+-libmxit_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_MXIT
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libmxit.la
+-libmxit_la_SOURCES = $(MXITSOURCES)
+-libmxit_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libmxit.la
+-libmxit_la_SOURCES = $(MXITSOURCES)
+-libmxit_la_LIBADD = $(GLIB_LIBS)
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,909 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/mxit
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-@STATIC_MXIT_FALSE@libmxit_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+-am__libmxit_la_SOURCES_DIST = actions.c actions.h aes.c aes.h chunk.c \
+- chunk.h cipher.c cipher.h filexfer.c filexfer.h formcmds.c \
+- formcmds.h http.c http.h login.c login.h markup.c markup.h \
+- multimx.c multimx.h mxit.c mxit.h profile.c profile.h \
+- protocol.c protocol.h roster.c roster.h splashscreen.c \
+- splashscreen.h voicevideo.c voicevideo.h
+-am__objects_1 = libmxit_la-actions.lo libmxit_la-aes.lo \
+- libmxit_la-chunk.lo libmxit_la-cipher.lo \
+- libmxit_la-filexfer.lo libmxit_la-formcmds.lo \
+- libmxit_la-http.lo libmxit_la-login.lo libmxit_la-markup.lo \
+- libmxit_la-multimx.lo libmxit_la-mxit.lo libmxit_la-profile.lo \
+- libmxit_la-protocol.lo libmxit_la-roster.lo \
+- libmxit_la-splashscreen.lo libmxit_la-voicevideo.lo
+-@STATIC_MXIT_FALSE@am_libmxit_la_OBJECTS = $(am__objects_1)
+-@STATIC_MXIT_TRUE@am_libmxit_la_OBJECTS = $(am__objects_1)
+-libmxit_la_OBJECTS = $(am_libmxit_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libmxit_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmxit_la_CFLAGS) \
+- $(CFLAGS) $(libmxit_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_MXIT_FALSE@am_libmxit_la_rpath = -rpath $(pkgdir)
+-@STATIC_MXIT_TRUE@am_libmxit_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libmxit_la_SOURCES)
+-DIST_SOURCES = $(am__libmxit_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-MXITSOURCES = \
+- actions.c \
+- actions.h \
+- aes.c \
+- aes.h \
+- chunk.c \
+- chunk.h \
+- cipher.c \
+- cipher.h \
+- filexfer.c \
+- filexfer.h \
+- formcmds.c \
+- formcmds.h \
+- http.c \
+- http.h \
+- login.c \
+- login.h \
+- markup.c \
+- markup.h \
+- multimx.c \
+- multimx.h \
+- mxit.c \
+- mxit.h \
+- profile.c \
+- profile.h \
+- protocol.c \
+- protocol.h \
+- roster.c \
+- roster.h \
+- splashscreen.c \
+- splashscreen.h \
+- voicevideo.c \
+- voicevideo.h
+-
+-AM_CFLAGS = $(st)
+-libmxit_la_LDFLAGS = -module -avoid-version
+-@STATIC_MXIT_FALSE@st =
+-@STATIC_MXIT_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_MXIT_TRUE@noinst_LTLIBRARIES = libmxit.la
+-@STATIC_MXIT_FALSE@libmxit_la_SOURCES = $(MXITSOURCES)
+-@STATIC_MXIT_TRUE@libmxit_la_SOURCES = $(MXITSOURCES)
+-@STATIC_MXIT_TRUE@libmxit_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_MXIT_FALSE@pkg_LTLIBRARIES = libmxit.la
+-@STATIC_MXIT_FALSE@libmxit_la_LIBADD = $(GLIB_LIBS)
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/mxit/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/mxit/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libmxit.la: $(libmxit_la_OBJECTS) $(libmxit_la_DEPENDENCIES) $(EXTRA_libmxit_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libmxit_la_LINK) $(am_libmxit_la_rpath) $(libmxit_la_OBJECTS) $(libmxit_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-actions.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-aes.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-chunk.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-cipher.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-filexfer.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-formcmds.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-http.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-login.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-markup.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-multimx.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-mxit.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-profile.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-protocol.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-roster.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-splashscreen.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmxit_la-voicevideo.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libmxit_la-actions.lo: actions.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-actions.lo -MD -MP -MF $(DEPDIR)/libmxit_la-actions.Tpo -c -o libmxit_la-actions.lo `test -f 'actions.c' || echo '$(srcdir)/'`actions.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-actions.Tpo $(DEPDIR)/libmxit_la-actions.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='actions.c' object='libmxit_la-actions.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-actions.lo `test -f 'actions.c' || echo '$(srcdir)/'`actions.c
+-
+-libmxit_la-aes.lo: aes.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-aes.lo -MD -MP -MF $(DEPDIR)/libmxit_la-aes.Tpo -c -o libmxit_la-aes.lo `test -f 'aes.c' || echo '$(srcdir)/'`aes.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-aes.Tpo $(DEPDIR)/libmxit_la-aes.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='aes.c' object='libmxit_la-aes.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-aes.lo `test -f 'aes.c' || echo '$(srcdir)/'`aes.c
+-
+-libmxit_la-chunk.lo: chunk.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-chunk.lo -MD -MP -MF $(DEPDIR)/libmxit_la-chunk.Tpo -c -o libmxit_la-chunk.lo `test -f 'chunk.c' || echo '$(srcdir)/'`chunk.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-chunk.Tpo $(DEPDIR)/libmxit_la-chunk.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='chunk.c' object='libmxit_la-chunk.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-chunk.lo `test -f 'chunk.c' || echo '$(srcdir)/'`chunk.c
+-
+-libmxit_la-cipher.lo: cipher.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-cipher.lo -MD -MP -MF $(DEPDIR)/libmxit_la-cipher.Tpo -c -o libmxit_la-cipher.lo `test -f 'cipher.c' || echo '$(srcdir)/'`cipher.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-cipher.Tpo $(DEPDIR)/libmxit_la-cipher.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='cipher.c' object='libmxit_la-cipher.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-cipher.lo `test -f 'cipher.c' || echo '$(srcdir)/'`cipher.c
+-
+-libmxit_la-filexfer.lo: filexfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-filexfer.lo -MD -MP -MF $(DEPDIR)/libmxit_la-filexfer.Tpo -c -o libmxit_la-filexfer.lo `test -f 'filexfer.c' || echo '$(srcdir)/'`filexfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-filexfer.Tpo $(DEPDIR)/libmxit_la-filexfer.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='filexfer.c' object='libmxit_la-filexfer.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-filexfer.lo `test -f 'filexfer.c' || echo '$(srcdir)/'`filexfer.c
+-
+-libmxit_la-formcmds.lo: formcmds.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-formcmds.lo -MD -MP -MF $(DEPDIR)/libmxit_la-formcmds.Tpo -c -o libmxit_la-formcmds.lo `test -f 'formcmds.c' || echo '$(srcdir)/'`formcmds.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-formcmds.Tpo $(DEPDIR)/libmxit_la-formcmds.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='formcmds.c' object='libmxit_la-formcmds.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-formcmds.lo `test -f 'formcmds.c' || echo '$(srcdir)/'`formcmds.c
+-
+-libmxit_la-http.lo: http.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-http.lo -MD -MP -MF $(DEPDIR)/libmxit_la-http.Tpo -c -o libmxit_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-http.Tpo $(DEPDIR)/libmxit_la-http.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='http.c' object='libmxit_la-http.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-http.lo `test -f 'http.c' || echo '$(srcdir)/'`http.c
+-
+-libmxit_la-login.lo: login.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-login.lo -MD -MP -MF $(DEPDIR)/libmxit_la-login.Tpo -c -o libmxit_la-login.lo `test -f 'login.c' || echo '$(srcdir)/'`login.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-login.Tpo $(DEPDIR)/libmxit_la-login.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='login.c' object='libmxit_la-login.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-login.lo `test -f 'login.c' || echo '$(srcdir)/'`login.c
+-
+-libmxit_la-markup.lo: markup.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-markup.lo -MD -MP -MF $(DEPDIR)/libmxit_la-markup.Tpo -c -o libmxit_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-markup.Tpo $(DEPDIR)/libmxit_la-markup.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='markup.c' object='libmxit_la-markup.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
+-
+-libmxit_la-multimx.lo: multimx.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-multimx.lo -MD -MP -MF $(DEPDIR)/libmxit_la-multimx.Tpo -c -o libmxit_la-multimx.lo `test -f 'multimx.c' || echo '$(srcdir)/'`multimx.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-multimx.Tpo $(DEPDIR)/libmxit_la-multimx.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='multimx.c' object='libmxit_la-multimx.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-multimx.lo `test -f 'multimx.c' || echo '$(srcdir)/'`multimx.c
+-
+-libmxit_la-mxit.lo: mxit.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-mxit.lo -MD -MP -MF $(DEPDIR)/libmxit_la-mxit.Tpo -c -o libmxit_la-mxit.lo `test -f 'mxit.c' || echo '$(srcdir)/'`mxit.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-mxit.Tpo $(DEPDIR)/libmxit_la-mxit.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='mxit.c' object='libmxit_la-mxit.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-mxit.lo `test -f 'mxit.c' || echo '$(srcdir)/'`mxit.c
+-
+-libmxit_la-profile.lo: profile.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-profile.lo -MD -MP -MF $(DEPDIR)/libmxit_la-profile.Tpo -c -o libmxit_la-profile.lo `test -f 'profile.c' || echo '$(srcdir)/'`profile.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-profile.Tpo $(DEPDIR)/libmxit_la-profile.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='profile.c' object='libmxit_la-profile.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-profile.lo `test -f 'profile.c' || echo '$(srcdir)/'`profile.c
+-
+-libmxit_la-protocol.lo: protocol.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-protocol.lo -MD -MP -MF $(DEPDIR)/libmxit_la-protocol.Tpo -c -o libmxit_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-protocol.Tpo $(DEPDIR)/libmxit_la-protocol.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='protocol.c' object='libmxit_la-protocol.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-protocol.lo `test -f 'protocol.c' || echo '$(srcdir)/'`protocol.c
+-
+-libmxit_la-roster.lo: roster.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-roster.lo -MD -MP -MF $(DEPDIR)/libmxit_la-roster.Tpo -c -o libmxit_la-roster.lo `test -f 'roster.c' || echo '$(srcdir)/'`roster.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-roster.Tpo $(DEPDIR)/libmxit_la-roster.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='roster.c' object='libmxit_la-roster.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-roster.lo `test -f 'roster.c' || echo '$(srcdir)/'`roster.c
+-
+-libmxit_la-splashscreen.lo: splashscreen.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-splashscreen.lo -MD -MP -MF $(DEPDIR)/libmxit_la-splashscreen.Tpo -c -o libmxit_la-splashscreen.lo `test -f 'splashscreen.c' || echo '$(srcdir)/'`splashscreen.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-splashscreen.Tpo $(DEPDIR)/libmxit_la-splashscreen.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='splashscreen.c' object='libmxit_la-splashscreen.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-splashscreen.lo `test -f 'splashscreen.c' || echo '$(srcdir)/'`splashscreen.c
+-
+-libmxit_la-voicevideo.lo: voicevideo.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -MT libmxit_la-voicevideo.lo -MD -MP -MF $(DEPDIR)/libmxit_la-voicevideo.Tpo -c -o libmxit_la-voicevideo.lo `test -f 'voicevideo.c' || echo '$(srcdir)/'`voicevideo.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmxit_la-voicevideo.Tpo $(DEPDIR)/libmxit_la-voicevideo.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='voicevideo.c' object='libmxit_la-voicevideo.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmxit_la_CFLAGS) $(CFLAGS) -c -o libmxit_la-voicevideo.lo `test -f 'voicevideo.c' || echo '$(srcdir)/'`voicevideo.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/mxit/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,92 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libmxit
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libmxit
+-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 = actions.c \
+- aes.c \
+- chunk.c \
+- cipher.c \
+- filexfer.c \
+- formcmds.c \
+- http.c \
+- login.c \
+- markup.c \
+- multimx.c \
+- mxit.c \
+- profile.c \
+- protocol.c \
+- roster.c \
+- splashscreen.c \
+- voicevideo.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)
+- 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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/markup.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/markup.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1231 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- convert between MXit and libPurple markup --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "markup.h"
+-#include "chunk.h"
+-#include "formcmds.h"
+-#include "roster.h"
+-
+-
+-/* define this to enable emoticon (markup) debugging */
+-#undef MXIT_DEBUG_EMO
+-/* define this to enable markup conversion debugging */
+-#undef MXIT_DEBUG_MARKUP
+-
+-
+-#define MXIT_FRAME_MAGIC "MXF\x01" /* mxit emoticon magic number */
+-#define MXIT_MAX_EMO_ID 16 /* maximum emoticon ID length */
+-#define COLORCODE_LEN 6 /* colour code ID length */
+-
+-
+-/* HTML tag types */
+-#define MXIT_TAG_COLOR 0x01 /* font color tag */
+-#define MXIT_TAG_SIZE 0x02 /* font size tag */
+-#define MXIT_MAX_MSG_TAGS 90 /* maximum tags per message (pigdin hack work around) */
+-
+-/*
+- * a HTML tag object
+- */
+-struct tag {
+- char type;
+- char* value;
+-};
+-
+-
+-#define MXIT_VIBE_MSG_COLOR "#9933FF"
+-#define MXIT_FAREWELL_MSG_COLOR "#949494"
+-
+-
+-/* vibes */
+-static const char* vibes[] = {
+- /* 0 */ N_( "Cool Vibrations" ),
+- /* 1 */ N_( "Purple Rain" ),
+- /* 2 */ N_( "Polite" ),
+- /* 3 */ N_( "Rock n Roll" ),
+- /* 4 */ N_( "Summer Slumber" ),
+- /* 5 */ N_( "Electric Razor" ),
+- /* 6 */ N_( "S.O.S" ),
+- /* 7 */ N_( "Jack Hammer" ),
+- /* 8 */ N_( "Bumble Bee" ),
+- /* 9 */ N_( "Ripple" )
+-};
+-
+-
+-
+-#ifdef MXIT_DEBUG_EMO
+-/*------------------------------------------------------------------------
+- * Dump a byte buffer as hexadecimal to the console for debugging purposes.
+- *
+- * @param buf The data to dump
+- * @param len The length of the data
+- */
+-static void hex_dump( const char* buf, int len )
+-{
+- char msg[256];
+- int pos;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Dumping data (%i bytes)\n", len );
+-
+- memset( msg, 0x00, sizeof( msg ) );
+- pos = 0;
+-
+- for ( i = 0; i < len; i++ ) {
+-
+- if ( pos == 0 )
+- pos += sprintf( &msg[pos], "%04i: ", i );
+-
+- pos += sprintf( &msg[pos], "0x%02X ", (unsigned char) buf[i] );
+-
+- if ( i % 16 == 15 ) {
+- pos += sprintf( &msg[pos], "\n" );
+- purple_debug_info( MXIT_PLUGIN_ID, msg );
+- pos = 0;
+- }
+- else if ( i % 16 == 7 )
+- pos += sprintf( &msg[pos], " " );
+- }
+-
+- if ( pos > 0 ) {
+- pos += sprintf( &msg[pos], "\n" );
+- purple_debug_info( MXIT_PLUGIN_ID, msg );
+- pos = 0;
+- }
+-}
+-#endif
+-
+-
+-/*------------------------------------------------------------------------
+- * Adds a link to a message
+- *
+- * @param mx The Markup message object
+- * @param replydata This is the what will be returned when the link gets clicked
+- * @param isStructured Indicates that the reply is a structured reply
+- * @param displaytext This is the text for the link which will be displayed in the UI
+- */
+-void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext )
+-{
+-#ifdef MXIT_LINK_CLICK
+- char retstr[256];
+- gchar* retstr64;
+- char link[256];
+- int len;
+-
+- /*
+- * The link content is encoded as follows:
+- * MXIT_LINK_KEY | ACCOUNT_USER | ACCOUNT_PROTO | REPLY_TO | REPLY_FORMAT | REPLY_DATA
+- */
+- len = g_snprintf( retstr, sizeof( retstr ), "%s|%s|%s|%s|%i|%s",
+- MXIT_LINK_KEY,
+- purple_account_get_username( mx->session->acc ),
+- purple_account_get_protocol_id( mx->session->acc ),
+- mx->from,
+- isStructured ? 1 : 0,
+- replydata );
+- retstr64 = purple_base64_encode( (const unsigned char*) retstr, len );
+- g_snprintf( link, sizeof( link ), "%s%s", MXIT_LINK_PREFIX, retstr64 );
+- g_free( retstr64 );
+-
+- g_string_append_printf( mx->msg, "<a href=\"%s\">%s</a>", link, displaytext );
+-#else
+- g_string_append_printf( mx->msg, "<b>%s</b>", replydata );
+-#endif
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Extract an ASN.1 formatted length field from the data.
+- *
+- * @param data The source data
+- * @param size The extracted length
+- * @return The number of bytes extracted
+- */
+-static unsigned int asn_getlength( const char* data, int* size )
+-{
+- unsigned int len = 0;
+- unsigned char bytes;
+- unsigned char byte;
+- int i;
+-
+- /* first byte specifies the number of bytes in the length */
+- bytes = ( data[0] & ~0x80 );
+- if ( bytes > sizeof( unsigned int ) ) {
+- /* file too big! */
+- return -1;
+- }
+- data++;
+-
+- /* parse out the actual length */
+- for ( i = 0; i < bytes; i++ ) {
+- byte = data[i];
+- len <<= 8;
+- len += byte;
+- }
+-
+- *size = len;
+- return bytes + 1;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Extract an ASN.1 formatted UTF-8 string field from the data.
+- *
+- * @param data The source data
+- * @param type Expected type of string
+- * @param utf8 The extracted string. Must be deallocated by caller.
+- * @return The number of bytes extracted
+- */
+-static int asn_getUtf8( const char* data, char type, char** utf8 )
+-{
+- int len;
+-
+- /* validate the field type [1 byte] */
+- if ( data[0] != type ) {
+- /* this is not a utf-8 string! */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid UTF-8 encoded string in ASN data (0x%02X)\n", (unsigned char) data[0] );
+- return -1;
+- }
+-
+- len = data[1]; /* length field [1 bytes] */
+- *utf8 = g_malloc( len + 1 );
+- memcpy( *utf8, &data[2], len ); /* data field */
+- (*utf8)[len] = '\0';
+-
+- return ( len + 2 );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free data associated with a Markup message object.
+- *
+- * @param mx The Markup message object
+- */
+-static void free_markupdata( struct RXMsgData* mx )
+-{
+- if ( mx ) {
+- if ( mx->msg )
+- g_string_free( mx->msg, TRUE );
+- if ( mx->from )
+- g_free( mx->from );
+- g_free( mx );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Split the message into smaller messages and send them one at a time
+- * to pidgin to be displayed on the UI
+- *
+- * @param mx The received message object
+- */
+-static void mxit_show_split_message( struct RXMsgData* mx )
+-{
+- GString* msg = NULL;
+- char* ch = NULL;
+- int pos = 0;
+- int start = 0;
+- int l_nl = 0;
+- int l_sp = 0;
+- int l_gt = 0;
+- int stop = 0;
+- int tags = 0;
+- gboolean intag = FALSE;
+-
+- /*
+- * awful hack to work around the awful hack in pidgin to work around GtkIMHtml's
+- * inefficient rendering of messages with lots of formatting changes.
+- * (reference: see the function pidgin_conv_write_conv() in gtkconv.c) the issue
+- * is that when you have more than 100 '<' characters in the message passed to
+- * pidgin, none of the markup (including links) are rendered and thus just dump
+- * all the text as is to the conversation window. this message dump is very
+- * confusing and makes it totally unusable. to work around this we will count
+- * the amount of tags and if its more than the pidgin threshold, we will just
+- * break the message up into smaller parts and send them separately to pidgin.
+- * to the user it will look like multiple messages, but at least he will be able
+- * to use and understand it.
+- */
+-
+- ch = mx->msg->str;
+- pos = start;
+- while ( ch[pos] ) {
+-
+- if ( ch[pos] == '<' ) {
+- tags++;
+- intag = TRUE;
+- }
+- else if ( ch[pos] == '\n' ) {
+- l_nl = pos;
+- }
+- else if ( ch[pos] == '>' ) {
+- l_gt = pos;
+- intag = FALSE;
+- }
+- else if ( ch[pos] == ' ' ) {
+- /* ignore spaces inside tags */
+- if ( !intag )
+- l_sp = pos;
+- }
+- else if ( ( ch[pos] == 'w' ) && ( pos + 4 < mx->msg->len ) && ( memcmp( &ch[pos], "www.", 4 ) == 0 ) ) {
+- tags += 2;
+- }
+- else if ( ( ch[pos] == 'h' ) && ( pos + 8 < mx->msg->len ) && ( memcmp( &ch[pos], "http://", 7 ) == 0 ) ) {
+- tags += 2;
+- }
+-
+- if ( tags > MXIT_MAX_MSG_TAGS ) {
+- /* we have reached the maximum amount of tags pidgin (gtk) can handle per message.
+- so its time to send what we have and then start building a new message */
+-
+- /* now find the right place to break the message */
+- if ( l_nl > start ) {
+- /* break at last '\n' char */
+- stop = l_nl;
+- ch[stop] = '\0';
+- msg = g_string_new( &ch[start] );
+- ch[stop] = '\n';
+- }
+- else if ( l_sp > start ) {
+- /* break at last ' ' char */
+- stop = l_sp;
+- ch[stop] = '\0';
+- msg = g_string_new( &ch[start] );
+- ch[stop] = ' ';
+- }
+- else {
+- /* break at the last '>' char */
+- char t;
+- stop = l_gt + 1;
+- t = ch[stop];
+- ch[stop] = '\0';
+- msg = g_string_new( &ch[start] );
+- ch[stop] = t;
+- stop--;
+- }
+-
+- /* push message to pidgin */
+- serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
+- g_string_free( msg, TRUE );
+- msg = NULL;
+-
+- /* next part need this flag set */
+- mx->flags |= PURPLE_MESSAGE_RAW;
+-
+- tags = 0;
+- start = stop + 1;
+- pos = start;
+- }
+- else
+- pos++;
+- }
+-
+- if ( start != pos ) {
+- /* send the last part of the message */
+-
+- /* build the string */
+- ch[pos] = '\0';
+- msg = g_string_new( &ch[start] );
+- ch[pos] = '\n';
+-
+- /* push message to pidgin */
+- serv_got_im( mx->session->con, mx->from, msg->str, mx->flags, mx->timestamp );
+- g_string_free( msg, TRUE );
+- msg = NULL;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Insert custom emoticons and inline images into the message (if there
+- * are any), then give the message to the UI to display to the user.
+- *
+- * @param mx The received message object
+- */
+-void mxit_show_message( struct RXMsgData* mx )
+-{
+- char* pos;
+- int start;
+- unsigned int end;
+- int emo_ofs;
+- char* ii;
+- char tag[64];
+- int* img_id;
+-
+- if ( mx->got_img ) {
+- /* search and replace all emoticon tags with proper image tags */
+-
+- while ( ( pos = strstr( mx->msg->str, MXIT_II_TAG ) ) != NULL ) {
+- start = pos - mx->msg->str; /* offset at which MXIT_II_TAG starts */
+- emo_ofs = start + strlen( MXIT_II_TAG ); /* offset at which EMO's ID starts */
+- end = emo_ofs + 1; /* offset at which MXIT_II_TAG ends */
+-
+- while ( ( end < mx->msg->len ) && ( mx->msg->str[end] != '>' ) )
+- end++;
+-
+- if ( end == mx->msg->len ) /* end of emoticon tag not found */
+- break;
+-
+- ii = g_strndup(&mx->msg->str[emo_ofs], end - emo_ofs);
+-
+- /* remove inline image tag */
+- g_string_erase( mx->msg, start, ( end - start ) + 1 );
+-
+- /* find the image entry */
+- img_id = (int*) g_hash_table_lookup( mx->session->iimages, ii );
+- if ( !img_id ) {
+- /* inline image not found, so we will just skip it */
+- purple_debug_error( MXIT_PLUGIN_ID, "inline image NOT found (%s)\n", ii );
+- }
+- else {
+- /* insert img tag */
+- g_snprintf( tag, sizeof( tag ), "<img id=\"%i\">", *img_id );
+- g_string_insert( mx->msg, start, tag );
+- }
+-
+- g_free(ii);
+- }
+- }
+-
+-#ifdef MXIT_DEBUG_MARKUP
+- purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (converted): '%s'\n", mx->msg->str );
+-#endif
+-
+- if ( mx->processed ) {
+- /* this message has already been taken care of, so just ignore it here */
+- }
+- else if ( mx->chatid < 0 ) {
+- /* normal chat message */
+- mxit_show_split_message( mx );
+- }
+- else {
+- /* this is a multimx message */
+- serv_got_chat_in( mx->session->con, mx->chatid, mx->from, mx->flags, mx->msg->str, mx->timestamp);
+- }
+-
+- /* freeup resource */
+- free_markupdata( mx );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Extract the custom emoticon ID from the message.
+- *
+- * @param message The input data
+- * @param emid The extracted emoticon ID
+- */
+-static void parse_emoticon_str( const char* message, char* emid )
+-{
+- int i;
+-
+- for ( i = 0; ( message[i] != '\0' && message[i] != '}' && i < MXIT_MAX_EMO_ID ); i++ ) {
+- emid[i] = message[i];
+- }
+-
+- if ( message[i] == '\0' ) {
+- /* end of message reached, ignore the tag */
+- emid[0] = '\0';
+- }
+- else if ( i == MXIT_MAX_EMO_ID ) {
+- /* invalid tag length, ignore the tag */
+- emid[0] = '\0';
+- }
+- else
+- emid[i] = '\0';
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback function invoked when a custom emoticon request to the WAP site completes.
+- *
+- * @param url_data
+- * @param user_data The Markup message object
+- * @param url_text The data returned from the WAP site
+- * @param len The length of the data returned
+- * @param error_message Descriptive error message
+- */
+-static void emoticon_returned( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
+-{
+- struct RXMsgData* mx = (struct RXMsgData*) user_data;
+- const char* data = url_text;
+- unsigned int pos = 0;
+- char emo[16];
+- int id;
+- char* str;
+- int em_size = 0;
+- char* em_data = NULL;
+- char* em_id = NULL;
+- int* intptr = NULL;
+- int res;
+-
+-#ifdef MXIT_DEBUG_EMO
+- purple_debug_info( MXIT_PLUGIN_ID, "emoticon_returned\n" );
+-#endif
+-
+- if ( !url_text ) {
+- /* no reply from the WAP site */
+- purple_debug_error( MXIT_PLUGIN_ID, "Error contacting the MXit WAP site. Please try again later (emoticon).\n" );
+- goto done;
+- }
+-
+-#ifdef MXIT_DEBUG_EMO
+- hex_dump( data, len );
+-#endif
+-
+- /* parse out the emoticon */
+- pos = 0;
+-
+- /* validate the binary data received from the wapsite */
+- if ( memcmp( MXIT_FRAME_MAGIC, &data[pos], strlen( MXIT_FRAME_MAGIC ) ) != 0 ) {
+- /* bad data, magic constant is wrong */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad magic)\n" );
+- goto done;
+- }
+- pos += strlen( MXIT_FRAME_MAGIC );
+-
+- /* validate the image frame desc byte */
+- if ( data[pos] != '\x6F' ) {
+- /* bad frame desc */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame desc)\n" );
+- goto done;
+- }
+- pos++;
+-
+- /* get the data length */
+- res = asn_getlength( &data[pos], &em_size );
+- if ( res <= 0 ) {
+- /* bad frame length */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad frame length)\n" );
+- goto done;
+- }
+- pos += res;
+-#ifdef MXIT_DEBUG_EMO
+- purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
+-#endif
+-
+- /* utf-8 (emoticon name) */
+- res = asn_getUtf8( &data[pos], 0x0C, &str );
+- if ( res <= 0 ) {
+- /* bad utf-8 string */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad name string)\n" );
+- goto done;
+- }
+- pos += res;
+-#ifdef MXIT_DEBUG_EMO
+- purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
+-#endif
+- g_free( str );
+- str = NULL;
+-
+- /* utf-8 (emoticon shortcut) */
+- res = asn_getUtf8( &data[pos], 0x81, &str );
+- if ( res <= 0 ) {
+- /* bad utf-8 string */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad shortcut string)\n" );
+- goto done;
+- }
+- pos += res;
+-#ifdef MXIT_DEBUG_EMO
+- purple_debug_info( MXIT_PLUGIN_ID, "read the string '%s'\n", str );
+-#endif
+- em_id = str;
+-
+- /* validate the image data type */
+- if ( data[pos] != '\x82' ) {
+- /* bad frame desc */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data type)\n" );
+- g_free( em_id );
+- goto done;
+- }
+- pos++;
+-
+- /* get the data length */
+- res = asn_getlength( &data[pos], &em_size );
+- if ( res <= 0 ) {
+- /* bad frame length */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid emoticon received from wapsite (bad data length)\n" );
+- g_free( em_id );
+- goto done;
+- }
+- pos += res;
+-#ifdef MXIT_DEBUG_EMO
+- purple_debug_info( MXIT_PLUGIN_ID, "read the length '%i'\n", em_size );
+-#endif
+-
+- if ( g_hash_table_lookup( mx->session->iimages, em_id ) ) {
+- /* emoticon found in the table, so ignore this one */
+- goto done;
+- }
+-
+- /* make a copy of the data */
+- em_data = g_malloc( em_size );
+- memcpy( em_data, &data[pos], em_size );
+-
+- /* strip the mxit markup tags from the emoticon id */
+- if ( ( em_id[0] == '.' ) && ( em_id[1] == '{' ) ) {
+- parse_emoticon_str( &em_id[2], emo );
+- strcpy( em_id, emo );
+- }
+-
+- /* we now have the emoticon, store it in the imagestore */
+- id = purple_imgstore_add_with_id( em_data, em_size, NULL );
+-
+- /* map the mxit emoticon id to purple image id */
+- intptr = g_malloc( sizeof( int ) );
+- *intptr = id;
+- g_hash_table_insert( mx->session->iimages, em_id, intptr );
+-
+- mx->flags |= PURPLE_MESSAGE_IMAGES;
+-done:
+- mx->img_count--;
+- if ( ( mx->img_count == 0 ) && ( mx->converted ) ) {
+- /*
+- * this was the last outstanding emoticon for this message,
+- * so we can now display it to the user.
+- */
+- mxit_show_message( mx );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a request to the MXit WAP site to download the specified emoticon.
+- *
+- * @param mx The Markup message object
+- * @param id The ID for the emoticon
+- */
+-static void emoticon_request( struct RXMsgData* mx, const char* id )
+-{
+- PurpleUtilFetchUrlData* url_data;
+- const char* wapserver;
+- char* url;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "sending request for emoticon '%s'\n", id );
+-
+- wapserver = purple_account_get_string( mx->session->acc, MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
+-
+- /* reference: "libpurple/util.h" */
+- url = g_strdup_printf( "%s/res/?type=emo&mlh=%i&sc=%s&ts=%li", wapserver, MXIT_EMOTICON_SIZE, id, time( NULL ) );
+- url_data = purple_util_fetch_url_request( url, TRUE, NULL, TRUE, NULL, FALSE, emoticon_returned, mx );
+- g_free( url );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse a Vibe command.
+- *
+- * @param mx The Markup message object
+- * @param message The message text (which contains the vibe)
+- * @return id The length of the message to skip
+- */
+-static int mxit_parse_vibe( struct RXMsgData* mx, const char* message )
+-{
+- int vibeid;
+-
+- vibeid = message[2] - '0';
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Vibe received (%i)\n", vibeid );
+-
+- if ( vibeid > ( ARRAY_SIZE( vibes ) - 1 ) ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "Unsupported vibe received (%i)\n", vibeid );
+- /* unsupported vibe */
+- return 0;
+- }
+-
+- g_string_append_printf( mx->msg, "<font color=\"%s\"><i>%s Vibe...</i></font>", MXIT_VIBE_MSG_COLOR, _( vibes[vibeid] ) );
+- return 2;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Extract the nickname from a chatroom message and display it nicely in
+- * libPurple-style (HTML) markup.
+- *
+- * @param mx The received message data object
+- * @param message The message text
+- * @return The length of the message to skip
+- */
+-static int mxit_extract_chatroom_nick( struct RXMsgData* mx, char* message, int len, int msgflags )
+-{
+- int i;
+-
+- if ( message[0] == '<' ) {
+- /*
+- * The message MIGHT contains an embedded nickname. But we can't
+- * be sure unless we find the end-of-nickname sequence: (>\n)
+- * Search for it....
+- */
+- gboolean found = FALSE;
+-
+- for ( i = 1; i < len; i++ ) {
+- if ( ( message[i] == '\n' ) && ( message[i-1] == '>' ) ) {
+- found = TRUE;
+- message[i-1] = '\0'; /* loose the '>' */
+- i++; /* and skip the new-line */
+- break;
+- }
+- }
+-
+- if ( found ) {
+- gchar* nickname;
+-
+- /*
+- * The message definitely had an embedded nickname - generate a marked-up
+- * message to be displayed.
+- */
+- nickname = g_markup_escape_text( &message[1], -1 );
+-
+- /* Remove any MXit escaping from nickname ("\X" --> "X") */
+- if ( msgflags & CP_MSG_MARKUP ) {
+- int nicklen = strlen( nickname );
+- int j, k;
+-
+- for ( j = 0, k = 0; j < nicklen; j++ ) {
+- if ( nickname[j] == '\\' )
+- j++;
+-
+- nickname[k] = nickname[j];
+- k++;
+- }
+-
+- nickname[k] = '\0'; /* terminate string */
+- }
+-
+- /* add nickname within some BOLD markup to the new converted message */
+- g_string_append_printf( mx->msg, "<b>%s:</b> ", nickname );
+-
+- /* free up the resources */
+- g_free( nickname );
+-
+- return i;
+- }
+- }
+-
+- return 0;
+-}
+-
+-
+-
+-/*------------------------------------------------------------------------
+- * Convert a message containing MXit protocol markup to libPurple-style (HTML) markup.
+- *
+- * @param mx The received message data object
+- * @param message The message text
+- * @param len The length of the message
+- */
+-void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags )
+-{
+- char tmpstr1[128];
+- char* ch;
+- int i = 0;
+-
+- /* tags */
+- gboolean tag_bold = FALSE;
+- gboolean tag_under = FALSE;
+- gboolean tag_italic = FALSE;
+- int font_size = 0;
+-
+-#ifdef MXIT_DEBUG_MARKUP
+- purple_debug_info( MXIT_PLUGIN_ID, "Markup RX (original): '%s'\n", message );
+-#endif
+-
+-
+- /*
+- * supported MXit markup:
+- * '*' bold
+- * '_' underline
+- * '/' italics
+- * '$' highlight text
+- * '.+' inc font size
+- * '.-' dec font size
+- * '#XXXXXX' foreground color
+- * '.{XX}' custom emoticon
+- * '\' escape the following character
+- * '::' MXit commands
+- */
+-
+-
+- if ( is_mxit_chatroom_contact( mx->session, mx->from ) ) {
+- /* chatroom message, so we need to extract and skip the sender's nickname
+- * which is embedded inside the message */
+- i = mxit_extract_chatroom_nick( mx, message, len, msgflags );
+- }
+-
+- /* run through the message and check for custom emoticons and markup */
+- for ( ; i < len; i++ ) {
+- switch ( message[i] ) {
+-
+-
+- /* mxit markup parsing */
+- case '*' :
+- if ( !( msgflags & CP_MSG_MARKUP ) ) {
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+-
+- /* bold markup */
+- if ( !tag_bold )
+- g_string_append( mx->msg, "<b>" );
+- else
+- g_string_append( mx->msg, "</b>" );
+- tag_bold = !tag_bold;
+- break;
+- case '_' :
+- if ( !( msgflags & CP_MSG_MARKUP ) ) {
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+-
+- /* underscore markup */
+- if ( !tag_under )
+- g_string_append( mx->msg, "<u>" );
+- else
+- g_string_append( mx->msg, "</u>" );
+- tag_under = !tag_under;
+- break;
+- case '/' :
+- if ( !( msgflags & CP_MSG_MARKUP ) ) {
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+-
+- /* italics markup */
+- if ( !tag_italic )
+- g_string_append( mx->msg, "<i>" );
+- else
+- g_string_append( mx->msg, "</i>" );
+- tag_italic = !tag_italic;
+- break;
+- case '$' :
+- if ( !( msgflags & CP_MSG_MARKUP ) ) {
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+- else if ( i + 1 >= len ) {
+- /* message too short for complete link */
+- g_string_append_c( mx->msg, '$' );
+- break;
+- }
+-
+- /* find the end tag */
+- ch = strstr( &message[i + 1], "$" );
+- if ( ch ) {
+- /* end found */
+- *ch = '\0';
+- mxit_add_html_link( mx, &message[i + 1], FALSE, &message[i + 1] );
+- *ch = '$';
+- i += ( ch - &message[i + 1] ) + 1;
+- }
+- else {
+- g_string_append_c( mx->msg, message[i] );
+- }
+- /* highlight text */
+- break;
+- case '#' :
+- if ( !( msgflags & CP_MSG_MARKUP ) ) {
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+- else if ( i + COLORCODE_LEN >= len ) {
+- /* message too short for complete colour code */
+- g_string_append_c( mx->msg, '#' );
+- break;
+- }
+-
+- /* foreground (text) color */
+- memcpy( tmpstr1, &message[i + 1], COLORCODE_LEN );
+- tmpstr1[ COLORCODE_LEN ] = '\0'; /* terminate string */
+- if ( strcmp( tmpstr1, "??????" ) == 0 ) {
+- /* need to reset the font */
+- g_string_append( mx->msg, "</font>" );
+- i += COLORCODE_LEN;
+- }
+- else if ( strspn( tmpstr1, "0123456789abcdefABCDEF") == COLORCODE_LEN ) {
+- /* definitely a numeric colour code */
+- g_string_append_printf( mx->msg, "<font color=\"#%s\">", tmpstr1 );
+- i += COLORCODE_LEN;
+- }
+- else {
+- /* not valid colour markup */
+- g_string_append_c( mx->msg, '#' );
+- }
+- break;
+- case '.' :
+- if ( i + 1 >= len ) {
+- /* message too short */
+- g_string_append_c( mx->msg, '.' );
+- break;
+- }
+-
+- if ( ( msgflags & CP_MSG_EMOTICON ) && ( message[i+1] == '{' ) ) {
+- /* custom emoticon */
+- if ( i + 2 >= len ) {
+- /* message too short */
+- g_string_append_c( mx->msg, '.' );
+- break;
+- }
+-
+- parse_emoticon_str( &message[i+2], tmpstr1 );
+- if ( tmpstr1[0] != '\0' ) {
+- mx->got_img = TRUE;
+-
+- if ( g_hash_table_lookup( mx->session->iimages, tmpstr1 ) ) {
+- /* emoticon found in the cache, so we do not have to request it from the WAPsite */
+- }
+- else {
+- /* request emoticon from the WAPsite */
+- mx->img_count++;
+- emoticon_request( mx, tmpstr1 );
+- }
+-
+- g_string_append_printf( mx->msg, MXIT_II_TAG"%s>", tmpstr1 );
+- i += strlen( tmpstr1 ) + 2;
+- }
+- else
+- g_string_append_c( mx->msg, '.' );
+- }
+- else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '+' ) ) {
+- /* increment text size */
+- font_size++;
+- g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+- i++;
+- }
+- else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) {
+- /* decrement text size */
+- font_size--;
+- g_string_append_printf( mx->msg, "<font size=\"%+i\">", font_size );
+- i++;
+- }
+- else
+- g_string_append_c( mx->msg, '.' );
+-
+- break;
+- case '\\' :
+- if ( i + 1 >= len ) {
+- /* message too short for an escaped character */
+- g_string_append_c( mx->msg, '\\' );
+- }
+- else {
+- /* ignore the next character, because its been escaped */
+- g_string_append_c( mx->msg, message[i + 1] );
+- i++;
+- }
+- break;
+-
+-
+- /* command parsing */
+- case ':' :
+- if ( i + 1 >= len ) {
+- /* message too short */
+- g_string_append_c( mx->msg, ':' );
+- break;
+- }
+-
+- if ( message[i+1] == '@' ) {
+- /* this is a vibe! */
+- int size;
+-
+- if ( i + 2 >= len ) {
+- /* message too short */
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+-
+- size = mxit_parse_vibe( mx, &message[i] );
+- if ( size == 0 )
+- g_string_append_c( mx->msg, message[i] );
+- else
+- i += size;
+- }
+- else if ( msgtype != CP_MSGTYPE_COMMAND ) {
+- /* this is not a command message */
+- g_string_append_c( mx->msg, message[i] );
+- }
+- else if ( message[i+1] == ':' ) {
+- /* parse out the command */
+- int size;
+-
+- size = mxit_parse_command( mx, &message[i] );
+- if ( size == 0 )
+- g_string_append_c( mx->msg, ':' );
+- else
+- i += size;
+- }
+- else {
+- g_string_append_c( mx->msg, ':' );
+- }
+- break;
+-
+-
+- /* these aren't MXit markup, but are interpreted by libPurple */
+- case '<' :
+- g_string_append( mx->msg, "&lt;" );
+- break;
+- case '>' :
+- g_string_append( mx->msg, "&gt;" );
+- break;
+- case '&' :
+- g_string_append( mx->msg, "&amp;" );
+- break;
+- case '"' :
+- g_string_append( mx->msg, "&quot;" );
+- break;
+-
+- default :
+- /* text */
+- g_string_append_c( mx->msg, message[i] );
+- break;
+- }
+- }
+-
+- if ( msgflags & CP_MSG_FAREWELL ) {
+- /* this is a farewell message */
+- g_string_prepend( mx->msg, "<font color=\""MXIT_FAREWELL_MSG_COLOR"\"><i>" );
+- g_string_append( mx->msg, "</i></font>" );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Insert an inline image command.
+- *
+- * @param mx The message text as processed so far.
+- * @oaram id The imgstore ID of the inline image.
+- */
+-static void inline_image_add( GString* mx, int id )
+-{
+- PurpleStoredImage *image;
+- gconstpointer img_data;
+- gsize img_size;
+- gchar* enc;
+-
+- image = purple_imgstore_find_by_id( id );
+- if ( image == NULL )
+- return;
+-
+- img_data = purple_imgstore_get_data( image );
+- img_size = purple_imgstore_get_size( image );
+-
+- enc = purple_base64_encode( img_data, img_size );
+-
+- g_string_append( mx, "::op=img|dat=" );
+- g_string_append( mx, enc );
+- g_string_append_c( mx, ':' );
+-
+- g_free( enc );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Convert libpurple (HTML) markup to MXit protocol markup (for sending to MXit).
+- * Any MXit markup codes in the original message also need to be escaped.
+- *
+- * @param message The message text containing libPurple (HTML) markup
+- * @return The message text containing MXit markup
+- */
+-char* mxit_convert_markup_tx( const char* message, int* msgtype )
+-{
+- GString* mx;
+- struct tag* tag;
+- GList* entry;
+- GList* tagstack = NULL;
+- char* reply;
+- char color[8];
+- int len = strlen ( message );
+- int i;
+-
+-#ifdef MXIT_DEBUG_MARKUP
+- purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (original): '%s'\n", message );
+-#endif
+-
+- /*
+- * libPurple uses the following HTML markup codes:
+- * Bold: <b>...</b>
+- * Italics: <i>...</i>
+- * Underline: <u>...</u>
+- * Strikethrough: <s>...</s> (NO MXIT SUPPORT)
+- * Font size: <font size="">...</font>
+- * Font type: <font face="">...</font> (NO MXIT SUPPORT)
+- * Font colour: <font color=#">...</font>
+- * Links: <a href="">...</a>
+- * Newline: <br>
+- * Inline image: <IMG ID="">
+- * The following characters are also encoded:
+- * &amp; &quot; &lt; &gt;
+- */
+-
+- /* new message data */
+- mx = g_string_sized_new( len );
+-
+- /* run through the message and check for HTML markup */
+- for ( i = 0; i < len; i++ ) {
+-
+- switch ( message[i] ) {
+- case '<' :
+- if ( purple_str_has_prefix( &message[i], "<b>" ) || purple_str_has_prefix( &message[i], "</b>" ) ) {
+- /* bold */
+- g_string_append_c( mx, '*' );
+- }
+- else if ( purple_str_has_prefix( &message[i], "<i>" ) || purple_str_has_prefix( &message[i], "</i>" ) ) {
+- /* italics */
+- g_string_append_c( mx, '/' );
+- }
+- else if ( purple_str_has_prefix( &message[i], "<u>" ) || purple_str_has_prefix( &message[i], "</u>" ) ) {
+- /* underline */
+- g_string_append_c( mx, '_' );
+- }
+- else if ( purple_str_has_prefix( &message[i], "<br>" ) ) {
+- /* newline */
+- g_string_append_c( mx, '\n' );
+- }
+- else if ( purple_str_has_prefix( &message[i], "<font size=" ) ) {
+- /* font size */
+- int fontsize;
+-
+- tag = g_new0( struct tag, 1 );
+- tag->type = MXIT_TAG_SIZE;
+- tagstack = g_list_prepend( tagstack, tag );
+- // TODO: implement size control
+- if ( sscanf( &message[i+12], "%i", &fontsize ) ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "Font size set to %i\n", fontsize );
+- }
+- }
+- else if ( purple_str_has_prefix( &message[i], "<font color=" ) ) {
+- /* font colour */
+- tag = g_new0( struct tag, 1 );
+- tag->type = MXIT_TAG_COLOR;
+- tagstack = g_list_append( tagstack, tag );
+- memset( color, 0x00, sizeof( color ) );
+- memcpy( color, &message[i + 13], 7 );
+- g_string_append( mx, color );
+- }
+- else if ( purple_str_has_prefix( &message[i], "</font>" ) ) {
+- /* end of font tag */
+- entry = g_list_last( tagstack );
+- if ( entry ) {
+- tag = entry->data;
+- if ( tag->type == MXIT_TAG_COLOR ) {
+- /* font color reset */
+- g_string_append( mx, "#??????" );
+- }
+- else if ( tag->type == MXIT_TAG_SIZE ) {
+- /* font size */
+- // TODO: implement size control
+- }
+- tagstack = g_list_remove( tagstack, tag );
+- g_free( tag );
+- }
+- }
+- else if ( purple_str_has_prefix( &message[i], "<IMG ID=" ) ) {
+- /* inline image */
+- int imgid;
+-
+- if ( sscanf( &message[i+9], "%i", &imgid ) ) {
+- inline_image_add( mx, imgid );
+- *msgtype = CP_MSGTYPE_COMMAND; /* inline image must be sent as a MXit command */
+- }
+- }
+-
+- /* skip to end of tag ('>') */
+- for ( i++; ( i < len ) && ( message[i] != '>' ) ; i++ );
+-
+- break;
+-
+- case '*' : /* MXit bold */
+- case '_' : /* MXit underline */
+- case '/' : /* MXit italic */
+- case '#' : /* MXit font color */
+- case '$' : /* MXit highlight text */
+- case '\\' : /* MXit escape backslash */
+- g_string_append( mx, "\\" ); /* escape character */
+- g_string_append_c( mx, message[i] ); /* character to escape */
+- break;
+-
+- case '.' : /* might be a MXit font size change, or custom emoticon */
+- if ( i + 1 < len ) {
+- if ( ( message[i+1] == '+' ) || ( message[i+1] == '-' ) )
+- g_string_append( mx, "\\." ); /* escape "." */
+- else
+- g_string_append_c( mx, '.' );
+- }
+- else
+- g_string_append_c( mx, '.' );
+- break;
+-
+- default:
+- g_string_append_c( mx, message[i] );
+- break;
+- }
+- }
+-
+- /* unescape HTML entities to their literal characters (reference: "libpurple/utils.h") */
+- reply = purple_unescape_html( mx->str );
+-
+- g_string_free( mx, TRUE );
+-
+-#ifdef MXIT_DEBUG_MARKUP
+- purple_debug_info( MXIT_PLUGIN_ID, "Markup TX (converted): '%s'\n", reply );
+-#endif
+-
+- return reply;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free an emoticon entry.
+- *
+- * @param key MXit emoticon ID
+- * @param value Imagestore ID for emoticon
+- * @param user_data NULL (unused)
+- * @return TRUE
+- */
+-static gboolean emoticon_entry_free( gpointer key, gpointer value, gpointer user_data )
+-{
+- int* imgid = value;
+-
+- /* key is a string */
+- g_free( key );
+-
+- /* value is 'id' in imagestore */
+- purple_imgstore_unref_by_id( *imgid );
+- g_free( value );
+-
+- return TRUE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free all entries in the emoticon cache.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_free_emoticon_cache( struct MXitSession* session )
+-{
+- g_hash_table_foreach_remove( session->iimages, emoticon_entry_free, NULL );
+- g_hash_table_destroy ( session->iimages );
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/markup.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/markup.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/markup.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,40 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- convert between MXit and libPurple markup --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_MARKUP_H_
+-#define _MXIT_MARKUP_H_
+-
+-#define MXIT_II_TAG "<MXII=" /* inline image placeholder string */
+-
+-
+-void mxit_parse_markup( struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags );
+-char* mxit_convert_markup_tx( const char* message, int* msgtype );
+-void mxit_add_html_link( struct RXMsgData* mx, const char* replydata, gboolean isStructured, const char* displaytext );
+-void mxit_show_message( struct RXMsgData* mx );
+-
+-void mxit_free_emoticon_cache( struct MXitSession* session );
+-
+-
+-#endif /* _MXIT_MARKUP_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/multimx.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/multimx.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,650 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MultiMx GroupChat --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-#include "prpl.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "multimx.h"
+-#include "markup.h"
+-
+-
+-#if 0
+-static void multimx_dump(struct multimx* multimx)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "MultiMX:\n");
+- purple_debug_info(MXIT_PLUGIN_ID, " Chat ID: %i\n", multimx->chatid);
+- purple_debug_info(MXIT_PLUGIN_ID, " Username: %s\n", multimx->roomid);
+- purple_debug_info(MXIT_PLUGIN_ID, " Alias: %s\n", multimx->roomname);
+- purple_debug_info(MXIT_PLUGIN_ID, " State: %i\n", multimx->state);
+-}
+-#endif
+-
+-
+-/*------------------------------------------------------------------------
+- * Find a MultiMx session based on libpurple chatID.
+- *
+- * @param session The MXit session object
+- * @param id The libpurple group-chat ID
+- * @return The MultiMX room object (or NULL if not found)
+- */
+-static struct multimx* find_room_by_id(struct MXitSession* session, int id)
+-{
+- GList* x = session->rooms;
+-
+- while (x != NULL) {
+- struct multimx* multimx = (struct multimx *) x->data;
+-
+- if (multimx->chatid == id)
+- return multimx;
+-
+- x = g_list_next(x);
+- }
+-
+- return NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Find a MultiMx session based on Alias
+- *
+- * @param session The MXit session object
+- * @param roomname The UI room-name
+- * @return The MultiMX room object (or NULL if not found)
+- */
+-static struct multimx* find_room_by_alias(struct MXitSession* session, const char* roomname)
+-{
+- GList* x = session->rooms;
+-
+- while (x != NULL) {
+- struct multimx* multimx = (struct multimx *) x->data;
+-
+- if (!strcmp(multimx->roomname, roomname))
+- return multimx;
+-
+- x = g_list_next(x);
+- }
+-
+- return NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Find a MultiMx session based on Username (MXit RoomId)
+- *
+- * @param session The MXit session object
+- * @param username The MXit RoomID (MultiMX contact username)
+- * @return The MultiMX room object (or NULL if not found)
+- */
+-static struct multimx* find_room_by_username(struct MXitSession* session, const char* username)
+-{
+- GList* x = session->rooms;
+-
+- while (x != NULL) {
+- struct multimx* multimx = (struct multimx *) x->data;
+-
+- if (!strcmp(multimx->roomid, username))
+- return multimx;
+-
+- x = g_list_next(x);
+- }
+-
+- return NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Create a GroupChat room, and add to list of rooms.
+- *
+- * @param session The MXit session object
+- * @param roomid The MXit RoomID (MultiMX contact username)
+- * @param roomname The UI room-name
+- * @param state The initial state of the room (see multimx.h)
+- * @return The MultiMX room object
+- */
+-static struct multimx* room_create(struct MXitSession* session, const char* roomid, const char* roomname, short state)
+-{
+- struct multimx* multimx = NULL;
+- static int groupchatID = 1;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat create - roomid='%s' roomname='%s'\n", roomid, roomname);
+-
+- /* Create a new GroupChat */
+- multimx = g_new0(struct multimx, 1);
+-
+- /* Initialize groupchat */
+- g_strlcpy(multimx->roomid, roomid, sizeof(multimx->roomid));
+- g_strlcpy(multimx->roomname, roomname, sizeof(multimx->roomname));
+- multimx->chatid = groupchatID++;
+- multimx->state = state;
+-
+- /* determine our nickname (from profile) */
+- if (session->profile && (session->profile->nickname[0] != '\0'))
+- multimx->nickname = g_strdup(session->profile->nickname);
+-
+- /* Add to GroupChat list */
+- session->rooms = g_list_append(session->rooms, multimx);
+-
+- return multimx;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free the Groupchat room.
+- *
+- * @param session The MXit session object
+- * @param multimx The MultiMX room object to deallocate
+- */
+-static void room_remove(struct MXitSession* session, struct multimx* multimx)
+-{
+- /* Remove from GroupChat list */
+- session->rooms = g_list_remove(session->rooms, multimx);
+-
+- /* free nickname */
+- if (multimx->nickname)
+- g_free(multimx->nickname);
+-
+- /* Deallocate it */
+- g_free (multimx);
+- multimx = NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Another user has join the GroupChat, add them to the member-list.
+- *
+- * @param convo The Conversation object
+- * @param nickname The nickname of the user who joined the room
+- */
+-static void member_added(PurpleConversation* convo, const char* nickname)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "member_added: '%s'\n", nickname);
+-
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), nickname, NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Another user has left the GroupChat, remove them from the member-list.
+- *
+- * @param convo The Conversation object
+- * @param nickname The nickname of the user who left the room
+- */
+-static void member_removed(PurpleConversation* convo, const char* nickname)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "member_removed: '%s'\n", nickname);
+-
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, NULL);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * A user was kicked from the GroupChat, remove them from the member-list.
+- *
+- * @param convo The Conversation object
+- * @param nickname The nickname of the user who was kicked
+- */
+-static void member_kicked(PurpleConversation* convo, const char* nickname)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "member_kicked: '%s'\n", nickname);
+-
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(convo), nickname, _("was kicked"));
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * You were kicked from the GroupChat.
+- *
+- * @param convo The Conversation object
+- * @param session The MXit session object
+- * @param multimx The MultiMX room object
+- */
+-static void you_kicked(PurpleConversation* convo, struct MXitSession* session, struct multimx* multimx)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "you_kicked\n");
+-
+- purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", _("You have been kicked from this MultiMX."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+- purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
+- serv_got_chat_left(session->con, multimx->chatid);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Update the full GroupChat member list.
+- *
+- * @param convo The Conversation object
+- * @param data The nicknames of the users in the room (separated by \n)
+- */
+-static void member_update(PurpleConversation* convo, char* data)
+-{
+- gchar** userlist;
+- int i = 0;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "member_update: '%s'\n", data);
+-
+- /* Clear list */
+- purple_conv_chat_clear_users(PURPLE_CONV_CHAT(convo));
+-
+- /* Add each member */
+- data = g_strstrip(data); /* string leading & trailing whitespace */
+- userlist = g_strsplit(data, "\n", 0); /* tokenize string */
+- while (userlist[i] != NULL) {
+- purple_debug_info(MXIT_PLUGIN_ID, "member_update - adding: '%s'\n", userlist[i]);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(convo), userlist[i], NULL, PURPLE_CBFLAGS_NONE, FALSE);
+- i++;
+- }
+- g_strfreev(userlist);
+-}
+-
+-
+-/* -------------------------------------------------------------------------------------------------
+- * Calls from MXit Protocol layer
+- * ------------------------------------------------------------------------------------------------- */
+-
+-/*------------------------------------------------------------------------
+- * Received a Subscription Request to a MultiMX room.
+- *
+- * @param session The MXit session object
+- * @param contact The invited MultiMX room's contact information
+- * @param creator The nickname of the room's creator / invitor
+- */
+-void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator)
+-{
+- GHashTable *components;
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s' (roomid='%s') by '%s'\n", contact->alias, contact->username, creator);
+-
+- /* Check if the room already exists (ie, already joined or invite pending) */
+- if (find_room_by_username(session, contact->username) != NULL)
+- return;
+-
+- /* Create a new room */
+- multimx = room_create(session, contact->username, contact->alias, STATE_INVITED);
+-
+- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- g_hash_table_insert(components, g_strdup("room"), g_strdup(contact->alias));
+-
+- /* Call libpurple - will trigger either 'mxit_chat_join' or 'mxit_chat_reject' */
+- serv_got_chat_invite(session->con, contact->alias, creator, NULL, components);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * MultiMX room has been added to the roster.
+- *
+- * @param session The MXit session object
+- * @param contact The MultiMX room's contact information
+- */
+-void multimx_created(struct MXitSession* session, struct contact* contact)
+-{
+- PurpleConnection *gc = session->con;
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat '%s' created as '%s'\n", contact->alias, contact->username);
+-
+- /* Find matching MultiMX group */
+- multimx = find_room_by_username(session, contact->username);
+- if (multimx == NULL) {
+- multimx = room_create(session, contact->username, contact->alias, TRUE);
+- }
+- else if (multimx->state == STATE_INVITED) {
+- /* After successfully accepting an invitation */
+- multimx->state = STATE_JOINED;
+- }
+-
+- /* Call libpurple - will trigger 'mxit_chat_join' */
+- serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
+-
+- /* Send ".list" command to GroupChat server to retrieve current member-list */
+- mxit_send_message(session, multimx->roomid, ".list", FALSE, FALSE);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Is this username a MultiMX contact?
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact
+- * @return TRUE if this contacts matches the RoomID of a MultiMX room.
+- */
+-gboolean is_multimx_contact(struct MXitSession* session, const char* username)
+-{
+- /* Check for username in list of open rooms */
+- return (find_room_by_username(session, username) != NULL);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Received a message from a MultiMX room.
+- *
+- */
+-void multimx_message_received(struct RXMsgData* mx, char* msg, int msglen, short msgtype, int msgflags)
+-{
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat message received: %s\n", msg);
+-
+- /* Find matching multimx group */
+- multimx = find_room_by_username(mx->session, mx->from);
+- if (multimx == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", mx->from);
+- return;
+- }
+-
+- /* Determine if system message or a message from a contact */
+- if (msg[0] == '<') {
+- /* Message contains embedded nickname - must be from contact */
+- unsigned int i;
+-
+- for (i = 1; i < strlen(msg); i++) { /* search for end of nickname */
+- if (msg[i] == '>') {
+- msg[i] = '\0';
+- g_free(mx->from);
+- mx->from = g_strdup(&msg[1]);
+- msg = &msg[i+2]; /* skip '>' and newline */
+- break;
+- }
+- }
+-
+- /* now do markup processing on the message */
+- mx->chatid = multimx->chatid;
+- mxit_parse_markup(mx, msg, strlen(msg), msgtype, msgflags);
+- }
+- else {
+- /* Must be a service message */
+- char* ofs;
+-
+- PurpleConversation* convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, mx->session->acc);
+- if (convo == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
+- return;
+- }
+-
+- /* Determine if somebody has joined or left - update member-list */
+- if ((ofs = strstr(msg, " has joined")) != NULL) {
+- /* Somebody has joined */
+- *ofs = '\0';
+- member_added(convo, msg);
+- mx->processed = TRUE;
+- }
+- else if ((ofs = strstr(msg, " has left")) != NULL) {
+- /* Somebody has left */
+- *ofs = '\0';
+- member_removed(convo, msg);
+- mx->processed = TRUE;
+- }
+- else if ((ofs = strstr(msg, " has been kicked")) != NULL) {
+- /* Somebody has been kicked */
+- *ofs = '\0';
+- member_kicked(convo, msg);
+- mx->processed = TRUE;
+- }
+- else if (strcmp(msg, "You have been kicked.") == 0) {
+- /* You have been kicked */
+- you_kicked(convo, mx->session, multimx);
+- mx->processed = TRUE;
+- }
+- else if (g_str_has_prefix(msg, "The following users are in this MultiMx:") == TRUE) {
+- member_update(convo, msg + strlen("The following users are in this MultiMx:") + 1);
+- mx->processed = TRUE;
+- }
+- else {
+- /* Display server message in chat window */
+- serv_got_chat_in(mx->session->con, multimx->chatid, "MXit", PURPLE_MESSAGE_SYSTEM, msg, mx->timestamp);
+- mx->processed = TRUE;
+- }
+- }
+-}
+-
+-
+-
+-/* -------------------------------------------------------------------------------------------------
+- * Callbacks from libpurple
+- * ------------------------------------------------------------------------------------------------- */
+-
+-/*------------------------------------------------------------------------
+- * User has selected "Add Chat" from the main menu.
+- *
+- * @param gc The connection object
+- * @return A list of chat configuration values
+- */
+-GList* mxit_chat_info(PurpleConnection *gc)
+-{
+- GList *m = NULL;
+- struct proto_chat_entry *pce;
+-
+- /* Configuration option: Room Name */
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _( "_Room Name:" );
+- pce->identifier = "room";
+- pce->required = TRUE;
+- m = g_list_append(m, pce);
+-
+- return m;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * User has joined a chatroom, either because they are creating it or they
+- * accepted an invite.
+- *
+- * @param gc The connection object
+- * @param components The list of chat configuration values
+- */
+-void mxit_chat_join(PurpleConnection *gc, GHashTable *components)
+-{
+- struct MXitSession* session = purple_connection_get_protocol_data(gc);
+- const char* roomname = NULL;
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_join\n");
+-
+- /* Determine if groupchat already exists */
+- roomname = g_hash_table_lookup(components, "room");
+- multimx = find_room_by_alias(session, roomname);
+-
+- if (multimx != NULL) {
+- /* The room information already exists */
+-
+- if (multimx->state == STATE_INVITED) {
+- /* Invite is pending */
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i accept sent\n", multimx->chatid);
+-
+- /* Send Subscription Accept to MXit */
+- mxit_send_allow_sub(session, multimx->roomid, multimx->roomname);
+- }
+- else {
+- /* Join existing room */
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i rejoined\n", multimx->chatid);
+-
+- serv_got_joined_chat(gc, multimx->chatid, multimx->roomname);
+- }
+- }
+- else {
+- /* Send Groupchat Create to MXit */
+- mxit_send_groupchat_create(session, roomname, 0, NULL);
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * User has rejected an invite to join a MultiMX room.
+- *
+- * @param gc The connection object
+- * @param components The list of chat configuration values
+- */
+-void mxit_chat_reject(PurpleConnection *gc, GHashTable* components)
+-{
+- struct MXitSession* session = purple_connection_get_protocol_data(gc);
+- const char* roomname = NULL;
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_chat_reject\n");
+-
+- roomname = g_hash_table_lookup(components, "room");
+- multimx = find_room_by_alias(session, roomname);
+- if (multimx == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Groupchat '%s' not found\n", roomname);
+- return;
+- }
+-
+- /* Send Subscription Reject to MXit */
+- mxit_send_deny_sub(session, multimx->roomid, NULL);
+-
+- /* Remove from our list of rooms */
+- room_remove(session, multimx);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return name of chatroom (on mouse hover)
+- *
+- * @param components The list of chat configuration values.
+- * @return The name of the chat room
+- */
+-char* mxit_chat_name(GHashTable *components)
+-{
+- return g_strdup(g_hash_table_lookup(components, "room"));
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * User has selected to invite somebody to a chatroom.
+- *
+- * @param gc The connection object
+- * @param id The chat room ID
+- * @param msg The invitation message entered by the user
+- * @param name The username of the person to invite
+- */
+-void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *username)
+-{
+- struct MXitSession* session = purple_connection_get_protocol_data(gc);
+- struct multimx* multimx = NULL;
+- PurpleBuddy* buddy;
+- PurpleConversation *convo;
+- char* tmp;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat invite to '%s'\n", username);
+-
+- /* Find matching MultiMX group */
+- multimx = find_room_by_id(session, id);
+- if (multimx == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
+- return;
+- }
+-
+- /* Send invite to MXit */
+- mxit_send_groupchat_invite(session, multimx->roomid, 1, &username);
+-
+- /* Find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy(session->acc, username);
+- if (!buddy) {
+- purple_debug_warning(MXIT_PLUGIN_ID, "mxit_chat_invite: unable to find the buddy '%s'\n", username);
+- return;
+- }
+-
+- convo = purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, multimx->roomname, session->acc);
+- if (convo == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Conversation '%s' not found\n", multimx->roomname);
+- return;
+- }
+-
+- /* Display system message in chat window */
+- tmp = g_strdup_printf("%s: %s", _("You have invited"), purple_buddy_get_alias(buddy));
+- purple_conv_chat_write(PURPLE_CONV_CHAT(convo), "MXit", tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * User as closed the chat window, and the chatroom is not marked as persistent.
+- *
+- * @param gc The connection object
+- * @param id The chat room ID
+- */
+-void mxit_chat_leave(PurpleConnection *gc, int id)
+-{
+- struct MXitSession* session = purple_connection_get_protocol_data(gc);
+- struct multimx* multimx = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i leave\n", id);
+-
+- /* Find matching multimx group */
+- multimx = find_room_by_id(session, id);
+- if (multimx == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
+- return;
+- }
+-
+- /* Send Remove Groupchat to MXit */
+- mxit_send_remove(session, multimx->roomid);
+-
+- /* Remove from our list of rooms */
+- room_remove(session, multimx);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * User has entered a message in a chatroom window, send it to the MXit server.
+- *
+- * @param gc The connection object
+- * @param id The chat room ID
+- * @param message The sent message data
+- * @param flags The message flags
+- * @return Indicates success / failure
+- */
+-int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
+-{
+- struct MXitSession* session = purple_connection_get_protocol_data(gc);
+- struct multimx* multimx = NULL;
+- const char* nickname;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Groupchat %i message send: '%s'\n", id, message);
+-
+- /* Find matching MultiMX group */
+- multimx = find_room_by_id(session, id);
+- if (multimx == NULL) {
+- purple_debug_error(MXIT_PLUGIN_ID, "Could not find groupchat %i\n", id);
+- return -1;
+- }
+-
+- /* Send packet to MXit */
+- mxit_send_message(session, multimx->roomid, message, TRUE, FALSE);
+-
+- /* Determine our nickname to display */
+- if (multimx->nickname)
+- nickname = multimx->nickname;
+- else
+- nickname = purple_account_get_alias(purple_connection_get_account(gc)); /* local alias */
+-
+- /* Display message in chat window */
+- serv_got_chat_in(gc, id, nickname, flags, message, time(NULL));
+-
+- return 0;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/multimx.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/multimx.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/multimx.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,105 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MultiMx GroupChat --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_MULTIMX_H_
+-#define _MXIT_MULTIMX_H_
+-
+-#include "roster.h"
+-
+-
+-/* GroupChat Room state */
+-#define STATE_CREATOR 0
+-#define STATE_INVITED 1
+-#define STATE_JOINED 2
+-
+-/*
+- * a MultiMX room
+- */
+-struct multimx {
+- char roomname[MXIT_CP_MAX_ALIAS_LEN]; /* name of the room */
+- char roomid[MXIT_CP_MAX_JID_LEN]; /* internal JID for room */
+- int chatid; /* libpurple chat ID */
+- char* nickname; /* our nickname in the room */
+- short state; /* state */
+-};
+-
+-
+-/*
+- * Received a Subscription Request to a MultiMX room.
+- */
+-void multimx_invite(struct MXitSession* session, struct contact* contact, const char* creator);
+-
+-/*
+- * MultiMX room has been added to the roster.
+- */
+-void multimx_created(struct MXitSession* session, struct contact* contact);
+-
+-/*
+- * Is this username a MultiMX contact?
+- */
+-gboolean is_multimx_contact(struct MXitSession* session, const char* username);
+-
+-/*
+- * Received a message from a MultiMX room.
+- */
+-void multimx_message_received(struct RXMsgData* mx, char* message, int len, short msgtype, int msgflags);
+-
+-/*
+- * User has selected "Add Chat" from the main menu.
+- */
+-GList* mxit_chat_info(PurpleConnection *gc);
+-
+-/*
+- * User has joined a chatroom, either because they are creating it or they accepted an invite.
+- */
+-void mxit_chat_join(PurpleConnection *gc, GHashTable *data);
+-
+-/*
+- * User has rejected an invite to join a MultiMX room.
+- */
+-void mxit_chat_reject(PurpleConnection *gc, GHashTable* components);
+-
+-/*
+- * Return name of chatroom (on mouse hover)
+- */
+-char* mxit_chat_name(GHashTable *data);
+-
+-/*
+- * User has selected to invite somebody to a chatroom.
+- */
+-void mxit_chat_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
+-
+-/*
+- * User as closed the chat window, and the chatroom is not marked as persistent.
+- */
+-void mxit_chat_leave(PurpleConnection *gc, int id);
+-
+-/*
+- * User has entered a message in a chatroom window, send it to the MXit server.
+- */
+-int mxit_chat_send(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
+-
+-
+-#endif /* _MXIT_MULTIMX_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/mxit.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/mxit.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,868 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit libPurple plugin API --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-#include "notify.h"
+-#include "plugin.h"
+-#include "version.h"
+-
+-#include "mxit.h"
+-#include "protocol.h"
+-#include "login.h"
+-#include "roster.h"
+-#include "chunk.h"
+-#include "filexfer.h"
+-#include "actions.h"
+-#include "multimx.h"
+-#include "voicevideo.h"
+-
+-
+-#ifdef MXIT_LINK_CLICK
+-
+-
+-/* pidgin callback function pointers for URI click interception */
+-static void *(*mxit_pidgin_uri_cb)(const char *uri);
+-static PurpleNotifyUiOps* mxit_nots_override_original;
+-static PurpleNotifyUiOps mxit_nots_override;
+-static int not_link_ref_count = 0;
+-
+-
+-/*------------------------------------------------------------------------
+- * Handle an URI clicked on the UI
+- *
+- * @param link the link name which has been clicked
+- */
+-static void* mxit_link_click( const char* link64 )
+-{
+- PurpleAccount* account;
+- PurpleConnection* gc;
+- gchar** parts = NULL;
+- gchar* link = NULL;
+- gsize len;
+- gboolean is_command = FALSE;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_link_click (%s)\n", link64 );
+-
+- if ( g_ascii_strncasecmp( link64, MXIT_LINK_PREFIX, strlen( MXIT_LINK_PREFIX ) ) != 0 ) {
+- /* this is not for us */
+- goto skip;
+- }
+-
+- /* decode the base64 payload */
+- link = (gchar*) purple_base64_decode( link64 + strlen( MXIT_LINK_PREFIX ), &len );
+- purple_debug_info( MXIT_PLUGIN_ID, "Clicked Link: '%s'\n", link );
+-
+- parts = g_strsplit( link, "|", 6 );
+-
+- /* check if this is a valid mxit link */
+- if ( ( !parts ) || ( !parts[0] ) || ( !parts[1] ) || ( !parts[2] ) || ( !parts[3] ) || ( !parts[4] ) || ( !parts[5] ) ) {
+- /* this is not for us */
+- goto skip;
+- }
+- else if ( g_ascii_strcasecmp( parts[0], MXIT_LINK_KEY ) != 0 ) {
+- /* this is not for us */
+- goto skip;
+- }
+-
+- /* find the account */
+- account = purple_accounts_find( parts[1], parts[2] );
+- if ( !account )
+- goto skip;
+- gc = purple_account_get_connection( account );
+- if ( !gc )
+- goto skip;
+-
+- /* determine if it's a command-response to send */
+- is_command = ( atoi( parts[4] ) == 1 );
+-
+- /* send click message back to MXit */
+- mxit_send_message( purple_connection_get_protocol_data( gc ), parts[3], parts[5], FALSE, is_command );
+-
+- g_free( link );
+- link = NULL;
+- g_strfreev( parts );
+- parts = NULL;
+-
+- return (void*) link64;
+-
+-skip:
+- /* this is not an internal mxit link */
+-
+- if ( link )
+- g_free( link );
+- link = NULL;
+-
+- if ( parts )
+- g_strfreev( parts );
+- parts = NULL;
+-
+- if ( mxit_pidgin_uri_cb )
+- return mxit_pidgin_uri_cb( link64 );
+- else
+- return (void*) link64;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Register MXit to receive URI click notifications from the UI
+- */
+-void mxit_register_uri_handler(void)
+-{
+- not_link_ref_count++;
+- if ( not_link_ref_count == 1 ) {
+- /* make copy of notifications */
+- mxit_nots_override_original = purple_notify_get_ui_ops();
+- memcpy( &mxit_nots_override, mxit_nots_override_original, sizeof( PurpleNotifyUiOps ) );
+-
+- /* save previously configured callback function pointer */
+- mxit_pidgin_uri_cb = mxit_nots_override.notify_uri;
+-
+- /* override the URI function call with MXit's own one */
+- mxit_nots_override.notify_uri = mxit_link_click;
+- purple_notify_set_ui_ops( &mxit_nots_override );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Unregister MXit from receiving URI click notifications from the UI
+- */
+-static void mxit_unregister_uri_handler()
+-{
+- not_link_ref_count--;
+- if ( not_link_ref_count == 0 ) {
+- /* restore the notifications to its original state */
+- purple_notify_set_ui_ops( mxit_nots_override_original );
+- }
+-}
+-
+-#endif
+-
+-
+-/*------------------------------------------------------------------------
+- * This gets called when a new chat conversation is opened by the user
+- *
+- * @param conv The conversation object
+- * @param session The MXit session object
+- */
+-static void mxit_cb_chat_created( PurpleConversation* conv, struct MXitSession* session )
+-{
+- PurpleConnection* gc;
+- struct contact* contact;
+- PurpleBuddy* buddy;
+- const char* who;
+- char* tmp;
+-
+- gc = purple_conversation_get_gc( conv );
+- if ( session->con != gc ) {
+- /* not our conversation */
+- return;
+- }
+- else if ( purple_conversation_get_type( conv ) != PURPLE_CONV_TYPE_IM ) {
+- /* wrong type of conversation */
+- return;
+- }
+-
+- /* get the contact name */
+- who = purple_conversation_get_name( conv );
+- if ( !who )
+- return;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Conversation started with '%s'\n", who );
+-
+- /* find the buddy object */
+- buddy = purple_find_buddy( session->acc, who );
+- if ( !buddy )
+- return;
+-
+- contact = purple_buddy_get_protocol_data(buddy);
+- if ( !contact )
+- return;
+-
+- /* we ignore all conversations with which we have chatted with in this session */
+- if ( find_active_chat( session->active_chats, who ) )
+- return;
+-
+- /* determine if this buddy is a MXit service */
+- switch ( contact->type ) {
+- case MXIT_TYPE_BOT :
+- case MXIT_TYPE_CHATROOM :
+- case MXIT_TYPE_GALLERY :
+- case MXIT_TYPE_INFO :
+- tmp = g_strdup_printf("<font color=\"#999999\">%s</font>\n", _( "Loading menu..." ));
+- serv_got_im( session->con, who, tmp, PURPLE_MESSAGE_NOTIFY, time( NULL ) );
+- g_free(tmp);
+- mxit_send_message( session, who, " ", FALSE, FALSE );
+- default :
+- break;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Enable some signals to handled by our plugin
+- *
+- * @param session The MXit session object
+- */
+-void mxit_enable_signals( struct MXitSession* session )
+-{
+- /* enable the signal when a new conversation is opened by the user */
+- purple_signal_connect_priority( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ),
+- session, PURPLE_SIGNAL_PRIORITY_HIGHEST );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Disable some signals handled by our plugin
+- *
+- * @param session The MXit session object
+- */
+-static void mxit_disable_signals( struct MXitSession* session )
+-{
+- /* disable the signal when a new conversation is opened by the user */
+- purple_signal_disconnect( purple_conversations_get_handle(), "conversation-created", session, PURPLE_CALLBACK( mxit_cb_chat_created ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the base icon name.
+- *
+- * @param account The MXit account object
+- * @param buddy The buddy
+- * @return The icon name (excluding extension)
+- */
+-static const char* mxit_list_icon( PurpleAccount* account, PurpleBuddy* buddy )
+-{
+- return "mxit";
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the emblem icon name.
+- *
+- * @param buddy The buddy
+- * @return The icon name (excluding extension)
+- */
+-static const char* mxit_list_emblem( PurpleBuddy* buddy )
+-{
+- struct contact* contact = purple_buddy_get_protocol_data(buddy);
+-
+- if ( !contact )
+- return NULL;
+-
+- /* subscription state is Pending, Rejected or Deleted */
+- if ( contact->subtype != MXIT_SUBTYPE_BOTH )
+- return "not-authorized";
+-
+- switch ( contact-> type ) {
+- case MXIT_TYPE_JABBER : /* external contacts via MXit */
+- case MXIT_TYPE_MSN :
+- case MXIT_TYPE_YAHOO :
+- case MXIT_TYPE_ICQ :
+- case MXIT_TYPE_AIM :
+- case MXIT_TYPE_QQ :
+- case MXIT_TYPE_WV :
+- return "external";
+-
+- case MXIT_TYPE_BOT : /* MXit services */
+- case MXIT_TYPE_GALLERY :
+- case MXIT_TYPE_INFO :
+- return "bot";
+-
+- case MXIT_TYPE_CHATROOM : /* MXit group chat services */
+- case MXIT_TYPE_MULTIMX :
+- default:
+- return NULL;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return short string representing buddy's status for display on buddy list.
+- * Returns status message (if one is set), or otherwise the mood.
+- *
+- * @param buddy The buddy.
+- * @return The status text
+- */
+-char* mxit_status_text( PurpleBuddy* buddy )
+-{
+- char* text = NULL;
+- struct contact* contact = purple_buddy_get_protocol_data(buddy);
+-
+- if ( !contact )
+- return NULL;
+-
+- if ( contact->statusMsg ) /* status message */
+- return g_strdup( contact-> statusMsg );
+- else if ( contact->mood != MXIT_MOOD_NONE ) /* mood */
+- return g_strdup( mxit_convert_mood_to_name( contact->mood ) );
+-
+- return text;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return UI tooltip information for a buddy when hovering in buddy list.
+- *
+- * @param buddy The buddy
+- * @param info The tooltip info being returned
+- * @param full Return full or summarized information
+- */
+-static void mxit_tooltip( PurpleBuddy* buddy, PurpleNotifyUserInfo* info, gboolean full )
+-{
+- struct contact* contact = purple_buddy_get_protocol_data(buddy);
+-
+- if ( !contact )
+- return;
+-
+- /* status (reference: "libpurple/notify.h") */
+- if ( contact->presence != MXIT_PRESENCE_OFFLINE )
+- purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
+-
+- /* status message */
+- if ( contact->statusMsg )
+- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+-
+- /* mood */
+- if ( contact->mood != MXIT_MOOD_NONE )
+- purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
+-
+- /* subscription type */
+- if ( contact->subtype != 0 )
+- purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
+-
+- /* rejection message */
+- if ( ( contact->subtype == MXIT_SUBTYPE_REJECTED ) && ( contact->msg != NULL ) )
+- purple_notify_user_info_add_pair( info, _( "Rejection Message" ), contact->msg );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Initiate the logout sequence, close the connection and clear the session data.
+- *
+- * @param gc The connection object
+- */
+-static void mxit_close( PurpleConnection* gc )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- /* disable signals */
+- mxit_disable_signals( session );
+-
+- /* close the connection */
+- mxit_close_connection( session );
+-
+-#ifdef MXIT_LINK_CLICK
+- /* unregister for uri click notification */
+- mxit_unregister_uri_handler();
+-#endif
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Releasing the session object..\n" );
+-
+- /* free the session memory */
+- g_free( session );
+- session = NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a message to a contact
+- *
+- * @param gc The connection object
+- * @param who The username of the recipient
+- * @param message The message text
+- * @param flags Message flags (defined in conversation.h)
+- * @return Positive value (success, and echo to conversation window)
+- Zero (success, no echo)
+- Negative value (error)
+- */
+-static int mxit_send_im( PurpleConnection* gc, const char* who, const char* message, PurpleMessageFlags flags )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "Sending message '%s' to buddy '%s'\n", message, who );
+-
+- mxit_send_message( gc->proto_data, who, message, TRUE, FALSE );
+-
+- return 1; /* echo to conversation window */
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user changed their current presence state.
+- *
+- * @param account The MXit account object
+- * @param status The new status (libPurple status type)
+- */
+-static void mxit_set_status( PurpleAccount* account, PurpleStatus* status )
+-{
+- struct MXitSession* session = purple_account_get_connection( account )->proto_data;
+- const char* statusid;
+- int presence;
+- char* statusmsg1;
+- char* statusmsg2;
+-
+- /* Handle mood changes */
+- if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+- const char* moodid = purple_status_get_attr_string( status, PURPLE_MOOD_NAME );
+- int mood;
+-
+- /* convert the purple mood to a mxit mood */
+- mood = mxit_convert_mood( moodid );
+- if ( mood < 0 ) {
+- /* error, mood not found */
+- purple_debug_info( MXIT_PLUGIN_ID, "Mood status NOT found! (id = %s)\n", moodid );
+- return;
+- }
+-
+- /* update mood state */
+- mxit_send_mood( session, mood );
+- return;
+- }
+-
+- /* get the status id (reference: "libpurple/status.h") */
+- statusid = purple_status_get_id( status );
+-
+- /* convert the purple status to a mxit status */
+- presence = mxit_convert_presence( statusid );
+- if ( presence < 0 ) {
+- /* error, status not found */
+- purple_debug_info( MXIT_PLUGIN_ID, "Presence status NOT found! (id = %s)\n", statusid );
+- return;
+- }
+-
+- statusmsg1 = purple_markup_strip_html( purple_status_get_attr_string( status, "message" ) );
+- statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_status: '%s'\n", statusmsg2 );
+-
+- /* update presence state */
+- mxit_send_presence( session, presence, statusmsg2 );
+-
+- g_free( statusmsg1 );
+- g_free( statusmsg2 );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * MXit supports messages to offline contacts.
+- *
+- * @param buddy The buddy
+- */
+-static gboolean mxit_offline_message( const PurpleBuddy *buddy )
+-{
+- return TRUE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Free the resources used to store a buddy.
+- *
+- * @param buddy The buddy
+- */
+-static void mxit_free_buddy( PurpleBuddy* buddy )
+-{
+- struct contact* contact;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_free_buddy\n" );
+-
+- contact = purple_buddy_get_protocol_data(buddy);
+- if ( contact ) {
+- if ( contact->statusMsg )
+- g_free( contact->statusMsg );
+- if ( contact->avatarId )
+- g_free( contact->avatarId );
+- if ( contact->msg )
+- g_free( contact->msg );
+- g_free( contact );
+- }
+-
+- purple_buddy_set_protocol_data(buddy, NULL);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Periodic task called every KEEPALIVE_INTERVAL (30 sec) to to maintain
+- * idle connections, timeouts and the transmission queue to the MXit server.
+- *
+- * @param gc The connection object
+- */
+-static void mxit_keepalive( PurpleConnection *gc )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- /* if not logged in, there is nothing to do */
+- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) )
+- return;
+-
+- /* pinging is only for socket connections (HTTP does polling) */
+- if ( session->http )
+- return;
+-
+- if ( session->last_tx <= ( mxit_now_milli() - ( MXIT_PING_INTERVAL * 1000 ) ) ) {
+- /*
+- * this connection has been idle for too long, better ping
+- * the server before it kills our connection.
+- */
+- mxit_send_ping( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Set or clear our Buddy icon.
+- *
+- * @param gc The connection object
+- * @param img The buddy icon data
+- */
+-static void mxit_set_buddy_icon( PurpleConnection *gc, PurpleStoredImage *img )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+-
+- if ( img == NULL )
+- mxit_set_avatar( session, NULL, 0 );
+- else
+- mxit_set_avatar( session, purple_imgstore_get_data( img ), purple_imgstore_get_size( img ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Request profile information for another MXit contact.
+- *
+- * @param gc The connection object
+- * @param who The username of the contact.
+- */
+-static void mxit_get_info( PurpleConnection *gc, const char *who )
+-{
+- PurpleBuddy* buddy;
+- struct contact* contact;
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
+- CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_REGCOUNTRY, CP_PROFILE_LASTSEEN,
+- CP_PROFILE_STATUS, CP_PROFILE_AVATAR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP };
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_info: '%s'\n", who );
+-
+- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy( session->acc, who );
+- if ( buddy ) {
+- /* user is in our contact-list, so it's not an invite */
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return;
+-
+- /* only MXit users have profiles */
+- if ( contact->type != MXIT_TYPE_MXIT ) {
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "No profile available" ), _( "This contact does not have a profile." ) );
+- return;
+- }
+- }
+-
+- /* send profile request */
+- mxit_send_extprofile_request( session, who, ARRAY_SIZE( profilelist ), profilelist );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return a list of labels to be used by Pidgin for assisting the user.
+- */
+-static GHashTable* mxit_get_text_table( PurpleAccount* acc )
+-{
+- GHashTable* table;
+-
+- table = g_hash_table_new( g_str_hash, g_str_equal );
+-
+- g_hash_table_insert( table, "login_label", (gpointer)_( "Your MXit ID..." ) );
+-
+- return table;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Re-Invite was selected from the buddy-list menu.
+- *
+- * @param node The entry in the buddy list.
+- * @param ignored (not used)
+- */
+-static void mxit_reinvite( PurpleBlistNode *node, gpointer ignored )
+-{
+- PurpleBuddy* buddy;
+- struct contact* contact;
+- PurpleConnection* gc;
+- struct MXitSession* session;
+-
+- buddy = (PurpleBuddy *)node;
+- gc = purple_account_get_connection( purple_buddy_get_account( buddy ) );
+- session = gc->proto_data;
+-
+- contact = purple_buddy_get_protocol_data( (PurpleBuddy*) node );
+- if ( !contact )
+- return;
+-
+- /* send a new invite */
+- mxit_send_invite( session, contact->username, TRUE, contact->alias, contact->groupname, NULL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Buddy-list menu.
+- *
+- * @param node The entry in the buddy list.
+- */
+-static GList* mxit_blist_menu( PurpleBlistNode *node )
+-{
+- PurpleBuddy* buddy;
+- struct contact* contact;
+- GList* m = NULL;
+- PurpleMenuAction* act;
+-
+- if ( !PURPLE_BLIST_NODE_IS_BUDDY( node ) )
+- return NULL;
+-
+- buddy = (PurpleBuddy *) node;
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return NULL;
+-
+- if ( ( contact->subtype == MXIT_SUBTYPE_DELETED ) || ( contact->subtype == MXIT_SUBTYPE_REJECTED ) || ( contact->subtype == MXIT_SUBTYPE_NONE ) ) {
+- /* contact is in Deleted, Rejected or None state */
+- act = purple_menu_action_new( _( "Re-Invite" ), PURPLE_CALLBACK( mxit_reinvite ), NULL, NULL );
+- m = g_list_append(m, act);
+- }
+-
+- return m;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return Chat-room default settings.
+- *
+- * @return Chat defaults list
+- */
+-static GHashTable *mxit_chat_info_defaults( PurpleConnection *gc, const char *chat_name )
+-{
+- return g_hash_table_new_full( g_str_hash, g_str_equal, NULL, g_free );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a typing indicator event.
+- *
+- * @param gc The connection object
+- * @param name The username of the contact
+- * @param state The typing state to be reported.
+- */
+-static unsigned int mxit_send_typing( PurpleConnection *gc, const char *name, PurpleTypingState state )
+-{
+- PurpleAccount* account = purple_connection_get_account( gc );
+- struct MXitSession* session = purple_connection_get_protocol_data( gc );
+- PurpleBuddy* buddy;
+- struct contact* contact;
+- gchar* messageId = NULL;
+-
+- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy( account, name );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_send_typing: unable to find the buddy '%s'\n", name );
+- return 0;
+- }
+-
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return 0;
+-
+- /* does this contact support and want typing notification? */
+- if ( ! ( contact->capabilities & MXIT_PFLAG_TYPING ) )
+- return 0;
+-
+- messageId = purple_uuid_random(); /* generate a unique message id */
+-
+- switch ( state ) {
+- case PURPLE_TYPING : /* currently typing */
+- mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_TYPING );
+- break;
+-
+- case PURPLE_TYPED : /* stopped typing */
+- case PURPLE_NOT_TYPING : /* not typing / erased all text */
+- mxit_send_msgevent( session, name, messageId, CP_MSGEVENT_STOPPED );
+- break;
+-
+- default:
+- break;
+- }
+-
+- g_free( messageId );
+-
+- return 0;
+-}
+-
+-
+-/*========================================================================================================================*/
+-
+-static PurplePluginProtocolInfo proto_info = {
+- OPT_PROTO_REGISTER_NOSCREENNAME | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE, /* options */
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- { /* icon_spec */
+- "png,jpeg,bmp", /* supported formats */
+- 32, 32, /* min width & height */
+- 800, 800, /* max width & height */
+- CP_MAX_FILESIZE, /* max filesize */
+- PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY /* scaling rules */
+- },
+- mxit_list_icon, /* list_icon */
+- mxit_list_emblem, /* list_emblem */
+- mxit_status_text, /* status_text */
+- mxit_tooltip, /* tooltip_text */
+- mxit_status_types, /* status types [roster.c] */
+- mxit_blist_menu, /* blist_node_menu */
+- mxit_chat_info, /* chat_info [multimx.c] */
+- mxit_chat_info_defaults,/* chat_info_defaults */
+- mxit_login, /* login [login.c] */
+- mxit_close, /* close */
+- mxit_send_im, /* send_im */
+- NULL, /* set_info */
+- mxit_send_typing, /* send_typing */
+- mxit_get_info, /* get_info */
+- mxit_set_status, /* set_status */
+- NULL, /* set_idle */
+- NULL, /* change_passwd */
+- NULL, /* add_buddy [roster.c] */
+- NULL, /* add_buddies */
+- mxit_remove_buddy, /* remove_buddy [roster.c] */
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- NULL, /* add_deny */
+- NULL, /* rem_permit */
+- NULL, /* rem_deny */
+- NULL, /* set_permit_deny */
+- mxit_chat_join, /* join_chat [multimx.c] */
+- mxit_chat_reject, /* reject chat invite [multimx.c] */
+- mxit_chat_name, /* get_chat_name [multimx.c] */
+- mxit_chat_invite, /* chat_invite [multimx.c] */
+- mxit_chat_leave, /* chat_leave [multimx.c] */
+- NULL, /* chat_whisper */
+- mxit_chat_send, /* chat_send [multimx.c] */
+- mxit_keepalive, /* keepalive */
+- mxit_register, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- mxit_buddy_alias, /* alias_buddy [roster.c] */
+- mxit_buddy_group, /* group_buddy [roster.c] */
+- mxit_rename_group, /* rename_group [roster.c] */
+- mxit_free_buddy, /* buddy_free */
+- NULL, /* convo_closed */
+- NULL, /* normalize */
+- mxit_set_buddy_icon, /* set_buddy_icon */
+- NULL, /* remove_group */ // TODO: Add function to move all contacts out of this group (cmd=30 - remove group)?
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- mxit_xfer_enabled, /* can_receive_file [filexfer.c] */
+- mxit_xfer_tx, /* send_file [filexfer.c */
+- mxit_xfer_new, /* new_xfer [filexfer.c] */
+- mxit_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- NULL, /* send_attention */
+- NULL, /* attention_types */
+- sizeof( PurplePluginProtocolInfo ), /* struct_size */
+- mxit_get_text_table, /* get_account_text_table */
+- mxit_media_initiate, /* initiate_media */
+- mxit_media_caps, /* get_media_caps */
+- mxit_get_moods, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- mxit_add_buddy, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-
+-static PurplePluginInfo plugin_info = {
+- PURPLE_PLUGIN_MAGIC, /* purple magic, this must always be PURPLE_PLUGIN_MAGIC */
+- PURPLE_MAJOR_VERSION, /* libpurple version */
+- PURPLE_MINOR_VERSION, /* libpurple version */
+- PURPLE_PLUGIN_PROTOCOL, /* plugin type (connecting to another network) */
+- NULL, /* UI requirement (NULL for core plugin) */
+- 0, /* plugin flags (zero is default) */
+- NULL, /* plugin dependencies (set this value to NULL no matter what) */
+- PURPLE_PRIORITY_DEFAULT, /* libpurple priority */
+-
+- MXIT_PLUGIN_ID, /* plugin id (must be unique) */
+- MXIT_PLUGIN_NAME, /* plugin name (this will be displayed in the UI) */
+- DISPLAY_VERSION, /* version of the plugin */
+-
+- MXIT_PLUGIN_SUMMARY, /* short summary of the plugin */
+- MXIT_PLUGIN_DESC, /* description of the plugin (can be long) */
+- MXIT_PLUGIN_EMAIL, /* plugin author name and email address */
+- MXIT_PLUGIN_WWW, /* plugin website (to find new versions and reporting of bugs) */
+-
+- NULL, /* function pointer for loading the plugin */
+- NULL, /* function pointer for unloading the plugin */
+- NULL, /* function pointer for destroying the plugin */
+-
+- NULL, /* pointer to an UI-specific struct */
+- &proto_info, /* pointer to either a PurplePluginLoaderInfo or PurplePluginProtocolInfo struct */
+- NULL, /* pointer to a PurplePluginUiInfo struct */
+- mxit_actions, /* function pointer where you can define plugin-actions */
+-
+- /* padding */
+- NULL, /* pointer reserved for future use */
+- NULL, /* pointer reserved for future use */
+- NULL, /* pointer reserved for future use */
+- NULL /* pointer reserved for future use */
+-};
+-
+-
+-/*------------------------------------------------------------------------
+- * Initialising the MXit plugin.
+- *
+- * @param plugin The plugin object
+- */
+-static void init_plugin( PurplePlugin* plugin )
+-{
+- PurpleAccountOption* option;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Loading MXit libPurple plugin...\n" );
+-
+- /* Configuration options */
+-
+- /* WAP server (reference: "libpurple/accountopt.h") */
+- option = purple_account_option_string_new( _( "WAP Server" ), MXIT_CONFIG_WAPSERVER, DEFAULT_WAPSITE );
+- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
+-
+- option = purple_account_option_bool_new( _( "Connect via HTTP" ), MXIT_CONFIG_USE_HTTP, FALSE );
+- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
+-
+- option = purple_account_option_bool_new( _( "Enable splash-screen popup" ), MXIT_CONFIG_SPLASHPOPUP, FALSE );
+- proto_info.protocol_options = g_list_append( proto_info.protocol_options, option );
+-}
+-
+-PURPLE_INIT_PLUGIN( mxit, init_plugin, plugin_info );
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/mxit.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/mxit.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/mxit.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,199 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit libPurple plugin API --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_H_
+-#define _MXIT_H_
+-
+-
+-#include "internal.h"
+-
+-
+-#if defined( __APPLE__ )
+-/* apple architecture */
+-#ifndef HOST_NAME_MAX
+-#define HOST_NAME_MAX 512
+-#endif
+-#elif defined( _WIN32 )
+-/* windows architecture */
+-#ifndef HOST_NAME_MAX
+-#define HOST_NAME_MAX 512
+-#endif
+-#include "libc_interface.h"
+-#elif defined( __linux__ )
+-/* linux architecture */
+-#include <net/if.h>
+-#include <sys/ioctl.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#include <arpa/inet.h>
+-#else
+-/* other architecture */
+-#ifndef HOST_NAME_MAX
+-#define HOST_NAME_MAX 512
+-#endif
+-#endif
+-
+-
+-#include "protocol.h"
+-#include "profile.h"
+-
+-
+-/* Plugin details */
+-#define MXIT_PLUGIN_ID "prpl-loubserp-mxit"
+-#define MXIT_PLUGIN_NAME "MXit"
+-#define MXIT_PLUGIN_EMAIL "Pieter Loubser <libpurple@mxit.com>"
+-#define MXIT_PLUGIN_WWW "http://www.mxit.com"
+-#define MXIT_PLUGIN_SUMMARY "MXit Protocol Plugin"
+-#define MXIT_PLUGIN_DESC "MXit"
+-
+-#define MXIT_HTTP_USERAGENT "libpurple-"DISPLAY_VERSION
+-
+-
+-/* default connection settings */
+-#define DEFAULT_SERVER "stream.mxit.co.za"
+-#define DEFAULT_PORT 9119
+-#define DEFAULT_WAPSITE "http://www.mxit.com"
+-#define DEFAULT_HTTP_SERVER "http://int.poll.mxit.com:80/mxit"
+-
+-
+-/* Purple account configuration variable names */
+-#define MXIT_CONFIG_STATE "state"
+-#define MXIT_CONFIG_WAPSERVER "wap_server"
+-#define MXIT_CONFIG_DISTCODE "distcode"
+-#define MXIT_CONFIG_CLIENTKEY "clientkey"
+-#define MXIT_CONFIG_DIALCODE "dialcode"
+-#define MXIT_CONFIG_SERVER_ADDR "server"
+-#define MXIT_CONFIG_SERVER_PORT "port"
+-#define MXIT_CONFIG_HTTPSERVER "httpserver"
+-#define MXIT_CONFIG_SPLASHID "splashid"
+-#define MXIT_CONFIG_SPLASHCLICK "splashclick"
+-#define MXIT_CONFIG_SPLASHPOPUP "splashpopup"
+-#define MXIT_CONFIG_COUNTRYCODE "cc"
+-#define MXIT_CONFIG_LOCALE "locale"
+-#define MXIT_CONFIG_USE_HTTP "use_http"
+-
+-
+-/* account states */
+-#define MXIT_STATE_LOGIN 0x00
+-#define MXIT_STATE_REGISTER1 0x01
+-#define MXIT_STATE_REGISTER2 0x02
+-
+-
+-/* Client session flags */
+-#define MXIT_FLAG_CONNECTED 0x01 /* established connection to the server */
+-#define MXIT_FLAG_LOGGEDIN 0x02 /* user currently logged in */
+-#define MXIT_FLAG_FIRSTROSTER 0x04 /* set to true once the first roster update has been received and processed */
+-
+-
+-/* Maximum number of search results */
+-#define MXIT_SEARCHRESULTS_MAX 30
+-
+-
+-/* define this to enable the link clicking support */
+-#define MXIT_LINK_CLICK
+-
+-#ifdef MXIT_LINK_CLICK
+-#define MXIT_LINK_PREFIX "gopher://"
+-#define MXIT_LINK_KEY "MXIT"
+-#endif
+-
+-
+-#define ARRAY_SIZE( x ) ( sizeof( x ) / sizeof( x[0] ) )
+-
+-
+-/*
+- * data structure containing all MXit session information
+- */
+-struct MXitSession {
+- /* socket connection */
+- char server[HOST_NAME_MAX]; /* MXit server name to connect to */
+- int port; /* MXit server port to connect on */
+- int fd; /* connection file descriptor */
+-
+- /* http connection */
+- gboolean http; /* connect to MXit via HTTP and not by socket */
+- char http_server[HOST_NAME_MAX]; /* MXit HTTP server */
+- unsigned int http_sesid; /* HTTP session id */
+- unsigned int http_seqno; /* HTTP request sequence number */
+- guint http_timer_id; /* timer resource id (pidgin) */
+- int http_interval; /* poll inverval */
+- gint64 http_last_poll; /* the last time a poll has been sent */
+- guint http_handler; /* HTTP connection handler */
+- void* http_out_req; /* HTTP outstanding request */
+-
+- /* other servers */
+- char voip_server[HOST_NAME_MAX]; /* voice/video server */
+-
+- /* client */
+- struct login_data* logindata;
+- char* encpwd; /* encrypted password */
+- char distcode[64]; /* distribution code */
+- char clientkey[16]; /* client key */
+- char dialcode[8]; /* dialing code */
+- short flags; /* client session flags (see above) */
+-
+- /* personal (profile) */
+- struct MXitProfile* profile; /* user's profile information */
+- char* uid; /* the user's UID */
+-
+- /* libpurple */
+- PurpleAccount* acc; /* pointer to the libpurple internal account struct */
+- PurpleConnection* con; /* pointer to the libpurple internal connection struct */
+-
+- /* transmit */
+- struct tx_queue queue; /* transmit packet queue (FIFO mode) */
+- gint64 last_tx; /* timestamp of last packet sent */
+- int outack; /* outstanding ack packet */
+- guint q_slow_timer_id; /* timer handle for slow tx queue */
+- guint q_fast_timer_id; /* timer handle for fast tx queue */
+-
+- /* receive */
+- char rx_lbuf[16]; /* receive byte buffer (socket packet length) */
+- char rx_dbuf[CP_MAX_PACKET]; /* receive byte buffer (raw data) */
+- unsigned int rx_i; /* receive buffer current index */
+- int rx_res; /* amount of bytes still outstanding for the current packet */
+- char rx_state; /* current receiver state */
+- gint64 last_rx; /* timestamp of last packet received */
+- GList* active_chats; /* list of all our contacts we received messages from (active chats) */
+- GList* invites; /* list of all the invites that we have received */
+-
+- /* groupchat */
+- GList* rooms; /* active groupchat rooms */
+-
+- /* inline images */
+- GHashTable* iimages; /* table which maps inline images (including emoticons) to purple's imgstore id's */
+-};
+-
+-
+-char* mxit_status_text( PurpleBuddy* buddy );
+-void mxit_enable_signals( struct MXitSession* session );
+-
+-#ifdef MXIT_LINK_CLICK
+-void mxit_register_uri_handler(void);
+-#endif
+-
+-
+-#endif /* _MXIT_H_ */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/profile.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/profile.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,366 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- user profile's --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#define _XOPEN_SOURCE
+-#include <time.h>
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "mxit.h"
+-#include "profile.h"
+-#include "roster.h"
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the MXit Relationship status as a string.
+- *
+- * @param id The Relationship status value (see profile.h)
+- * @return The relationship status as a text string.
+- */
+-const char* mxit_relationship_to_name( short id )
+-{
+- switch ( id ) {
+- case MXIT_RELATIONSHIP_UNKNOWN :
+- return _( "Unknown" );
+- case MXIT_RELATIONSHIP_DONTSAY :
+- return _( "Don't want to say" );
+- case MXIT_RELATIONSHIP_SINGLE :
+- return _( "Single" );
+- case MXIT_RELATIONSHIP_INVOLVED :
+- return _( "In a relationship" );
+- case MXIT_RELATIONSHIP_ENGAGED :
+- return _( "Engaged" );
+- case MXIT_RELATIONSHIP_MARRIED :
+- return _( "Married" );
+- case MXIT_RELATIONSHIP_COMPLICATED :
+- return _( "It's complicated" );
+- case MXIT_RELATIONSHIP_WIDOWED :
+- return _( "Widowed" );
+- case MXIT_RELATIONSHIP_SEPARATED :
+- return _( "Separated" );
+- case MXIT_RELATIONSHIP_DIVORCED :
+- return _( "Divorced" );
+- default :
+- return "";
+- }
+-}
+-
+-/*------------------------------------------------------------------------
+- * Returns true if it is a valid date.
+- *
+- * @param bday Date-of-Birth string (YYYY-MM-DD)
+- * @return TRUE if valid, else FALSE
+- */
+-gboolean validateDate( const char* bday )
+-{
+- struct tm* tm;
+- time_t t;
+- int cur_year;
+- int max_days[13] = { 0, 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
+- char date[16];
+- int year;
+- int month;
+- int day;
+-
+- /* validate length */
+- if ( strlen( bday ) != 10 ) {
+- return FALSE;
+- }
+-
+- /* validate the format */
+- if ( ( !isdigit( bday[0] ) ) || ( !isdigit( bday[1] ) ) || ( !isdigit( bday[2] ) ) || ( !isdigit( bday[3] ) ) || /* year */
+- ( bday[4] != '-' ) ||
+- ( !isdigit( bday[5] ) ) || ( !isdigit( bday[6] ) ) || /* month */
+- ( bday[7] != '-' ) ||
+- ( !isdigit( bday[8] ) ) || ( !isdigit( bday[9] ) ) ) { /* day */
+- return FALSE;
+- }
+-
+- /* convert */
+- t = time( NULL );
+- tm = gmtime( &t );
+- cur_year = tm->tm_year + 1900;
+- memcpy( date, bday, 10 );
+- date[4] = '\0';
+- date[7] = '\0';
+- date[10] = '\0';
+- year = atoi( &date[0] );
+- month = atoi( &date[5] );
+- day = atoi( &date[8] );
+-
+- /* validate month */
+- if ( ( month < 1 ) || ( month > 12 ) ) {
+- return FALSE;
+- }
+-
+- /* validate day */
+- if ( ( day < 1 ) || ( day > max_days[month] ) ) {
+- return FALSE;
+- }
+-
+- /* validate year */
+- if ( ( year < ( cur_year - 100 ) ) || ( year >= cur_year ) ) {
+- /* you are either tooo old or tooo young to join mxit... sorry */
+- return FALSE;
+- }
+-
+- /* special case leap-year */
+- if ( ( year % 4 != 0 ) && ( month == 2 ) && ( day == 29 ) ) {
+- /* cannot have 29 days in February in non leap-years! */
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Calculate an Age from the date-of-birth.
+- *
+- * @param date Date-of-Birth string (YYYY-MM-DD)
+- * @return The age
+- */
+-static int calculateAge( const char* date )
+-{
+- time_t t;
+- struct tm now, bdate;
+- int age;
+-
+- if ( ( !date ) || ( strlen( date ) == 0 ) )
+- return 0;
+-
+- /* current time */
+- t = time(NULL);
+- localtime_r( &t, &now );
+-
+- /* decode hdate */
+- memset( &bdate, 0, sizeof( struct tm ) );
+- purple_str_to_time(date, FALSE, &bdate, NULL, NULL);
+-
+- /* calculate difference */
+- age = now.tm_year - bdate.tm_year;
+- if ( now.tm_mon < bdate.tm_mon ) /* is before month of birth */
+- age--;
+- else if ( (now.tm_mon == bdate.tm_mon ) && ( now.tm_mday < bdate.tm_mday ) ) /* before birthday in current month */
+- age--;
+-
+- return age;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Returns timestamp field in date & time format (DD-MM-YYYY HH:MM:SS)
+- *
+- * @param msecs The timestamps (milliseconds since epoch)
+- * @return Date & Time in a display'able format.
+- */
+-static const char* datetime( gint64 msecs )
+-{
+- time_t secs = msecs / 1000;
+-
+- struct tm t;
+- localtime_r( &secs, &t );
+-
+- return purple_utf8_strftime( "%d-%m-%Y %H:%M:%S", &t );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the profile information.
+- *
+- * @param session The MXit session object
+- * @param username The username who's profile information this is
+- * @param profile The profile
+- */
+-void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile )
+-{
+- PurpleNotifyUserInfo* info = purple_notify_user_info_new();
+- struct contact* contact = NULL;
+- PurpleBuddy* buddy;
+- gchar* tmp = NULL;
+-
+- buddy = purple_find_buddy( session->acc, username );
+- if ( buddy ) {
+- purple_notify_user_info_add_pair( info, _( "Alias" ), purple_buddy_get_alias( buddy ) );
+- purple_notify_user_info_add_section_break( info );
+- contact = purple_buddy_get_protocol_data(buddy);
+- }
+-
+- purple_notify_user_info_add_pair( info, _( "Display Name" ), profile->nickname );
+-
+- tmp = g_strdup_printf("%s (%i)", profile->birthday, calculateAge( profile->birthday ) );
+- purple_notify_user_info_add_pair( info, _( "Birthday" ), tmp );
+- g_free( tmp );
+-
+- purple_notify_user_info_add_pair( info, _( "Gender" ), profile->male ? _( "Male" ) : _( "Female" ) );
+-
+- /* optional information */
+- purple_notify_user_info_add_pair( info, _( "First Name" ), profile->firstname );
+- purple_notify_user_info_add_pair( info, _( "Last Name" ), profile->lastname );
+- purple_notify_user_info_add_pair( info, _( "Country" ), profile->regcountry );
+-
+- if ( strlen( profile->aboutme ) > 0 )
+- purple_notify_user_info_add_pair( info, _( "About Me" ), profile->aboutme );
+- if ( strlen( profile->whereami ) > 0 )
+- purple_notify_user_info_add_pair( info, _( "Where I Live" ), profile->whereami );
+-
+- purple_notify_user_info_add_pair_plaintext( info, _( "Relationship Status" ), mxit_relationship_to_name( profile->relationship ) );
+-
+- purple_notify_user_info_add_section_break( info );
+-
+- if ( contact ) {
+- /* presence */
+- purple_notify_user_info_add_pair( info, _( "Status" ), mxit_convert_presence_to_name( contact->presence ) );
+-
+- /* last online */
+- if ( contact->presence == MXIT_PRESENCE_OFFLINE )
+- purple_notify_user_info_add_pair( info, _( "Last Online" ), ( profile->lastonline == 0 ) ? _( "Unknown" ) : datetime( profile->lastonline ) );
+-
+- /* mood */
+- if ( contact->mood != MXIT_MOOD_NONE )
+- purple_notify_user_info_add_pair( info, _( "Mood" ), mxit_convert_mood_to_name( contact->mood ) );
+- else
+- purple_notify_user_info_add_pair( info, _( "Mood" ), _( "None" ) );
+-
+- /* status message */
+- if ( contact->statusMsg )
+- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+-
+- /* subscription type */
+- purple_notify_user_info_add_pair( info, _( "Subscription" ), mxit_convert_subtype_to_name( contact->subtype ) );
+- }
+- else {
+- /* this is an invite */
+- contact = get_mxit_invite_contact( session, username );
+- if ( contact ) {
+- /* invite found */
+-
+- if ( contact->msg )
+- purple_notify_user_info_add_pair( info, _( "Invite Message" ), contact->msg );
+-
+- if ( contact->imgid ) {
+- /* this invite has a avatar */
+- char* img_text;
+- img_text = g_strdup_printf( "<img id='%d'>", contact->imgid );
+- purple_notify_user_info_add_pair( info, _( "Photo" ), img_text );
+- g_free( img_text );
+- }
+-
+- if ( contact->statusMsg )
+- purple_notify_user_info_add_pair( info, _( "Status Message" ), contact->statusMsg );
+- }
+- }
+-
+- purple_notify_userinfo( session->con, username, info, NULL, NULL );
+- purple_notify_user_info_destroy( info );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the profiles of search results.
+- *
+- * @param gc The connection object
+- * @param row The selected row from search-results
+- * @param user_data NULL (unused)
+- */
+-static void mxit_search_results_add_cb( PurpleConnection *gc, GList *row, gpointer user_data )
+-{
+- /* display add buddy dialog */
+- purple_blist_request_add_buddy( purple_connection_get_account( gc ), g_list_nth_data( row, 0 ), NULL, g_list_nth_data( row, 1 ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the profiles of search results.
+- *
+- * @param session The MXit session object
+- * @param searchType The type of search (CP_SUGGEST_*)
+- * @param maxResults The maximum number of results
+- * @param entries The list of profile entries
+- */
+-void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries )
+-{
+- PurpleNotifySearchResults* results;
+- PurpleNotifySearchColumn* column;
+- gchar* text;
+-
+- if ( !entries ) {
+- mxit_popup( PURPLE_NOTIFY_MSG_INFO, _( "No results" ), _( "No contacts found." ) );
+- return;
+- }
+-
+- results = purple_notify_searchresults_new();
+- if ( !results )
+- return;
+-
+- /* define columns */
+- column = purple_notify_searchresults_column_new( _( "UserId" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "Display Name" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "First Name" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "Last Name" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "Gender" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "Age" ) );
+- purple_notify_searchresults_column_add( results, column );
+- column = purple_notify_searchresults_column_new( _( "Where I live" ) );
+- purple_notify_searchresults_column_add( results, column );
+-
+- while (entries != NULL) {
+- struct MXitProfile* profile = ( struct MXitProfile *) entries->data;
+- GList* row;
+- gchar* tmp = purple_base64_encode( (unsigned char *) profile->userid, strlen( profile->userid ) );
+-
+- /* column values */
+- row = g_list_append( NULL, g_strdup_printf( "#%s", tmp ) );
+- row = g_list_append( row, g_strdup( profile->nickname ) );
+- row = g_list_append( row, g_strdup( profile->firstname ) );
+- row = g_list_append( row, g_strdup( profile->lastname ) );
+- row = g_list_append( row, g_strdup( profile->male ? "Male" : "Female" ) );
+- row = g_list_append( row, g_strdup_printf( "%i", calculateAge( profile->birthday ) ) );
+- row = g_list_append( row, g_strdup( profile->whereami ) );
+-
+- purple_notify_searchresults_row_add( results, row );
+- entries = g_list_next( entries );
+-
+- g_free( tmp );
+- }
+-
+- /* button */
+- purple_notify_searchresults_button_add( results, PURPLE_NOTIFY_BUTTON_INVITE, mxit_search_results_add_cb );
+-
+- if ( searchType == CP_SUGGEST_FRIENDS )
+- text = g_strdup_printf( dngettext( PACKAGE, "You have %i suggested friend.", "You have %i suggested friends.", maxResults ), maxResults );
+- else
+- text = g_strdup_printf( dngettext( PACKAGE, "We found %i contact that matches your search.", "We found %i contacts that match your search.", maxResults ), maxResults );
+-
+- purple_notify_searchresults( session->con, NULL, text, NULL, results, NULL, NULL );
+-
+- g_free( text);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/profile.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/profile.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/profile.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,76 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- user profile's --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_PROFILE_H_
+-#define _MXIT_PROFILE_H_
+-
+-#include <glib.h>
+-
+-
+-/* MXit relationship status types */
+-#define MXIT_RELATIONSHIP_UNKNOWN 0
+-#define MXIT_RELATIONSHIP_DONTSAY 1
+-#define MXIT_RELATIONSHIP_SINGLE 2
+-#define MXIT_RELATIONSHIP_INVOLVED 3
+-#define MXIT_RELATIONSHIP_ENGAGED 4
+-#define MXIT_RELATIONSHIP_MARRIED 5
+-#define MXIT_RELATIONSHIP_COMPLICATED 6
+-#define MXIT_RELATIONSHIP_WIDOWED 7
+-#define MXIT_RELATIONSHIP_SEPARATED 8
+-#define MXIT_RELATIONSHIP_DIVORCED 9
+-
+-struct MXitProfile {
+- /* required */
+- char loginname[64]; /* name user uses to log into MXit with (aka 'mxitid') */
+- char userid[51]; /* internal UserId (only in search results) */
+- char nickname[101]; /* user's own display name (aka 'display name', aka 'fullname', aka 'alias') in MXit */
+- char birthday[16]; /* user's birthday "YYYY-MM-DD" */
+- gboolean male; /* true if the user's gender is male (otherwise female) */
+- char pin[16]; /* user's password */
+-
+- /* optional */
+- char title[21]; /* user's title */
+- char firstname[51]; /* user's first name */
+- char lastname[51]; /* user's last name (aka 'surname') */
+- char email[201]; /* user's email address */
+- char mobilenr[21]; /* user's mobile number */
+- char regcountry[3]; /* user's registered country code */
+- char whereami[51]; /* where am I / where I live */
+- char aboutme[513]; /* about me */
+- int relationship; /* relationship status */
+-
+- int flags; /* user's profile flags */
+- gint64 lastonline; /* user's last-online timestamp */
+-};
+-
+-struct MXitSession;
+-void mxit_show_profile( struct MXitSession* session, const char* username, struct MXitProfile* profile );
+-void mxit_show_search_results( struct MXitSession* session, int searchType, int maxResults, GList* entries );
+-const char* mxit_relationship_to_name( short id );
+-
+-gboolean validateDate( const char* bday );
+-
+-
+-#endif /* _MXIT_PROFILE_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/protocol.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/protocol.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2949 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit client protocol implementation --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "roster.h"
+-#include "chunk.h"
+-#include "filexfer.h"
+-#include "markup.h"
+-#include "multimx.h"
+-#include "splashscreen.h"
+-#include "login.h"
+-#include "formcmds.h"
+-#include "http.h"
+-#include "voicevideo.h"
+-
+-
+-#define MXIT_MS_OFFSET 3
+-
+-/* configure the right record terminator char to use */
+-#define CP_REC_TERM ( ( session->http ) ? CP_HTTP_REC_TERM : CP_SOCK_REC_TERM )
+-
+-
+-/*------------------------------------------------------------------------
+- * return the current timestamp in milliseconds
+- */
+-gint64 mxit_now_milli( void )
+-{
+- GTimeVal now;
+-
+- g_get_current_time( &now );
+-
+- return ( ( now.tv_sec * 1000 ) + ( now.tv_usec / 1000 ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display a notification popup message to the user.
+- *
+- * @param type The type of notification:
+- * - info: PURPLE_NOTIFY_MSG_INFO
+- * - warning: PURPLE_NOTIFY_MSG_WARNING
+- * - error: PURPLE_NOTIFY_MSG_ERROR
+- * @param heading Heading text
+- * @param message Message text
+- */
+-void mxit_popup( int type, const char* heading, const char* message )
+-{
+- /* (reference: "libpurple/notify.h") */
+- purple_notify_message( NULL, type, _( MXIT_POPUP_WIN_NAME ), heading, message, NULL, NULL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * For compatibility with legacy clients, all usernames are sent from MXit with a domain
+- * appended. For MXit contacts, this domain is set to "@m". This function strips
+- * those fake domains.
+- *
+- * @param username The username of the contact
+- */
+-void mxit_strip_domain( char* username )
+-{
+- if ( g_str_has_suffix( username, "@m" ) )
+- username[ strlen(username) - 2 ] = '\0';
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Dump a byte buffer to the console for debugging purposes.
+- *
+- * @param buf The data
+- * @param len The data length
+- */
+-void dump_bytes( struct MXitSession* session, const char* buf, int len )
+-{
+- char msg[( len * 3 ) + 1];
+- int i;
+-
+- memset( msg, 0x00, sizeof( msg ) );
+-
+- for ( i = 0; i < len; i++ ) {
+- if ( buf[i] == CP_REC_TERM ) /* record terminator */
+- msg[i] = '!';
+- else if ( buf[i] == CP_FLD_TERM ) /* field terminator */
+- msg[i] = '^';
+- else if ( buf[i] == CP_PKT_TERM ) /* packet terminator */
+- msg[i] = '@';
+- else if ( buf[i] < 0x20 )
+- msg[i] = '_';
+- else
+- msg[i] = buf[i];
+-
+- }
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Determine if we have an active chat with a specific contact
+- *
+- * @param session The MXit session object
+- * @param who The contact name
+- * @return Return true if we have an active chat with the contact
+- */
+-gboolean find_active_chat( const GList* chats, const char* who )
+-{
+- const GList* list = chats;
+- const char* chat = NULL;
+-
+- while ( list ) {
+- chat = (const char*) list->data;
+-
+- if ( strcmp( chat, who ) == 0 )
+- return TRUE;
+-
+- list = g_list_next( list );
+- }
+-
+- return FALSE;
+-}
+-
+-
+-/*========================================================================================================================
+- * Low-level Packet transmission
+- */
+-
+-/*------------------------------------------------------------------------
+- * Remove next packet from transmission queue.
+- *
+- * @param session The MXit session object
+- * @return The next packet for transmission (or NULL)
+- */
+-static struct tx_packet* pop_tx_packet( struct MXitSession* session )
+-{
+- struct tx_packet* packet = NULL;
+-
+- if ( session->queue.count > 0 ) {
+- /* dequeue the next packet */
+- packet = session->queue.packets[session->queue.rd_i];
+- session->queue.packets[session->queue.rd_i] = NULL;
+- session->queue.rd_i = ( session->queue.rd_i + 1 ) % MAX_QUEUE_SIZE;
+- session->queue.count--;
+- }
+-
+- return packet;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Add packet to transmission queue.
+- *
+- * @param session The MXit session object
+- * @param packet The packet to transmit
+- * @return Return TRUE if packet was enqueue, or FALSE if queue is full.
+- */
+-static gboolean push_tx_packet( struct MXitSession* session, struct tx_packet* packet )
+-{
+- if ( session->queue.count < MAX_QUEUE_SIZE ) {
+- /* enqueue packet */
+- session->queue.packets[session->queue.wr_i] = packet;
+- session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
+- session->queue.count++;
+- return TRUE;
+- }
+- else
+- return FALSE; /* queue is full */
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Deallocate transmission packet.
+- *
+- * @param packet The packet to deallocate.
+- */
+-static void free_tx_packet( struct tx_packet* packet )
+-{
+- g_free( packet->data );
+- g_free( packet );
+- packet = NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Flush all the packets from the tx queue and release the resources.
+- *
+- * @param session The MXit session object
+- */
+-static void flush_queue( struct MXitSession* session )
+-{
+- struct tx_packet* packet;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "flushing the tx queue\n" );
+-
+- while ( (packet = pop_tx_packet( session ) ) != NULL )
+- free_tx_packet( packet );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * TX Step 3: Write the packet data to the TCP connection.
+- *
+- * @param fd The file descriptor
+- * @param pktdata The packet data
+- * @param pktlen The length of the packet data
+- * @return Return -1 on error, otherwise 0
+- */
+-static int mxit_write_sock_packet( int fd, const char* pktdata, int pktlen )
+-{
+- int written;
+- int res;
+-
+- written = 0;
+- while ( written < pktlen ) {
+- res = write( fd, &pktdata[written], pktlen - written );
+- if ( res <= 0 ) {
+- /* error on socket */
+- if ( errno == EAGAIN )
+- continue;
+-
+- purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
+- return -1;
+- }
+- written += res;
+- }
+-
+- return 0;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback called for handling a HTTP GET response
+- *
+- * @param url_data libPurple internal object (see purple_util_fetch_url_request)
+- * @param user_data The MXit session object
+- * @param url_text The data returned (could be NULL if error)
+- * @param len The length of the data returned (0 if error)
+- * @param error_message Descriptive error message
+- */
+-static void mxit_cb_http_rx( PurpleUtilFetchUrlData* url_data, gpointer user_data, const gchar* url_text, gsize len, const gchar* error_message )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+-
+- /* clear outstanding request */
+- session->http_out_req = NULL;
+-
+- if ( ( !url_text ) || ( len == 0 ) ) {
+- /* error with request */
+- purple_debug_error( MXIT_PLUGIN_ID, "HTTP response error (%s)\n", error_message );
+- return;
+- }
+-
+- /* convert the HTTP result */
+- memcpy( session->rx_dbuf, url_text, len );
+- session->rx_i = len;
+-
+- mxit_parse_packet( session );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * TX Step 3: Write the packet data to the HTTP connection (GET style).
+- *
+- * @param session The MXit session object
+- * @param pktdata The packet data
+- * @param pktlen The length of the packet data
+- * @return Return -1 on error, otherwise 0
+- */
+-static void mxit_write_http_get( struct MXitSession* session, struct tx_packet* packet )
+-{
+- char* part = NULL;
+- char* url = NULL;
+-
+- if ( packet->datalen > 0 ) {
+- char* tmp = NULL;
+-
+- tmp = g_strndup( packet->data, packet->datalen );
+- part = g_strdup( purple_url_encode( tmp ) );
+- g_free( tmp );
+- }
+-
+- url = g_strdup_printf( "%s?%s%s", session->http_server, purple_url_encode( packet->header ), ( !part ) ? "" : part );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP GET: '%s'\n", url );
+-#endif
+-
+- /* send the HTTP request */
+- session->http_out_req = purple_util_fetch_url_request( url, TRUE, MXIT_HTTP_USERAGENT, TRUE, NULL, FALSE, mxit_cb_http_rx, session );
+-
+- g_free( url );
+- if ( part )
+- g_free( part );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * TX Step 3: Write the packet data to the HTTP connection (POST style).
+- *
+- * @param session The MXit session object
+- * @param pktdata The packet data
+- * @param pktlen The length of the packet data
+- * @return Return -1 on error, otherwise 0
+- */
+-static void mxit_write_http_post( struct MXitSession* session, struct tx_packet* packet )
+-{
+- char request[256 + packet->datalen];
+- int reqlen;
+- char* host_name;
+- int host_port;
+- gboolean ok;
+-
+- /* extract the HTTP host name and host port number to connect to */
+- ok = purple_url_parse( session->http_server, &host_name, &host_port, NULL, NULL, NULL );
+- if ( !ok ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "HTTP POST error: (host name '%s' not valid)\n", session->http_server );
+- }
+-
+- /* strip off the last '&' from the header */
+- packet->header[packet->headerlen - 1] = '\0';
+- packet->headerlen--;
+-
+- /* build the HTTP request packet */
+- reqlen = g_snprintf( request, 256,
+- "POST %s?%s HTTP/1.1\r\n"
+- "User-Agent: " MXIT_HTTP_USERAGENT "\r\n"
+- "Content-Type: application/octet-stream\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %d\r\n"
+- "\r\n",
+- session->http_server,
+- purple_url_encode( packet->header ),
+- host_name,
+- packet->datalen - MXIT_MS_OFFSET
+- );
+-
+- /* copy over the packet body data (could be binary) */
+- memcpy( request + reqlen, packet->data + MXIT_MS_OFFSET, packet->datalen - MXIT_MS_OFFSET );
+- reqlen += packet->datalen;
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "HTTP POST:\n" );
+- dump_bytes( session, request, reqlen );
+-#endif
+-
+- /* send the request to the HTTP server */
+- mxit_http_send_request( session, host_name, host_port, request, reqlen );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * TX Step 2: Handle the transmission of the packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param packet The packet to transmit
+- */
+-static void mxit_send_packet( struct MXitSession* session, struct tx_packet* packet )
+-{
+- int res;
+-
+- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+- /* we are not connected so ignore all packets to be send */
+- purple_debug_error( MXIT_PLUGIN_ID, "Dropping TX packet (we are not connected)\n" );
+- return;
+- }
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
+-#ifdef DEBUG_PROTOCOL
+- dump_bytes( session, packet->header, packet->headerlen );
+- dump_bytes( session, packet->data, packet->datalen );
+-#endif
+-
+- if ( !session->http ) {
+- /* socket connection */
+- char data[packet->datalen + packet->headerlen];
+- int datalen;
+-
+- /* create raw data buffer */
+- memcpy( data, packet->header, packet->headerlen );
+- memcpy( data + packet->headerlen, packet->data, packet->datalen );
+- datalen = packet->headerlen + packet->datalen;
+-
+- res = mxit_write_sock_packet( session->fd, data, datalen );
+- if ( res < 0 ) {
+- /* we must have lost the connection, so terminate it so that we can reconnect */
+- purple_connection_error( session->con, _( "We have lost the connection to MXit. Please reconnect." ) );
+- }
+- }
+- else {
+- /* http connection */
+-
+- if ( packet->cmd == CP_CMD_MEDIA ) {
+- /* multimedia packets must be send with a HTTP POST */
+- mxit_write_http_post( session, packet );
+- }
+- else {
+- mxit_write_http_get( session, packet );
+- }
+- }
+-
+- /* update the timestamp of the last-transmitted packet */
+- session->last_tx = mxit_now_milli();
+-
+- /*
+- * we need to remember that we are still waiting for the ACK from
+- * the server on this request
+- */
+- session->outack = packet->cmd;
+-
+- /* free up the packet resources */
+- free_tx_packet( packet );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * TX Step 1: Create a new Tx packet and queue it for sending.
+- *
+- * @param session The MXit session object
+- * @param data The packet data (payload)
+- * @param datalen The length of the packet data
+- * @param cmd The MXit command for this packet
+- */
+-static void mxit_queue_packet( struct MXitSession* session, const char* data, int datalen, int cmd )
+-{
+- struct tx_packet* packet;
+- char header[256];
+- int hlen;
+-
+- /* create a packet for sending */
+- packet = g_new0( struct tx_packet, 1 );
+- packet->data = g_malloc0( datalen );
+- packet->cmd = cmd;
+- packet->headerlen = 0;
+-
+- /* create generic packet header */
+- hlen = snprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client msisdn */
+-
+- if ( session->http ) {
+- /* http connection only */
+- hlen += sprintf( header + hlen, "s=" );
+- if ( session->http_sesid > 0 ) {
+- hlen += sprintf( header + hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */
+- }
+- session->http_seqno++;
+- hlen += sprintf( header + hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */
+- }
+-
+- hlen += sprintf( header + hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */
+-
+- if ( !session->http ) {
+- /* socket connection only */
+- packet->headerlen += sprintf( packet->header, "ln=%i%c", ( datalen + hlen ), CP_REC_TERM ); /* packet length */
+- }
+-
+- /* copy the header to packet */
+- memcpy( packet->header + packet->headerlen, header, hlen );
+- packet->headerlen += hlen;
+-
+- /* copy payload to packet */
+- if ( datalen > 0 )
+- memcpy( packet->data, data, datalen );
+- packet->datalen = datalen;
+-
+-
+- /* shortcut */
+- if ( ( session->queue.count == 0 ) && ( session->outack == 0 ) ) {
+- /* the queue is empty and there are no outstanding acks so we can write it directly */
+- mxit_send_packet( session, packet );
+- }
+- else {
+- /* we need to queue this packet */
+-
+- if ( ( packet->cmd == CP_CMD_PING ) || ( packet->cmd == CP_CMD_POLL ) ) {
+- /* we do NOT queue HTTP poll nor socket ping packets */
+- free_tx_packet( packet );
+- return;
+- }
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "queueing packet for later sending cmd=%i\n", cmd );
+- if ( !push_tx_packet( session, packet ) ) {
+- /* packet could not be queued for transmission */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Message Send Error" ), _( "Unable to process your request at this time" ) );
+- free_tx_packet( packet );
+- }
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Manage the packet send queue (send next packet, timeout's, etc).
+- *
+- * @param session The MXit session object
+- */
+-static void mxit_manage_queue( struct MXitSession* session )
+-{
+- struct tx_packet* packet = NULL;
+- gint64 now = mxit_now_milli();
+-
+- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+- /* we are not connected, so ignore the queue */
+- return;
+- }
+- else if ( session->outack > 0 ) {
+- /* we are still waiting for an outstanding ACK from the MXit server */
+- if ( session->last_tx <= mxit_now_milli() - ( MXIT_ACK_TIMEOUT * 1000 ) ) {
+- /* ack timeout! so we close the connection here */
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_manage_queue: Timeout awaiting ACK for command '%i'\n", session->outack );
+- purple_connection_error( session->con, _( "Timeout while waiting for a response from the MXit server." ) );
+- }
+- return;
+- }
+-
+- /*
+- * the mxit server has flood detection and it prevents you from sending messages to fast.
+- * this is a self defense mechanism, a very annoying feature. so the client must ensure that
+- * it does not send messages too fast otherwise mxit will ignore the user for 30 seconds.
+- * this is what we are trying to avoid here..
+- */
+- if ( session->q_fast_timer_id == 0 ) {
+- /* the fast timer has not been set yet */
+- if ( session->last_tx > ( now - MXIT_TX_DELAY ) ) {
+- /* we need to wait a little before sending the next packet, so schedule a wakeup call */
+- gint64 tdiff = now - ( session->last_tx );
+- guint delay = ( MXIT_TX_DELAY - tdiff ) + 9;
+- if ( delay <= 0 )
+- delay = MXIT_TX_DELAY;
+- session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
+- }
+- else {
+- /* get the next packet from the queue to send */
+- packet = pop_tx_packet( session );
+- if ( packet != NULL ) {
+- /* there was a packet waiting to be sent to the server, now is the time to do something about it */
+-
+- /* send the packet to MXit server */
+- mxit_send_packet( session, packet );
+- }
+- }
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Slow callback to manage the packet send queue.
+- *
+- * @param session The MXit session object
+- */
+-gboolean mxit_manage_queue_slow( gpointer user_data )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+-
+- mxit_manage_queue( session );
+-
+- /* continue running */
+- return TRUE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Fast callback to manage the packet send queue.
+- *
+- * @param session The MXit session object
+- */
+-gboolean mxit_manage_queue_fast( gpointer user_data )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+-
+- session->q_fast_timer_id = 0;
+- mxit_manage_queue( session );
+-
+- /* stop running */
+- return FALSE;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback to manage HTTP server polling (HTTP connections ONLY)
+- *
+- * @param session The MXit session object
+- */
+-gboolean mxit_manage_polling( gpointer user_data )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+- gboolean poll = FALSE;
+- gint64 now = mxit_now_milli();
+- int polldiff;
+- gint64 rxdiff;
+-
+- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
+- /* we only poll if we are actually logged in */
+- return TRUE;
+- }
+-
+- /* calculate the time differences */
+- rxdiff = now - session->last_rx;
+- polldiff = now - session->http_last_poll;
+-
+- if ( rxdiff < MXIT_HTTP_POLL_MIN ) {
+- /* we received some reply a few moments ago, so reset the poll interval */
+- session->http_interval = MXIT_HTTP_POLL_MIN;
+- }
+- else if ( session->http_last_poll < ( now - session->http_interval ) ) {
+- /* time to poll again */
+- poll = TRUE;
+-
+- /* back-off some more with the polling */
+- session->http_interval = session->http_interval + ( session->http_interval / 2 );
+- if ( session->http_interval > MXIT_HTTP_POLL_MAX )
+- session->http_interval = MXIT_HTTP_POLL_MAX;
+- }
+-
+- /* debugging */
+- //purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i,%i)\n", session->http_interval, rxdiff, polldiff );
+-
+- if ( poll ) {
+- /* send poll request */
+- session->http_last_poll = mxit_now_milli();
+- mxit_send_poll( session );
+- }
+-
+- return TRUE;
+-}
+-
+-
+-/*========================================================================================================================
+- * Send MXit operations.
+- */
+-
+-/*------------------------------------------------------------------------
+- * Send a ping/keepalive packet to MXit server.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_send_ping( struct MXitSession* session )
+-{
+- /* queue packet for transmission */
+- mxit_queue_packet( session, NULL, 0, CP_CMD_PING );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a poll request to the HTTP server (HTTP connections ONLY).
+- *
+- * @param session The MXit session object
+- */
+-void mxit_send_poll( struct MXitSession* session )
+-{
+- /* queue packet for transmission */
+- mxit_queue_packet( session, NULL, 0, CP_CMD_POLL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a logout packet to the MXit server.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_send_logout( struct MXitSession* session )
+-{
+- /* queue packet for transmission */
+- mxit_queue_packet( session, NULL, 0, CP_CMD_LOGOUT );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a register packet to the MXit server.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_send_register( struct MXitSession* session )
+-{
+- struct MXitProfile* profile = session->profile;
+- const char* locale;
+- char data[CP_MAX_PACKET];
+- int datalen;
+- char* clientVersion;
+- unsigned int features = MXIT_CP_FEATURES;
+-
+- locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
+-
+- /* Voice and Video supported */
+- if (mxit_audio_enabled() && mxit_video_enabled())
+- features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
+- else if (mxit_audio_enabled())
+- features |= MXIT_CF_VOICE;
+-
+- /* generate client version string (eg, P-2.7.10-Y-PURPLE) */
+- clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%i%c%s%c" /* "ms"=password\1version\1maxreplyLen\1name\1 */
+- "%s%c%i%c%s%c%s%c" /* dateOfBirth\1gender\1location\1capabilities\1 */
+- "%s%c%i%c%s%c%s" /* dc\1features\1dialingcode\1locale */
+- "%c%i%c%i", /* \1protocolVer\1lastRosterUpdate */
+- session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, CP_MAX_FILESIZE, CP_FLD_TERM, profile->nickname, CP_FLD_TERM,
+- profile->birthday, CP_FLD_TERM, ( profile->male ) ? 1 : 0, CP_FLD_TERM, MXIT_DEFAULT_LOC, CP_FLD_TERM, MXIT_CP_CAP, CP_FLD_TERM,
+- session->distcode, CP_FLD_TERM, features, CP_FLD_TERM, session->dialcode, CP_FLD_TERM, locale,
+- CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_REGISTER );
+-
+- g_free( clientVersion );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a login packet to the MXit server.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_send_login( struct MXitSession* session )
+-{
+- const char* splashId;
+- const char* locale;
+- char data[CP_MAX_PACKET];
+- int datalen;
+- char* clientVersion;
+- unsigned int features = MXIT_CP_FEATURES;
+-
+- locale = purple_account_get_string( session->acc, MXIT_CONFIG_LOCALE, MXIT_DEFAULT_LOCALE );
+-
+- /* Voice and Video supported */
+- if (mxit_audio_enabled() && mxit_video_enabled())
+- features |= (MXIT_CF_VOICE | MXIT_CF_VIDEO);
+- else if (mxit_audio_enabled())
+- features |= MXIT_CF_VOICE;
+-
+- /* generate client version string (eg, P-2.7.10-Y-PURPLE) */
+- clientVersion = g_strdup_printf( "%c-%i.%i.%i-%s-%s", MXIT_CP_DISTCODE, PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION, PURPLE_MICRO_VERSION, MXIT_CP_ARCH, MXIT_CP_PLATFORM );
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%i%c" /* "ms"=password\1version\1getContacts\1 */
+- "%s%c%s%c%i%c" /* capabilities\1dc\1features\1 */
+- "%s%c%s%c" /* dialingcode\1locale\1 */
+- "%i%c%i%c%i", /* maxReplyLen\1protocolVer\1lastRosterUpdate */
+- session->encpwd, CP_FLD_TERM, clientVersion, CP_FLD_TERM, 1, CP_FLD_TERM,
+- MXIT_CP_CAP, CP_FLD_TERM, session->distcode, CP_FLD_TERM, features, CP_FLD_TERM,
+- session->dialcode, CP_FLD_TERM, locale, CP_FLD_TERM,
+- CP_MAX_FILESIZE, CP_FLD_TERM, MXIT_CP_PROTO_VESION, CP_FLD_TERM, 0
+- );
+-
+- /* include "custom resource" information */
+- splashId = splash_current( session );
+- if ( splashId != NULL )
+- datalen += sprintf( data + datalen, "%ccr=%s", CP_REC_TERM, splashId );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_LOGIN );
+-
+- g_free( clientVersion );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a chat message packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param to The username of the recipient
+- * @param msg The message text
+- */
+-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command )
+-{
+- char data[CP_MAX_PACKET];
+- char* markuped_msg;
+- int datalen;
+- int msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
+-
+- /* first we need to convert the markup from libPurple to MXit format */
+- if ( parse_markup )
+- markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
+- else
+- markuped_msg = g_strdup( msg );
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%i%c%i", /* "ms"=jid\1msg\1type\1flags */
+- to, CP_FLD_TERM, markuped_msg, CP_FLD_TERM, msgtype, CP_FLD_TERM, CP_MSG_MARKUP | CP_MSG_EMOTICON
+- );
+-
+- /* free the resources */
+- g_free( markuped_msg );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_TX_MSG );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a extended profile request packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username Username who's profile is being requested (NULL = our own)
+- * @param nr_attribs Number of attributes being requested
+- * @param attribute The names of the attributes
+- */
+-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+- unsigned int i;
+-
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
+- ( username ? username : "" ), CP_FLD_TERM, nr_attrib
+- );
+-
+- /* add attributes */
+- for ( i = 0; i < nr_attrib; i++ )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_GET );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send an update profile packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param password The new password to be used for logging in (optional)
+- * @param nr_attrib The number of attributes
+- * @param attributes String containing the attribute-name, attribute-type and value (seperated by '\01')
+- */
+-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes )
+-{
+- char data[CP_MAX_PACKET];
+- gchar** parts = NULL;
+- int datalen;
+- unsigned int i;
+-
+- if ( attributes )
+- parts = g_strsplit( attributes, "\01", 1 + ( nr_attrib * 3 ) );
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%i", /* "ms"=password\1nr_attibutes */
+- ( password ) ? password : "", CP_FLD_TERM, nr_attrib
+- );
+-
+- /* add attributes */
+- for ( i = 1; i < nr_attrib * 3; i+=3 )
+- datalen += sprintf( data + datalen, "%c%s%c%s%c%s", /* \1name\1type\1value */
+- CP_FLD_TERM, parts[i], CP_FLD_TERM, parts[i + 1], CP_FLD_TERM, parts[i + 2] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_EXTPROFILE_SET );
+-
+- /* freeup the memory */
+- g_strfreev( parts );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send packet to request list of suggested friends.
+- *
+- * @param session The MXit session object
+- * @param max Maximum number of results to return
+- * @param nr_attribs Number of attributes being requested
+- * @param attribute The names of the attributes
+- */
+-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+- unsigned int i;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+- CP_SUGGEST_FRIENDS, CP_FLD_TERM, "", CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+-
+- /* add attributes */
+- for ( i = 0; i < nr_attrib; i++ )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send packet to perform a search for users.
+- *
+- * @param session The MXit session object
+- * @param max Maximum number of results to return
+- * @param text The search text
+- * @param nr_attribs Number of attributes being requested
+- * @param attribute The names of the attributes
+- */
+-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+- unsigned int i;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%i%c%s%c%i%c%i%c%i", /* inputType \1 input \1 maxSuggestions \1 startIndex \1 numAttributes \1 name0 \1 name1 ... \1 nameN */
+- CP_SUGGEST_SEARCH, CP_FLD_TERM, text, CP_FLD_TERM, max, CP_FLD_TERM, 0, CP_FLD_TERM, nr_attrib );
+-
+- /* add attributes */
+- for ( i = 0; i < nr_attrib; i++ )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, attribute[i] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_SUGGESTCONTACTS );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a presence update packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param presence The presence (as per MXit types)
+- * @param statusmsg The status message (can be NULL)
+- */
+-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%i%c", /* "ms"=show\1status */
+- presence, CP_FLD_TERM
+- );
+-
+- /* append status message (if one is set) */
+- if ( statusmsg )
+- datalen += sprintf( data + datalen, "%s", statusmsg );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_STATUS );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a mood update packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param mood The mood (as per MXit types)
+- */
+-void mxit_send_mood( struct MXitSession* session, int mood )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%i", /* "ms"=mood */
+- mood
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MOOD );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send an invite contact packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact being invited
+- * @param mxitid Indicates the username is a MXitId.
+- * @param alias Our alias for the contact
+- * @param groupname Group in which contact should be stored.
+- * @param message Invite message
+- */
+-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%s%c%i%c%s%c%i", /* "ms"=group \1 username \1 alias \1 type \1 msg \1 isuserid */
+- groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias,
+- CP_FLD_TERM, MXIT_TYPE_MXIT, CP_FLD_TERM,
+- ( message ? message : "" ), CP_FLD_TERM,
+- ( mxitid ? 0 : 1 )
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_INVITE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a remove contact packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact being removed
+- */
+-void mxit_send_remove( struct MXitSession* session, const char* username )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s", /* "ms"=username */
+- username
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_REMOVE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send an accept subscription (invite) packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact being accepted
+- * @param alias Our alias for the contact
+- */
+-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%s", /* "ms"=username\1group\1alias */
+- username, CP_FLD_TERM, "", CP_FLD_TERM, alias
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_ALLOW );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send an deny subscription (invite) packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact being denied
+- * @param reason The message describing the reason for the rejection (can be NULL).
+- */
+-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s", /* "ms"=username */
+- username
+- );
+-
+- /* append reason (if one is set) */
+- if ( reason )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, reason );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_DENY );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send an update contact packet to the MXit server.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact being denied
+- * @param alias Our alias for the contact
+- * @param groupname Group in which contact should be stored.
+- */
+-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%s", /* "ms"=groupname\1username\1alias */
+- groupname, CP_FLD_TERM, username, CP_FLD_TERM, alias
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_UPDATE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a splash-screen click event packet.
+- *
+- * @param session The MXit session object
+- * @param splashid The identifier of the splash-screen
+- */
+-void mxit_send_splashclick( struct MXitSession* session, const char* splashid )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s", /* "ms"=splashId */
+- splashid
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_SPLASHCLICK );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a message event packet.
+- *
+- * @param session The MXit session object
+- * @param to The username of the original sender (ie, recipient of the event)
+- * @param id The identifier of the event (received in message)
+- * @param event Identified the type of event
+- */
+-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event)
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_msgevent: to=%s id=%s event=%i\n", to, id, event );
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%s%c%i", /* "ms"=contactAddress \1 id \1 event */
+- to, CP_FLD_TERM, id, CP_FLD_TERM, event
+- );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MSGEVENT );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send packet to create a MultiMX room.
+- *
+- * @param session The MXit session object
+- * @param groupname Name of the room to create
+- * @param nr_usernames Number of users in initial invite
+- * @param usernames The usernames of the users in the initial invite
+- */
+-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+- int i;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%i", /* "ms"=roomname\1nr_jids\1jid0\1..\1jidN */
+- groupname, CP_FLD_TERM, nr_usernames
+- );
+-
+- /* add usernames */
+- for ( i = 0; i < nr_usernames; i++ )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_CREATE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send packet to invite users to existing MultiMX room.
+- *
+- * @param session The MXit session object
+- * @param roomid The unique RoomID for the MultiMx room.
+- * @param nr_usernames Number of users being invited
+- * @param usernames The usernames of the users being invited
+- */
+-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen;
+- int i;
+-
+- /* convert the packet to a byte stream */
+- datalen = snprintf( data, sizeof( data ),
+- "ms=%s%c%i", /* "ms"=roomid\1nr_jids\1jid0\1..\1jidN */
+- roomid, CP_FLD_TERM, nr_usernames
+- );
+-
+- /* add usernames */
+- for ( i = 0; i < nr_usernames; i++ )
+- datalen += sprintf( data + datalen, "%c%s", CP_FLD_TERM, usernames[i] );
+-
+- /* queue packet for transmission */
+- mxit_queue_packet( session, data, datalen, CP_CMD_GRPCHAT_INVITE );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "send file direct" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param username The username of the recipient
+- * @param filename The name of the file being sent
+- * @param buf The content of the file
+- * @param buflen The length of the file contents
+- */
+-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %i bytes to user '%s'\n", filename, buflen, username );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating senddirect chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_DIRECT_SND );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "reject file" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param fileid A unique ID that identifies this file
+- */
+-void mxit_send_file_reject( struct MXitSession* session, const char* fileid )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_reject( chunk_data( chunk ), fileid );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating reject chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_REJECT );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "get file" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param fileid A unique ID that identifies this file
+- * @param filesize The number of bytes to retrieve
+- * @param offset Offset in file at which to start retrieving
+- */
+-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating getfile chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_GET );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "received file" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param status The status of the file-transfer
+- */
+-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_received( chunk_data(chunk), fileid, status );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating received chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_RECEIVED );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "set avatar" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param data The avatar data
+- * @param buflen The length of the avatar data
+- */
+-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %i bytes\n", avatarlen );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating set avatar chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_SET_AVATAR );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Send a "get avatar" multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param mxitId The username who's avatar to request
+- * @param avatarId The id of the avatar image (as string)
+- * @param data The avatar data
+- * @param buflen The length of the avatar data
+- */
+-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId )
+-{
+- char data[CP_MAX_PACKET];
+- int datalen = 0;
+- gchar* chunk;
+- int size;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId );
+-
+- /* convert the packet to a byte stream */
+- datalen = sprintf( data, "ms=" );
+-
+- /* map chunk header over data buffer */
+- chunk = &data[datalen];
+-
+- size = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId );
+- if ( size < 0 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "Error creating get avatar chunk (%i)\n", size );
+- return;
+- }
+-
+- set_chunk_type( chunk, CP_CHUNK_GET_AVATAR );
+- set_chunk_length( chunk, size );
+- datalen += MXIT_CHUNK_HEADER_SIZE + size;
+-
+- /* send the byte stream to the mxit server */
+- mxit_queue_packet( session, data, datalen, CP_CMD_MEDIA );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a login message packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_login( struct MXitSession* session, struct record** records, int rcount )
+-{
+- PurpleStatus* status;
+- int presence;
+- const char* statusmsg;
+- const char* profilelist[] = { CP_PROFILE_BIRTHDATE, CP_PROFILE_GENDER, CP_PROFILE_FULLNAME,
+- CP_PROFILE_TITLE, CP_PROFILE_FIRSTNAME, CP_PROFILE_LASTNAME, CP_PROFILE_EMAIL,
+- CP_PROFILE_MOBILENR, CP_PROFILE_WHEREAMI, CP_PROFILE_ABOUTME, CP_PROFILE_RELATIONSHIP, CP_PROFILE_FLAGS };
+-
+- purple_account_set_int( session->acc, MXIT_CONFIG_STATE, MXIT_STATE_LOGIN );
+-
+- /* we were not yet logged in so we need to complete the login sequence here */
+- session->flags |= MXIT_FLAG_LOGGEDIN;
+- purple_connection_update_progress( session->con, _( "Successfully Logged In..." ), 3, 4 );
+- purple_connection_set_state( session->con, PURPLE_CONNECTED );
+-
+- /* save extra info if this is a HTTP connection */
+- if ( session->http ) {
+- /* save the http server to use for this session */
+- g_strlcpy( session->http_server, records[1]->fields[3]->data, sizeof( session->http_server ) );
+-
+- /* save the session id */
+- session->http_sesid = atoi( records[0]->fields[0]->data );
+- }
+-
+- /* extract UserId (from protocol 5.9) */
+- if ( records[1]->fcount >= 9 )
+- session->uid = g_strdup( records[1]->fields[8]->data );
+-
+- /* extract VoIP server (from protocol 6.2) */
+- if ( records[1]->fcount >= 11 )
+- g_strlcpy( session->voip_server, records[1]->fields[10]->data, sizeof( session->voip_server ) );
+-
+- /* display the current splash-screen */
+- if ( splash_popup_enabled( session ) )
+- splash_display( session );
+-
+- /* update presence status */
+- status = purple_account_get_active_status( session->acc );
+- presence = mxit_convert_presence( purple_status_get_id( status ) );
+- statusmsg = purple_status_get_attr_string( status, "message" );
+-
+- if ( ( presence != MXIT_PRESENCE_ONLINE ) || ( statusmsg ) ) {
+- /* when logging into MXit, your default presence is online. but with the UI, one can change
+- * the presence to whatever. in the case where its changed to a different presence setting
+- * we need to send an update to the server, otherwise the user's presence will be out of
+- * sync between the UI and MXit.
+- */
+- char* statusmsg1 = purple_markup_strip_html( statusmsg );
+- char* statusmsg2 = g_strndup( statusmsg1, CP_MAX_STATUS_MSG );
+-
+- mxit_send_presence( session, presence, statusmsg2 );
+-
+- g_free( statusmsg1 );
+- g_free( statusmsg2 );
+- }
+-
+- /* retrieve our MXit profile */
+- mxit_send_extprofile_request( session, NULL, ARRAY_SIZE( profilelist ), profilelist );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received message packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_message( struct MXitSession* session, struct record** records, int rcount )
+-{
+- struct RXMsgData* mx = NULL;
+- char* message = NULL;
+- char* sender = NULL;
+- int msglen = 0;
+- int msgflags = 0;
+- int msgtype = 0;
+-
+- if ( ( rcount == 1 ) || ( records[0]->fcount < 2 ) || ( records[1]->fcount == 0 ) || ( records[1]->fields[0]->len == 0 ) ) {
+- /* packet contains no message or an empty message */
+- return;
+- }
+-
+- message = records[1]->fields[0]->data;
+- msglen = strlen( message );
+-
+- /* strip off dummy domain */
+- sender = records[0]->fields[0]->data;
+- mxit_strip_domain( sender );
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
+-#endif
+-
+- /* decode message flags (if any) */
+- if ( records[0]->fcount >= 5 )
+- msgflags = atoi( records[0]->fields[4]->data );
+- msgtype = atoi( records[0]->fields[2]->data );
+-
+- if ( msgflags & CP_MSG_PWD_ENCRYPTED ) {
+- /* this is a password encrypted message. we do not currently support those so ignore it */
+- PurpleBuddy* buddy;
+- const char* name;
+- char msg[128];
+-
+- buddy = purple_find_buddy( session->acc, sender );
+- if ( buddy )
+- name = purple_buddy_get_alias( buddy );
+- else
+- name = sender;
+- g_snprintf( msg, sizeof( msg ), _( "%s sent you an encrypted message, but it is not supported on this client." ), name );
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), msg );
+- return;
+- }
+- else if ( msgflags & CP_MSG_TL_ENCRYPTED ) {
+- /* this is a transport-layer encrypted message. */
+- message = mxit_decrypt_message( session, message );
+- if ( !message ) {
+- /* could not be decrypted */
+- serv_got_im( session->con, sender, _( "An encrypted message was received which could not be decrypted." ), PURPLE_MESSAGE_ERROR, time( NULL ) );
+- return;
+- }
+- }
+-
+- if ( msgflags & CP_MSG_NOTIFY_DELIVERY ) {
+- /* delivery notification is requested */
+- if ( records[0]->fcount >= 4 )
+- mxit_send_msgevent( session, sender, records[0]->fields[3]->data, CP_MSGEVENT_DELIVERED );
+- }
+-
+- /* create and initialise new markup struct */
+- mx = g_new0( struct RXMsgData, 1 );
+- mx->msg = g_string_sized_new( msglen );
+- mx->session = session;
+- mx->from = g_strdup( sender );
+- mx->timestamp = atoi( records[0]->fields[1]->data );
+- mx->got_img = FALSE;
+- mx->chatid = -1;
+- mx->img_count = 0;
+-
+- /* update list of active chats */
+- if ( !find_active_chat( session->active_chats, mx->from ) ) {
+- session->active_chats = g_list_append( session->active_chats, g_strdup( mx->from ) );
+- }
+-
+- if ( is_multimx_contact( session, mx->from ) ) {
+- /* this is a MultiMx chatroom message */
+- multimx_message_received( mx, message, msglen, msgtype, msgflags );
+- }
+- else {
+- mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
+- }
+-
+- /* we are now done parsing the message */
+- mx->converted = TRUE;
+- if ( mx->img_count == 0 ) {
+- /* we have all the data we need for this message to be displayed now. */
+- mxit_show_message( mx );
+- }
+- else {
+- /* this means there are still images outstanding for this message and
+- * still need to wait for them before we can display the message.
+- * so the image received callback function will eventually display
+- * the message. */
+- }
+-
+- /* cleanup */
+- if ( msgflags & CP_MSG_TL_ENCRYPTED )
+- g_free( message );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received subscription request packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_new_sub( struct MXitSession* session, struct record** records, int rcount )
+-{
+- struct contact* contact;
+- struct record* rec;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
+-
+- for ( i = 0; i < rcount; i++ ) {
+- rec = records[i];
+-
+- if ( rec->fcount < 4 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
+- break;
+- }
+-
+- /* build up a new contact info struct */
+- contact = g_new0( struct contact, 1 );
+-
+- g_strlcpy( contact->username, rec->fields[0]->data, sizeof( contact->username ) );
+- mxit_strip_domain( contact->username ); /* remove dummy domain */
+- g_strlcpy( contact->alias, rec->fields[1]->data, sizeof( contact->alias ) );
+- contact->type = atoi( rec->fields[2]->data );
+-
+- if ( rec->fcount >= 5 ) {
+- /* there is a personal invite message attached */
+- if ( ( rec->fields[4]->data ) && ( strlen( rec->fields[4]->data ) > 0 ) )
+- contact->msg = strdup( rec->fields[4]->data );
+- }
+-
+- /* handle the subscription */
+- if ( contact-> type == MXIT_TYPE_MULTIMX ) { /* subscription to a MultiMX room */
+- char* creator = NULL;
+-
+- if ( rec->fcount >= 6 )
+- creator = rec->fields[5]->data;
+-
+- multimx_invite( session, contact, creator );
+- }
+- else
+- mxit_new_subscription( session, contact );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received contact update packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_contact( struct MXitSession* session, struct record** records, int rcount )
+-{
+- struct contact* contact = NULL;
+- struct record* rec;
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
+-
+- for ( i = 0; i < rcount; i++ ) {
+- rec = records[i];
+-
+- if ( rec->fcount < 6 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
+- break;
+- }
+-
+- /* build up a new contact info struct */
+- contact = g_new0( struct contact, 1 );
+-
+- g_strlcpy( contact->groupname, rec->fields[0]->data, sizeof( contact->groupname ) );
+- g_strlcpy( contact->username, rec->fields[1]->data, sizeof( contact->username ) );
+- mxit_strip_domain( contact->username ); /* remove dummy domain */
+- g_strlcpy( contact->alias, rec->fields[2]->data, sizeof( contact->alias ) );
+-
+- contact->presence = atoi( rec->fields[3]->data );
+- contact->type = atoi( rec->fields[4]->data );
+- contact->mood = atoi( rec->fields[5]->data );
+-
+- if ( rec->fcount > 6 ) {
+- /* added in protocol 5.9 - flags & subtype */
+- contact->flags = atoi( rec->fields[6]->data );
+- contact->subtype = rec->fields[7]->data[0];
+- }
+- if ( rec->fcount > 8 ) {
+- /* added in protocol 6.0 - reject message */
+- contact->msg = g_strdup( rec->fields[8]->data );
+- }
+-
+- /* add the contact to the buddy list */
+- if ( contact-> type == MXIT_TYPE_MULTIMX ) /* contact is a MultiMX room */
+- multimx_created( session, contact );
+- else
+- mxit_update_contact( session, contact );
+- }
+-
+- if ( !( session->flags & MXIT_FLAG_FIRSTROSTER ) ) {
+- session->flags |= MXIT_FLAG_FIRSTROSTER;
+- mxit_update_blist( session );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received presence update packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_presence( struct MXitSession* session, struct record** records, int rcount )
+-{
+- int i;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_presence (%i recs)\n", rcount );
+-
+- for ( i = 0; i < rcount; i++ ) {
+- struct record* rec = records[i];
+- int flags = 0;
+-
+- if ( rec->fcount < 6 ) {
+- purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
+- break;
+- }
+-
+- /*
+- * The format of the record is:
+- * contactAddressN \1 presenceN \1 moodN \1 customMoodN \1 statusMsgN \1 avatarIdN [ \1 flagsN ]
+- */
+- mxit_strip_domain( rec->fields[0]->data ); /* contactAddress */
+-
+- if ( rec->fcount >= 7 ) /* flags field is included */
+- flags = atoi( rec->fields[6]->data );
+-
+- mxit_update_buddy_presence( session, rec->fields[0]->data, atoi( rec->fields[1]->data ), atoi( rec->fields[2]->data ),
+- rec->fields[3]->data, rec->fields[4]->data, flags );
+- mxit_update_buddy_avatar( session, rec->fields[0]->data, rec->fields[5]->data );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received extended profile packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_extprofile( struct MXitSession* session, struct record** records, int rcount )
+-{
+- const char* mxitId = records[0]->fields[0]->data;
+- struct MXitProfile* profile = NULL;
+- int count;
+- int i;
+- const char* avatarId = NULL;
+- char* statusMsg = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_extprofile: profile for '%s'\n", mxitId );
+-
+- if ( ( records[0]->fields[0]->len == 0 ) || ( session->uid && ( strcmp( session->uid, records[0]->fields[0]->data ) == 0 ) ) ) {
+- /* No UserId or Our UserId provided, so this must be our own profile information */
+- if ( session->profile == NULL )
+- session->profile = g_new0( struct MXitProfile, 1 );
+- profile = session->profile;
+- }
+- else {
+- /* is a buddy's profile */
+- profile = g_new0( struct MXitProfile, 1 );
+- }
+-
+- /* set the count for attributes */
+- count = atoi( records[0]->fields[1]->data );
+-
+- for ( i = 0; i < count; i++ ) {
+- char* fname;
+- char* fvalue;
+- char* fstatus;
+- int f = ( i * 3 ) + 2;
+-
+- fname = records[0]->fields[f]->data; /* field name */
+- fvalue = records[0]->fields[f + 1]->data; /* field value */
+- fstatus = records[0]->fields[f + 2]->data; /* field status */
+-
+- /* first check the status on the returned attribute */
+- if ( fstatus[0] != '0' ) {
+- /* error: attribute requested was NOT found */
+- purple_debug_error( MXIT_PLUGIN_ID, "Bad profile status on attribute '%s' \n", fname );
+- continue;
+- }
+-
+- if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
+- /* birthdate */
+- if ( records[0]->fields[f + 1]->len > 10 ) {
+- fvalue[10] = '\0';
+- records[0]->fields[f + 1]->len = 10;
+- }
+- memcpy( profile->birthday, fvalue, records[0]->fields[f + 1]->len );
+- }
+- else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
+- /* gender */
+- profile->male = ( fvalue[0] == '1' );
+- }
+- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
+- /* nickname */
+- g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
+- }
+- else if ( strcmp( CP_PROFILE_STATUS, fname ) == 0 ) {
+- /* status message - just keep a reference to the value */
+- statusMsg = g_markup_escape_text( fvalue, -1 );
+- }
+- else if ( strcmp( CP_PROFILE_AVATAR, fname ) == 0 ) {
+- /* avatar id - just keep a reference to the value */
+- avatarId = fvalue;
+- }
+- else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
+- /* title */
+- g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
+- }
+- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
+- /* first name */
+- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
+- }
+- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
+- /* last name */
+- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
+- }
+- else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
+- /* email address */
+- g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
+- }
+- else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
+- /* mobile number */
+- g_strlcpy( profile->mobilenr, fvalue, sizeof( profile->mobilenr ) );
+- }
+- else if ( strcmp( CP_PROFILE_REGCOUNTRY, fname ) == 0 ) {
+- /* registered country */
+- g_strlcpy( profile->regcountry, fvalue, sizeof( profile->regcountry ) );
+- }
+- else if ( strcmp( CP_PROFILE_FLAGS, fname ) == 0 ) {
+- /* profile flags */
+- profile->flags = strtoll( fvalue, NULL, 10 );
+- }
+- else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
+- /* last seen online */
+- profile->lastonline = strtoll( fvalue, NULL, 10 );
+- }
+- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
+- /* where am I */
+- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
+- }
+- else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
+- /* about me */
+- g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
+- }
+- else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
+- /* relatinship status */
+- profile->relationship = strtol( fvalue, NULL, 10 );
+- }
+- else {
+- /* invalid profile attribute */
+- purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile attribute received '%s' \n", fname );
+- }
+- }
+-
+- if ( profile != session->profile ) {
+- /* not our own profile */
+- struct contact* contact = NULL;
+-
+- contact = get_mxit_invite_contact( session, mxitId );
+- if ( contact ) {
+- /* this is an invite, so update its profile info */
+- if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
+- /* update the status message */
+- if ( contact->statusMsg )
+- g_free( contact->statusMsg );
+- contact->statusMsg = strdup( statusMsg );
+- }
+- else
+- contact->statusMsg = NULL;
+- if ( contact->profile )
+- g_free( contact->profile );
+- contact->profile = profile;
+- if ( ( avatarId ) && ( strlen( avatarId ) > 0 ) ) {
+- /* avatar must be requested for this invite before we can display it */
+- mxit_get_avatar( session, mxitId, avatarId );
+- if ( contact->avatarId )
+- g_free( contact->avatarId );
+- contact->avatarId = strdup( avatarId );
+- }
+- else {
+- /* display what we have */
+- contact->avatarId = NULL;
+- mxit_show_profile( session, mxitId, profile );
+- }
+- }
+- else {
+- /* this is a contact */
+- if ( avatarId )
+- mxit_update_buddy_avatar( session, mxitId, avatarId );
+-
+- if ( ( statusMsg ) && ( strlen( statusMsg ) > 0 ) ) {
+- /* update the status message */
+- PurpleBuddy* buddy = NULL;
+-
+- buddy = purple_find_buddy( session->acc, mxitId );
+- if ( buddy ) {
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( contact ) {
+- if ( contact->statusMsg )
+- g_free( contact->statusMsg );
+- contact->statusMsg = strdup( statusMsg );
+- }
+- }
+- }
+-
+- /* show the profile */
+- mxit_show_profile( session, mxitId, profile );
+- g_free( profile );
+- }
+- }
+-
+- g_free( statusMsg );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received suggest-contacts packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_suggestcontacts( struct MXitSession* session, struct record** records, int rcount )
+-{
+- GList* entries = NULL;
+- int searchType;
+- int maxResults;
+- int count;
+- int i;
+-
+- /*
+- * searchType \1 numSuggestions \1 total \1 numAttributes \1 name0 \1 name1 \1 ... \1 nameN \0
+- * userid \1 contactType \1 value0 \1 value1 ... valueN \0
+- * ...
+- * userid \1 contactType \1 value0 \1 value1 ... valueN
+- */
+-
+- /* the type of results */
+- searchType = atoi( records[0]->fields[0]->data );
+-
+- /* the maximum number of results */
+- maxResults = atoi( records[0]->fields[2]->data );
+-
+- /* set the count for attributes */
+- count = atoi( records[0]->fields[3]->data );
+-
+- for ( i = 1; i < rcount; i ++ ) {
+- struct record* rec = records[i];
+- struct MXitProfile* profile = g_new0( struct MXitProfile, 1 );
+- int j;
+-
+- g_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
+- // TODO: ContactType - User or Service
+-
+- for ( j = 0; j < count; j++ ) {
+- char* fname;
+- char* fvalue = "";
+-
+- fname = records[0]->fields[4 + j]->data; /* field name */
+- if ( records[i]->fcount > ( 2 + j ) )
+- fvalue = records[i]->fields[2 + j]->data; /* field value */
+-
+- purple_debug_info( MXIT_PLUGIN_ID, " %s: field='%s' value='%s'\n", profile->userid, fname, fvalue );
+-
+- if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
+- /* birthdate */
+- g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
+- }
+- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
+- /* first name */
+- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
+- }
+- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
+- /* last name */
+- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
+- }
+- else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
+- /* gender */
+- profile->male = ( fvalue[0] == '1' );
+- }
+- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
+- /* nickname */
+- g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
+- }
+- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
+- /* where am I */
+- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
+- }
+- /* ignore other attibutes */
+- }
+-
+- entries = g_list_append( entries, profile );
+- }
+-
+- /* display */
+- mxit_show_search_results( session, searchType, maxResults, entries );
+-
+- /* cleanup */
+- g_list_foreach( entries, (GFunc)g_free, NULL );
+-}
+-
+-/*------------------------------------------------------------------------
+- * Process a received message event packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_msgevent( struct MXitSession* session, struct record** records, int rcount )
+-{
+- int event;
+-
+- /*
+- * contactAddress \1 dateTime \1 id \1 event
+- */
+-
+- /* strip off dummy domain */
+- mxit_strip_domain( records[0]->fields[0]->data );
+-
+- event = atoi( records[0]->fields[3]->data );
+-
+- switch ( event ) {
+- case CP_MSGEVENT_TYPING : /* user is typing */
+- case CP_MSGEVENT_ANGRY : /* user is typing angrily */
+- serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_TYPING );
+- break;
+-
+- case CP_MSGEVENT_STOPPED : /* user has stopped typing */
+- serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
+- break;
+-
+- case CP_MSGEVENT_ERASING : /* user is erasing text */
+- case CP_MSGEVENT_DELIVERED : /* message was delivered */
+- case CP_MSGEVENT_DISPLAYED : /* message was viewed */
+- /* these are currently not supported by libPurple */
+- break;
+-
+- default:
+- purple_debug_error( MXIT_PLUGIN_ID, "Unknown message event received (%i)\n", event );
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the length of a multimedia chunk
+- *
+- * @return The actual chunk data length in bytes
+- */
+-static int get_chunk_len( const char* chunkdata )
+-{
+- int* sizeptr;
+-
+- sizeptr = (int*) &chunkdata[1]; /* we skip the first byte (type field) */
+-
+- return ntohl( *sizeptr );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a received multimedia packet.
+- *
+- * @param session The MXit session object
+- * @param records The packet's data records
+- * @param rcount The number of data records
+- */
+-static void mxit_parse_cmd_media( struct MXitSession* session, struct record** records, int rcount )
+-{
+- char type;
+- int size;
+-
+- type = records[0]->fields[0]->data[0];
+- size = get_chunk_len( records[0]->fields[0]->data );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i bytes)\n", rcount, size );
+-
+- /* supported chunked data types */
+- switch ( type ) {
+- case CP_CHUNK_CUSTOM : /* custom resource */
+- {
+- struct cr_chunk chunk;
+-
+- /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct cr_chunk ) );
+- mxit_chunk_parse_cr( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "chunk info id=%s handle=%s op=%i\n", chunk.id, chunk.handle, chunk.operation );
+-
+- /* this is a splash-screen operation */
+- if ( strcmp( chunk.handle, HANDLE_SPLASH2 ) == 0 ) {
+- if ( chunk.operation == CR_OP_UPDATE ) { /* update the splash-screen */
+- struct splash_chunk *splash = chunk.resources->data; // TODO: Fix - assuming 1st resource is splash
+- gboolean clickable = ( g_list_length( chunk.resources ) > 1 ); // TODO: Fix - if 2 resources, then is clickable
+-
+- if ( splash != NULL )
+- splash_update( session, chunk.id, splash->data, splash->datalen, clickable );
+- }
+- else if ( chunk.operation == CR_OP_REMOVE ) /* remove the splash-screen */
+- splash_remove( session );
+- }
+-
+- /* cleanup custom resources */
+- g_list_foreach( chunk.resources, (GFunc)g_free, NULL );
+-
+- }
+- break;
+-
+- case CP_CHUNK_OFFER : /* file offer */
+- {
+- struct offerfile_chunk chunk;
+-
+- /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct offerfile_chunk ) );
+- mxit_chunk_parse_offer( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* process the offer */
+- mxit_xfer_rx_offer( session, chunk.username, chunk.filename, chunk.filesize, chunk.fileid );
+- }
+- break;
+-
+- case CP_CHUNK_GET : /* get file response */
+- {
+- struct getfile_chunk chunk;
+-
+- /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct getfile_chunk ) );
+- mxit_chunk_parse_get( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* process the getfile */
+- mxit_xfer_rx_file( session, chunk.fileid, chunk.data, chunk.length );
+- }
+- break;
+-
+- case CP_CHUNK_GET_AVATAR : /* get avatars */
+- {
+- struct getavatar_chunk chunk;
+- struct contact* contact = NULL;
+-
+- /* decode the chunked data */
+- memset( &chunk, 0, sizeof( struct getavatar_chunk ) );
+- mxit_chunk_parse_get_avatar( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- /* update avatar image */
+- if ( chunk.data ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "updating avatar for contact '%s'\n", chunk.mxitid );
+-
+- contact = get_mxit_invite_contact( session, chunk.mxitid );
+- if ( contact ) {
+- /* this is an invite (add image to the internal image store) */
+- contact->imgid = purple_imgstore_add_with_id( g_memdup( chunk.data, chunk.length ), chunk.length, NULL );
+- /* show the profile */
+- mxit_show_profile( session, chunk.mxitid, contact->profile );
+- }
+- else {
+- /* this is a contact's avatar, so update it */
+- purple_buddy_icons_set_for_user( session->acc, chunk.mxitid, g_memdup( chunk.data, chunk.length), chunk.length, chunk.avatarid );
+- }
+- }
+- }
+- break;
+-
+- case CP_CHUNK_SET_AVATAR :
+- /* this is a reply packet to a set avatar request. no action is required */
+- break;
+-
+- case CP_CHUNK_DIRECT_SND :
+- /* this is a ack for a file send. */
+- {
+- struct sendfile_chunk chunk;
+-
+- memset( &chunk, 0, sizeof( struct sendfile_chunk ) );
+- mxit_chunk_parse_sendfile( &records[0]->fields[0]->data[sizeof( char ) + sizeof( int )], records[0]->fields[0]->len, &chunk );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "file-send send to '%s' [status=%i message='%s']\n", chunk.username, chunk.status, chunk.statusmsg );
+-
+- if ( chunk.status != 0 ) /* not success */
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "File Send Failed" ), chunk.statusmsg );
+- }
+- break;
+-
+- case CP_CHUNK_RECEIVED :
+- /* this is a ack for a file received. no action is required */
+- break;
+-
+- default :
+- purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", type );
+- break;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Handle a redirect sent from the MXit server.
+- *
+- * @param session The MXit session object
+- * @param url The redirect information
+- */
+-static void mxit_perform_redirect( struct MXitSession* session, const char* url )
+-{
+- gchar** parts;
+- gchar** host;
+- int type;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s\n", url );
+-
+- /* tokenize the URL string */
+- parts = g_strsplit( url, ";", 0 );
+-
+- /* Part 1: protocol://host:port */
+- host = g_strsplit( parts[0], ":", 4 );
+- if ( strcmp( host[0], "socket" ) == 0 ) {
+- /* redirect to a MXit socket proxy */
+- g_strlcpy( session->server, &host[1][2], sizeof( session->server ) );
+- session->port = atoi( host[2] );
+- }
+- else {
+- purple_connection_error( session->con, _( "Cannot perform redirect using the specified protocol" ) );
+- goto redirect_fail;
+- }
+-
+- /* Part 2: type of redirect */
+- type = atoi( parts[1] );
+- if ( type == CP_REDIRECT_PERMANENT ) {
+- /* permanent redirect, so save new MXit server and port */
+- purple_account_set_string( session->acc, MXIT_CONFIG_SERVER_ADDR, session->server );
+- purple_account_set_int( session->acc, MXIT_CONFIG_SERVER_PORT, session->port );
+- }
+-
+- /* Part 3: message (optional) */
+- if ( parts[2] != NULL )
+- purple_connection_notice( session->con, parts[2] );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_perform_redirect: %s redirect to %s:%i\n",
+- ( type == CP_REDIRECT_PERMANENT ) ? "Permanent" : "Temporary", session->server, session->port );
+-
+- /* perform the re-connect to the new MXit server */
+- mxit_reconnect( session );
+-
+-redirect_fail:
+- g_strfreev( parts );
+- g_strfreev( host );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process a success response received from the MXit server.
+- *
+- * @param session The MXit session object
+- * @param packet The received packet
+- */
+-static int process_success_response( struct MXitSession* session, struct rx_packet* packet )
+-{
+- /* ignore ping/poll packets */
+- if ( ( packet->cmd != CP_CMD_PING ) && ( packet->cmd != CP_CMD_POLL ) )
+- session->last_rx = mxit_now_milli();
+-
+- /*
+- * when we pass the packet records to the next level for parsing
+- * we minus 3 records because 1) the first record is the packet
+- * type 2) packet reply status 3) the last record is bogus
+- */
+-
+- /* packet command */
+- switch ( packet->cmd ) {
+-
+- case CP_CMD_REGISTER :
+- /* fall through, when registeration successful, MXit will auto login */
+- case CP_CMD_LOGIN :
+- /* login response */
+- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
+- mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
+- }
+- break;
+-
+- case CP_CMD_LOGOUT :
+- /* logout response */
+- session->flags &= ~MXIT_FLAG_LOGGEDIN;
+- purple_account_disconnect( session->acc );
+-
+- /* note:
+- * we do not prompt the user here for a reconnect, because this could be the user
+- * logging in with his phone. so we just disconnect the account otherwise
+- * mxit will start to bounce between the phone and pidgin. also could be a valid
+- * disconnect selected by the user.
+- */
+- return -1;
+-
+- case CP_CMD_CONTACT :
+- /* contact update */
+- mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
+- break;
+-
+- case CP_CMD_PRESENCE :
+- /* presence update */
+- mxit_parse_cmd_presence(session, &packet->records[2], packet->rcount - 3 );
+- break;
+-
+- case CP_CMD_RX_MSG :
+- /* incoming message (no bogus record) */
+- mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
+- break;
+-
+- case CP_CMD_NEW_SUB :
+- /* new subscription request */
+- mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
+- break;
+-
+- case CP_CMD_MEDIA :
+- /* multi-media message */
+- mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
+- break;
+-
+- case CP_CMD_EXTPROFILE_GET :
+- /* profile update */
+- mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
+- break;
+-
+- case CP_CMD_SUGGESTCONTACTS :
+- /* suggest contacts */
+- mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
+- break;
+-
+- case CP_CMD_GOT_MSGEVENT :
+- /* received message event */
+- mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
+- break;
+-
+- case CP_CMD_MOOD :
+- /* mood update */
+- case CP_CMD_UPDATE :
+- /* update contact information */
+- case CP_CMD_ALLOW :
+- /* allow subscription ack */
+- case CP_CMD_DENY :
+- /* deny subscription ack */
+- case CP_CMD_INVITE :
+- /* invite contact ack */
+- case CP_CMD_REMOVE :
+- /* remove contact ack */
+- case CP_CMD_TX_MSG :
+- /* outgoing message ack */
+- case CP_CMD_STATUS :
+- /* presence update ack */
+- case CP_CMD_GRPCHAT_CREATE :
+- /* create groupchat */
+- case CP_CMD_GRPCHAT_INVITE :
+- /* groupchat invite */
+- case CP_CMD_PING :
+- /* ping reply */
+- case CP_CMD_POLL :
+- /* HTTP poll reply */
+- case CP_CMD_EXTPROFILE_SET :
+- /* profile update */
+- // TODO: Protocol 6.2 indicates status for each attribute, and current value.
+- case CP_CMD_SPLASHCLICK :
+- /* splash-screen clickthrough */
+- case CP_CMD_MSGEVENT :
+- /* event message */
+- break;
+-
+- default :
+- /* unknown packet */
+- purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
+- }
+-
+- return 0;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Process an error response received from the MXit server.
+- *
+- * @param session The MXit session object
+- * @param packet The received packet
+- */
+-static int process_error_response( struct MXitSession* session, struct rx_packet* packet )
+-{
+- char errmsg[256];
+- const char* errdesc;
+-
+- /* set the error description to be shown to the user */
+- if ( packet->errmsg )
+- errdesc = packet->errmsg;
+- else
+- errdesc = _( "An internal MXit server error occurred." );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Error Reply %i:%s\n", packet->errcode, errdesc );
+-
+- if ( packet->errcode == MXIT_ERRCODE_LOGGEDOUT ) {
+- /* we are not currently logged in, so we need to reconnect */
+- purple_connection_error( session->con, _( errdesc ) );
+- }
+-
+- /* packet command */
+- switch ( packet->cmd ) {
+-
+- case CP_CMD_REGISTER :
+- case CP_CMD_LOGIN :
+- if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
+- mxit_perform_redirect( session, packet->errmsg );
+- return 0;
+- }
+- else {
+- snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
+- purple_connection_error( session->con, errmsg );
+- return -1;
+- }
+- case CP_CMD_LOGOUT :
+- snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
+- purple_connection_error_reason( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
+- return -1;
+- case CP_CMD_CONTACT :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_RX_MSG :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_TX_MSG :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_STATUS :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_MOOD :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_KICK :
+- /*
+- * the MXit server sends this packet if we were idle for too long.
+- * to stop the server from closing this connection we need to resend
+- * the login packet.
+- */
+- mxit_send_login( session );
+- break;
+- case CP_CMD_INVITE :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_REMOVE :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_ALLOW :
+- case CP_CMD_DENY :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_UPDATE :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_MEDIA :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_GRPCHAT_CREATE :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
+- break;
+- case CP_CMD_GRPCHAT_INVITE :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_EXTPROFILE_GET :
+- case CP_CMD_EXTPROFILE_SET :
+- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
+- break;
+- case CP_CMD_SPLASHCLICK :
+- case CP_CMD_MSGEVENT :
+- /* ignore error */
+- break;
+- case CP_CMD_PING :
+- case CP_CMD_POLL :
+- break;
+- default :
+- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
+- break;
+- }
+-
+- return 0;
+-}
+-
+-
+-/*========================================================================================================================
+- * Low-level Packet receive
+- */
+-
+-#ifdef DEBUG_PROTOCOL
+-/*------------------------------------------------------------------------
+- * Dump a received packet structure.
+- *
+- * @param p The received packet
+- */
+-static void dump_packet( struct rx_packet* p )
+-{
+- struct record* r = NULL;
+- struct field* f = NULL;
+- int i;
+- int j;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
+-
+- for ( i = 0; i < p->rcount; i++ ) {
+- r = p->records[i];
+- purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
+-
+- for ( j = 0; j < r->fcount; j++ ) {
+- f = r->fields[j];
+- purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%i) '%s' \n", f->len, f->data );
+- }
+- }
+-}
+-#endif
+-
+-
+-/*------------------------------------------------------------------------
+- * Free up memory used by a packet structure.
+- *
+- * @param p The received packet
+- */
+-static void free_rx_packet( struct rx_packet* p )
+-{
+- struct record* r = NULL;
+- struct field* f = NULL;
+- int i;
+- int j;
+-
+- for ( i = 0; i < p->rcount; i++ ) {
+- r = p->records[i];
+-
+- for ( j = 0; j < r->fcount; j++ ) {
+- g_free( f );
+- }
+- g_free( r->fields );
+- g_free( r );
+- }
+- g_free( p->records );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Add a new field to a record.
+- *
+- * @param r Parent record object
+- * @return The newly created field
+- */
+-static struct field* add_field( struct record* r )
+-{
+- struct field* field;
+-
+- field = g_new0( struct field, 1 );
+-
+- r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
+- r->fields[r->fcount] = field;
+- r->fcount++;
+-
+- return field;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Add a new record to a packet.
+- *
+- * @param p The packet object
+- * @return The newly created record
+- */
+-static struct record* add_record( struct rx_packet* p )
+-{
+- struct record* rec;
+-
+- rec = g_new0( struct record, 1 );
+-
+- p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
+- p->records[p->rcount] = rec;
+- p->rcount++;
+-
+- return rec;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Parse the received byte stream into a proper client protocol packet.
+- *
+- * @param session The MXit session object
+- * @return Success (0) or Failure (!0)
+- */
+-int mxit_parse_packet( struct MXitSession* session )
+-{
+- struct rx_packet packet;
+- struct record* rec;
+- struct field* field;
+- gboolean pbreak;
+- unsigned int i;
+- int res = 0;
+-
+-#ifdef DEBUG_PROTOCOL
+- purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
+- dump_bytes( session, session->rx_dbuf, session->rx_i );
+-#endif
+-
+- i = 0;
+- while ( i < session->rx_i ) {
+-
+- /* create first record and field */
+- rec = NULL;
+- field = NULL;
+- memset( &packet, 0x00, sizeof( struct rx_packet ) );
+- rec = add_record( &packet );
+- pbreak = FALSE;
+-
+- /* break up the received packet into fields and records for easy parsing */
+- while ( ( i < session->rx_i ) && ( !pbreak ) ) {
+-
+- switch ( session->rx_dbuf[i] ) {
+- case CP_SOCK_REC_TERM :
+- /* new record */
+- if ( packet.rcount == 1 ) {
+- /* packet command */
+- packet.cmd = atoi( packet.records[0]->fields[0]->data );
+- }
+- else if ( packet.rcount == 2 ) {
+- /* special case: binary multimedia packets should not be parsed here */
+- if ( packet.cmd == CP_CMD_MEDIA ) {
+- /* add the chunked to new record */
+- rec = add_record( &packet );
+- field = add_field( rec );
+- field->data = &session->rx_dbuf[i + 1];
+- field->len = session->rx_i - i;
+- /* now skip the binary data */
+- res = get_chunk_len( field->data );
+- /* determine if we have more packets */
+- if ( res + 6 + i < session->rx_i ) {
+- /* we have more than one packet in this stream */
+- i += res + 6;
+- pbreak = TRUE;
+- }
+- else {
+- i = session->rx_i;
+- }
+- }
+- }
+- else if ( !field ) {
+- field = add_field( rec );
+- field->data = &session->rx_dbuf[i];
+- }
+- session->rx_dbuf[i] = '\0';
+- rec = add_record( &packet );
+- field = NULL;
+-
+- break;
+- case CP_FLD_TERM :
+- /* new field */
+- session->rx_dbuf[i] = '\0';
+- if ( !field ) {
+- field = add_field( rec );
+- field->data = &session->rx_dbuf[i];
+- }
+- field = NULL;
+- break;
+- case CP_PKT_TERM :
+- /* packet is done! */
+- session->rx_dbuf[i] = '\0';
+- pbreak = TRUE;
+- break;
+- default :
+- /* skip non special characters */
+- if ( !field ) {
+- field = add_field( rec );
+- field->data = &session->rx_dbuf[i];
+- }
+- field->len++;
+- break;
+- }
+-
+- i++;
+- }
+-
+- if ( packet.rcount < 2 ) {
+- /* bad packet */
+- purple_connection_error( session->con, _( "Invalid packet received from MXit." ) );
+- free_rx_packet( &packet );
+- continue;
+- }
+-
+- session->rx_dbuf[session->rx_i] = '\0';
+- packet.errcode = atoi( packet.records[1]->fields[0]->data );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Packet received CMD:%i (%i)\n", packet.cmd, packet.errcode );
+-#ifdef DEBUG_PROTOCOL
+- /* debug */
+- dump_packet( &packet );
+-#endif
+-
+- /* reset the out ack */
+- if ( session->outack == packet.cmd ) {
+- /* outstanding ack received from mxit server */
+- session->outack = 0;
+- }
+-
+- /* check packet status */
+- if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
+- /* error reply! */
+- if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
+- packet.errmsg = packet.records[1]->fields[1]->data;
+- else
+- packet.errmsg = NULL;
+-
+- res = process_error_response( session, &packet );
+- }
+- else {
+- /* success reply! */
+- res = process_success_response( session, &packet );
+- }
+-
+- /* free up the packet resources */
+- free_rx_packet( &packet );
+- }
+-
+- if ( session->outack == 0 )
+- mxit_manage_queue( session );
+-
+- return res;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Callback when data is received from the MXit server.
+- *
+- * @param user_data The MXit session object
+- * @param source The file-descriptor on which data was received
+- * @param cond Condition which caused the callback (PURPLE_INPUT_READ)
+- */
+-void mxit_cb_rx( gpointer user_data, gint source, PurpleInputCondition cond )
+-{
+- struct MXitSession* session = (struct MXitSession*) user_data;
+- char ch;
+- int res;
+- int len;
+-
+- if ( session->rx_state == RX_STATE_RLEN ) {
+- /* we are reading in the packet length */
+- len = read( session->fd, &ch, 1 );
+- if ( len < 0 ) {
+- /* connection error */
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
+- return;
+- }
+- else if ( len == 0 ) {
+- /* connection closed */
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
+- return;
+- }
+- else {
+- /* byte read */
+- if ( ch == CP_REC_TERM ) {
+- /* the end of the length record found */
+- session->rx_lbuf[session->rx_i] = '\0';
+- session->rx_res = atoi( &session->rx_lbuf[3] );
+- if ( session->rx_res > CP_MAX_PACKET ) {
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x03)" ) );
+- }
+- session->rx_state = RX_STATE_DATA;
+- session->rx_i = 0;
+- }
+- else {
+- /* still part of the packet length record */
+- session->rx_lbuf[session->rx_i] = ch;
+- session->rx_i++;
+- if ( session->rx_i >= sizeof( session->rx_lbuf ) ) {
+- /* malformed packet length record (too long) */
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x04)" ) );
+- return;
+- }
+- }
+- }
+- }
+- else if ( session->rx_state == RX_STATE_DATA ) {
+- /* we are reading in the packet data */
+- len = read( session->fd, &session->rx_dbuf[session->rx_i], session->rx_res );
+- if ( len < 0 ) {
+- /* connection error */
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
+- return;
+- }
+- else if ( len == 0 ) {
+- /* connection closed */
+- purple_connection_error( session->con, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
+- return;
+- }
+- else {
+- /* data read */
+- session->rx_i += len;
+- session->rx_res -= len;
+-
+- if ( session->rx_res == 0 ) {
+- /* ok, so now we have read in the whole packet */
+- session->rx_state = RX_STATE_PROC;
+- }
+- }
+- }
+-
+- if ( session->rx_state == RX_STATE_PROC ) {
+- /* we have a full packet, which we now need to process */
+- res = mxit_parse_packet( session );
+-
+- if ( res == 0 ) {
+- /* we are still logged in */
+- session->rx_state = RX_STATE_RLEN;
+- session->rx_res = 0;
+- session->rx_i = 0;
+- }
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Log the user off MXit and close the connection
+- *
+- * @param session The MXit session object
+- */
+-void mxit_close_connection( struct MXitSession* session )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_close_connection\n" );
+-
+- if ( !( session->flags & MXIT_FLAG_CONNECTED ) ) {
+- /* we are already closed */
+- return;
+- }
+- else if ( session->flags & MXIT_FLAG_LOGGEDIN ) {
+- /* we are currently logged in so we need to send a logout packet */
+- if ( !session->http ) {
+- mxit_send_logout( session );
+- }
+- session->flags &= ~MXIT_FLAG_LOGGEDIN;
+- }
+- session->flags &= ~MXIT_FLAG_CONNECTED;
+-
+- /* cancel outstanding HTTP request */
+- if ( ( session->http ) && ( session->http_out_req ) ) {
+- purple_util_fetch_url_cancel( (PurpleUtilFetchUrlData*) session->http_out_req );
+- session->http_out_req = NULL;
+- }
+-
+- /* remove the input cb function */
+- if ( session->con->inpa ) {
+- purple_input_remove( session->con->inpa );
+- session->con->inpa = 0;
+- }
+-
+- /* remove HTTP poll timer */
+- if ( session->http_timer_id > 0 )
+- purple_timeout_remove( session->http_timer_id );
+-
+- /* remove slow queue manager timer */
+- if ( session->q_slow_timer_id > 0 )
+- purple_timeout_remove( session->q_slow_timer_id );
+-
+- /* remove fast queue manager timer */
+- if ( session->q_fast_timer_id > 0 )
+- purple_timeout_remove( session->q_fast_timer_id );
+-
+- /* remove all groupchat rooms */
+- while ( session->rooms != NULL ) {
+- struct multimx* multimx = (struct multimx *) session->rooms->data;
+-
+- session->rooms = g_list_remove( session->rooms, multimx );
+-
+- free( multimx );
+- }
+- g_list_free( session->rooms );
+- session->rooms = NULL;
+-
+- /* remove all rx chats names */
+- while ( session->active_chats != NULL ) {
+- char* chat = (char*) session->active_chats->data;
+-
+- session->active_chats = g_list_remove( session->active_chats, chat );
+-
+- g_free( chat );
+- }
+- g_list_free( session->active_chats );
+- session->active_chats = NULL;
+-
+- /* clear the internal invites */
+- while ( session->invites != NULL ) {
+- struct contact* contact = (struct contact*) session->invites->data;
+-
+- session->invites = g_list_remove( session->invites, contact );
+-
+- if ( contact->msg )
+- g_free( contact->msg );
+- if ( contact->statusMsg )
+- g_free( contact->statusMsg );
+- if ( contact->profile )
+- g_free( contact->profile );
+- g_free( contact );
+- }
+- g_list_free( session->invites );
+- session->invites = NULL;
+-
+- /* free profile information */
+- if ( session->profile )
+- free( session->profile );
+-
+- /* free custom emoticons */
+- mxit_free_emoticon_cache( session );
+-
+- /* free allocated memory */
+- if ( session->uid )
+- g_free( session->uid );
+- g_free( session->encpwd );
+- session->encpwd = NULL;
+-
+- /* flush all the commands still in the queue */
+- flush_queue( session );
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/protocol.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/protocol.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/protocol.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,352 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- MXit client protocol implementation --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_PROTO_H_
+-#define _MXIT_PROTO_H_
+-
+-
+-/* Client protocol constants */
+-#define CP_SOCK_REC_TERM '\x00' /* socket record terminator */
+-#define CP_HTTP_REC_TERM '\x26' /* http record terminator '&' */
+-#define CP_FLD_TERM '\x01' /* field terminator */
+-#define CP_PKT_TERM '\x02' /* packet terminator */
+-
+-
+-#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */
+-#define CP_MAX_FILESIZE ( CP_MAX_PACKET - 1000 ) /* maximum file size (reserve some space for packet headers) */
+-#define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */
+-#define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */
+-
+-/* Avatars */
+-#define MXIT_AVATAR_SIZE 96 /* default avatar image size 96x96 */
+-#define MXIT_AVATAR_TYPE "PNG" /* request avatars in this file type (only a suggestion) */
+-#define MXIT_AVATAR_BITDEPT 24 /* request avatars with this bit depth (only a suggestion) */
+-
+-/* Protocol error codes */
+-#define MXIT_ERRCODE_SUCCESS 0
+-#define MXIT_ERRCODE_REDIRECT 16
+-#define MXIT_ERRCODE_LOGGEDOUT 42
+-
+-/* MXit client features */
+-#define MXIT_CF_NONE 0x000000
+-#define MXIT_CF_FORMS 0x000001
+-#define MXIT_CF_FILE_TRANSFER 0x000002
+-#define MXIT_CF_CAMERA 0x000004
+-#define MXIT_CF_COMMANDS 0x000008
+-#define MXIT_CF_SMS 0x000010
+-#define MXIT_CF_FILE_ACCESS 0x000020
+-#define MXIT_CF_MIDP2 0x000040
+-#define MXIT_CF_SKINS 0x000080
+-#define MXIT_CF_AUDIO 0x000100
+-#define MXIT_CF_ENCRYPTION 0x000200
+-#define MXIT_CF_VOICE_REC 0x000400
+-#define MXIT_CF_VECTOR_GFX 0x000800
+-#define MXIT_CF_IMAGES 0x001000
+-#define MXIT_CF_MARKUP 0x002000
+-#define MXIT_CF_VIBES 0x004000
+-#define MXIT_CF_SELECT_CONTACT 0x008000
+-#define MXIT_CF_CUSTOM_EMO 0x010000
+-#define MXIT_CF_ALERT_PROFILES 0x020000
+-#define MXIT_CF_EXT_MARKUP 0x040000
+-#define MXIT_CF_PLAIN_PWD 0x080000
+-#define MXIT_CF_NO_GATEWAYS 0x100000
+-#define MXIT_CF_NO_AVATARS 0x200000
+-#define MXIT_CF_GAMING 0x400000
+-#define MXIT_CF_GAMING_UPDATE 0x800000
+-#define MXIT_CF_VOICE 0x1000000
+-#define MXIT_CF_VIDEO 0x2000000
+-#define MXIT_CF_TOUCHSCREEN 0x4000000
+-#define MXIT_CF_SVC_CONNECTION 0x8000000
+-#define MXIT_CF_MXML 0x10000000
+-#define MXIT_CF_TYPING_NOTIFY 0x20000000
+-
+-/* Client features supported by this implementation */
+-#define MXIT_CP_FEATURES ( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 | MXIT_CF_TYPING_NOTIFY )
+-
+-
+-#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */
+-#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */
+-#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */
+-
+-/* MXit client version */
+-#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */
+-#define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */
+-#define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */
+-#define MXIT_CP_PLATFORM "PURPLE" /* client platform */
+-#define MXIT_CP_PROTO_VESION 63 /* client protocol version */
+-
+-/* set operating system name */
+-#if defined( __APPLE__ )
+-#define MXIT_CP_OS "apple"
+-#elif defined( _WIN32 )
+-#define MXIT_CP_OS "windows"
+-#elif defined( __linux__ )
+-#define MXIT_CP_OS "linux"
+-#else
+-#define MXIT_CP_OS "unknown"
+-#endif
+-
+-/* Client capabilities */
+-#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID
+-
+-/* Client settings */
+-#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */
+-#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */
+-#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */
+-#define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */
+-
+-/* Client protocol commands */
+-#define CP_CMD_LOGIN 0x0001 /* (1) login */
+-#define CP_CMD_LOGOUT 0x0002 /* (2) logout */
+-#define CP_CMD_CONTACT 0x0003 /* (3) get contacts */
+-#define CP_CMD_UPDATE 0x0005 /* (5) update contact information */
+-#define CP_CMD_INVITE 0x0006 /* (6) subscribe to new contact */
+-#define CP_CMD_PRESENCE 0x0007 /* (7) get presence */
+-#define CP_CMD_REMOVE 0x0008 /* (8) remove contact */
+-#define CP_CMD_RX_MSG 0x0009 /* (9) get new messages */
+-#define CP_CMD_TX_MSG 0x000A /* (10) send new message */
+-#define CP_CMD_REGISTER 0x000B /* (11) register */
+-//#define CP_CMD_PROFILE_SET 0x000C /* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */
+-#define CP_CMD_SUGGESTCONTACTS 0x000D /* (13) suggest contacts */
+-#define CP_CMD_POLL 0x0011 /* (17) poll the HTTP server for an update */
+-//#define CP_CMD_PROFILE_GET 0x001A /* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */
+-#define CP_CMD_MEDIA 0x001B /* (27) get multimedia message */
+-#define CP_CMD_SPLASHCLICK 0x001F /* (31) splash-screen clickthrough */
+-#define CP_CMD_STATUS 0x0020 /* (32) set shown presence & status */
+-#define CP_CMD_MSGEVENT 0x0023 /* (35) Raise message event */
+-#define CP_CMD_GOT_MSGEVENT 0x0024 /* (36) Get message event */
+-#define CP_CMD_MOOD 0x0029 /* (41) set mood */
+-#define CP_CMD_KICK 0x002B /* (43) login kick */
+-#define CP_CMD_GRPCHAT_CREATE 0x002C /* (44) create new groupchat */
+-#define CP_CMD_GRPCHAT_INVITE 0x002D /* (45) add new groupchat member */
+-#define CP_CMD_NEW_SUB 0x0033 /* (51) get new subscription */
+-#define CP_CMD_ALLOW 0x0034 /* (52) allow subscription */
+-#define CP_CMD_DENY 0x0037 /* (55) deny subscription */
+-#define CP_CMD_EXTPROFILE_GET 0x0039 /* (57) get extended profile */
+-#define CP_CMD_EXTPROFILE_SET 0x003A /* (58) set extended profile */
+-#define CP_CMD_PING 0x03E8 /* (1000) ping (keepalive) */
+-
+-/* HTTP connection */
+-#define MXIT_HTTP_POLL_MIN 7 /* minimum time between HTTP polls (seconds) */
+-#define MXIT_HTTP_POLL_MAX ( 10 * 60 ) /* maximum time between HTTP polls (seconds) */
+-
+-/* receiver states */
+-#define RX_STATE_RLEN 0x01 /* reading packet length section */
+-#define RX_STATE_DATA 0x02 /* reading packet data section */
+-#define RX_STATE_PROC 0x03 /* process read data */
+-
+-/* message flags */
+-#define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */
+-#define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */
+-#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */
+-#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */
+-#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */
+-#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */
+-#define CP_MSG_MARKUP 0x0200 /* message may contain markup */
+-#define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */
+-#define CP_MSG_FAREWELL 0x0800 /* this is a farewell message */
+-
+-/* redirect types */
+-#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */
+-#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */
+-
+-/* message tx types */
+-#define CP_MSGTYPE_NORMAL 0x01 /* normal message */
+-#define CP_MSGTYPE_CHAT 0x02 /* chat message */
+-#define CP_MSGTYPE_HEADLINE 0x03 /* headline message */
+-#define CP_MSGTYPE_ERROR 0x04 /* error message */
+-#define CP_MSGTYPE_GROUPCHAT 0x05 /* groupchat message */
+-#define CP_MSGTYPE_FORM 0x06 /* mxit custom form */
+-#define CP_MSGTYPE_COMMAND 0x07 /* mxit command */
+-
+-/* message event types */
+-#define CP_MSGEVENT_DELIVERED 0x02 /* message was delivered */
+-#define CP_MSGEVENT_DISPLAYED 0x04 /* message was viewed */
+-#define CP_MSGEVENT_TYPING 0x10 /* user is typing */
+-#define CP_MSGEVENT_STOPPED 0x20 /* user has stopped typing */
+-#define CP_MSGEVENT_ANGRY 0x40 /* user is typing angrily */
+-#define CP_MSGEVENT_ERASING 0x80 /* user is erasing text */
+-
+-/* extended profile attribute fields */
+-#define CP_PROFILE_BIRTHDATE "birthdate" /* Birthdate (String - ISO 8601 format) */
+-#define CP_PROFILE_GENDER "gender" /* Gender (Boolean - 0=female, 1=male) */
+-// #define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */
+-#define CP_PROFILE_FULLNAME "fullname" /* Fullname (UTF8 String) */
+-#define CP_PROFILE_STATUS "statusmsg" /* Status Message (UTF8 String) */
+-#define CP_PROFILE_PREVSTATUS "prevstatusmsgs" /* Previous Status Messages (UTF8 String) */
+-#define CP_PROFILE_AVATAR "avatarid" /* Avatar ID (String) */
+-#define CP_PROFILE_MODIFIED "lastmodified" /* Last-Modified timestamp */
+-#define CP_PROFILE_TITLE "title" /* Title (UTF8 String) */
+-#define CP_PROFILE_FIRSTNAME "firstname" /* First name (UTF8 String) */
+-#define CP_PROFILE_LASTNAME "lastname" /* Last name (UTF8 String) */
+-#define CP_PROFILE_EMAIL "email" /* Email address (UTF8 String) */
+-#define CP_PROFILE_MOBILENR "mobilenumber" /* Mobile Number (UTF8 String) */
+-#define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */
+-#define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */
+-#define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */
+-#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */
+-#define CP_PROFILE_ABOUTME "aboutme" /* About me */
+-#define CP_PROFILE_RELATIONSHIP "relationship" /* Relationship Status */
+-
+-/* extended profile field types */
+-#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */
+-#define CP_PROFILE_TYPE_SHORT 0x04 /* short (16-bit) */
+-#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */
+-#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */
+-#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */
+-#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */
+-
+-/* profile flags */
+-#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */
+-#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */
+-#define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */
+-
+-/* suggestion types */
+-#define CP_SUGGEST_ADDRESSBOOK 0 /* address book search */
+-#define CP_SUGGEST_FRIENDS 1 /* suggested friends */
+-#define CP_SUGGEST_SEARCH 2 /* free-text search */
+-#define CP_SUGGEST_MXITID 3 /* MXitId search */
+-
+-/* define this to enable protocol debugging (very verbose logging) */
+-#define DEBUG_PROTOCOL
+-
+-
+-/* ======================================================================================= */
+-
+-struct MXitSession;
+-
+-/*------------------------------------------*/
+-
+-struct field {
+- char* data;
+- int len;
+-};
+-
+-struct record {
+- struct field** fields;
+- int fcount;
+-};
+-
+-struct rx_packet {
+- int cmd;
+- int errcode;
+- char* errmsg;
+- struct record** records;
+- int rcount;
+-};
+-
+-struct tx_packet {
+- int cmd;
+- char header[256];
+- int headerlen;
+- char* data;
+- int datalen;
+-};
+-
+-/*------------------------------------------*/
+-
+-
+-/*
+- * A received message data object
+- */
+-struct RXMsgData {
+- struct MXitSession* session; /* MXit session object */
+- char* from; /* the sender's name */
+- time_t timestamp; /* time at which the message was sent */
+- GString* msg; /* newly created message converted to libPurple formatting */
+- gboolean got_img; /* flag to say if this message got any images/emoticons embedded */
+- short img_count; /* the amount of images/emoticons still outstanding for the message */
+- int chatid; /* multimx chatroom id */
+- int flags; /* libPurple conversation flags */
+- gboolean converted; /* true if the message has been completely parsed and converted to libPurple markup */
+- gboolean processed; /* the message has been processed completely and should be freed up */
+-};
+-
+-
+-
+-/*
+- * The packet transmission queue.
+- */
+-struct tx_queue {
+- struct tx_packet* packets[MAX_QUEUE_SIZE]; /* array of packet pointers */
+- int count; /* number of packets queued */
+- int rd_i; /* queue current read index (queue offset for reading a packet) */
+- int wr_i; /* queue current write index (queue offset for adding new packet) */
+-};
+-
+-
+-/* ======================================================================================= */
+-
+-void mxit_popup( int type, const char* heading, const char* message );
+-void mxit_strip_domain( char* username );
+-gboolean find_active_chat( const GList* chats, const char* who );
+-
+-void mxit_cb_rx( gpointer data, gint source, PurpleInputCondition cond );
+-gboolean mxit_manage_queue_slow( gpointer user_data );
+-gboolean mxit_manage_queue_fast( gpointer user_data );
+-gboolean mxit_manage_polling( gpointer user_data );
+-
+-void mxit_send_register( struct MXitSession* session );
+-void mxit_send_login( struct MXitSession* session );
+-void mxit_send_logout( struct MXitSession* session );
+-void mxit_send_ping( struct MXitSession* session );
+-void mxit_send_poll( struct MXitSession* session );
+-
+-void mxit_send_presence( struct MXitSession* session, int presence, const char* statusmsg );
+-void mxit_send_mood( struct MXitSession* session, int mood );
+-void mxit_send_message( struct MXitSession* session, const char* to, const char* msg, gboolean parse_markup, gboolean is_command );
+-
+-void mxit_send_extprofile_update( struct MXitSession* session, const char* password, unsigned int nr_attrib, const char* attributes );
+-void mxit_send_extprofile_request( struct MXitSession* session, const char* username, unsigned int nr_attrib, const char* attribute[] );
+-
+-void mxit_send_suggest_friends( struct MXitSession* session, int max, unsigned int nr_attrib, const char* attribute[] );
+-void mxit_send_suggest_search( struct MXitSession* session, int max, const char* text, unsigned int nr_attrib, const char* attribute[] );
+-
+-void mxit_send_invite( struct MXitSession* session, const char* username, gboolean mxitid, const char* alias, const char* groupname, const char* message );
+-void mxit_send_remove( struct MXitSession* session, const char* username );
+-void mxit_send_allow_sub( struct MXitSession* session, const char* username, const char* alias );
+-void mxit_send_deny_sub( struct MXitSession* session, const char* username, const char* reason );
+-void mxit_send_update_contact( struct MXitSession* session, const char* username, const char* alias, const char* groupname );
+-void mxit_send_splashclick( struct MXitSession* session, const char* splashid );
+-void mxit_send_msgevent( struct MXitSession* session, const char* to, const char* id, int event);
+-
+-void mxit_send_file( struct MXitSession* session, const char* username, const char* filename, const unsigned char* buf, int buflen );
+-void mxit_send_file_reject( struct MXitSession* session, const char* fileid );
+-void mxit_send_file_accept( struct MXitSession* session, const char* fileid, int filesize, int offset );
+-void mxit_send_file_received( struct MXitSession* session, const char* fileid, short status );
+-void mxit_set_avatar( struct MXitSession* session, const unsigned char* avatar, int avatarlen );
+-void mxit_get_avatar( struct MXitSession* session, const char* mxitId, const char* avatarId );
+-
+-void mxit_send_groupchat_create( struct MXitSession* session, const char* groupname, int nr_usernames, const char* usernames[] );
+-void mxit_send_groupchat_invite( struct MXitSession* session, const char* roomid, int nr_usernames, const char* usernames[] );
+-
+-int mxit_parse_packet( struct MXitSession* session );
+-void dump_bytes( struct MXitSession* session, const char* buf, int len );
+-void mxit_close_connection( struct MXitSession* session );
+-gint64 mxit_now_milli( void );
+-
+-
+-#endif /* _MXIT_PROTO_H_ */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/roster.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/roster.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,902 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- user roster management (mxit contacts) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "purple.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "roster.h"
+-
+-
+-struct contact_invite {
+- struct MXitSession* session; /* MXit session object */
+- struct contact* contact; /* The contact performing the invite */
+-};
+-
+-
+-/*========================================================================================================================
+- * Presence / Status
+- */
+-
+-/* statuses (reference: libpurple/status.h) */
+-static struct status
+-{
+- PurpleStatusPrimitive primitive;
+- int mxit;
+- const char* id;
+- const char* name;
+-} const mxit_statuses[] = {
+- /* primitive, no, id, name */
+- { PURPLE_STATUS_OFFLINE, MXIT_PRESENCE_OFFLINE, "offline", N_( "Offline" ) }, /* 0 */
+- { PURPLE_STATUS_AVAILABLE, MXIT_PRESENCE_ONLINE, "online", N_( "Available" ) }, /* 1 */
+- { PURPLE_STATUS_AWAY, MXIT_PRESENCE_AWAY, "away", N_( "Away" ) }, /* 2 */
+- { PURPLE_STATUS_AVAILABLE, MXIT_PRESENCE_AVAILABLE, "chat", N_( "Chatty" ) }, /* 3 */
+- { PURPLE_STATUS_UNAVAILABLE, MXIT_PRESENCE_DND, "dnd", N_( "Do Not Disturb" ) } /* 4 */
+-};
+-
+-
+-/*------------------------------------------------------------------------
+- * Return list of supported statuses. (see status.h)
+- *
+- * @param account The MXit account object
+- * @return List of PurpleStatusType
+- */
+-GList* mxit_status_types( PurpleAccount* account )
+-{
+- GList* statuslist = NULL;
+- PurpleStatusType* type;
+- unsigned int i;
+-
+- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
+- const struct status* status = &mxit_statuses[i];
+-
+- /* add mxit status (reference: "libpurple/status.h") */
+- type = purple_status_type_new_with_attrs( status->primitive, status->id, _( status->name ), TRUE, TRUE, FALSE,
+- "message", _( "Message" ), purple_value_new( PURPLE_TYPE_STRING ),
+- NULL );
+-
+- statuslist = g_list_append( statuslist, type );
+- }
+-
+- /* add Mood option */
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD, "mood", NULL, FALSE, TRUE, TRUE,
+- PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new( PURPLE_TYPE_STRING ),
+- NULL);
+- statuslist = g_list_append( statuslist, type );
+-
+- return statuslist;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Returns the MXit presence code, given the unique status ID.
+- *
+- * @param id The status ID
+- * @return The MXit presence code
+- */
+-int mxit_convert_presence( const char* id )
+-{
+- unsigned int i;
+-
+- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
+- if ( strcmp( mxit_statuses[i].id, id ) == 0 ) /* status found! */
+- return mxit_statuses[i].mxit;
+- }
+-
+- return -1;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Returns the MXit presence as a string, given the MXit presence ID.
+- *
+- * @param no The MXit presence I (see above)
+- * @return The presence as a text string
+- */
+-const char* mxit_convert_presence_to_name( short no )
+-{
+- unsigned int i;
+-
+- for ( i = 0; i < ARRAY_SIZE( mxit_statuses ); i++ ) {
+- if ( mxit_statuses[i].mxit == no ) /* status found! */
+- return _( mxit_statuses[i].name );
+- }
+-
+- return "";
+-}
+-
+-
+-/*========================================================================================================================
+- * Moods
+- */
+-
+-/* moods (reference: libpurple/status.h) */
+-static PurpleMood mxit_moods[] = {
+- {"angry", N_("Angry"), NULL},
+- {"excited", N_("Excited"), NULL},
+- {"grumpy", N_("Grumpy"), NULL},
+- {"happy", N_("Happy"), NULL},
+- {"in_love", N_("In love"), NULL},
+- {"invincible", N_("Invincible"), NULL},
+- {"sad", N_("Sad"), NULL},
+- {"hot", N_("Hot"), NULL},
+- {"sick", N_("Sick"), NULL},
+- {"sleepy", N_("Sleepy"), NULL},
+- {"bored", N_("Bored"), NULL},
+- {"cold", N_("Cold"), NULL},
+- {"confused", N_("Confused"), NULL},
+- {"hungry", N_("Hungry"), NULL},
+- {"stressed", N_("Stressed"), NULL},
+- /* Mark the last record. */
+- { NULL, NULL, NULL }
+-};
+-
+-
+-/*------------------------------------------------------------------------
+- * Returns the MXit mood code, given the unique mood ID.
+- *
+- * @param id The mood ID
+- * @return The MXit mood code
+- */
+-int mxit_convert_mood( const char* id )
+-{
+- unsigned int i;
+-
+- /* Mood is being unset */
+- if ( id == NULL )
+- return MXIT_MOOD_NONE;
+-
+- for ( i = 0; i < ARRAY_SIZE( mxit_moods ) - 1; i++ ) {
+- if ( strcmp( mxit_moods[i].mood, id ) == 0 ) /* mood found! */
+- return i + 1; /* because MXIT_MOOD_NONE is 0 */
+- }
+-
+- return -1;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the list of MXit-supported moods.
+- *
+- * @param account The MXit account object
+- */
+-PurpleMood* mxit_get_moods(PurpleAccount *account)
+-{
+- return mxit_moods;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Returns the MXit mood as a string, given the MXit mood's ID.
+- *
+- * @param id The MXit mood ID (see roster.h)
+- * @return The mood as a text string
+- */
+-const char* mxit_convert_mood_to_name( short id )
+-{
+- switch ( id ) {
+- case MXIT_MOOD_ANGRY :
+- return _( "Angry" );
+- case MXIT_MOOD_EXCITED :
+- return _( "Excited" );
+- case MXIT_MOOD_GRUMPY :
+- return _( "Grumpy" );
+- case MXIT_MOOD_HAPPY :
+- return _( "Happy" );
+- case MXIT_MOOD_INLOVE :
+- return _( "In Love" );
+- case MXIT_MOOD_INVINCIBLE :
+- return _( "Invincible" );
+- case MXIT_MOOD_SAD :
+- return _( "Sad" );
+- case MXIT_MOOD_HOT :
+- return _( "Hot" );
+- case MXIT_MOOD_SICK :
+- return _( "Sick" );
+- case MXIT_MOOD_SLEEPY :
+- return _( "Sleepy" );
+- case MXIT_MOOD_BORED :
+- return _( "Bored" );
+- case MXIT_MOOD_COLD :
+- return _( "Cold" );
+- case MXIT_MOOD_CONFUSED :
+- return _( "Confused" );
+- case MXIT_MOOD_HUNGRY :
+- return _( "Hungry" );
+- case MXIT_MOOD_STRESSED :
+- return _( "Stressed" );
+- case MXIT_MOOD_NONE :
+- default :
+- return "";
+- }
+-}
+-
+-
+-/*========================================================================================================================
+- * Subscription Types
+- */
+-
+-/*------------------------------------------------------------------------
+- * Returns a Contact subscription type as a string.
+- *
+- * @param subtype The subscription type
+- * @return The subscription type as a text string
+- */
+-const char* mxit_convert_subtype_to_name( short subtype )
+-{
+- switch ( subtype ) {
+- case MXIT_SUBTYPE_BOTH :
+- return _( "Both" );
+- case MXIT_SUBTYPE_PENDING :
+- return _( "Pending" );
+- case MXIT_SUBTYPE_ASK :
+- return _( "Invited" );
+- case MXIT_SUBTYPE_REJECTED :
+- return _( "Rejected" );
+- case MXIT_SUBTYPE_DELETED :
+- return _( "Deleted" );
+- case MXIT_SUBTYPE_NONE :
+- return _( "None" );
+- default :
+- return "";
+- }
+-}
+-
+-
+-/*========================================================================================================================
+- * Calls from the MXit Protocol layer
+- */
+-
+-#if 0
+-/*------------------------------------------------------------------------
+- * Dump a contact's info the the debug console.
+- *
+- * @param contact The contact
+- */
+-static void dump_contact( struct contact* contact )
+-{
+- purple_debug_info( MXIT_PLUGIN_ID, "CONTACT: name='%s', alias='%s', group='%s', type='%i', presence='%i', mood='%i'\n",
+- contact->username, contact->alias, contact->groupname, contact->type, contact->presence, contact->mood );
+-}
+-#endif
+-
+-
+-#if 0
+-/*------------------------------------------------------------------------
+- * Move a buddy from one group to another
+- *
+- * @param buddy the buddy to move between groups
+- * @param group the new group to move the buddy to
+- */
+-static PurpleBuddy* mxit_update_buddy_group( struct MXitSession* session, PurpleBuddy* buddy, PurpleGroup* group )
+-{
+- struct contact* contact = NULL;
+- PurpleGroup* current_group = purple_buddy_get_group( buddy );
+- PurpleBuddy* newbuddy = NULL;
+-
+- /* make sure the groups actually differs */
+- if ( strcmp( current_group->name, group->name ) != 0 ) {
+- /* groupnames does not match, so we need to make the update */
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "Moving '%s' from group '%s' to '%s'\n", buddy->alias, current_group->name, group->name );
+-
+- /*
+- * XXX: libPurple does not currently provide an API to change or rename the group name
+- * for a specific buddy. One option is to remove the buddy from the list and re-adding
+- * him in the new group, but by doing that makes the buddy go offline and then online
+- * again. This is really not ideal and very irritating, but how else then?
+- */
+-
+- /* create new buddy */
+- newbuddy = purple_buddy_new( session->acc, buddy->name, buddy->alias );
+- newbuddy->proto_data = buddy->proto_data;
+- buddy->proto_data = NULL;
+-
+- /* remove the buddy */
+- purple_blist_remove_buddy( buddy );
+-
+- /* add buddy */
+- purple_blist_add_buddy( newbuddy, NULL, group, NULL );
+-
+- /* now re-instate his presence again */
+- contact = newbuddy->proto_data;
+- if ( contact ) {
+-
+- /* update the buddy's status (reference: "libpurple/prpl.h") */
+- if ( contact->statusMsg )
+- purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
+- else
+- purple_prpl_got_user_status( session->acc, newbuddy->name, mxit_statuses[contact->presence].id, NULL );
+-
+- /* update the buddy's mood */
+- if ( contact->mood == MXIT_MOOD_NONE )
+- purple_prpl_got_user_status_deactive( session->acc, newbuddy->name, "mood" );
+- else
+- purple_prpl_got_user_status( session->acc, newbuddy->name, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+-
+- /* update avatar */
+- if ( contact->avatarId ) {
+- mxit_get_avatar( session, newbuddy->name, contact->avatarId );
+- g_free( contact->avatarId );
+- contact->avatarId = NULL;
+- }
+- }
+-
+- return newbuddy;
+- }
+- else
+- return buddy;
+-}
+-#endif
+-
+-
+-/*------------------------------------------------------------------------
+- * A contact update packet was received from the MXit server, so update the buddy's
+- * information.
+- *
+- * @param session The MXit session object
+- * @param contact The contact
+- */
+-void mxit_update_contact( struct MXitSession* session, struct contact* contact )
+-{
+- PurpleBuddy* buddy = NULL;
+- PurpleGroup* group = NULL;
+- const char* id = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_contact: user='%s' alias='%s' group='%s'\n", contact->username, contact->alias, contact->groupname );
+-
+- /*
+- * libPurple requires all contacts to be in a group.
+- * So if this MXit contact isn't in a group, pretend it is.
+- */
+- if ( *contact->groupname == '\0' ) {
+- g_strlcpy( contact->groupname, MXIT_DEFAULT_GROUP, sizeof( contact->groupname ) );
+- }
+-
+- /* find or create a group for this contact */
+- group = purple_find_group( contact->groupname );
+- if ( !group )
+- group = purple_group_new( contact->groupname );
+-
+- /* see if the buddy is not in the group already */
+- buddy = purple_find_buddy_in_group( session->acc, contact->username, group );
+- if ( !buddy ) {
+- /* buddy not found in the group */
+-
+- /* lets try finding him in all groups */
+- buddy = purple_find_buddy( session->acc, contact->username );
+- if ( buddy ) {
+- /* ok, so we found him in another group. to switch him between groups we must delete him and add him again. */
+- purple_blist_remove_buddy( buddy );
+- buddy = NULL;
+- }
+-
+- /* create new buddy */
+- buddy = purple_buddy_new( session->acc, contact->username, contact->alias );
+- purple_buddy_set_protocol_data(buddy, contact);
+-
+- /* add new buddy to list */
+- purple_blist_add_buddy( buddy, NULL, group, NULL );
+- }
+- else {
+- /* buddy was found in the group */
+-
+- gpointer data = NULL;
+-
+- /* now update the buddy's alias */
+- purple_blist_alias_buddy( buddy, contact->alias );
+-
+- /* replace the buddy's contact struct */
+- if ( ( data = purple_buddy_get_protocol_data( buddy ) ) )
+- free( data );
+- purple_buddy_set_protocol_data( buddy, contact );
+- }
+-
+- /* load buddy's avatar id */
+- id = purple_buddy_icons_get_checksum_for_user( buddy );
+- if ( id )
+- contact->avatarId = g_strdup( id );
+- else
+- contact->avatarId = NULL;
+-
+- /* update the buddy's status (reference: "libpurple/prpl.h") */
+- purple_prpl_got_user_status( session->acc, contact->username, mxit_statuses[contact->presence].id, NULL );
+-
+- /* update the buddy's mood */
+- if ( contact->mood == MXIT_MOOD_NONE )
+- purple_prpl_got_user_status_deactive( session->acc, contact->username, "mood" );
+- else
+- purple_prpl_got_user_status( session->acc, contact->username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * A presence update packet was received from the MXit server, so update the buddy's
+- * information.
+- *
+- * @param session The MXit session object
+- * @param username The contact which presence to update
+- * @param presence The new presence state for the contact
+- * @param mood The new mood for the contact
+- * @param customMood The custom mood identifier
+- * @param statusMsg This is the contact's status message
+- * @param flags The contact's presence flags.
+- */
+-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags )
+-{
+- PurpleBuddy* buddy = NULL;
+- struct contact* contact = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: user='%s' presence=%i mood=%i customMood='%s' statusMsg='%s'\n",
+- username, presence, mood, customMood, statusMsg );
+-
+- if ( ( presence < MXIT_PRESENCE_OFFLINE ) || ( presence > MXIT_PRESENCE_DND ) ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: invalid presence state %i\n", presence );
+- return; /* ignore packet */
+- }
+-
+- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy( session->acc, username );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
+- return;
+- }
+-
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return;
+-
+- contact->presence = presence;
+- contact->mood = mood;
+- contact->capabilities = flags;
+-
+- /* validate mood */
+- if ( ( contact->mood < MXIT_MOOD_NONE ) || ( contact->mood > MXIT_MOOD_STRESSED ) )
+- contact->mood = MXIT_MOOD_NONE;
+-
+- g_strlcpy( contact->customMood, customMood, sizeof( contact->customMood ) );
+- // TODO: Download custom mood frame.
+-
+- /* update status message */
+- if ( contact->statusMsg ) {
+- g_free( contact->statusMsg );
+- contact->statusMsg = NULL;
+- }
+- if ( ( statusMsg ) && ( statusMsg[0] != '\0' ) )
+- contact->statusMsg = g_markup_escape_text( statusMsg, -1 );
+-
+- /* update the buddy's status (reference: "libpurple/prpl.h") */
+- if ( contact->statusMsg )
+- purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, "message", contact->statusMsg, NULL );
+- else
+- purple_prpl_got_user_status( session->acc, username, mxit_statuses[contact->presence].id, NULL );
+-
+- /* update the buddy's mood */
+- if ( contact->mood == MXIT_MOOD_NONE )
+- purple_prpl_got_user_status_deactive( session->acc, username, "mood" );
+- else
+- purple_prpl_got_user_status( session->acc, username, "mood", PURPLE_MOOD_NAME, mxit_moods[contact->mood-1].mood, NULL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Update the buddy's avatar.
+- * Either a presence update packet was received from the MXit server, or a profile response.
+- *
+- * @param session The MXit session object
+- * @param username The contact which presence to update
+- * @param avatarId This is the contact's avatar id
+- */
+-void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId )
+-{
+- PurpleBuddy* buddy = NULL;
+- struct contact* contact = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_update_buddy_avatar: user='%s' avatar='%s'\n", username, avatarId );
+-
+- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy( session->acc, username );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_update_buddy_presence: unable to find the buddy '%s'\n", username );
+- return;
+- }
+-
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return;
+-
+- if ( ( contact->avatarId ) && ( g_ascii_strcasecmp( contact->avatarId, avatarId ) == 0 ) ) {
+- /* avatar has not changed - do nothing */
+- }
+- else if ( avatarId[0] != '\0' ) { /* avatar has changed */
+- if ( contact->avatarId )
+- g_free( contact->avatarId );
+- contact->avatarId = g_strdup( avatarId );
+-
+- /* Send request to download new avatar image */
+- mxit_get_avatar( session, username, avatarId );
+- }
+- else /* clear current avatar */
+- purple_buddy_icons_set_for_user( session->acc, username, NULL, 0, NULL );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * update the blist cached by libPurple. We need to do this to keep
+- * libPurple and MXit's rosters in sync with each other.
+- *
+- * @param session The MXit session object
+- */
+-void mxit_update_blist( struct MXitSession* session )
+-{
+- PurpleBuddy* buddy = NULL;
+- GSList* list = NULL;
+- unsigned int i;
+-
+- /* remove all buddies we did not receive a roster update for.
+- * these contacts must have been removed from another client */
+- list = purple_find_buddies( session->acc, NULL );
+-
+- for ( i = 0; i < g_slist_length( list ); i++ ) {
+- buddy = g_slist_nth_data( list, i );
+-
+- if ( !purple_buddy_get_protocol_data( buddy ) ) {
+- const gchar* alias = purple_buddy_get_alias( buddy );
+- const gchar* name = purple_buddy_get_name( buddy );
+-
+- /* this buddy should be removed, because we did not receive him in our roster update from MXit */
+- purple_debug_info( MXIT_PLUGIN_ID, "Removed 'old' buddy from the blist '%s' (%s)\n", alias, name );
+- purple_blist_remove_buddy( buddy );
+- }
+- }
+-
+- /* tell the UI to update the blist */
+- purple_blist_add_account( session->acc );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user authorized an invite (subscription request).
+- *
+- * @param user_data Object associated with the invite
+- */
+-static void mxit_cb_buddy_auth( gpointer user_data )
+-{
+- struct contact_invite* invite = (struct contact_invite*) user_data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_auth '%s'\n", invite->contact->username );
+-
+- /* send a allow subscription packet to MXit */
+- mxit_send_allow_sub( invite->session, invite->contact->username, invite->contact->alias );
+-
+- /* remove the invite from our internal invites list */
+- invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
+-
+- /* freeup invite object */
+- if ( invite->contact->msg )
+- g_free( invite->contact->msg );
+- if ( invite->contact->statusMsg )
+- g_free( invite->contact->statusMsg );
+- if ( invite->contact->profile )
+- g_free( invite->contact->profile );
+- g_free( invite->contact );
+- g_free( invite );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user rejected an invite (subscription request).
+- *
+- * @param user_data Object associated with the invite
+- */
+-static void mxit_cb_buddy_deny( gpointer user_data )
+-{
+- struct contact_invite* invite = (struct contact_invite*) user_data;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_cb_buddy_deny '%s'\n", invite->contact->username );
+-
+- /* send a deny subscription packet to MXit */
+- mxit_send_deny_sub( invite->session, invite->contact->username, NULL );
+-
+- /* remove the invite from our internal invites list */
+- invite->session->invites = g_list_remove( invite->session->invites, invite->contact );
+-
+- /* freeup invite object */
+- if ( invite->contact->msg )
+- g_free( invite->contact->msg );
+- if ( invite->contact->statusMsg )
+- g_free( invite->contact->statusMsg );
+- if ( invite->contact->profile )
+- g_free( invite->contact->profile );
+- g_free( invite->contact );
+- g_free( invite );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * A new subscription request packet was received from the MXit server.
+- * Prompt user to accept or reject it.
+- *
+- * @param session The MXit session object
+- * @param contact The contact performing the invite
+- */
+-void mxit_new_subscription( struct MXitSession* session, struct contact* contact )
+-{
+- struct contact_invite* invite;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_new_subscription from '%s' (%s)\n", contact->username, contact->alias );
+-
+- invite = g_new0( struct contact_invite, 1 );
+- invite->session = session;
+- invite->contact = contact;
+-
+- /* add the invite to our internal invites list */
+- invite->session->invites = g_list_append( invite->session->invites, invite->contact );
+-
+- /* (reference: "libpurple/account.h") */
+- purple_account_request_authorization( session->acc, contact->username, NULL, contact->alias, contact->msg, FALSE, mxit_cb_buddy_auth, mxit_cb_buddy_deny, invite );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the contact object for a mxit invite
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact
+- * @return The contact object for the inviting user
+- */
+-struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username )
+-{
+- struct contact* con = NULL;
+- struct contact* match = NULL;
+- int i;
+-
+- /* run through all the invites and try and find the match */
+- for ( i = 0; i < g_list_length( session->invites ); i++ ) {
+- con = g_list_nth_data( session->invites, i );
+- if ( strcmp( con->username, username ) == 0 ) {
+- /* invite found */
+- match = con;
+- break;
+- }
+- }
+-
+- return match;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return TRUE if this is a MXit Chatroom contact.
+- *
+- * @param session The MXit session object
+- * @param username The username of the contact
+- */
+-gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username )
+-{
+- PurpleBuddy* buddy;
+- struct contact* contact = NULL;
+-
+- /* find the buddy */
+- buddy = purple_find_buddy( session->acc, username );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "is_mxit_chatroom_contact: unable to find the buddy '%s'\n", username );
+- return FALSE;
+- }
+-
+- contact = purple_buddy_get_protocol_data( buddy );
+- if ( !contact )
+- return FALSE;
+-
+- return ( contact->type == MXIT_TYPE_CHATROOM );
+-}
+-
+-
+-/*========================================================================================================================
+- * Callbacks from libpurple
+- */
+-
+-/*------------------------------------------------------------------------
+- * The user has added a buddy to the list, so send an invite request.
+- *
+- * @param gc The connection object
+- * @param buddy The new buddy
+- * @param group The group of the new buddy
+- * @param message The invite message
+- */
+-void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- GSList* list = NULL;
+- PurpleBuddy* mxbuddy = NULL;
+- unsigned int i;
+- const gchar * buddy_name = purple_buddy_get_name( buddy );
+- const gchar * buddy_alias = purple_buddy_get_alias( buddy );
+- const gchar * group_name = purple_group_get_name( group );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy '%s' (group='%s')\n", buddy_name, group_name );
+-
+- list = purple_find_buddies( session->acc, buddy_name );
+- if ( g_slist_length( list ) == 1 ) {
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 1) (list:%i)\n", g_slist_length( list ) );
+- /*
+- * we only send an invite to MXit when the user is not already inside our
+- * blist. this is done because purple does an add_buddy() call when
+- * you accept an invite. so in that case the user is already
+- * in our blist and ready to be chatted to.
+- */
+-
+- if ( buddy_name[0] == '#' ) {
+- gchar *tmp = (gchar*) purple_base64_decode( buddy_name + 1, NULL );
+- mxit_send_invite( session, tmp, FALSE, buddy_alias, group_name, message );
+- g_free( tmp );
+- }
+- else
+- mxit_send_invite( session, buddy_name, TRUE, buddy_alias, group_name, message );
+- }
+- else {
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_add_buddy (scenario 2) (list:%i)\n", g_slist_length( list ) );
+- /*
+- * we already have the buddy in our list, so we will only update
+- * his information here and not send another invite message
+- */
+-
+- /* find the correct buddy */
+- for ( i = 0; i < g_slist_length( list ); i++ ) {
+- mxbuddy = g_slist_nth_data( list, i );
+-
+- if ( purple_buddy_get_protocol_data( mxbuddy ) != NULL ) {
+- /* this is our REAL MXit buddy! */
+-
+- /* now update the buddy's alias */
+- purple_blist_alias_buddy( mxbuddy, buddy_alias );
+-
+- /* now update the buddy's group */
+-// mxbuddy = mxit_update_buddy_group( session, mxbuddy, group );
+-
+- /* send the update to the MXit server */
+- mxit_send_update_contact( session, purple_buddy_get_name( mxbuddy ), purple_buddy_get_alias( mxbuddy ), group_name );
+- }
+- }
+- }
+-
+- /*
+- * we remove the buddy here from the buddy list because the MXit server
+- * will send us a proper contact update packet if this succeeds. now
+- * we do not have to worry about error handling in case of adding an
+- * invalid contact. so the user will still see the contact as offline
+- * until he eventually accepts the invite.
+- */
+- purple_blist_remove_buddy( buddy );
+-
+- g_slist_free( list );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has removed a buddy from the list.
+- *
+- * @param gc The connection object
+- * @param buddy The buddy being removed
+- * @param group The group the buddy was in
+- */
+-void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const gchar * buddy_name = purple_buddy_get_name( buddy );
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_remove_buddy '%s'\n", buddy_name );
+-
+- mxit_send_remove( session, buddy_name );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user changed the buddy's alias.
+- *
+- * @param gc The connection object
+- * @param who The username of the buddy
+- * @param alias The new alias
+- */
+-void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleBuddy* buddy = NULL;
+- PurpleGroup* group = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_alias '%s' to '%s\n", who, alias );
+-
+- /* find the buddy */
+- buddy = purple_find_buddy( session->acc, who );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the buddy '%s'\n", who );
+- return;
+- }
+-
+- /* find buddy group */
+- group = purple_buddy_get_group( buddy );
+- if ( !group ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_alias: unable to find the group for buddy '%s'\n", who );
+- return;
+- }
+-
+- mxit_send_update_contact( session, who, alias, purple_group_get_name( group ) );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user changed the group for a single buddy.
+- *
+- * @param gc The connection object
+- * @param who The username of the buddy
+- * @param old_group The old group's name
+- * @param new_group The new group's name
+- */
+-void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleBuddy* buddy = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_buddy_group from '%s' to '%s'\n", old_group, new_group );
+-
+- /* find the buddy */
+- buddy = purple_find_buddy( session->acc, who );
+- if ( !buddy ) {
+- purple_debug_warning( MXIT_PLUGIN_ID, "mxit_buddy_group: unable to find the buddy '%s'\n", who );
+- return;
+- }
+-
+- mxit_send_update_contact( session, who, purple_buddy_get_alias( buddy ), new_group );
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has selected to rename a group, so update all contacts in that
+- * group.
+- *
+- * @param gc The connection object
+- * @param old_name The old group name
+- * @param group The updated group object
+- * @param moved_buddies The buddies affected by the rename
+- */
+-void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies )
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- PurpleBuddy* buddy = NULL;
+- GList* item = NULL;
+-
+- purple_debug_info( MXIT_PLUGIN_ID, "mxit_rename_group from '%s' to '%s\n", old_name, purple_group_get_name( group ) );
+-
+- // TODO: Might be more efficient to use the "rename group" command (cmd=29).
+-
+- /* loop through all the contacts in the group and send updates */
+- item = moved_buddies;
+- while ( item ) {
+- buddy = item->data;
+- mxit_send_update_contact( session, purple_buddy_get_name( buddy ), purple_buddy_get_alias( buddy ), purple_group_get_name( group ) );
+- item = g_list_next( item );
+- }
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/roster.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/roster.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/roster.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,159 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- user roster management (mxit contacts) --
+- *
+- * Pieter Loubser <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_ROSTER_H_
+-#define _MXIT_ROSTER_H_
+-
+-
+-/* MXit contact presence states */
+-#define MXIT_PRESENCE_OFFLINE 0x00
+-#define MXIT_PRESENCE_ONLINE 0x01
+-#define MXIT_PRESENCE_AWAY 0x02
+-#define MXIT_PRESENCE_AVAILABLE 0x03
+-#define MXIT_PRESENCE_DND 0x04
+-
+-
+-/* MXit contact types */
+-#define MXIT_TYPE_MXIT 0x00
+-#define MXIT_TYPE_JABBER 0x01
+-#define MXIT_TYPE_MSN 0x02
+-#define MXIT_TYPE_YAHOO 0x03
+-#define MXIT_TYPE_ICQ 0x04
+-#define MXIT_TYPE_AIM 0x05
+-#define MXIT_TYPE_QQ 0x06
+-#define MXIT_TYPE_WV 0x07
+-#define MXIT_TYPE_BOT 0x08
+-#define MXIT_TYPE_CHATROOM 0x09
+-#define MXIT_TYPE_SMS 0x0A
+-#define MXIT_TYPE_GROUP 0x0B
+-#define MXIT_TYPE_GALLERY 0x0C
+-#define MXIT_TYPE_INFO 0x0D
+-#define MXIT_TYPE_MULTIMX 0x0E
+-#define MXIT_TYPE_HYBRID 0x0F
+-
+-
+-/* MXit contact moods */
+-#define MXIT_MOOD_NONE 0x00
+-#define MXIT_MOOD_ANGRY 0x01
+-#define MXIT_MOOD_EXCITED 0x02
+-#define MXIT_MOOD_GRUMPY 0x03
+-#define MXIT_MOOD_HAPPY 0x04
+-#define MXIT_MOOD_INLOVE 0x05
+-#define MXIT_MOOD_INVINCIBLE 0x06
+-#define MXIT_MOOD_SAD 0x07
+-#define MXIT_MOOD_HOT 0x08
+-#define MXIT_MOOD_SICK 0x09
+-#define MXIT_MOOD_SLEEPY 0x0A
+-#define MXIT_MOOD_BORED 0x0B
+-#define MXIT_MOOD_COLD 0x0C
+-#define MXIT_MOOD_CONFUSED 0x0D
+-#define MXIT_MOOD_HUNGRY 0x0E
+-#define MXIT_MOOD_STRESSED 0x0F
+-
+-
+-/* MXit contact flags */
+-//#define MXIT_CFLAG_HIDDEN 0x02 /* (DEPRECATED) */
+-#define MXIT_CFLAG_GATEWAY 0x04
+-#define MXIT_CFLAG_FOCUS_SEND_BLANK 0x20000
+-
+-
+-/* MXit presence flags */
+-#define MXIT_PFLAG_VOICE 0x1
+-#define MXIT_PFLAG_VIDEO 0x2
+-#define MXIT_PFLAG_TYPING 0x4
+-
+-
+-/* Subscription types */
+-#define MXIT_SUBTYPE_BOTH 'B'
+-#define MXIT_SUBTYPE_PENDING 'P'
+-#define MXIT_SUBTYPE_ASK 'A'
+-#define MXIT_SUBTYPE_REJECTED 'R'
+-#define MXIT_SUBTYPE_DELETED 'D'
+-#define MXIT_SUBTYPE_NONE 'N'
+-
+-
+-/* client protocol constants */
+-#define MXIT_CP_MAX_JID_LEN 64
+-#define MXIT_CP_MAX_GROUP_LEN 32
+-#define MXIT_CP_MAX_ALIAS_LEN 100
+-
+-#define MXIT_DEFAULT_GROUP "MXit"
+-
+-
+-/*
+- * a MXit contact
+- */
+-struct contact {
+- char username[MXIT_CP_MAX_JID_LEN+1]; /* unique contact name (with domain) */
+- char alias[MXIT_CP_MAX_ALIAS_LEN+1]; /* contact alias (what will be seen) */
+- char groupname[MXIT_CP_MAX_GROUP_LEN+1]; /* contact group name */
+-
+- short type; /* contact type */
+- short mood; /* contact current mood */
+- int flags; /* contact flags */
+- short presence; /* presence state */
+- int capabilities; /* contact capabilities */
+- short subtype; /* subscription type */
+-
+- char* msg; /* invite/rejection message */
+-
+- char customMood[16]; /* custom mood */
+- char* statusMsg; /* status message */
+- char* avatarId; /* avatarId */
+-
+- /* invites only */
+- void* profile; /* user's profile (if available) */
+- int imgid; /* avatar image id in the imgstore */
+-};
+-
+-/* Presence / Status */
+-GList* mxit_status_types( PurpleAccount* account );
+-int mxit_convert_presence( const char* id );
+-const char* mxit_convert_presence_to_name( short no );
+-const char* mxit_convert_subtype_to_name( short subtype );
+-
+-/* Moods */
+-int mxit_convert_mood( const char* id );
+-const char* mxit_convert_mood_to_name( short id );
+-
+-/* MXit Protocol callbacks */
+-void mxit_update_contact( struct MXitSession* session, struct contact* contact );
+-void mxit_update_buddy_presence( struct MXitSession* session, const char* username, short presence, short mood, const char* customMood, const char* statusMsg, int flags );
+-void mxit_update_buddy_avatar( struct MXitSession* session, const char* username, const char* avatarId );
+-void mxit_new_subscription( struct MXitSession* session, struct contact* contact );
+-void mxit_update_blist( struct MXitSession* session );
+-gboolean is_mxit_chatroom_contact( struct MXitSession* session, const char* username );
+-struct contact* get_mxit_invite_contact( struct MXitSession* session, const char* username );
+-
+-/* libPurple callbacks */
+-void mxit_add_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group, const char* message );
+-void mxit_remove_buddy( PurpleConnection* gc, PurpleBuddy* buddy, PurpleGroup* group );
+-void mxit_buddy_alias( PurpleConnection* gc, const char* who, const char* alias );
+-void mxit_buddy_group( PurpleConnection* gc, const char* who, const char* old_group, const char* new_group );
+-void mxit_rename_group( PurpleConnection* gc, const char* old_name, PurpleGroup* group, GList* moved_buddies );
+-PurpleMood* mxit_get_moods(PurpleAccount *account);
+-
+-
+-#endif /* _MXIT_ROSTER_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,222 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- splash screens --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-
+-#include "purple.h"
+-#include "imgstore.h"
+-
+-#include "protocol.h"
+-#include "mxit.h"
+-#include "splashscreen.h"
+-
+-
+-/*------------------------------------------------------------------------
+- * Return the ID of the current splash-screen.
+- *
+- * @param session The MXit session object
+- * @return The ID of the splash-screen (or NULL if no splash-screen)
+- */
+-const char* splash_current(struct MXitSession* session)
+-{
+- const char* splashId = purple_account_get_string(session->acc, MXIT_CONFIG_SPLASHID, NULL);
+-
+- if ((splashId != NULL) && (*splashId != '\0')) {
+- purple_debug_info(MXIT_PLUGIN_ID, "Current splashId: '%s'\n", splashId);
+- return splashId;
+- }
+- else
+- return NULL;
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Indicate if splash-screen popups are enabled.
+- *
+- * @param session The MXit session object
+- * @return TRUE if the popup is enabled.
+- */
+-gboolean splash_popup_enabled(struct MXitSession* session)
+-{
+- return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHPOPUP, DEFAULT_SPLASH_POPUP);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Return if the current splash-screen is clickable.
+- *
+- * @param session The MXit session object
+- * @return TRUE or FALSE
+- */
+-static gboolean splash_clickable(struct MXitSession* session)
+-{
+- return purple_account_get_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Remove the stored splash-screen (if it exists).
+- *
+- * @param session The MXit session object
+- */
+-void splash_remove(struct MXitSession* session)
+-{
+- const char* splashId = NULL;
+- char* filename;
+-
+- /* Get current splash ID */
+- splashId = splash_current(session);
+-
+- if (splashId != NULL) {
+- purple_debug_info(MXIT_PLUGIN_ID, "Removing splashId: '%s'\n", splashId);
+-
+- /* Delete stored splash image */
+- filename = g_strdup_printf("%s/mxit/%s.png", purple_user_dir(), splashId);
+- g_unlink(filename);
+- g_free(filename);
+-
+- /* Clear current splash ID from settings */
+- purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, "");
+- purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, FALSE);
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Save a new splash-screen for later display.
+- *
+- * @param session The MXit session object
+- * @param splashID The ID of the splash-screen
+- * @param data Splash-screen image data (PNG format)
+- * @param datalen Splash-screen image data size
+- */
+-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable)
+-{
+- char* dir;
+- char* filename;
+-
+- /* Remove the current splash-screen */
+- splash_remove(session);
+-
+- /* Save the new splash image */
+- dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "mxit", purple_user_dir());
+- purple_build_dir(dir, S_IRUSR | S_IWUSR | S_IXUSR); /* ensure directory exists */
+-
+- filename = g_strdup_printf("%s" G_DIR_SEPARATOR_S "%s.png", dir, purple_escape_filename(splashId));
+- if (purple_util_write_data_to_file_absolute(filename, data, datalen)) {
+- /* Store new splash-screen ID to settings */
+- purple_account_set_string(session->acc, MXIT_CONFIG_SPLASHID, splashId);
+- purple_account_set_bool(session->acc, MXIT_CONFIG_SPLASHCLICK, clickable );
+- }
+-
+- g_free(dir);
+- g_free(filename);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * The user has clicked OK on the Splash request form.
+- *
+- * @param gc The connection object
+- * @param fields The list of fields in the accepted form
+- */
+-static void splash_click_ok(PurpleConnection* gc, PurpleRequestFields* fields)
+-{
+- struct MXitSession* session = (struct MXitSession*) gc->proto_data;
+- const char* splashId;
+-
+- /* Get current splash ID */
+- splashId = splash_current(session);
+- if (splashId == NULL) /* no splash-screen */
+- return;
+-
+- /* if is clickable, then send click event */
+- if (splash_clickable(session))
+- mxit_send_splashclick(session, splashId);
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Display the current splash-screen.
+- *
+- * @param session The MXit session object
+- */
+-void splash_display(struct MXitSession* session)
+-{
+- const char* splashId = NULL;
+- char* filename;
+- gchar* imgdata;
+- gsize imglen;
+- int imgid = -1;
+-
+- /* Get current splash ID */
+- splashId = splash_current(session);
+- if (splashId == NULL) /* no splash-screen */
+- return;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "Display Splash: '%s'\n", splashId);
+-
+- /* Load splash-screen image from file */
+- filename = g_strdup_printf("%s/mxit/%s.png", purple_user_dir(), splashId);
+- if (g_file_get_contents(filename, &imgdata, &imglen, NULL)) {
+- char buf[128];
+-
+- /* Add splash-image to imagestore */
+- imgid = purple_imgstore_add_with_id(g_memdup(imgdata, imglen), imglen, NULL);
+-
+- /* Generate and display message */
+- g_snprintf(buf, sizeof(buf), "<img id=\"%d\">", imgid);
+-
+- /* Open a request-type popup to display the image */
+- {
+- PurpleRequestFields* fields;
+- PurpleRequestFieldGroup* group;
+- PurpleRequestField* field;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_image_new("splash", "", imgdata, imglen); /* add splash image */
+- purple_request_field_group_add_field(group, field);
+-
+- if (splash_clickable(session)) {
+- purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
+- _("More Information"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
+- }
+- else {
+- purple_request_fields(session->con, _("MXit Advertising"), NULL, NULL, fields,
+- _("Continue"), G_CALLBACK(splash_click_ok), _("Close"), NULL, session->acc, NULL, NULL, session->con);
+- }
+- }
+-
+- /* Release reference to image */
+- purple_imgstore_unref_by_id(imgid);
+-
+- g_free(imgdata);
+- }
+-
+- g_free(filename);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/splashscreen.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/splashscreen.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,59 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- splash screens --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_SPLASHSCREEN_H_
+-#define _MXIT_SPLASHSCREEN_H_
+-
+-#define HANDLE_SPLASH1 "plas1.png"
+-#define HANDLE_SPLASH2 "plas2.png"
+-
+-#define DEFAULT_SPLASH_POPUP FALSE /* disabled by default */
+-
+-/*
+- * Return the ID of the current splash-screen.
+- */
+-const char* splash_current(struct MXitSession* session);
+-
+-/*
+- * Indicate if splash-screen popups are enabled.
+- */
+-gboolean splash_popup_enabled(struct MXitSession* session);
+-
+-/*
+- * Save a new splash-screen.
+- */
+-void splash_update(struct MXitSession* session, const char* splashId, const char* data, int datalen, gboolean clickable);
+-
+-/*
+- * Remove the stored splash-screen (if it exists).
+- */
+-void splash_remove(struct MXitSession* session);
+-
+-/*
+- * Display the current splash-screen.
+- */
+-void splash_display(struct MXitSession* session);
+-
+-#endif /* _MXIT_SPLASHSCREEN_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.c pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.c
+--- pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,242 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- voice & video --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "purple.h"
+-#include "mxit.h"
+-#include "roster.h"
+-#include "voicevideo.h"
+-
+-#if defined(USE_VV) && defined(MXIT_DEV_VV)
+-
+-#warning "MXit VV support enabled."
+-
+-/*------------------------------------------------------------------------
+- * Does this client support Voice?
+- */
+-gboolean mxit_audio_enabled(void)
+-{
+- PurpleMediaManager *manager = purple_media_manager_get();
+- PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
+-
+- return (caps & PURPLE_MEDIA_CAPS_AUDIO);
+-}
+-
+-/*------------------------------------------------------------------------
+- * Does this client support Voice and Video?
+- */
+-gboolean mxit_video_enabled(void)
+-{
+- PurpleMediaManager *manager = purple_media_manager_get();
+- PurpleMediaCaps caps = purple_media_manager_get_ui_caps(manager);
+-
+- return (caps & PURPLE_MEDIA_CAPS_VIDEO);
+-}
+-
+-/*------------------------------------------------------------------------
+- * Return the list of media capabilities this contact supports.
+- *
+- * @param account The MXit account object
+- * @param who The username of the contact.
+- * @return The media capabilities supported
+- */
+-PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who)
+-{
+- struct MXitSession* session = purple_account_get_connection(account)->proto_data;
+- PurpleBuddy* buddy;
+- struct contact* contact;
+- PurpleMediaCaps capa = PURPLE_MEDIA_CAPS_NONE;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_caps: buddy '%s'\n", who);
+-
+- /* We need to have a voice/video server */
+- if (strlen(session->voip_server) == 0)
+- return PURPLE_MEDIA_CAPS_NONE;
+-
+- /* find the buddy information for this contact (reference: "libpurple/blist.h") */
+- buddy = purple_find_buddy(account, who);
+- if (!buddy) {
+- purple_debug_warning(MXIT_PLUGIN_ID, "mxit_media_caps: unable to find the buddy '%s'\n", who);
+- return PURPLE_MEDIA_CAPS_NONE;
+- }
+-
+- contact = purple_buddy_get_protocol_data(buddy);
+- if (!contact)
+- return PURPLE_MEDIA_CAPS_NONE;
+-
+- /* can only communicate with MXit users */
+- if (contact->type != MXIT_TYPE_MXIT)
+- return PURPLE_MEDIA_CAPS_NONE;
+-
+- /* and only with contacts in the 'Both' subscription state */
+- if (contact->subtype != MXIT_SUBTYPE_BOTH)
+- return PURPLE_MEDIA_CAPS_NONE;
+-
+- /* and only when they're online */
+- if (contact->presence == MXIT_PRESENCE_OFFLINE)
+- return MXIT_PRESENCE_OFFLINE;
+-
+- /* they support voice-only */
+- if (contact->capabilities & MXIT_PFLAG_VOICE)
+- capa |= PURPLE_MEDIA_CAPS_AUDIO;
+-
+- /* they support voice-and-video */
+- if (contact->capabilities & MXIT_PFLAG_VIDEO)
+- capa |= (PURPLE_MEDIA_CAPS_AUDIO | PURPLE_MEDIA_CAPS_VIDEO | PURPLE_MEDIA_CAPS_AUDIO_VIDEO);
+-
+- return capa;
+-}
+-
+-
+-static void mxit_candidates_prepared_cb(PurpleMedia* media, gchar* sessionid, gchar* who, void* session)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_candidates_prepared_cb: buddy '%s', session '%s'\n", who, sessionid);
+-
+- if (purple_media_is_initiator(media, sessionid, who)) {
+- // TODO: Send INVITE via SIP.
+- }
+- else {
+- // TODO: ??
+- }
+-}
+-
+-static void mxit_stream_info_cb(PurpleMedia* media, PurpleMediaInfoType type, char* sessionid, gchar* who, gboolean local, void* session)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_stream_info_cb: buddy '%s', session '%s', info %d \n", who, sessionid, type);
+-
+- switch (type) {
+- case PURPLE_MEDIA_INFO_HANGUP:
+- break;
+- case PURPLE_MEDIA_INFO_ACCEPT:
+- break;
+- case PURPLE_MEDIA_INFO_REJECT:
+- break;
+- case PURPLE_MEDIA_INFO_MUTE:
+- break;
+- case PURPLE_MEDIA_INFO_UNMUTE:
+- break;
+- case PURPLE_MEDIA_INFO_PAUSE:
+- break;
+- case PURPLE_MEDIA_INFO_UNPAUSE:
+- break;
+- case PURPLE_MEDIA_INFO_HOLD:
+- break;
+- case PURPLE_MEDIA_INFO_UNHOLD:
+- break;
+- }
+-}
+-
+-static void mxit_state_changed_cb(PurpleMedia* media, PurpleMediaState state, gchar* sessionid, char* who, void* session)
+-{
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_state_changed_cb: buddy '%s', session '%s', state %d\n", who, sessionid, state);
+-
+- switch (state) {
+- case PURPLE_MEDIA_STATE_NEW:
+- break;
+- case PURPLE_MEDIA_STATE_CONNECTED:
+- break;
+- case PURPLE_MEDIA_STATE_END:
+- break;
+- }
+-}
+-
+-
+-/*------------------------------------------------------------------------
+- * Initiate a voice/video session with a contact.
+- *
+- * @param account The MXit account object
+- * @param who The username of the contact.
+- * @param type The type of media session to initiate
+- * @return TRUE if session was initiated
+- */
+-gboolean mxit_media_initiate(PurpleAccount *account, const char *who, PurpleMediaSessionType type)
+-{
+- gchar* transmitter = "rawudp";
+- PurpleMedia* media = NULL;
+-
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_initiate: buddy '%s'\n", who);
+-
+- media = purple_media_manager_create_media(
+- purple_media_manager_get(),
+- account,
+- "fsrtpconference",
+- who,
+- TRUE
+- );
+-
+- if (!media) {
+- purple_debug_info(MXIT_PLUGIN_ID, "mxit_media_initiate: could not create media session\n");
+- return FALSE;
+- }
+-
+- /* attach callbacks */
+- g_signal_connect(G_OBJECT(media), "candidates-prepared", G_CALLBACK(mxit_candidates_prepared_cb), NULL);
+- g_signal_connect(G_OBJECT(media), "stream-info", G_CALLBACK(mxit_stream_info_cb), NULL);
+- g_signal_connect(G_OBJECT(media), "state-changed", G_CALLBACK(mxit_state_changed_cb), NULL);
+-
+- /* initiate audio session */
+- if ((type & PURPLE_MEDIA_AUDIO) &&
+- (!purple_media_add_stream(media, "audio", who, PURPLE_MEDIA_AUDIO, TRUE, transmitter, 0, NULL))) {
+- purple_media_end(media, NULL, NULL);
+- return FALSE;
+- }
+-
+- /* initiate video session */
+- if ((type & PURPLE_MEDIA_VIDEO) &&
+- (!purple_media_add_stream(media, "video", who, PURPLE_MEDIA_VIDEO, TRUE, transmitter, 0, NULL))) {
+- purple_media_end(media, NULL, NULL);
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-#else
+-
+-/*
+- * Voice and Video not supported.
+- */
+-
+-gboolean mxit_audio_enabled(void)
+-{
+- return FALSE;
+-}
+-
+-gboolean mxit_video_enabled(void)
+-{
+- return FALSE;
+-}
+-
+-PurpleMediaCaps mxit_media_caps(PurpleAccount *account, const char *who)
+-{
+- return PURPLE_MEDIA_CAPS_NONE;
+-}
+-
+-gboolean mxit_media_initiate(PurpleAccount *account, const char *who, PurpleMediaSessionType type)
+-{
+- return FALSE;
+-}
+-
+-#endif
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.h pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.h
+--- pidgin-2.10.7/libpurple/protocols/mxit/voicevideo.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/mxit/voicevideo.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,41 +0,0 @@
+-/*
+- * MXit Protocol libPurple Plugin
+- *
+- * -- voice & video --
+- *
+- * Andrew Victor <libpurple@mxit.com>
+- *
+- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd.
+- * <http://www.mxitlifestyle.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MXIT_VOICEVICEO_H_
+-#define _MXIT_VOICEVIDEO_H_
+-
+-#include "media.h"
+-
+-
+-#undef MXIT_DEV_VV
+-
+-
+-gboolean mxit_audio_enabled(void);
+-gboolean mxit_video_enabled(void);
+-PurpleMediaCaps mxit_media_caps(PurpleAccount* account, const char* who);
+-gboolean mxit_media_initiate(PurpleAccount* account, const char* who, PurpleMediaSessionType type);
+-
+-
+-#endif /* _MXIT_VOICEVIDEO_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,44 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-MSIMSOURCES = markup.c \
+- markup.h \
+- message.c \
+- message.h \
+- myspace.c \
+- myspace.h \
+- persist.h \
+- session.c \
+- session.h \
+- user.c \
+- user.h \
+- zap.c \
+- zap.h
+-
+-AM_CFLAGS = $(st)
+-
+-libmyspace_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_MYSPACE
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libmyspace.la
+-libmyspace_la_SOURCES = $(MSIMSOURCES)
+-libmyspace_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libmyspace.la
+-libmyspace_la_SOURCES = $(MSIMSOURCES)
+-libmyspace_la_LIBADD = $(GLIB_LIBS)
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,803 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/myspace
+-DIST_COMMON = README $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-@STATIC_MYSPACE_FALSE@libmyspace_la_DEPENDENCIES = \
+-@STATIC_MYSPACE_FALSE@ $(am__DEPENDENCIES_1)
+-am__libmyspace_la_SOURCES_DIST = markup.c markup.h message.c message.h \
+- myspace.c myspace.h persist.h session.c session.h user.c \
+- user.h zap.c zap.h
+-am__objects_1 = libmyspace_la-markup.lo libmyspace_la-message.lo \
+- libmyspace_la-myspace.lo libmyspace_la-session.lo \
+- libmyspace_la-user.lo libmyspace_la-zap.lo
+-@STATIC_MYSPACE_FALSE@am_libmyspace_la_OBJECTS = $(am__objects_1)
+-@STATIC_MYSPACE_TRUE@am_libmyspace_la_OBJECTS = $(am__objects_1)
+-libmyspace_la_OBJECTS = $(am_libmyspace_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libmyspace_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libmyspace_la_CFLAGS) \
+- $(CFLAGS) $(libmyspace_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_MYSPACE_FALSE@am_libmyspace_la_rpath = -rpath $(pkgdir)
+-@STATIC_MYSPACE_TRUE@am_libmyspace_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libmyspace_la_SOURCES)
+-DIST_SOURCES = $(am__libmyspace_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-MSIMSOURCES = markup.c \
+- markup.h \
+- message.c \
+- message.h \
+- myspace.c \
+- myspace.h \
+- persist.h \
+- session.c \
+- session.h \
+- user.c \
+- user.h \
+- zap.c \
+- zap.h
+-
+-AM_CFLAGS = $(st)
+-libmyspace_la_LDFLAGS = -module -avoid-version
+-@STATIC_MYSPACE_FALSE@st =
+-@STATIC_MYSPACE_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_MYSPACE_TRUE@noinst_LTLIBRARIES = libmyspace.la
+-@STATIC_MYSPACE_FALSE@libmyspace_la_SOURCES = $(MSIMSOURCES)
+-@STATIC_MYSPACE_TRUE@libmyspace_la_SOURCES = $(MSIMSOURCES)
+-@STATIC_MYSPACE_TRUE@libmyspace_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_MYSPACE_FALSE@pkg_LTLIBRARIES = libmyspace.la
+-@STATIC_MYSPACE_FALSE@libmyspace_la_LIBADD = $(GLIB_LIBS)
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/myspace/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/myspace/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libmyspace.la: $(libmyspace_la_OBJECTS) $(libmyspace_la_DEPENDENCIES) $(EXTRA_libmyspace_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libmyspace_la_LINK) $(am_libmyspace_la_rpath) $(libmyspace_la_OBJECTS) $(libmyspace_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-markup.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-message.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-myspace.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-session.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-user.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libmyspace_la-zap.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libmyspace_la-markup.lo: markup.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-markup.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-markup.Tpo -c -o libmyspace_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-markup.Tpo $(DEPDIR)/libmyspace_la-markup.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='markup.c' object='libmyspace_la-markup.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-markup.lo `test -f 'markup.c' || echo '$(srcdir)/'`markup.c
+-
+-libmyspace_la-message.lo: message.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-message.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-message.Tpo -c -o libmyspace_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-message.Tpo $(DEPDIR)/libmyspace_la-message.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='message.c' object='libmyspace_la-message.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-message.lo `test -f 'message.c' || echo '$(srcdir)/'`message.c
+-
+-libmyspace_la-myspace.lo: myspace.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-myspace.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-myspace.Tpo -c -o libmyspace_la-myspace.lo `test -f 'myspace.c' || echo '$(srcdir)/'`myspace.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-myspace.Tpo $(DEPDIR)/libmyspace_la-myspace.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='myspace.c' object='libmyspace_la-myspace.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-myspace.lo `test -f 'myspace.c' || echo '$(srcdir)/'`myspace.c
+-
+-libmyspace_la-session.lo: session.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-session.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-session.Tpo -c -o libmyspace_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-session.Tpo $(DEPDIR)/libmyspace_la-session.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='session.c' object='libmyspace_la-session.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-session.lo `test -f 'session.c' || echo '$(srcdir)/'`session.c
+-
+-libmyspace_la-user.lo: user.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-user.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-user.Tpo -c -o libmyspace_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-user.Tpo $(DEPDIR)/libmyspace_la-user.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='user.c' object='libmyspace_la-user.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-user.lo `test -f 'user.c' || echo '$(srcdir)/'`user.c
+-
+-libmyspace_la-zap.lo: zap.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -MT libmyspace_la-zap.lo -MD -MP -MF $(DEPDIR)/libmyspace_la-zap.Tpo -c -o libmyspace_la-zap.lo `test -f 'zap.c' || echo '$(srcdir)/'`zap.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libmyspace_la-zap.Tpo $(DEPDIR)/libmyspace_la-zap.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='zap.c' object='libmyspace_la-zap.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libmyspace_la_CFLAGS) $(CFLAGS) -c -o libmyspace_la-zap.lo `test -f 'zap.c' || echo '$(srcdir)/'`zap.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/myspace/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,81 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libmyspace
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libmyspace
+-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 = myspace.c message.c zap.c session.c markup.c user.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_INSTALL_DIR)
+- cp $(TARGET).dll $(DLL_INSTALL_DIR)
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-##
+-## BUILD DLL
+-##
+-$(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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/markup.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/markup.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,763 +0,0 @@
+-/* MySpaceIM Protocol Plugin - markup
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "myspace.h"
+-
+-typedef int (*MSIM_XMLNODE_CONVERT)(MsimSession *, xmlnode *, gchar **, gchar **);
+-
+-/* Globals */
+-
+-/* The names in in emoticon_names (for <i n=whatever>) map to corresponding
+- * entries in emoticon_symbols (for the ASCII representation of the emoticon).
+- *
+- * Multiple emoticon symbols in Pidgin can map to one name. List the
+- * canonical form, as inserted by the "Smile!" dialog, first. For example,
+- * :) comes before :-), because although both are recognized as 'happy',
+- * the first is inserted by the smiley button (first symbol in theme).
+- *
+- * Note that symbols are case-sensitive in Pidgin -- :-X is not :-x. */
+-static struct MSIM_EMOTICON
+-{
+- gchar *name;
+- gchar *symbol;
+-} msim_emoticons[] = {
+- /* Unfortunately, this list duplicates much of the file
+- * pidgin/pidgin/pixmaps/emotes/default/22/default.theme.in, because
+- * that file is part of Pidgin, but we're part of libpurple.
+- */
+- { "bigsmile", ":D" },
+- { "bigsmile", ":-D" },
+- { "devil", "}:)" },
+- { "frazzled", ":Z" },
+- { "geek", "B)" },
+- { "googles", "%)" },
+- { "growl", ":E" },
+- { "laugh", ":))" }, /* Must be before ':)' */
+- { "happy", ":)" },
+- { "happy", ":-)" },
+- { "happi", ":)" },
+- { "heart", ":X" },
+- { "mohawk", "-:" },
+- { "mad", "X(" },
+- { "messed", "X)" },
+- { "nerd", "Q)" },
+- { "oops", ":G" },
+- { "pirate", "P)" },
+- { "scared", ":O" },
+- { "sidefrown", ":{" },
+- { "sinister", ":B" },
+- { "smirk", ":," },
+- { "straight", ":|" },
+- { "tongue", ":P" },
+- { "tongue", ":p" },
+- { "tongy", ":P" },
+- { "upset", "B|" },
+- { "wink", ";-)" },
+- { "wink", ";)" },
+- { "winc", ";)" },
+- { "worried", ":[" },
+- { "kiss", ":x" },
+- { NULL, NULL }
+-};
+-
+-/* Indexes of this array + 1 map HTML font size to scale of normal font size. *
+- * Based on _point_sizes from libpurple/gtkimhtml.c
+- * 1 2 3 4 5 6 7 */
+-static gdouble _font_scale[] = { .85, .95, 1, 1.2, 1.44, 1.728, 2.0736 };
+-
+-/* Purple maximum font size. Equivalent to sizeof(_font_scale) / sizeof(_font_scale[0]) */
+-#define MAX_FONT_SIZE 7
+-
+-#define POINTS_PER_INCH 72 /* How many pt's in an inch */
+-
+-/* Text formatting bits for <f s=#> */
+-#define MSIM_TEXT_BOLD 1
+-#define MSIM_TEXT_ITALIC 2
+-#define MSIM_TEXT_UNDERLINE 4
+-
+-/* Default baseline size of purple's fonts, in points. What is size 3 in points.
+- * _font_scale specifies scaling factor relative to this point size. Note this
+- * is only the default; it is configurable in account options. */
+-#define MSIM_BASE_FONT_POINT_SIZE 8
+-
+-/* Default display's DPI. 96 is common but it can differ. Also configurable
+- * in account options. */
+-#define MSIM_DEFAULT_DPI 96
+-
+-/* round is part of C99, but sometimes is unavailable before then.
+- * Based on http://forums.belution.com/en/cpp/000/050/13.shtml
+- */
+-static double msim_round(double value)
+-{
+- if (value < 0) {
+- return -(floor(-value + 0.5));
+- } else {
+- return floor( value + 0.5);
+- }
+-}
+-
+-/**
+- * Convert typographical font point size to HTML font size.
+- * Based on libpurple/gtkimhtml.c
+- */
+-static guint
+-msim_point_to_purple_size(MsimSession *session, guint point)
+-{
+- guint size, this_point, base;
+-
+- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
+-
+- for (size = 0; size < MAX_FONT_SIZE; ++size) {
+- this_point = (guint)msim_round(base * _font_scale[size]);
+-
+- if (this_point >= point) {
+- purple_debug_info("msim", "msim_point_to_purple_size: %d pt -> size=%d\n",
+- point, size);
+- return size;
+- }
+- }
+-
+- /* No HTML font size was this big; return largest possible. */
+- return this_point;
+-}
+-
+-/**
+- * Convert HTML font size to point size.
+- */
+-static guint
+-msim_purple_size_to_point(MsimSession *session, guint size)
+-{
+- gdouble scale;
+- guint point;
+- guint base;
+-
+- scale = _font_scale[CLAMP(size, 1, MAX_FONT_SIZE) - 1];
+-
+- base = purple_account_get_int(session->account, "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
+-
+- point = (guint)msim_round(scale * base);
+-
+- purple_debug_info("msim", "msim_purple_size_to_point: size=%d -> %d pt\n",
+- size, point);
+-
+- return point;
+-}
+-
+-/**
+- * Convert a msim markup font pixel height to the more usual point size, for incoming messages.
+- */
+-static guint
+-msim_height_to_point(MsimSession *session, guint height)
+-{
+- guint dpi;
+-
+- dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
+-
+- return (guint)msim_round((POINTS_PER_INCH * 1. / dpi) * height);
+-
+- /* See also: libpurple/protocols/bonjour/jabber.c
+- * _font_size_ichat_to_purple */
+-}
+-
+-/**
+- * Convert point size to msim pixel height font size specification, for outgoing messages.
+- */
+-static guint
+-msim_point_to_height(MsimSession *session, guint point)
+-{
+- guint dpi;
+-
+- dpi = purple_account_get_int(session->account, "dpi", MSIM_DEFAULT_DPI);
+-
+- return (guint)msim_round((dpi * 1. / POINTS_PER_INCH) * point);
+-}
+-
+-/**
+- * Convert the msim markup <f> (font) tag into HTML.
+- */
+-static void
+-msim_markup_f_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- const gchar *face, *height_str, *decor_str;
+- GString *gs_end, *gs_begin;
+- guint decor, height;
+-
+- face = xmlnode_get_attrib(root, "f");
+- height_str = xmlnode_get_attrib(root, "h");
+- decor_str = xmlnode_get_attrib(root, "s");
+-
+- /* Validate the font face, to avoid constructing invalid HTML later */
+- if (face != NULL && strchr(face, '\'') != NULL)
+- face = NULL;
+-
+- height = height_str != NULL ? atol(height_str) : 12;
+- decor = decor_str != NULL ? atol(decor_str) : 0;
+-
+- /*
+- * The HTML we're constructing here is a bit redudant. Ideally we
+- * would use only the font-family and font-size CSS span, but Pidgin
+- * doesn't support it (it's included for other UIs). For Pidgin we
+- * wrap the whole thing in an ugly font tag, and Pidgin will happily
+- * ignore the <span>.
+- */
+- gs_begin = g_string_new("");
+- if (height && !face) {
+- guint point_size = msim_height_to_point(session, height);
+- g_string_printf(gs_begin,
+- "<font size='%d'><span style='font-size: %dpt'>",
+- msim_point_to_purple_size(session, point_size),
+- point_size);
+- } else if (height && face) {
+- guint point_size = msim_height_to_point(session, height);
+- g_string_printf(gs_begin,
+- "<font face='%s' size='%d'><span style='font-family: %s; font-size: %dpt'>",
+- face, msim_point_to_purple_size(session, point_size),
+- face, point_size);
+- } else {
+- g_string_printf(gs_begin, "<font><span>");
+- }
+-
+- gs_end = g_string_new("</span></font>");
+-
+- if (decor & MSIM_TEXT_BOLD) {
+- g_string_append(gs_begin, "<b>");
+- g_string_prepend(gs_end, "</b>");
+- }
+-
+- if (decor & MSIM_TEXT_ITALIC) {
+- g_string_append(gs_begin, "<i>");
+- g_string_append(gs_end, "</i>");
+- }
+-
+- if (decor & MSIM_TEXT_UNDERLINE) {
+- g_string_append(gs_begin, "<u>");
+- g_string_append(gs_end, "</u>");
+- }
+-
+- *begin = g_string_free(gs_begin, FALSE);
+- *end = g_string_free(gs_end, FALSE);
+-}
+-
+-/**
+- * Convert a msim markup color to a color suitable for libpurple.
+- *
+- * @param msim Either a color name, or an rgb(x,y,z) code.
+- *
+- * @return A new string, either a color name or #rrggbb code. Must g_free().
+- */
+-static char *
+-msim_color_to_purple(const char *msim)
+-{
+- guint red, green, blue;
+-
+- if (!msim) {
+- return g_strdup("black");
+- }
+-
+- if (sscanf(msim, "rgb(%d,%d,%d)", &red, &green, &blue) != 3) {
+- /* Color name. */
+- return g_strdup(msim);
+- }
+- /* TODO: rgba (alpha). */
+-
+- return g_strdup_printf("#%.2x%.2x%.2x", red, green, blue);
+-}
+-
+-/**
+- * Convert the msim markup <a> (anchor) tag into HTML.
+- */
+-static void
+-msim_markup_a_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- const gchar *href;
+-
+- href = xmlnode_get_attrib(root, "h");
+- if (!href) {
+- href = "";
+- }
+-
+- *begin = g_strdup_printf("<a href=\"%s\">%s", href, href);
+- *end = g_strdup("</a>");
+-}
+-
+-/**
+- * Convert the msim markup <p> (paragraph) tag into HTML.
+- */
+-static void
+-msim_markup_p_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- /* Just pass through unchanged.
+- *
+- * Note: attributes currently aren't passed, if there are any. */
+- *begin = g_strdup("<p>");
+- *end = g_strdup("</p>");
+-}
+-
+-/**
+- * Convert the msim markup <c> tag (text color) into HTML.
+- */
+-static void
+-msim_markup_c_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- const gchar *color;
+- gchar *purple_color;
+-
+- color = xmlnode_get_attrib(root, "v");
+- if (!color) {
+- purple_debug_info("msim", "msim_markup_c_to_html: <c> tag w/o v attr\n");
+- *begin = g_strdup("");
+- *end = g_strdup("");
+- /* TODO: log as unrecognized */
+- return;
+- }
+-
+- purple_color = msim_color_to_purple(color);
+-
+-#ifdef USE_CSS_FORMATTING
+- *begin = g_strdup_printf("<span style='color: %s'>", purple_color);
+- *end = g_strdup("</span>");
+-#else
+- *begin = g_strdup_printf("<font color='%s'>", purple_color);
+- *end = g_strdup("</font>");
+-#endif
+-
+- g_free(purple_color);
+-}
+-
+-/**
+- * Convert the msim markup <b> tag (background color) into HTML.
+- */
+-static void
+-msim_markup_b_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- const gchar *color;
+- gchar *purple_color;
+-
+- color = xmlnode_get_attrib(root, "v");
+- if (!color) {
+- *begin = g_strdup("");
+- *end = g_strdup("");
+- purple_debug_info("msim", "msim_markup_b_to_html: <b> w/o v attr\n");
+- /* TODO: log as unrecognized. */
+- return;
+- }
+-
+- purple_color = msim_color_to_purple(color);
+-
+-#ifdef USE_CSS_FORMATTING
+- *begin = g_strdup_printf("<span style='background-color: %s'>", purple_color);
+- *end = g_strdup("</span>");
+-#else
+- *begin = g_strdup_printf("<body bgcolor='%s'>", purple_color);
+- *end = g_strdup("</body>");
+-#endif
+-
+- g_free(purple_color);
+-}
+-
+-/**
+- * Convert the msim markup <i> tag (emoticon image) into HTML.
+- */
+-static void
+-msim_markup_i_to_html(MsimSession *session, xmlnode *root, gchar **begin, gchar **end)
+-{
+- const gchar *name;
+- guint i;
+- struct MSIM_EMOTICON *emote;
+-
+- name = xmlnode_get_attrib(root, "n");
+- if (!name) {
+- purple_debug_info("msim", "msim_markup_i_to_html: <i> w/o n\n");
+- *begin = g_strdup("");
+- *end = g_strdup("");
+- /* TODO: log as unrecognized */
+- return;
+- }
+-
+- /* Find and use canonical form of smiley symbol. */
+- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
+- if (g_str_equal(name, emote->name)) {
+- *begin = g_strdup(emote->symbol);
+- *end = g_strdup("");
+- return;
+- }
+- }
+-
+- /* Couldn't find it, sorry. Try to degrade gracefully. */
+- *begin = g_strdup_printf("**%s**", name);
+- *end = g_strdup("");
+-}
+-
+-/**
+- * Convert an individual msim markup tag to HTML.
+- */
+-static int
+-msim_markup_tag_to_html(MsimSession *session, xmlnode *root, gchar **begin,
+- gchar **end)
+-{
+- g_return_val_if_fail(root != NULL, 0);
+-
+- if (g_str_equal(root->name, "f")) {
+- msim_markup_f_to_html(session, root, begin, end);
+- } else if (g_str_equal(root->name, "a")) {
+- msim_markup_a_to_html(session, root, begin, end);
+- } else if (g_str_equal(root->name, "p")) {
+- msim_markup_p_to_html(session, root, begin, end);
+- } else if (g_str_equal(root->name, "c")) {
+- msim_markup_c_to_html(session, root, begin, end);
+- } else if (g_str_equal(root->name, "b")) {
+- msim_markup_b_to_html(session, root, begin, end);
+- } else if (g_str_equal(root->name, "i")) {
+- msim_markup_i_to_html(session, root, begin, end);
+- } else {
+- purple_debug_info("msim", "msim_markup_tag_to_html: "
+- "unknown tag name=%s, ignoring\n",
+- root->name ? root->name : "(NULL)");
+- *begin = g_strdup("");
+- *end = g_strdup("");
+- }
+- return 0;
+-}
+-
+-/**
+- * Convert an individual HTML tag to msim markup.
+- */
+-static int
+-html_tag_to_msim_markup(MsimSession *session, xmlnode *root, gchar **begin,
+- gchar **end)
+-{
+- int ret = 0;
+-
+- if (!purple_utf8_strcasecmp(root->name, "root") ||
+- !purple_utf8_strcasecmp(root->name, "html")) {
+- *begin = g_strdup("");
+- *end = g_strdup("");
+- /* TODO: Coalesce nested tags into one <f> tag!
+- * Currently, the 's' value will be overwritten when b/i/u is nested
+- * within another one, and only the inner-most formatting will be
+- * applied to the text. */
+- } else if (!purple_utf8_strcasecmp(root->name, "b")) {
+- if (root->child->type == XMLNODE_TYPE_DATA) {
+- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_BOLD);
+- *end = g_strdup("</f>");
+- } else {
+- if (!purple_utf8_strcasecmp(root->child->name,"i")) {
+- ret++;
+- if (root->child->child->type == XMLNODE_TYPE_DATA) {
+- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC));
+- *end = g_strdup("</f>");
+- } else {
+- if (!purple_utf8_strcasecmp(root->child->child->name,"u")) {
+- ret++;
+- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
+- *end = g_strdup("</f>");
+- }
+- }
+- } else if (!purple_utf8_strcasecmp(root->child->name,"u")) {
+- ret++;
+- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_BOLD + MSIM_TEXT_UNDERLINE));
+- *end = g_strdup("</f>");
+- }
+- }
+- } else if (!purple_utf8_strcasecmp(root->name, "i")) {
+- if (root->child->type == XMLNODE_TYPE_DATA) {
+- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_ITALIC);
+- *end = g_strdup("</f>");
+- } else {
+- if (!purple_utf8_strcasecmp(root->child->name,"u")) {
+- ret++;
+- *begin = g_strdup_printf("<f s='%d'>", (MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE));
+- *end = g_strdup("</f>");
+- }
+- }
+- } else if (!purple_utf8_strcasecmp(root->name, "u")) {
+- *begin = g_strdup_printf("<f s='%d'>", MSIM_TEXT_UNDERLINE);
+- *end = g_strdup("</f>");
+- } else if (!purple_utf8_strcasecmp(root->name, "a")) {
+- const gchar *href;
+- gchar *link_text;
+-
+- href = xmlnode_get_attrib(root, "href");
+-
+- if (!href) {
+- href = xmlnode_get_attrib(root, "HREF");
+- }
+-
+- link_text = xmlnode_get_data(root);
+-
+- if (href) {
+- if (g_str_equal(link_text, href)) {
+- /* Purple gives us: <a href="URL">URL</a>
+- * Translate to <a h='URL' />
+- * Displayed as text of URL with link to URL
+- */
+- *begin = g_strdup_printf("<a h='%s' />", href);
+- } else {
+- /* But if we get: <a href="URL">text</a>
+- * Translate to: text: <a h='URL' />
+- *
+- * Because official client only supports self-closed <a>
+- * tags; you can't change the link text.
+- */
+- *begin = g_strdup_printf("%s: <a h='%s' />", link_text, href);
+- }
+- } else {
+- *begin = g_strdup("<a />");
+- }
+-
+- /* Sorry, kid. MySpace doesn't support you within <a> tags. */
+- xmlnode_free(root->child);
+- g_free(link_text);
+- root->child = NULL;
+-
+- *end = g_strdup("");
+- } else if (!purple_utf8_strcasecmp(root->name, "font")) {
+- GString *tmpbegin, *tmpend;
+- const gchar *size;
+- const gchar *face;
+- const gchar *color;
+-
+- size = xmlnode_get_attrib(root, "size");
+- face = xmlnode_get_attrib(root, "face");
+- color = xmlnode_get_attrib(root, "color");
+-
+- tmpbegin = g_string_new("<f");
+- tmpend = g_string_new("</f>");
+-
+- if (face != NULL)
+- g_string_append_printf(tmpbegin, " f='%s'", face);
+-
+- if (size != NULL)
+- g_string_append_printf(tmpbegin, " h='%d'",
+- msim_point_to_height(session,
+- msim_purple_size_to_point(session, atoi(size))));
+-
+- /* Close the <f> tag */
+- g_string_append(tmpbegin, ">");
+-
+- if (color != NULL) {
+- g_string_append_printf(tmpbegin, "<c v='%s'>", color);
+- g_string_prepend(tmpend, "</c>");
+- }
+-
+- *begin = g_string_free(tmpbegin, FALSE);
+- *end = g_string_free(tmpend, FALSE);
+-
+- } else if (!purple_utf8_strcasecmp(root->name, "body")) {
+- const gchar *bgcolor;
+-
+- bgcolor = xmlnode_get_attrib(root, "bgcolor");
+-
+- if (bgcolor != NULL) {
+- *begin = g_strdup_printf("<b v='%s'>", bgcolor);
+- *end = g_strdup("</b>");
+- }
+-
+- } else {
+- gchar *err;
+-
+-#ifdef MSIM_MARKUP_SHOW_UNKNOWN_TAGS
+- *begin = g_strdup_printf("[%s]", root->name);
+- *end = g_strdup_printf("[/%s]", root->name);
+-#else
+- *begin = g_strdup("");
+- *end = g_strdup("");
+-#endif
+-
+- err = g_strdup_printf("html_tag_to_msim_markup: unrecognized "
+- "HTML tag %s was sent by the IM client; ignoring",
+- root->name ? root->name : "(NULL)");
+- msim_unrecognized(NULL, NULL, err);
+- g_free(err);
+- }
+- return ret;
+-}
+-
+-/**
+- * Convert an xmlnode of msim markup or HTML to an HTML string or msim markup.
+- *
+- * @param f Function to convert tags.
+- *
+- * @return An HTML string. Caller frees.
+- */
+-static void
+-msim_convert_xmlnode(MsimSession *session, GString *out, xmlnode *root, MSIM_XMLNODE_CONVERT f, int nodes_processed)
+-{
+- xmlnode *node;
+- gchar *begin, *end, *tmp;
+- int descended = nodes_processed;
+-
+- if (!root || !root->name)
+- return;
+-
+- purple_debug_info("msim", "msim_convert_xmlnode: got root=%s\n",
+- root->name);
+-
+- begin = end = NULL;
+-
+- if (descended == 0) /* We've not formatted this yet.. :) */
+- descended = f(session, root, &begin, &end); /* Get the value that our format function has already descended for us */
+-
+- g_string_append(out, begin);
+- g_free(begin);
+-
+- /* Loop over all child nodes. */
+- for (node = root->child; node != NULL; node = node->next) {
+- switch (node->type) {
+- case XMLNODE_TYPE_ATTRIB:
+- /* Attributes handled above. */
+- break;
+-
+- case XMLNODE_TYPE_TAG:
+- /* A tag or tag with attributes. Recursively descend. */
+- msim_convert_xmlnode(session, out, node, f, descended);
+-
+- purple_debug_info("msim", " ** node name=%s\n",
+- node->name ? node->name : "(NULL)");
+- break;
+-
+- case XMLNODE_TYPE_DATA:
+- /* Literal text. */
+- /*
+- * TODO: Why is it necessary to escape here? I thought
+- * node->data was already escaped?
+- */
+- tmp = g_markup_escape_text(node->data, node->data_sz);
+- g_string_append(out, tmp);
+- g_free(tmp);
+- break;
+-
+- default:
+- purple_debug_warning("msim",
+- "msim_convert_xmlnode: unknown node type\n");
+- }
+- }
+-
+- /* TODO: Note that msim counts each piece of text enclosed by <f> as
+- * a paragraph and will display each on its own line. You actually have
+- * to _nest_ <f> tags to intersperse different text in one paragraph!
+- * Comment out this line below to see. */
+- g_string_append(out, end);
+- g_free(end);
+-}
+-
+-/**
+- * Convert XML to something based on MSIM_XMLNODE_CONVERT.
+- */
+-static gchar *
+-msim_convert_xml(MsimSession *session, const gchar *raw, MSIM_XMLNODE_CONVERT f)
+-{
+- xmlnode *root;
+- GString *str;
+- gchar *enclosed_raw;
+-
+- g_return_val_if_fail(raw != NULL, NULL);
+-
+- /* Enclose text in one root tag, to try to make it valid XML for parsing. */
+- enclosed_raw = g_strconcat("<root>", raw, "</root>", NULL);
+-
+- root = xmlnode_from_str(enclosed_raw, -1);
+-
+- if (!root) {
+- purple_debug_warning("msim", "msim_markup_to_html: couldn't parse "
+- "%s as XML, returning raw: %s\n", enclosed_raw, raw);
+- /* TODO: msim_unrecognized */
+- g_free(enclosed_raw);
+- return g_strdup(raw);
+- }
+-
+- g_free(enclosed_raw);
+-
+- str = g_string_new(NULL);
+- msim_convert_xmlnode(session, str, root, f, 0);
+- xmlnode_free(root);
+-
+- purple_debug_info("msim", "msim_markup_to_html: returning %s\n", str->str);
+-
+- return g_string_free(str, FALSE);
+-}
+-
+-/**
+- * Convert plaintext smileys to <i> markup tags.
+- *
+- * @param before Original text with ASCII smileys. Will be freed.
+- * @return A new string with <i> tags, if applicable. Must be g_free()'d.
+- */
+-static gchar *
+-msim_convert_smileys_to_markup(gchar *before)
+-{
+- gchar *old, *new, *replacement;
+- guint i;
+- struct MSIM_EMOTICON *emote;
+-
+- old = before;
+- new = NULL;
+-
+- for (i = 0; (emote = &msim_emoticons[i]) && emote->name != NULL; ++i) {
+- gchar *name, *symbol;
+-
+- name = emote->name;
+- symbol = emote->symbol;
+-
+- replacement = g_strdup_printf("<i n=\"%s\"/>", name);
+-
+- purple_debug_info("msim", "msim_convert_smileys_to_markup: %s->%s\n",
+- symbol ? symbol : "(NULL)",
+- replacement ? replacement : "(NULL)");
+- new = purple_strreplace(old, symbol, replacement);
+-
+- g_free(replacement);
+- g_free(old);
+-
+- old = new;
+- }
+-
+- return new;
+-}
+-
+-/**
+- * High-level function to convert MySpaceIM markup to Purple (HTML) markup.
+- *
+- * @return Purple markup string, must be g_free()'d. */
+-gchar *
+-msim_markup_to_html(MsimSession *session, const gchar *raw)
+-{
+- return msim_convert_xml(session, raw, msim_markup_tag_to_html);
+-}
+-
+-/**
+- * High-level function to convert Purple (HTML) to MySpaceIM markup.
+- *
+- * TODO: consider using purple_markup_html_to_xhtml() to make valid XML.
+- *
+- * @return HTML markup string, must be g_free()'d. */
+-gchar *
+-html_to_msim_markup(MsimSession *session, const gchar *raw)
+-{
+- gchar *markup;
+-
+- markup = msim_convert_xml(session, raw, html_tag_to_msim_markup);
+-
+- if (purple_account_get_bool(session->account, "emoticons", TRUE)) {
+- /* Frees markup and allocates a new one. */
+- markup = msim_convert_smileys_to_markup(markup);
+- }
+-
+- return markup;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/markup.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/markup.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/markup.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-/* MySpaceIM Protocol Plugin - markup
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_MARKUP_H
+-#define _MYSPACE_MARKUP_H
+-
+-/* High-level msim markup <=> Purple html conversion functions. */
+-gchar *msim_markup_to_html(MsimSession *, const gchar *raw);
+-gchar *html_to_msim_markup(MsimSession *, const gchar *raw);
+-
+-#endif /* !_MYSPACE_MARKUP_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/message.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/message.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1413 +0,0 @@
+-/** MySpaceIM protocol messages
+- *
+- * \author Jeff Connelly
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "myspace.h"
+-#include "message.h"
+-
+-static void msim_msg_debug_string_element(gpointer data, gpointer user_data);
+-
+-/**
+- * Escape codes and associated replacement text, used for protocol message
+- * escaping and unescaping.
+- */
+-static struct MSIM_ESCAPE_REPLACEMENT {
+- gchar *code;
+- gchar text;
+-} msim_escape_replacements[] = {
+- { "/1", '/' },
+- { "/2", '\\' },
+- /* { "/3", "|" }, */ /* Not used here -- only for within arrays */
+- { NULL, 0 }
+-};
+-
+-/**
+- * Escape a protocol message.
+- *
+- * @return The escaped message. Caller must g_free().
+- */
+-gchar *
+-msim_escape(const gchar *msg)
+-{
+- GString *gs;
+- guint i, j;
+- guint msg_len;
+-
+- gs = g_string_new("");
+- msg_len = strlen(msg);
+-
+- for (i = 0; i < msg_len; ++i) {
+- struct MSIM_ESCAPE_REPLACEMENT *replacement;
+- gchar *replace;
+-
+- replace = NULL;
+-
+- /* Check for characters that need to be escaped, and escape them. */
+- for (j = 0; (replacement = &msim_escape_replacements[j]) &&
+- replacement->code != NULL; ++j) {
+- if (msg[i] == replacement->text) {
+- replace = replacement->code;
+- break;
+- }
+- }
+-
+- if (replace) {
+- g_string_append(gs, replace);
+- } else {
+- g_string_append_c(gs, msg[i]);
+- }
+- }
+-
+-#ifdef MSIM_DEBUG_ESCAPE
+- purple_debug_info("msim", "msim_escape: msg=%s, ret=%s\n", msg, gs->str);
+-#endif
+-
+- return g_string_free(gs, FALSE);
+-}
+-
+-/**
+- * Unescape a protocol message.
+- *
+- * @return The unescaped message, caller must g_free().
+- */
+-gchar *
+-msim_unescape(const gchar *msg)
+-{
+- GString *gs;
+- guint i, j;
+- guint msg_len;
+-
+- gs = g_string_new("");
+- msg_len = strlen(msg);
+-
+- for (i = 0; i < msg_len; ++i) {
+- struct MSIM_ESCAPE_REPLACEMENT *replacement;
+- gchar replace;
+-
+- replace = msg[i];
+-
+- for (j = 0; (replacement = &msim_escape_replacements[j]) &&
+- replacement->code != NULL; ++j) {
+- if (msg[i] == replacement->code[0] &&
+- i + 1 < msg_len &&
+- msg[i + 1] == replacement->code[1]) {
+- replace = replacement->text;
+- ++i;
+- break;
+- }
+- }
+-
+- g_string_append_c(gs, replace);
+- }
+-
+-#ifdef MSIM_DEBUG_ESCAPE
+- purple_debug_info("msim", "msim_unescape: msg=%s, ret=%s\n", msg, gs->str);
+-#endif
+-
+- return g_string_free(gs, FALSE);
+-}
+-
+-/**
+- * Create a new message from va_list and its first argument.
+- *
+- * @param first_key The first argument (a key), or NULL to take all arguments
+- * from argp.
+- * @param argp A va_list of variadic arguments, already started with va_start().
+- * @return New MsimMessage *, must be freed with msim_msg_free().
+- *
+- * For internal use - users probably want msim_msg_new() or msim_send().
+- */
+-static MsimMessage *
+-msim_msg_new_v(gchar *first_key, va_list argp)
+-{
+- gchar *key, *value;
+- MsimMessageType type;
+- MsimMessage *msg;
+- gboolean first;
+-
+- GString *gs;
+- GList *gl;
+- MsimMessage *dict;
+-
+- /* Begin with an empty message. */
+- msg = NULL;
+-
+- /* First parameter can be given explicitly. */
+- first = first_key != NULL;
+-
+- /* Read key, type, value triplets until NULL. */
+- do {
+- if (first) {
+- key = first_key;
+- first = FALSE;
+- } else {
+- key = va_arg(argp, gchar *);
+- if (!key) {
+- break;
+- }
+- }
+-
+- type = va_arg(argp, int);
+-
+- /* Interpret variadic arguments. */
+- switch (type) {
+- case MSIM_TYPE_INTEGER:
+- case MSIM_TYPE_BOOLEAN:
+- msg = msim_msg_append(msg, key, type, GUINT_TO_POINTER(va_arg(argp, int)));
+- break;
+-
+- case MSIM_TYPE_STRING:
+- value = va_arg(argp, char *);
+-
+- g_return_val_if_fail(value != NULL, FALSE);
+-
+- msg = msim_msg_append(msg, key, type, value);
+- break;
+-
+- case MSIM_TYPE_BINARY:
+- gs = va_arg(argp, GString *);
+-
+- g_return_val_if_fail(gs != NULL, FALSE);
+-
+- /* msim_msg_free() will free this GString the caller created. */
+- msg = msim_msg_append(msg, key, type, gs);
+- break;
+-
+- case MSIM_TYPE_LIST:
+- gl = va_arg(argp, GList *);
+-
+- g_return_val_if_fail(gl != NULL, FALSE);
+-
+- msg = msim_msg_append(msg, key, type, gl);
+- break;
+-
+- case MSIM_TYPE_DICTIONARY:
+- dict = va_arg(argp, MsimMessage *);
+-
+- g_return_val_if_fail(dict != NULL, FALSE);
+-
+- msg = msim_msg_append(msg, key, type, dict);
+- break;
+-
+- default:
+- purple_debug_info("msim", "msim_send: unknown type %d\n", type);
+- break;
+- }
+- } while(key);
+-
+- return msg;
+-}
+-
+-/**
+- * Create a new MsimMessage.
+- *
+- * @param first_key The first key in the sequence, or NULL for an empty message.
+- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
+- *
+- * See msim_msg_append() documentation for details on types.
+- */
+-MsimMessage *
+-msim_msg_new(gchar *first_key, ...)
+-{
+- MsimMessage *ret = NULL;
+- va_list argp;
+-
+- if (first_key) {
+- va_start(argp, first_key);
+- ret = msim_msg_new_v(first_key, argp);
+- va_end(argp);
+- }
+-
+- return ret;
+-}
+-
+-/**
+- * Pack a string using the given GFunc and seperator.
+- * Used by msim_msg_dump() and msim_msg_pack().
+- */
+-static gchar *
+-msim_msg_pack_using(MsimMessage *msg,
+- GFunc gf,
+- const gchar *sep,
+- const gchar *begin, const gchar *end)
+-{
+- int num_items;
+- gchar **strings;
+- gchar **strings_tmp;
+- gchar *joined;
+- gchar *final;
+- int i;
+-
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- num_items = g_list_length(msg);
+-
+- /* Add one for NULL terminator for g_strjoinv(). */
+- strings = (gchar **)g_new0(gchar *, num_items + 1);
+-
+- strings_tmp = strings;
+- g_list_foreach(msg, gf, &strings_tmp);
+-
+- joined = g_strjoinv(sep, strings);
+- final = g_strconcat(begin, joined, end, NULL);
+- g_free(joined);
+-
+- /* Clean up. */
+- for (i = 0; i < num_items; ++i) {
+- g_free(strings[i]);
+- }
+-
+- g_free(strings);
+-
+- return final;
+-}
+-
+-/**
+- * Return a human-readable string of the message.
+- *
+- * @return A new gchar *, must be g_free()'d.
+- */
+-static gchar *
+-msim_msg_dump_to_str(MsimMessage *msg)
+-{
+- gchar *debug_str;
+-
+- if (!msg) {
+- debug_str = g_strdup("<MsimMessage: empty>");
+- } else {
+- debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element,
+- "\n", "<MsimMessage: \n", "\n/MsimMessage>");
+- }
+-
+- return debug_str;
+-}
+-
+-/**
+- * Store a human-readable string describing the element.
+- *
+- * @param data Pointer to an MsimMessageElement.
+- * @param user_data
+- */
+-static void
+-msim_msg_debug_string_element(gpointer data, gpointer user_data)
+-{
+- MsimMessageElement *elem;
+- gchar *string;
+- GString *gs;
+- gchar *binary;
+- gchar ***items; /* wow, a pointer to a pointer to a pointer */
+-
+- gchar *s;
+- GList *gl;
+- guint i;
+-
+- elem = (MsimMessageElement *)data;
+- items = user_data;
+-
+- switch (elem->type) {
+- case MSIM_TYPE_INTEGER:
+- string = g_strdup_printf("%s(integer): %d", elem->name,
+- GPOINTER_TO_UINT(elem->data));
+- break;
+-
+- case MSIM_TYPE_RAW:
+- string = g_strdup_printf("%s(raw): %s", elem->name,
+- elem->data ? (gchar *)elem->data : "(NULL)");
+- break;
+-
+- case MSIM_TYPE_STRING:
+- string = g_strdup_printf("%s(string): %s", elem->name,
+- elem->data ? (gchar *)elem->data : "(NULL)");
+- break;
+-
+- case MSIM_TYPE_BINARY:
+- gs = (GString *)elem->data;
+- binary = purple_base64_encode((guchar*)gs->str, gs->len);
+- string = g_strdup_printf("%s(binary, %d bytes): %s", elem->name, (int)gs->len, binary);
+- g_free(binary);
+- break;
+-
+- case MSIM_TYPE_BOOLEAN:
+- string = g_strdup_printf("%s(boolean): %s", elem->name,
+- elem->data ? "TRUE" : "FALSE");
+- break;
+-
+- case MSIM_TYPE_DICTIONARY:
+- if (!elem->data) {
+- s = g_strdup("(NULL)");
+- } else {
+- s = msim_msg_dump_to_str((MsimMessage *)elem->data);
+- }
+-
+- if (!s) {
+- s = g_strdup("(NULL, couldn't msim_msg_dump_to_str)");
+- }
+-
+- string = g_strdup_printf("%s(dict): %s", elem->name, s);
+-
+- g_free(s);
+- break;
+-
+- case MSIM_TYPE_LIST:
+- gs = g_string_new("");
+- g_string_append_printf(gs, "%s(list): \n", elem->name);
+-
+- i = 0;
+- for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
+- g_string_append_printf(gs, " %d. %s\n", i, (gchar *)(gl->data));
+- ++i;
+- }
+-
+- string = g_string_free(gs, FALSE);
+- break;
+-
+- default:
+- string = g_strdup_printf("%s(unknown type %d",
+- elem->name ? elem->name : "(NULL)", elem->type);
+- break;
+- }
+-
+- **items = string;
+- ++(*items);
+-}
+-
+-/**
+- * Search for and return the node in msg, matching name, or NULL.
+- *
+- * @param msg Message to search within.
+- * @param name Field name to search for.
+- *
+- * @return The GList * node for the MsimMessageElement with the given name, or NULL if not found or name is NULL.
+- *
+- * For internal use - users probably want to use msim_msg_get() to
+- * access the MsimMessageElement *, instead of the GList * container.
+- *
+- */
+-static GList *
+-msim_msg_get_node(const MsimMessage *msg, const gchar *name)
+-{
+- GList *node;
+-
+- if (!name || !msg) {
+- return NULL;
+- }
+-
+- /* Linear search for the given name. O(n) but n is small. */
+- for (node = (GList*)msg; node != NULL; node = g_list_next(node)) {
+- MsimMessageElement *elem;
+-
+- elem = (MsimMessageElement *)node->data;
+-
+- g_return_val_if_fail(elem != NULL, NULL);
+- g_return_val_if_fail(elem->name != NULL, NULL);
+-
+- if (strcmp(elem->name, name) == 0) {
+- return node;
+- }
+- }
+- return NULL;
+-}
+-
+-/**
+- * Create a new MsimMessageElement * - must be g_free()'d.
+- *
+- * For internal use; users probably want msim_msg_append() or msim_msg_insert_before().
+- *
+- * @param dynamic_name Whether 'name' should be freed when the message is destroyed.
+- */
+-static MsimMessageElement *
+-msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data, gboolean dynamic_name)
+-{
+- MsimMessageElement *elem;
+-
+- elem = g_new0(MsimMessageElement, 1);
+-
+- elem->name = name;
+- elem->dynamic_name = dynamic_name;
+- elem->type = type;
+- elem->data = data;
+-
+- return elem;
+-}
+-
+-/**
+- * Append a new element to a message.
+- *
+- * @param name Textual name of element (static string, neither copied nor freed).
+- * @param type An MSIM_TYPE_* code.
+- * @param data Pointer to data, see below.
+- *
+- * @return The new message - must be assigned to as with GList*. For example:
+- *
+- * msg = msim_msg_append(msg, ...)
+- *
+- * The data parameter depends on the type given:
+- *
+- * * MSIM_TYPE_INTEGER: Use GUINT_TO_POINTER(x).
+- *
+- * * MSIM_TYPE_BINARY: Same as integer, non-zero is TRUE and zero is FALSE.
+- *
+- * * MSIM_TYPE_STRING: gchar *. The data WILL BE FREED - use g_strdup() if needed.
+- *
+- * * MSIM_TYPE_RAW: gchar *. The data WILL BE FREED - use g_strdup() if needed.
+- *
+- * * MSIM_TYPE_BINARY: g_string_new_len(data, length). The data AND GString will be freed.
+- *
+- * * MSIM_TYPE_DICTIONARY: An MsimMessage *. Freed when message is destroyed.
+- *
+- * * MSIM_TYPE_LIST: GList * of gchar *. Again, everything will be freed.
+- *
+- * */
+-MsimMessage *
+-msim_msg_append(MsimMessage *msg, const gchar *name,
+- MsimMessageType type, gpointer data)
+-{
+- return g_list_append(msg, msim_msg_element_new(name, type, data, FALSE));
+-}
+-
+-/**
+- * Append a new element, but with a dynamically-allocated name.
+- * Exactly the same as msim_msg_append(), except 'name' will be freed when
+- * the message is destroyed. Normally, it isn't, because a static string is given.
+- */
+-static MsimMessage *
+-msim_msg_append_dynamic_name(MsimMessage *msg, gchar *name,
+- MsimMessageType type, gpointer data)
+-{
+- return g_list_append(msg, msim_msg_element_new(name, type, data, TRUE));
+-}
+-
+-/**
+- * Insert a new element into a message, before the given element name.
+- *
+- * @param name_before Name of the element to insert the new element before. If
+- * could not be found or NULL, new element will be inserted at end.
+- *
+- * See msim_msg_append() for usage of other parameters, and an important note about return value.
+- */
+-MsimMessage *
+-msim_msg_insert_before(MsimMessage *msg, const gchar *name_before,
+- const gchar *name, MsimMessageType type, gpointer data)
+-{
+- MsimMessageElement *new_elem;
+- GList *node_before;
+-
+- new_elem = msim_msg_element_new(name, type, data, FALSE);
+-
+- node_before = msim_msg_get_node(msg, name_before);
+-
+- return g_list_insert_before(msg, node_before, new_elem);
+-}
+-
+-/**
+- * Perform a deep copy on a GList * of gchar * strings. Free with msim_msg_list_free().
+- */
+-static GList *
+-msim_msg_list_copy(const GList *old)
+-{
+- GList *new_list;
+-
+- new_list = NULL;
+-
+- /* Deep copy (g_list_copy is shallow). Copy each string. */
+- for (; old != NULL; old = g_list_next(old)) {
+- new_list = g_list_append(new_list, g_strdup(old->data));
+- }
+-
+- return new_list;
+-}
+-
+-/**
+- * Clone an individual element.
+- *
+- * @param data MsimMessageElement * to clone.
+- * @param user_data Pointer to MsimMessage * to add cloned element to.
+- */
+-static void
+-msim_msg_clone_element(gpointer data, gpointer user_data)
+-{
+- MsimMessageElement *elem;
+- MsimMessage **new;
+- gpointer new_data;
+-
+- GString *gs;
+- MsimMessage *dict;
+-
+- elem = (MsimMessageElement *)data;
+- new = (MsimMessage **)user_data;
+-
+- switch (elem->type) {
+- case MSIM_TYPE_BOOLEAN:
+- case MSIM_TYPE_INTEGER:
+- new_data = elem->data;
+- break;
+-
+- case MSIM_TYPE_RAW:
+- case MSIM_TYPE_STRING:
+- new_data = g_strdup((gchar *)elem->data);
+- break;
+-
+- case MSIM_TYPE_LIST:
+- new_data = (gpointer)msim_msg_list_copy((GList *)(elem->data));
+- break;
+-
+- case MSIM_TYPE_BINARY:
+- gs = (GString *)elem->data;
+-
+- new_data = g_string_new_len(gs->str, gs->len);
+- break;
+- case MSIM_TYPE_DICTIONARY:
+- dict = (MsimMessage *)elem->data;
+-
+- new_data = msim_msg_clone(dict);
+- break;
+-
+- default:
+- purple_debug_info("msim", "msim_msg_clone_element: unknown type %d\n", elem->type);
+- g_return_if_reached();
+- }
+-
+- /* Append cloned data. Note that the 'name' field is a static string, so it
+- * never needs to be copied nor freed. */
+- if (elem->dynamic_name)
+- *new = msim_msg_append_dynamic_name(*new, g_strdup(elem->name), elem->type, new_data);
+- else
+- *new = msim_msg_append(*new, elem->name, elem->type, new_data);
+-}
+-
+-/**
+- * Clone an existing MsimMessage.
+- *
+- * @return Cloned message; caller should free with msim_msg_free().
+- */
+-MsimMessage *
+-msim_msg_clone(MsimMessage *old)
+-{
+- MsimMessage *new;
+-
+- if (old == NULL) {
+- return NULL;
+- }
+-
+- new = msim_msg_new(FALSE);
+-
+- g_list_foreach(old, msim_msg_clone_element, &new);
+-
+- return new;
+-}
+-
+-/**
+- * Free the data of a message element.
+- *
+- * @param elem The MsimMessageElement *
+- *
+- * Note this only frees the element data; you may also want to free the
+- * element itself with g_free() (see msim_msg_free_element()).
+- */
+-void
+-msim_msg_free_element_data(MsimMessageElement *elem)
+-{
+- switch (elem->type) {
+- case MSIM_TYPE_BOOLEAN:
+- case MSIM_TYPE_INTEGER:
+- /* Integer value stored in gpointer - no need to free(). */
+- break;
+-
+- case MSIM_TYPE_RAW:
+- case MSIM_TYPE_STRING:
+- /* Always free strings - caller should have g_strdup()'d if
+- * string was static or temporary and not to be freed. */
+- g_free(elem->data);
+- break;
+-
+- case MSIM_TYPE_BINARY:
+- /* Free the GString itself and the binary data. */
+- g_string_free((GString *)elem->data, TRUE);
+- break;
+-
+- case MSIM_TYPE_DICTIONARY:
+- msim_msg_free((MsimMessage *)elem->data);
+- break;
+-
+- case MSIM_TYPE_LIST:
+- g_list_free((GList *)elem->data);
+- break;
+-
+- default:
+- purple_debug_info("msim", "msim_msg_free_element_data: "
+- "not freeing unknown type %d\n", elem->type);
+- break;
+- }
+-}
+-
+-/**
+- * Free a GList * of MsimMessageElement *'s.
+- */
+-void
+-msim_msg_list_free(GList *l)
+-{
+-
+- for (; l != NULL; l = g_list_next(l)) {
+- MsimMessageElement *elem;
+-
+- elem = (MsimMessageElement *)l->data;
+-
+- /* Note that name is almost never dynamically allocated elsewhere;
+- * it is usually a static string, but not in lists. So cast it. */
+- g_free((gchar *)elem->name);
+- g_free(elem->data);
+- g_free(elem);
+- }
+- g_list_free(l);
+-}
+-
+-/**
+- * Free an individual message element.
+- *
+- * @param data MsimMessageElement * to free.
+- * @param user_data Not used; required to match g_list_foreach() callback prototype.
+- *
+- * Frees both the element data and the element itself.
+- * Also frees the name if dynamic_name is TRUE.
+- */
+-static void
+-msim_msg_free_element(gpointer data, gpointer user_data)
+-{
+- MsimMessageElement *elem;
+-
+- elem = (MsimMessageElement *)data;
+-
+- msim_msg_free_element_data(elem);
+-
+- if (elem->dynamic_name)
+- /* Need to cast to remove const-ness, because
+- * elem->name is almost always a constant, static
+- * string, but not in this case. */
+- g_free((gchar *)elem->name);
+-
+- g_free(elem);
+-}
+-
+-/**
+- * Free a complete message.
+- */
+-void
+-msim_msg_free(MsimMessage *msg)
+-{
+- if (!msg) {
+- /* already free as can be */
+- return;
+- }
+-
+- g_list_foreach(msg, msim_msg_free_element, NULL);
+- g_list_free(msg);
+-}
+-
+-/**
+- * Pack an element into its protocol representation.
+- *
+- * @param data Pointer to an MsimMessageElement.
+- * @param user_data Pointer to a gchar ** array of string items.
+- *
+- * Called by msim_msg_pack(). Will pack the MsimMessageElement into
+- * a part of the protocol string and append it to the array. Caller
+- * is responsible for creating array to correct dimensions, and
+- * freeing each string element of the array added by this function.
+- */
+-static void
+-msim_msg_pack_element(gpointer data, gpointer user_data)
+-{
+- MsimMessageElement *elem;
+- gchar *string, *data_string;
+- gchar ***items;
+-
+- elem = (MsimMessageElement *)data;
+- items = (gchar ***)user_data;
+-
+- /* Exclude elements beginning with '_' from packed protocol messages. */
+- if (elem->name[0] == '_') {
+- return;
+- }
+-
+- data_string = msim_msg_pack_element_data(elem);
+-
+- switch (elem->type) {
+- /* These types are represented by key name/value pairs (converted above). */
+- case MSIM_TYPE_INTEGER:
+- case MSIM_TYPE_RAW:
+- case MSIM_TYPE_STRING:
+- case MSIM_TYPE_BINARY:
+- case MSIM_TYPE_DICTIONARY:
+- case MSIM_TYPE_LIST:
+- string = g_strconcat(elem->name, "\\", data_string, NULL);
+- break;
+-
+- /* Boolean is represented by absence or presence of name. */
+- case MSIM_TYPE_BOOLEAN:
+- if (GPOINTER_TO_UINT(elem->data)) {
+- /* True - leave in, with blank value. */
+- string = g_strdup_printf("%s\\", elem->name);
+- } else {
+- /* False - leave out. */
+- string = g_strdup("");
+- }
+- break;
+-
+- default:
+- g_free(data_string);
+- g_return_if_reached();
+- break;
+- }
+-
+- g_free(data_string);
+-
+- **items = string;
+- ++(*items);
+-}
+-
+-/**
+- * Pack an element into its protcol representation inside a dictionary.
+- *
+- * See msim_msg_pack_element().
+- */
+-static void
+-msim_msg_pack_element_dict(gpointer data, gpointer user_data)
+-{
+- MsimMessageElement *elem;
+- gchar *string, *data_string, ***items;
+-
+- elem = (MsimMessageElement *)data;
+- items = (gchar ***)user_data;
+-
+- /* Exclude elements beginning with '_' from packed protocol messages. */
+- if (elem->name[0] == '_') {
+- return;
+- }
+-
+- data_string = msim_msg_pack_element_data(elem);
+-
+- g_return_if_fail(data_string != NULL);
+-
+- switch (elem->type) {
+- /* These types are represented by key name/value pairs (converted above). */
+- case MSIM_TYPE_INTEGER:
+- case MSIM_TYPE_RAW:
+- case MSIM_TYPE_STRING:
+- case MSIM_TYPE_BINARY:
+- case MSIM_TYPE_DICTIONARY:
+- case MSIM_TYPE_LIST:
+- case MSIM_TYPE_BOOLEAN: /* Boolean is On or Off */
+- string = g_strconcat(elem->name, "=", data_string, NULL);
+- break;
+-
+- default:
+- g_free(data_string);
+- g_return_if_fail(FALSE);
+- break;
+- }
+-
+- g_free(data_string);
+-
+- **items = string;
+- ++(*items);
+-}
+-
+-/**
+- * Return a packed string of a message suitable for sending over the wire.
+- *
+- * @return A string. Caller must g_free().
+- */
+-gchar *
+-msim_msg_pack(MsimMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- return msim_msg_pack_using(msg, msim_msg_pack_element, "\\", "\\", "\\final\\");
+-}
+-
+-/**
+- * Return a packed string of a dictionary, suitable for embedding in MSIM_TYPE_DICTIONARY.
+- *
+- * @return A string; caller must g_free().
+- */
+-static gchar *
+-msim_msg_pack_dict(MsimMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, NULL);
+-
+- return msim_msg_pack_using(msg, msim_msg_pack_element_dict, "\034", "", "");
+-}
+-
+-/**
+- * Send an existing MsimMessage.
+- */
+-gboolean
+-msim_msg_send(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *raw;
+- gboolean success;
+-
+- raw = msim_msg_pack(msg);
+- g_return_val_if_fail(raw != NULL, FALSE);
+- success = msim_send_raw(session, raw);
+- g_free(raw);
+-
+- return success;
+-}
+-
+-/**
+- * Return a message element data as a new string for a raw protocol message,
+- * converting from other types (integer, etc.) if necessary.
+- *
+- * @return const gchar * The data as a string, or NULL. Caller must g_free().
+- *
+- * Returns a string suitable for inclusion in a raw protocol message, not necessarily
+- * optimal for human consumption. For example, strings are escaped. Use
+- * msim_msg_get_string() if you want a string, which in some cases is same as this.
+- */
+-gchar *
+-msim_msg_pack_element_data(MsimMessageElement *elem)
+-{
+- GString *gs;
+- GList *gl;
+-
+- g_return_val_if_fail(elem != NULL, NULL);
+-
+- switch (elem->type) {
+- case MSIM_TYPE_INTEGER:
+- return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
+-
+- case MSIM_TYPE_RAW:
+- /* Not un-escaped - this is a raw element, already escaped if necessary. */
+- return (gchar *)g_strdup((gchar *)elem->data);
+-
+- case MSIM_TYPE_STRING:
+- /* Strings get escaped. msim_escape() creates a new string. */
+- g_return_val_if_fail(elem->data != NULL, NULL);
+- return elem->data ? msim_escape((gchar *)elem->data) :
+- g_strdup("(NULL)");
+-
+- case MSIM_TYPE_BINARY:
+- gs = (GString *)elem->data;
+- /* Do not escape! */
+- return purple_base64_encode((guchar *)gs->str, gs->len);
+-
+- case MSIM_TYPE_BOOLEAN:
+- /* Not used by messages in the wire protocol * -- see msim_msg_pack_element.
+- * Only used by dictionaries, see msim_msg_pack_element_dict. */
+- return elem->data ? g_strdup("On") : g_strdup("Off");
+-
+- case MSIM_TYPE_DICTIONARY:
+- return msim_msg_pack_dict((MsimMessage *)elem->data);
+-
+- case MSIM_TYPE_LIST:
+- /* Pack using a|b|c|d|... */
+- gs = g_string_new("");
+-
+- for (gl = (GList *)elem->data; gl != NULL; gl = g_list_next(gl)) {
+- g_string_append_printf(gs, "%s", (gchar*)(gl->data));
+-
+- /* All but last element is separated by a bar. */
+- if (g_list_next(gl))
+- g_string_append(gs, "|");
+- }
+-
+- return g_string_free(gs, FALSE);
+-
+- default:
+- purple_debug_info("msim", "field %s, unknown type %d\n",
+- elem->name ? elem->name : "(NULL)",
+- elem->type);
+- return NULL;
+- }
+-}
+-
+-/**
+- * Send a message to the server, whose contents is specified using
+- * variable arguments.
+- *
+- * @param session
+- * @param ... A sequence of gchar* key/type/value triplets, terminated with NULL.
+- *
+- * This function exists for coding convenience: it allows a message to be created
+- * and sent in one line of code. Internally it calls msim_msg_send().
+- *
+- * IMPORTANT: See msim_msg_append() documentation for details on element types.
+- *
+- */
+-gboolean
+-msim_send(MsimSession *session, ...)
+-{
+- gboolean success;
+- MsimMessage *msg;
+- va_list argp;
+-
+- va_start(argp, session);
+- msg = msim_msg_new_v(NULL, argp);
+- va_end(argp);
+-
+- /* Actually send the message. */
+- success = msim_msg_send(session, msg);
+-
+- /* Cleanup. */
+- msim_msg_free(msg);
+-
+- return success;
+-}
+-
+-/**
+- * Print a human-readable string of the message to Purple's debug log.
+- *
+- * @param fmt_string A static string, in which '%s' will be replaced.
+- */
+-void
+-msim_msg_dump(const gchar *fmt_string, MsimMessage *msg)
+-{
+- gchar *debug_str;
+-
+- g_return_if_fail(fmt_string != NULL);
+-
+- debug_str = msim_msg_dump_to_str(msg);
+-
+- g_return_if_fail(debug_str != NULL);
+-
+- purple_debug_info("msim", fmt_string, debug_str);
+-
+- g_free(debug_str);
+-}
+-
+-/**
+- * Parse a raw protocol message string into a MsimMessage *.
+- *
+- * @param raw The raw message string to parse, will be g_free()'d.
+- *
+- * @return MsimMessage *. Caller should msim_msg_free() when done.
+- */
+-MsimMessage *
+-msim_parse(const gchar *raw)
+-{
+- MsimMessage *msg;
+- gchar *token;
+- gchar **tokens;
+- gchar *key;
+- gchar *value;
+- int i;
+-
+- g_return_val_if_fail(raw != NULL, NULL);
+-
+- purple_debug_info("msim", "msim_parse: got <%s>\n", raw);
+-
+- key = NULL;
+-
+- /* All messages begin with a \. */
+- if (raw[0] != '\\' || raw[1] == 0) {
+- purple_debug_info("msim", "msim_parse: incomplete/bad string, "
+- "missing initial backslash: <%s>\n", raw);
+- /* XXX: Should we try to recover, and read to first backslash? */
+-
+- return NULL;
+- }
+-
+- msg = msim_msg_new(FALSE);
+-
+- for (tokens = g_strsplit(raw + 1, "\\", 0), i = 0;
+- (token = tokens[i]);
+- i++) {
+-#ifdef MSIM_DEBUG_PARSE
+- purple_debug_info("msim", "tok=<%s>, i%2=%d\n", token, i % 2);
+-#endif
+- if (i % 2) {
+- /* Odd-numbered ordinal is a value. */
+-
+- value = token;
+-
+- /* Incoming protocol messages get tagged as MSIM_TYPE_RAW, which
+- * represents an untyped piece of data. msim_msg_get_* will
+- * convert to appropriate types for caller, and handle unescaping if needed. */
+- msg = msim_msg_append_dynamic_name(msg, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
+-#ifdef MSIM_DEBUG_PARSE
+- purple_debug_info("msim", "insert string: |%s|=|%s|\n", key, value);
+-#endif
+- } else {
+- /* Even numbered indexes are key names. */
+- key = token;
+- }
+- }
+- g_strfreev(tokens);
+-
+- return msg;
+-}
+-
+-/**
+- * Return the first MsimMessageElement * with given name in the MsimMessage *.
+- *
+- * @param name Name to search for.
+- *
+- * @return MsimMessageElement * matching name, or NULL.
+- *
+- * Note: useful fields of MsimMessageElement are 'data' and 'type', which
+- * you can access directly. But it is often more convenient to use
+- * another msim_msg_get_* that converts the data to what type you want.
+- */
+-MsimMessageElement *
+-msim_msg_get(const MsimMessage *msg, const gchar *name)
+-{
+- GList *node;
+-
+- node = msim_msg_get_node(msg, name);
+- if (node) {
+- return (MsimMessageElement *)node->data;
+- } else {
+- return NULL;
+- }
+-}
+-
+-gchar *
+-msim_msg_get_string_from_element(MsimMessageElement *elem)
+-{
+- g_return_val_if_fail(elem != NULL, NULL);
+- switch (elem->type) {
+- case MSIM_TYPE_INTEGER:
+- return g_strdup_printf("%d", GPOINTER_TO_UINT(elem->data));
+-
+- case MSIM_TYPE_RAW:
+- /* Raw element from incoming message - if its a string, it'll
+- * be escaped. */
+- return msim_unescape((gchar *)elem->data);
+-
+- case MSIM_TYPE_STRING:
+- /* Already unescaped. */
+- return g_strdup((gchar *)elem->data);
+-
+- default:
+- purple_debug_info("msim", "msim_msg_get_string_element: type %d unknown, name %s\n",
+- elem->type, elem->name ? elem->name : "(NULL)");
+- return NULL;
+- }
+-}
+-
+-/**
+- * Return the data of an element of a given name, as a string.
+- *
+- * @param name Name of element.
+- *
+- * @return gchar * The data as a string, or NULL if not found.
+- * Caller must g_free().
+- *
+- * Note that msim_msg_pack_element_data() is similar, but returns a string
+- * for inclusion into a raw protocol string (escaped and everything).
+- * This function unescapes the string for you, if needed.
+- */
+-gchar *
+-msim_msg_get_string(const MsimMessage *msg, const gchar *name)
+-{
+- MsimMessageElement *elem;
+-
+- elem = msim_msg_get(msg, name);
+- if (!elem) {
+- return NULL;
+- }
+-
+- return msim_msg_get_string_from_element(elem);
+-}
+-
+-/**
+- * Parse a |-separated string into a new GList. Free with msim_msg_list_free().
+- */
+-static GList *
+-msim_msg_list_parse(const gchar *raw)
+-{
+- gchar **array;
+- GList *list;
+- guint i;
+-
+- array = g_strsplit(raw, "|", 0);
+- list = NULL;
+-
+- /* TODO: escape/unescape /3 <-> | within list elements */
+-
+- for (i = 0; array[i] != NULL; ++i) {
+- MsimMessageElement *elem;
+-
+- /* Freed in msim_msg_list_free() */
+- elem = g_new0(MsimMessageElement, 1);
+-
+- /* Give the element a name for debugging purposes.
+- * Not supposed to be looked up by this name; instead,
+- * lookup the elements by indexing the array. */
+- elem->name = g_strdup_printf("(list item #%d)", i);
+- elem->type = MSIM_TYPE_RAW;
+- elem->data = g_strdup(array[i]);
+-
+- list = g_list_append(list, elem);
+- }
+-
+- g_strfreev(array);
+-
+- return list;
+-}
+-
+-static GList *
+-msim_msg_get_list_from_element(MsimMessageElement *elem)
+-{
+- g_return_val_if_fail(elem != NULL, NULL);
+- switch (elem->type) {
+- case MSIM_TYPE_LIST:
+- return msim_msg_list_copy((GList *)elem->data);
+-
+- case MSIM_TYPE_RAW:
+- return msim_msg_list_parse((gchar *)elem->data);
+-
+- default:
+- purple_debug_info("msim_msg_get_list", "type %d unknown, name %s\n",
+- elem->type, elem->name ? elem->name : "(NULL)");
+- return NULL;
+- }
+-}
+-
+-/**
+- * Return an element as a new list. Caller frees with msim_msg_list_free().
+- */
+-GList *
+-msim_msg_get_list(const MsimMessage *msg, const gchar *name)
+-{
+- MsimMessageElement *elem;
+-
+- elem = msim_msg_get(msg, name);
+- if (!elem) {
+- return NULL;
+- }
+-
+- return msim_msg_get_list_from_element(elem);
+-}
+-
+-/**
+- * Parse a \x1c-separated "dictionary" of key=value pairs into a hash table.
+- *
+- * @param raw The text of the dictionary to parse. Often the
+- * value for the 'body' field.
+- *
+- * @return A new MsimMessage *. Must msim_msg_free() when done.
+- */
+-static MsimMessage *
+-msim_msg_dictionary_parse(const gchar *raw)
+-{
+- MsimMessage *dict;
+- gchar *item;
+- gchar **items;
+- gchar **elements;
+- guint i;
+-
+- g_return_val_if_fail(raw != NULL, NULL);
+-
+- dict = msim_msg_new(NULL);
+-
+- for (items = g_strsplit(raw, "\x1c", 0), i = 0;
+- (item = items[i]);
+- i++) {
+- gchar *key, *value;
+-
+- elements = g_strsplit(item, "=", 2);
+-
+- key = elements[0];
+- if (!key) {
+- purple_debug_info("msim", "msim_msg_dictionary_parse(%s): null key\n",
+- raw);
+- g_strfreev(elements);
+- break;
+- }
+-
+- value = elements[1];
+- if (!value) {
+- purple_debug_info("msim", "msim_msg_dictionary_prase(%s): null value\n",
+- raw);
+- g_strfreev(elements);
+- break;
+- }
+-
+-#ifdef MSIM_DEBUG_PARSE
+- purple_debug_info("msim_msg_dictionary_parse","-- %s: %s\n", key ? key : "(NULL)",
+- value ? value : "(NULL)");
+-#endif
+- /* Append with _dynamic_name since g_strdup(key) is dynamic, and
+- * needs to be freed when the message is destroyed. It isn't static as usual. */
+- dict = msim_msg_append_dynamic_name(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
+-
+- g_strfreev(elements);
+- }
+-
+- g_strfreev(items);
+-
+- return dict;
+-}
+-
+-static MsimMessage *
+-msim_msg_get_dictionary_from_element(MsimMessageElement *elem)
+-{
+- g_return_val_if_fail(elem != NULL, NULL);
+- switch (elem->type) {
+- case MSIM_TYPE_DICTIONARY:
+- return msim_msg_clone((MsimMessage *)elem->data);
+-
+- case MSIM_TYPE_RAW:
+- return msim_msg_dictionary_parse(elem->data);
+-
+- default:
+- purple_debug_info("msim_msg_get_dictionary", "type %d unknown, name %s\n",
+- elem->type, elem->name ? elem->name : "(NULL)");
+- return NULL;
+- }
+-}
+-
+-/**
+- * Return an element as a new dictionary. Caller frees with msim_msg_free().
+- */
+-MsimMessage *
+-msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name)
+-{
+- MsimMessageElement *elem;
+-
+- elem = msim_msg_get(msg, name);
+- if (!elem) {
+- return NULL;
+- }
+-
+- return msim_msg_get_dictionary_from_element(elem);
+-}
+-
+-guint
+-msim_msg_get_integer_from_element(MsimMessageElement *elem)
+-{
+- g_return_val_if_fail(elem != NULL, 0);
+- switch (elem->type) {
+- case MSIM_TYPE_INTEGER:
+- return GPOINTER_TO_UINT(elem->data);
+-
+- case MSIM_TYPE_RAW:
+- case MSIM_TYPE_STRING:
+- /* TODO: find out if we need larger integers */
+- return (guint)atoi((gchar *)elem->data);
+-
+- default:
+- return 0;
+- }
+-}
+-
+-/**
+- * Return the data of an element of a given name, as an unsigned integer.
+- *
+- * @param name Name of element.
+- *
+- * @return guint Numeric representation of data, or 0 if could not be converted / not found.
+- *
+- * Useful to obtain an element's data if you know it should be an integer,
+- * even if it is not stored as an MSIM_TYPE_INTEGER. MSIM_TYPE_STRING will
+- * be converted handled correctly, for example.
+- */
+-guint
+-msim_msg_get_integer(const MsimMessage *msg, const gchar *name)
+-{
+- MsimMessageElement *elem;
+-
+- elem = msim_msg_get(msg, name);
+-
+- if (!elem) {
+- return 0;
+- }
+-
+- return msim_msg_get_integer_from_element(elem);
+-}
+-
+-static gboolean
+-msim_msg_get_binary_from_element(MsimMessageElement *elem, gchar **binary_data, gsize *binary_length)
+-{
+- GString *gs;
+-
+- g_return_val_if_fail(elem != NULL, FALSE);
+-
+- switch (elem->type) {
+- case MSIM_TYPE_RAW:
+- /* Incoming messages are tagged with MSIM_TYPE_RAW, and
+- * converted appropriately. They can still be "strings", just they won't
+- * be tagged as MSIM_TYPE_STRING (as MSIM_TYPE_STRING is intended to be used
+- * by msimprpl code for things like instant messages - stuff that should be
+- * escaped if needed). DWIM.
+- */
+-
+- /* Previously, incoming messages were stored as MSIM_TYPE_STRING.
+- * This was fine for integers and strings, since they can easily be
+- * converted in msim_get_*, as desirable. However, it does not work
+- * well for binary strings. Consider:
+- *
+- * If incoming base64'd elements were tagged as MSIM_TYPE_STRING.
+- * msim_msg_get_binary() sees MSIM_TYPE_STRING, base64 decodes, returns.
+- * everything is fine.
+- * But then, msim_send() is called on the incoming message, which has
+- * a base64'd MSIM_TYPE_STRING that really is encoded binary. The values
+- * will be escaped since strings are escaped, and / becomes /2; no good.
+- *
+- */
+- *binary_data = (gchar *)purple_base64_decode((const gchar *)elem->data, binary_length);
+- return ((*binary_data) != NULL);
+-
+- case MSIM_TYPE_BINARY:
+- gs = (GString *)elem->data;
+-
+- /* Duplicate data, so caller can g_free() it. */
+- *binary_data = g_memdup(gs->str, gs->len);
+- *binary_length = gs->len;
+-
+- return TRUE;
+-
+-
+- /* Rejected because if it isn't already a GString, have to g_new0 it and
+- * then caller has to ALSO free the GString!
+- *
+- * return (GString *)elem->data; */
+-
+- default:
+- purple_debug_info("msim", "msim_msg_get_binary: unhandled type %d for key %s\n",
+- elem->type, elem->name ? elem->name : "(NULL)");
+- return FALSE;
+- }
+-}
+-
+-/**
+- * Return the data of an element of a given name, as a binary GString.
+- *
+- * @param binary_data A pointer to a new pointer, which will be filled in with the binary data. CALLER MUST g_free().
+- *
+- * @param binary_length A pointer to an integer, which will be set to the binary data length.
+- *
+- * @return TRUE if successful, FALSE if not.
+- */
+-gboolean
+-msim_msg_get_binary(const MsimMessage *msg, const gchar *name,
+- gchar **binary_data, gsize *binary_length)
+-{
+- MsimMessageElement *elem;
+-
+- elem = msim_msg_get(msg, name);
+- if (!elem) {
+- return FALSE;
+- }
+-
+- return msim_msg_get_binary_from_element(elem, binary_data, binary_length);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/message.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/message.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/message.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,109 +0,0 @@
+-/** MySpaceIM protocol messages
+- *
+- * \author Jeff Connelly
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_MESSAGE_H
+-#define _MYSPACE_MESSAGE_H
+-
+-#include <glib.h>
+-
+-#define MsimMessage GList /* #define instead of typedef to avoid casting */
+-typedef gchar MsimMessageType;
+-typedef struct _MsimMessageElement MsimMessageElement;
+-
+-#include "session.h"
+-
+-/* Types */
+-struct _MsimMessageElement
+-{
+- const gchar *name; /**< Textual name of element. */
+- gboolean dynamic_name; /**< TRUE if 'name' is a dynamic string to be freed, not static. */
+- guint type; /**< MSIM_TYPE_* code. */
+- gpointer data; /**< Pointer to data, or GUINT_TO_POINTER for int/bool. */
+-};
+-
+-#define msim_msg_get_next_element_node(msg) ((MsimMessage *)(msg->next))
+-
+-/* Protocol field types */
+-#define MSIM_TYPE_RAW '-'
+-#define MSIM_TYPE_INTEGER 'i'
+-#define MSIM_TYPE_STRING 's'
+-#define MSIM_TYPE_BINARY 'b'
+-#define MSIM_TYPE_BOOLEAN 'f'
+-#define MSIM_TYPE_DICTIONARY 'd'
+-#define MSIM_TYPE_LIST 'l'
+-
+-gchar *msim_escape(const gchar *msg);
+-gchar *msim_unescape(const gchar *msg);
+-
+-MsimMessage *msim_msg_new(gchar *first_key, ...);
+-/* No sentinel attribute, because can leave off varargs if not_empty is FALSE. */
+-
+-MsimMessage *msim_msg_clone(MsimMessage *old);
+-void msim_msg_free_element_data(MsimMessageElement *elem);
+-void msim_msg_free(MsimMessage *msg);
+-MsimMessage *msim_msg_append(MsimMessage *msg, const gchar *name, MsimMessageType type, gpointer data);
+-MsimMessage *msim_msg_insert_before(MsimMessage *msg, const gchar *name_before, const gchar *name, MsimMessageType type, gpointer data);
+-gchar *msim_msg_pack_element_data(MsimMessageElement *elem);
+-void msim_msg_dump(const char *fmt_string, MsimMessage *msg);
+-gchar *msim_msg_pack(MsimMessage *msg);
+-
+-void msim_msg_list_free(GList *l);
+-
+-/* Based on http://permalink.gmane.org/gmane.comp.parsers.sparse/695
+- * Define macros for useful gcc attributes. */
+-#ifdef __GNUC__
+-#define GCC_VERSION (__GNUC__ * 1000 + __GNUC_MINOR__)
+-#define FORMAT_ATTR(pos) __attribute__ ((__format__ (__printf__, pos, pos+1)))
+-#define NORETURN_ATTR __attribute__ ((__noreturn__))
+-/* __sentinel__ attribute was introduced in gcc 3.5 */
+-#if (GCC_VERSION >= 3005)
+- #define SENTINEL_ATTR __attribute__ ((__sentinel__(0)))
+-#else
+- #define SENTINEL_ATTR
+-#endif /* gcc >= 3.5 */
+-#else
+- #define FORMAT_ATTR(pos)
+- #define NORETURN_ATTR
+- #define SENTINEL_ATTR
+-#endif
+-
+-/* Cause gcc to emit "a missing sentinel in function call" if forgot
+- * to write NULL as last, terminating parameter. */
+-gboolean msim_send(struct _MsimSession *session, ...) SENTINEL_ATTR;
+-
+-gboolean msim_msg_send(struct _MsimSession *session, MsimMessage *msg);
+-
+-MsimMessage *msim_parse(const gchar *raw);
+-
+-MsimMessageElement *msim_msg_get(const MsimMessage *msg, const gchar *name);
+-
+-/* Retrieve data by name */
+-gchar *msim_msg_get_string(const MsimMessage *msg, const gchar *name);
+-GList *msim_msg_get_list(const MsimMessage *msg, const gchar *name);
+-MsimMessage *msim_msg_get_dictionary(const MsimMessage *msg, const gchar *name);
+-guint msim_msg_get_integer(const MsimMessage *msg, const gchar *name);
+-gboolean msim_msg_get_binary(const MsimMessage *msg, const gchar *name, gchar **binary_data, gsize *binary_length);
+-
+-/* Retrieve data by element (MsimMessageElement *), returned from msim_msg_get() */
+-gchar *msim_msg_get_string_from_element(MsimMessageElement *elem);
+-guint msim_msg_get_integer_from_element(MsimMessageElement *elem);
+-
+-#endif /* _MYSPACE_MESSAGE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/myspace.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/myspace.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,3667 +0,0 @@
+-/**
+- * MySpaceIM Protocol Plugin
+- *
+- * \author Jeff Connelly
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.pidgin.im>
+- *
+- * Based on Purple's "C Plugin HOWTO" hello world example.
+- *
+- * Code also drawn from mockprpl:
+- * http://snarfed.org/space/purple+mock+protocol+plugin
+- * Copyright (C) 2004-2007, Ryan Barrett <mockprpl@ryanb.org>
+- *
+- * and some constructs also based on existing Purple plugins, which are:
+- * Copyright (C) 2003, Robbert Haarman <purple@inglorion.net>
+- * Copyright (C) 2003, Ethan Blanton <eblanton@cs.purdue.edu>
+- * Copyright (C) 2000-2003, Rob Flynn <rob@tgflinux.com>
+- * Copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#define PURPLE_PLUGIN
+-
+-#include "myspace.h"
+-
+-#include "privacy.h"
+-
+-static void msim_set_status(PurpleAccount *account, PurpleStatus *status);
+-static void msim_set_idle(PurpleConnection *gc, int time);
+-
+-/**
+- * Perform actual postprocessing on a message, adding userid as specified.
+- *
+- * @param msg The message to postprocess.
+- * @param uid_before Name of field where to insert new field before, or NULL for end.
+- * @param uid_field_name Name of field to add uid to.
+- * @param uid The userid to insert.
+- *
+- * If the field named by uid_field_name already exists, then its string contents will
+- * be used for the field, except "<uid>" will be replaced by the userid.
+- *
+- * If the field named by uid_field_name does not exist, it will be added before the
+- * field named by uid_before, as an integer, with the userid.
+- *
+- * Does not handle sending, or scheduling userid lookup. For that, see msim_postprocess_outgoing().
+- */
+-static MsimMessage *
+-msim_do_postprocessing(MsimMessage *msg, const gchar *uid_before,
+- const gchar *uid_field_name, guint uid)
+-{
+- MsimMessageElement *elem;
+-
+- /* First, check - if the field already exists, replace <uid> within it */
+- if ((elem = msim_msg_get(msg, uid_field_name)) != NULL) {
+- gchar *fmt_string;
+- gchar *uid_str, *new_str;
+-
+- /* Get the packed element, flattening it. This allows <uid> to be
+- * replaced within nested data structures, since the replacement is done
+- * on the linear, packed data, not on a complicated data structure.
+- *
+- * For example, if the field was originally a dictionary or a list, you
+- * would have to iterate over all the items in it to see what needs to
+- * be replaced. But by packing it first, the <uid> marker is easily replaced
+- * just by a string replacement.
+- */
+- fmt_string = msim_msg_pack_element_data(elem);
+-
+- uid_str = g_strdup_printf("%d", uid);
+- new_str = purple_strreplace(fmt_string, "<uid>", uid_str);
+- g_free(uid_str);
+- g_free(fmt_string);
+-
+- /* Free the old element data */
+- msim_msg_free_element_data(elem->data);
+-
+- /* Replace it with our new data */
+- elem->data = new_str;
+- elem->type = MSIM_TYPE_RAW;
+-
+- } else {
+- /* Otherwise, insert new field into outgoing message. */
+- msg = msim_msg_insert_before(msg, uid_before, uid_field_name, MSIM_TYPE_INTEGER, GUINT_TO_POINTER(uid));
+- }
+-
+- return msg;
+-}
+-
+-/**
+- * Callback for msim_postprocess_outgoing() to add a userid to a message, and send it (once receiving userid).
+- *
+- * @param session
+- * @param userinfo The user information reply message, containing the user ID
+- * @param data The message to postprocess and send.
+- *
+- * The data message should contain these fields:
+- *
+- * _uid_field_name: string, name of field to add with userid from userinfo message
+- * _uid_before: string, name of field before field to insert, or NULL for end
+- */
+-static void
+-msim_postprocess_outgoing_cb(MsimSession *session, const MsimMessage *userinfo,
+- gpointer data)
+-{
+- gchar *uid_field_name, *uid_before, *username;
+- guint uid;
+- MsimMessage *msg, *body;
+-
+- msg = (MsimMessage *)data;
+-
+- /* Obtain userid from userinfo message. */
+- body = msim_msg_get_dictionary(userinfo, "body");
+- g_return_if_fail(body != NULL);
+-
+- uid = msim_msg_get_integer(body, "UserID");
+- msim_msg_free(body);
+-
+- username = msim_msg_get_string(msg, "_username");
+-
+- if (!uid) {
+- gchar *msg;
+-
+- msg = g_strdup_printf(_("No such user: %s"), username);
+- if (!purple_conv_present_error(username, session->account, msg)) {
+- purple_notify_error(NULL, NULL, _("User lookup"), msg);
+- }
+-
+- g_free(msg);
+- g_free(username);
+- /* TODO: free
+- * msim_msg_free(msg);
+- */
+- return;
+- }
+-
+- uid_field_name = msim_msg_get_string(msg, "_uid_field_name");
+- uid_before = msim_msg_get_string(msg, "_uid_before");
+-
+- msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
+-
+- /* Send */
+- if (!msim_msg_send(session, msg)) {
+- msim_msg_dump("msim_postprocess_outgoing_cb: sending failed for message: %s\n", msg);
+- }
+-
+-
+- /* Free field names AFTER sending message, because MsimMessage does NOT copy
+- * field names - instead, treats them as static strings (which they usually are).
+- */
+- g_free(uid_field_name);
+- g_free(uid_before);
+- g_free(username);
+- /* TODO: free
+- * msim_msg_free(msg);
+- */
+-}
+-
+-/**
+- * Postprocess and send a message.
+- *
+- * @param session
+- * @param msg Message to postprocess. Will NOT be freed.
+- * @param username Username to resolve. Assumed to be a static string (will not be freed or copied).
+- * @param uid_field_name Name of new field to add, containing uid of username. Static string.
+- * @param uid_before Name of existing field to insert username field before. Static string.
+- *
+- * @return TRUE if successful.
+- */
+-static gboolean
+-msim_postprocess_outgoing(MsimSession *session, MsimMessage *msg,
+- const gchar *username, const gchar *uid_field_name,
+- const gchar *uid_before)
+-{
+- PurpleBuddy *buddy;
+- guint uid;
+- gboolean rc;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- /* Store information for msim_postprocess_outgoing_cb(). */
+- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
+- msg = msim_msg_append(msg, "_uid_field_name", MSIM_TYPE_STRING, g_strdup(uid_field_name));
+- msg = msim_msg_append(msg, "_uid_before", MSIM_TYPE_STRING, g_strdup(uid_before));
+-
+- /* First, try the most obvious. If numeric userid is given, use that directly. */
+- if (msim_is_userid(username)) {
+- uid = atol(username);
+- } else {
+- /* Next, see if on buddy list and know uid. */
+- buddy = purple_find_buddy(session->account, username);
+- if (buddy) {
+- uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
+- } else {
+- uid = 0;
+- }
+-
+- if (!buddy || !uid) {
+- /* Don't have uid offhand - need to ask for it, and wait until hear back before sending. */
+- purple_debug_info("msim", ">>> msim_postprocess_outgoing: couldn't find username %s in blist\n",
+- username ? username : "(NULL)");
+- msim_lookup_user(session, username, msim_postprocess_outgoing_cb, msim_msg_clone(msg));
+- return TRUE; /* not sure of status yet - haven't sent! */
+- }
+- }
+-
+- /* Already have uid, postprocess and send msg immediately. */
+- purple_debug_info("msim", "msim_postprocess_outgoing: found username %s has uid %d\n",
+- username ? username : "(NULL)", uid);
+-
+- msg = msim_do_postprocessing(msg, uid_before, uid_field_name, uid);
+-
+- rc = msim_msg_send(session, msg);
+-
+- /* TODO: free
+- * msim_msg_free(msg);
+- */
+-
+- return rc;
+-}
+-
+-/**
+- * Send a buddy message of a given type.
+- *
+- * @param session
+- * @param who Username to send message to.
+- * @param text Message text to send. Not freed; will be copied.
+- * @param type A MSIM_BM_* constant.
+- *
+- * @return TRUE if success, FALSE if fail.
+- *
+- * Buddy messages ('bm') include instant messages, action messages, status messages, etc.
+- */
+-gboolean
+-msim_send_bm(MsimSession *session, const gchar *who, const gchar *text,
+- int type)
+-{
+- gboolean rc;
+- MsimMessage *msg;
+- const gchar *from_username;
+-
+- g_return_val_if_fail(who != NULL, FALSE);
+- g_return_val_if_fail(text != NULL, FALSE);
+-
+- from_username = session->account->username;
+-
+- g_return_val_if_fail(from_username != NULL, FALSE);
+-
+- purple_debug_info("msim", "sending %d message from %s to %s: %s\n",
+- type, from_username, who, text);
+-
+- msg = msim_msg_new(
+- "bm", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(type),
+- "sesskey", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(session->sesskey),
+- /* 't' will be inserted here */
+- "cv", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(MSIM_CLIENT_VERSION),
+- "msg", MSIM_TYPE_STRING, g_strdup(text),
+- NULL);
+-
+- rc = msim_postprocess_outgoing(session, msg, who, "t", "cv");
+-
+- msim_msg_free(msg);
+-
+- return rc;
+-}
+-
+-/**
+- * Lookup a username by userid, from buddy list.
+- *
+- * @param wanted_uid
+- *
+- * @return Username of wanted_uid, if on blist, or NULL.
+- * This is a static string, so don't free it. Copy it if needed.
+- *
+- */
+-static const gchar *
+-msim_uid2username_from_blist(PurpleAccount *account, guint wanted_uid)
+-{
+- GSList *buddies, *cur;
+- const gchar *ret;
+-
+- buddies = purple_find_buddies(account, NULL);
+-
+- if (!buddies)
+- {
+- purple_debug_info("msim", "msim_uid2username_from_blist: no buddies?\n");
+- return NULL;
+- }
+-
+- ret = NULL;
+-
+- for (cur = buddies; cur != NULL; cur = g_slist_next(cur))
+- {
+- PurpleBuddy *buddy;
+- guint uid;
+- const gchar *name;
+-
+- /* See finch/gnthistory.c */
+- buddy = cur->data;
+-
+- uid = purple_blist_node_get_int(PURPLE_BLIST_NODE(buddy), "UserID");
+- name = purple_buddy_get_name(buddy);
+-
+- if (uid == wanted_uid)
+- {
+- ret = name;
+- break;
+- }
+- }
+-
+- g_slist_free(buddies);
+- return ret;
+-}
+-
+-/**
+- * Setup a callback, to be called when a reply is received with the returned rid.
+- *
+- * @param cb The callback, an MSIM_USER_LOOKUP_CB.
+- * @param data Arbitrary user data to be passed to callback (probably an MsimMessage *).
+- *
+- * @return The request/reply ID, used to link replies with requests, or -1.
+- * Put the rid in your request, 'rid' field.
+- *
+- * TODO: Make more generic and more specific:
+- * 1) MSIM_USER_LOOKUP_CB - make it for PERSIST_REPLY, not just user lookup
+- * 2) data - make it an MsimMessage?
+- */
+-guint
+-msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb,
+- gpointer data)
+-{
+- guint rid;
+-
+- rid = session->next_rid++;
+-
+- g_hash_table_insert(session->user_lookup_cb, GUINT_TO_POINTER(rid), cb);
+- g_hash_table_insert(session->user_lookup_cb_data, GUINT_TO_POINTER(rid), data);
+-
+- return rid;
+-}
+-
+-/**
+- * Return the icon name for a buddy and account.
+- *
+- * @param acct The account to find the icon for, or NULL for protocol icon.
+- * @param buddy The buddy to find the icon for, or NULL for the account icon.
+- *
+- * @return The base icon name string.
+- */
+-static const gchar *
+-msim_list_icon(PurpleAccount *acct, PurpleBuddy *buddy)
+-{
+- /* Use a MySpace icon submitted by hbons at
+- * http://developer.pidgin.im/wiki/MySpaceIM. */
+- return "myspace";
+-}
+-
+-/**
+- * Obtain the status text for a buddy.
+- *
+- * @param buddy The buddy to obtain status text for.
+- *
+- * @return Status text, or NULL if error. Caller g_free()'s.
+- */
+-static char *
+-msim_status_text(PurpleBuddy *buddy)
+-{
+- MsimUser *user;
+- const gchar *display_name = NULL, *headline = NULL;
+- PurpleAccount *account;
+-
+- g_return_val_if_fail(buddy != NULL, NULL);
+-
+- account = purple_buddy_get_account(buddy);
+-
+- user = msim_get_user_from_buddy(buddy, FALSE);
+- if (user != NULL) {
+- /* Retrieve display name and/or headline, depending on user preference. */
+- if (purple_account_get_bool(account, "show_headline", TRUE)) {
+- headline = user->headline;
+- }
+-
+- if (purple_account_get_bool(account, "show_display_name", FALSE)) {
+- display_name = user->display_name;
+- }
+- }
+-
+- /* Return appropriate combination of display name and/or headline, or neither. */
+-
+- if (display_name && headline) {
+- return g_strconcat(display_name, " ", headline, NULL);
+- } else if (display_name) {
+- return g_strdup(display_name);
+- } else if (headline) {
+- return g_strdup(headline);
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Obtain the tooltip text for a buddy.
+- *
+- * @param buddy Buddy to obtain tooltip text on.
+- * @param user_info Variable modified to have the tooltip text.
+- * @param full TRUE if should obtain full tooltip text.
+- */
+-static void
+-msim_tooltip_text(PurpleBuddy *buddy, PurpleNotifyUserInfo *user_info,
+- gboolean full)
+-{
+- MsimUser *user;
+-
+- g_return_if_fail(buddy != NULL);
+- g_return_if_fail(user_info != NULL);
+-
+- user = msim_get_user_from_buddy(buddy, TRUE);
+-
+- if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
+- MsimSession *session;
+- PurpleAccount *account = purple_buddy_get_account(buddy);
+- PurpleConnection *gc = purple_account_get_connection(account);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /* TODO: if (full), do something different? */
+-
+- /* TODO: request information? have to figure out how to do
+- * the asynchronous lookup like oscar does (tooltip shows
+- * 'retrieving...' if not yet available, then changes when it is).
+- *
+- * Right now, only show what we have on hand.
+- */
+-
+- /* Show abbreviated user info. */
+- msim_append_user_info(session, user_info, user, FALSE);
+- }
+-}
+-
+-/**
+- * Get possible user status types. Based on mockprpl.
+- *
+- * @return GList of status types.
+- */
+-static GList *
+-msim_status_types(PurpleAccount *acct)
+-{
+- GList *types;
+- PurpleStatusType *status;
+-
+- purple_debug_info("myspace", "returning status types\n");
+-
+- types = NULL;
+-
+- /* Statuses are almost all the same. Define a macro to reduce code repetition. */
+-#define _MSIM_ADD_NEW_STATUS(prim) status = \
+- purple_status_type_new_with_attrs( \
+- prim, /* PurpleStatusPrimitive */ \
+- NULL, /* id - use default */ \
+- NULL, /* name - use default */ \
+- TRUE, /* saveable */ \
+- TRUE, /* user_settable */ \
+- FALSE, /* not independent */ \
+- \
+- /* Attributes - each status can have a message. */ \
+- "message", \
+- _("Message"), \
+- purple_value_new(PURPLE_TYPE_STRING), \
+- NULL); \
+- \
+- \
+- types = g_list_append(types, status)
+-
+-
+- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AVAILABLE);
+- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_AWAY);
+- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_OFFLINE);
+- _MSIM_ADD_NEW_STATUS(PURPLE_STATUS_INVISIBLE);
+-
+- /* Except tune status is different... */
+- status = purple_status_type_new_with_attrs(
+- PURPLE_STATUS_TUNE, /* primitive */
+- "tune", /* ID */
+- NULL, /* name - use default */
+- FALSE, /* saveable */
+- TRUE, /* should be user_settable some day */
+- TRUE, /* independent */
+-
+- PURPLE_TUNE_ARTIST, _("Tune Artist"), purple_value_new(PURPLE_TYPE_STRING),
+- PURPLE_TUNE_TITLE, _("Tune Title"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+-
+- types = g_list_append(types, status);
+-
+- return types;
+-}
+-
+-/*
+- * TODO: This define is stolen from oscar.h.
+- * It's also in yahoo.h.
+- * It should be in libpurple/util.c
+- */
+-#define msim_put32(buf, data) ( \
+- (*((buf)) = (unsigned char)((data)>>24)&0xff), \
+- (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
+- (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
+- (*((buf)+3) = (unsigned char)(data)&0xff), \
+- 4)
+-
+-/**
+- * Compute the base64'd login challenge response based on username, password, nonce, and IPs.
+- *
+- * @param nonce The base64 encoded nonce ('nc') field from the server.
+- * @param email User's email address (used as login name).
+- * @param password User's cleartext password.
+- * @param response_len Will be written with response length.
+- *
+- * @return Binary login challenge response, ready to send to the server.
+- * Must be g_free()'d when finished. NULL if error.
+- */
+-static gchar *
+-msim_compute_login_response(const gchar nonce[2 * NONCE_SIZE],
+- const gchar *email, const gchar *password, guint *response_len)
+-{
+- PurpleCipherContext *key_context;
+- PurpleCipher *sha1;
+- PurpleCipherContext *rc4;
+-
+- guchar hash_pw[HASH_SIZE];
+- guchar key[HASH_SIZE];
+- gchar *password_truncated, *password_utf16le, *password_utf8_lc;
+- GString *data;
+- guchar *data_out;
+- size_t data_out_len;
+- gsize conv_bytes_read, conv_bytes_written;
+- GError *conv_error;
+-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
+- int i;
+-#endif
+-
+- g_return_val_if_fail(nonce != NULL, NULL);
+- g_return_val_if_fail(email != NULL, NULL);
+- g_return_val_if_fail(password != NULL, NULL);
+- g_return_val_if_fail(response_len != NULL, NULL);
+-
+- /*
+- * Truncate password to 10 characters. Their "change password"
+- * web page doesn't let you enter more than 10 characters, but you
+- * can enter more than 10 when logging in on myspace.com and they
+- * truncate it.
+- */
+- password_truncated = g_strndup(password, 10);
+-
+- /* Convert password to lowercase (required for passwords containing
+- * uppercase characters). MySpace passwords are lowercase,
+- * see ticket #2066. */
+- password_utf8_lc = g_utf8_strdown(password_truncated, -1);
+- g_free(password_truncated);
+-
+- /* Convert ASCII password to UTF16 little endian */
+- purple_debug_info("msim", "converting password to UTF-16LE\n");
+- conv_error = NULL;
+- password_utf16le = g_convert(password_utf8_lc, -1, "UTF-16LE", "UTF-8",
+- &conv_bytes_read, &conv_bytes_written, &conv_error);
+- g_free(password_utf8_lc);
+-
+- if (conv_error != NULL) {
+- purple_debug_error("msim",
+- "g_convert password UTF8->UTF16LE failed: %s",
+- conv_error->message);
+- g_error_free(conv_error);
+- return NULL;
+- }
+-
+- /* Compute password hash */
+- purple_cipher_digest_region("sha1", (guchar *)password_utf16le,
+- conv_bytes_written, sizeof(hash_pw), hash_pw, NULL);
+- g_free(password_utf16le);
+-
+-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
+- purple_debug_info("msim", "pwhash = ");
+- for (i = 0; i < sizeof(hash_pw); i++)
+- purple_debug_info("msim", "%.2x ", hash_pw[i]);
+- purple_debug_info("msim", "\n");
+-#endif
+-
+- /* key = sha1(sha1(pw) + nonce2) */
+- sha1 = purple_ciphers_find_cipher("sha1");
+- key_context = purple_cipher_context_new(sha1, NULL);
+- purple_cipher_context_append(key_context, hash_pw, HASH_SIZE);
+- purple_cipher_context_append(key_context, (guchar *)(nonce + NONCE_SIZE), NONCE_SIZE);
+- purple_cipher_context_digest(key_context, sizeof(key), key, NULL);
+- purple_cipher_context_destroy(key_context);
+-
+-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
+- purple_debug_info("msim", "key = ");
+- for (i = 0; i < sizeof(key); i++) {
+- purple_debug_info("msim", "%.2x ", key[i]);
+- }
+- purple_debug_info("msim", "\n");
+-#endif
+-
+- rc4 = purple_cipher_context_new_by_name("rc4", NULL);
+-
+- /* Note: 'key' variable is 0x14 bytes (from SHA-1 hash),
+- * but only first 0x10 used for the RC4 key. */
+- purple_cipher_context_set_option(rc4, "key_len", (gpointer)0x10);
+- purple_cipher_context_set_key(rc4, key);
+-
+- /* rc4 encrypt:
+- * nonce1+email+IP list */
+-
+- data = g_string_new(NULL);
+- g_string_append_len(data, nonce, NONCE_SIZE);
+-
+- /* Include the null terminator */
+- g_string_append_len(data, email, strlen(email) + 1);
+-
+- while (data->len % 4 != 0)
+- g_string_append_c(data, 0xfb);
+-
+-#ifdef SEND_OUR_IP_ADDRESSES
+- /* TODO: Obtain IPs of network interfaces instead of using this hardcoded value */
+- g_string_set_size(data, data->len + 4);
+- msim_put32(data->str + data->len - 4, MSIM_LOGIN_IP_LIST_LEN);
+- g_string_append_len(data, MSIM_LOGIN_IP_LIST, MSIM_LOGIN_IP_LIST_LEN);
+-#else
+- g_string_set_size(data, data->len + 4);
+- msim_put32(data->str + data->len - 4, 0);
+-#endif /* !SEND_OUR_IP_ADDRESSES */
+-
+- data_out = g_new0(guchar, data->len);
+-
+- purple_cipher_context_encrypt(rc4, (const guchar *)data->str,
+- data->len, data_out, &data_out_len);
+- purple_cipher_context_destroy(rc4);
+-
+- if (data_out_len != data->len) {
+- purple_debug_info("msim", "msim_compute_login_response: "
+- "data length mismatch: %" G_GSIZE_FORMAT " != %"
+- G_GSIZE_FORMAT "\n", data_out_len, data->len);
+- }
+-
+- g_string_free(data, TRUE);
+-
+-#ifdef MSIM_DEBUG_LOGIN_CHALLENGE
+- purple_debug_info("msim", "response=<%s>\n", data_out);
+-#endif
+-
+- *response_len = data_out_len;
+-
+- return (gchar *)data_out;
+-}
+-
+-/**
+- * Process a login challenge, sending a response.
+- *
+- * @param session
+- * @param msg Login challenge message.
+- *
+- * @return TRUE if successful, FALSE if not
+- */
+-static gboolean
+-msim_login_challenge(MsimSession *session, MsimMessage *msg)
+-{
+- PurpleAccount *account;
+- gchar *response;
+- guint response_len;
+- gchar *nc;
+- gsize nc_len;
+- gboolean ret;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- g_return_val_if_fail(msim_msg_get_binary(msg, "nc", &nc, &nc_len), FALSE);
+-
+- account = session->account;
+-
+- g_return_val_if_fail(account != NULL, FALSE);
+-
+- purple_connection_update_progress(session->gc, _("Reading challenge"), 1, 4);
+-
+- purple_debug_info("msim", "nc is %" G_GSIZE_FORMAT
+- " bytes, decoded\n", nc_len);
+-
+- if (nc_len != MSIM_AUTH_CHALLENGE_LENGTH) {
+- purple_debug_info("msim", "bad nc length: %" G_GSIZE_MODIFIER
+- "x != 0x%x\n", nc_len, MSIM_AUTH_CHALLENGE_LENGTH);
+- purple_connection_error_reason (session->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unexpected challenge length from server"));
+- return FALSE;
+- }
+-
+- purple_connection_update_progress(session->gc, _("Logging in"), 2, 4);
+-
+- response_len = 0;
+- response = msim_compute_login_response(nc, account->username, account->password, &response_len);
+-
+- g_free(nc);
+-
+- ret = msim_send(session,
+- "login2", MSIM_TYPE_INTEGER, MSIM_AUTH_ALGORITHM,
+- /* This is actually user's email address. */
+- "username", MSIM_TYPE_STRING, g_strdup(account->username),
+- /* GString will be freed in msim_msg_free() in msim_send(). */
+- "response", MSIM_TYPE_BINARY, g_string_new_len(response, response_len),
+- "clientver", MSIM_TYPE_INTEGER, MSIM_CLIENT_VERSION,
+- "langid", MSIM_TYPE_INTEGER, MSIM_LANGUAGE_ID_ENGLISH,
+- "imlang", MSIM_TYPE_STRING, g_strdup(MSIM_LANGUAGE_NAME_ENGLISH),
+- "reconn", MSIM_TYPE_INTEGER, 0,
+- "status", MSIM_TYPE_INTEGER, 100,
+- "id", MSIM_TYPE_INTEGER, 1,
+- NULL);
+-
+- g_free(response);
+-
+- return ret;
+-}
+-
+-/**
+- * Process unrecognized information.
+- *
+- * @param session
+- * @param msg An MsimMessage that was unrecognized, or NULL.
+- * @param note Information on what was unrecognized, or NULL.
+- */
+-void
+-msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note)
+-{
+- /* TODO: Some more context, outwardly equivalent to a backtrace,
+- * for helping figure out what this msg is for. What was going on?
+- * But not too much information so that a user
+- * posting this dump reveals confidential information.
+- */
+-
+- /* TODO: dump unknown msgs to file, so user can send them to me
+- * if they wish, to help add support for new messages (inspired
+- * by Alexandr Shutko, who maintains OSCAR protocol documentation).
+- *
+- * Filed enhancement ticket for libpurple as #4688.
+- */
+-
+- purple_debug_info("msim", "Unrecognized data on account for %s\n",
+- (session && session->account && session->account->username) ?
+- session->account->username : "(NULL)");
+- if (note) {
+- purple_debug_info("msim", "(Note: %s)\n", note);
+- }
+-
+- if (msg) {
+- msim_msg_dump("Unrecognized message dump: %s\n", msg);
+- }
+-}
+-
+-/** Called when the session key arrives to check whether the user
+- * has a username, and set one if desired. */
+-static gboolean
+-msim_is_username_set(MsimSession *session, MsimMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, FALSE);
+- g_return_val_if_fail(session->gc != NULL, FALSE);
+-
+- session->sesskey = msim_msg_get_integer(msg, "sesskey");
+- purple_debug_info("msim", "SESSKEY=<%d>\n", session->sesskey);
+-
+- /* What is proof? Used to be uid, but now is 52 base64'd bytes... */
+-
+- /* Comes with: proof,profileid,userid,uniquenick -- all same values
+- * some of the time, but can vary. This is our own user ID. */
+- session->userid = msim_msg_get_integer(msg, "userid");
+-
+- /* Save uid to account so this account can be looked up by uid. */
+- purple_account_set_int(session->account, "uid", session->userid);
+-
+- /* Not sure what profileid is used for. */
+- if (msim_msg_get_integer(msg, "profileid") != session->userid) {
+- msim_unrecognized(session, msg,
+- "Profile ID didn't match user ID, don't know why");
+- }
+-
+- /* We now know are our own username, only after we're logged in..
+- * which is weird, but happens because you login with your email
+- * address and not username. Will be freed in msim_session_destroy(). */
+- session->username = msim_msg_get_string(msg, "uniquenick");
+-
+- /* If user lacks a username, help them get one. */
+- if (msim_msg_get_integer(msg, "uniquenick") == session->userid) {
+- purple_debug_info("msim_is_username_set", "no username is set\n");
+- purple_request_yes_no(session->gc,
+- _("MySpaceIM - No Username Set"),
+- _("You appear to have no MySpace username."),
+- _("Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)"),
+- 0,
+- session->account,
+- NULL,
+- NULL,
+- session->gc,
+- G_CALLBACK(msim_set_username_cb),
+- G_CALLBACK(msim_do_not_set_username_cb));
+- purple_debug_info("msim_is_username_set","'username not set' alert prompted\n");
+- return FALSE;
+- }
+- return TRUE;
+-}
+-
+-#ifdef MSIM_USE_KEEPALIVE
+-/**
+- * Check if the connection is still alive, based on last communication.
+- */
+-static gboolean
+-msim_check_alive(gpointer data)
+-{
+- MsimSession *session;
+- time_t delta;
+-
+- session = (MsimSession *)data;
+-
+- delta = time(NULL) - session->last_comm;
+-
+- /* purple_debug_info("msim", "msim_check_alive: delta=%d\n", delta); */
+- if (delta >= MSIM_KEEPALIVE_INTERVAL) {
+- purple_debug_info("msim",
+- "msim_check_alive: %zu > interval of %d, presumed dead\n",
+- delta, MSIM_KEEPALIVE_INTERVAL);
+- purple_connection_error_reason(session->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Lost connection with server"));
+-
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-#endif
+-
+-/**
+- * Handle mail reply checks.
+- */
+-static void
+-msim_check_inbox_cb(MsimSession *session, const MsimMessage *reply, gpointer data)
+-{
+- MsimMessage *body;
+- guint i, n;
+- /* Information for each new inbox message type. */
+- static struct
+- {
+- const gchar *key;
+- guint bit;
+- const gchar *url;
+- const gchar *text;
+- } message_types[] = {
+- { "Mail", MSIM_INBOX_MAIL, "http://messaging.myspace.com/index.cfm?fuseaction=mail.inbox", NULL },
+- { "BlogComment", MSIM_INBOX_BLOG_COMMENT, "http://blog.myspace.com/index.cfm?fuseaction=blog", NULL },
+- { "ProfileComment", MSIM_INBOX_PROFILE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL },
+- { "FriendRequest", MSIM_INBOX_FRIEND_REQUEST, "http://messaging.myspace.com/index.cfm?fuseaction=mail.friendRequests", NULL },
+- { "PictureComment", MSIM_INBOX_PICTURE_COMMENT, "http://home.myspace.com/index.cfm?fuseaction=user", NULL }
+- };
+- const gchar *froms[G_N_ELEMENTS(message_types) + 1] = { "" },
+- *tos[G_N_ELEMENTS(message_types) + 1] = { "" },
+- *urls[G_N_ELEMENTS(message_types) + 1] = { "" },
+- *subjects[G_N_ELEMENTS(message_types) + 1] = { "" };
+-
+- g_return_if_fail(reply != NULL);
+-
+- /* Can't write _()'d strings in array initializers. Workaround. */
+- /* khc: then use N_() in the array initializer and use _() when they are
+- used */
+- message_types[0].text = _("New mail messages");
+- message_types[1].text = _("New blog comments");
+- message_types[2].text = _("New profile comments");
+- message_types[3].text = _("New friend requests!");
+- message_types[4].text = _("New picture comments");
+-
+- body = msim_msg_get_dictionary(reply, "body");
+-
+- if (body == NULL)
+- return;
+-
+- n = 0;
+-
+- for (i = 0; i < G_N_ELEMENTS(message_types); ++i) {
+- const gchar *key;
+- guint bit;
+-
+- key = message_types[i].key;
+- bit = message_types[i].bit;
+-
+- if (msim_msg_get(body, key)) {
+- /* Notify only on when _changes_ from no mail -> has mail
+- * (edge triggered) */
+- if (!(session->inbox_status & bit)) {
+- purple_debug_info("msim", "msim_check_inbox_cb: got %s, at %d\n",
+- key ? key : "(NULL)", n);
+-
+- subjects[n] = message_types[i].text;
+- froms[n] = _("MySpace");
+- tos[n] = session->username;
+- /* TODO: append token, web challenge, so automatically logs in.
+- * Would also need to free strings because they won't be static
+- */
+- urls[n] = message_types[i].url;
+-
+- ++n;
+- } else {
+- purple_debug_info("msim",
+- "msim_check_inbox_cb: already notified of %s\n",
+- key ? key : "(NULL)");
+- }
+-
+- session->inbox_status |= bit;
+- }
+- }
+-
+- if (n) {
+- purple_debug_info("msim",
+- "msim_check_inbox_cb: notifying of %d\n", n);
+-
+- /* TODO: free strings with callback _if_ change to dynamic (w/ token) */
+- purple_notify_emails(session->gc, /* handle */
+- n, /* count */
+- TRUE, /* detailed */
+- subjects, froms, tos, urls,
+- NULL, /* PurpleNotifyCloseCallback cb */
+- NULL); /* gpointer user_data */
+-
+- }
+-
+- msim_msg_free(body);
+-}
+-
+-/**
+- * Send request to check if there is new mail.
+- */
+-static gboolean
+-msim_check_inbox(gpointer data)
+-{
+- MsimSession *session;
+-
+- session = (MsimSession *)data;
+-
+- purple_debug_info("msim", "msim_check_inbox: checking mail\n");
+- g_return_val_if_fail(msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_DSN,
+- "lid", MSIM_TYPE_INTEGER, MG_CHECK_MAIL_LID,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "rid", MSIM_TYPE_INTEGER,
+- msim_new_reply_callback(session, msim_check_inbox_cb, NULL),
+- "body", MSIM_TYPE_STRING, g_strdup(""),
+- NULL), TRUE);
+-
+- /* Always return true, so that we keep checking for mail. */
+- return TRUE;
+-}
+-
+-/**
+- * Add contact from server to buddy list, after looking up username.
+- * Callback from msim_add_contact_from_server().
+- *
+- * @param data An MsimMessage * of the contact information. Will be freed.
+- */
+-static void
+-msim_add_contact_from_server_cb(MsimSession *session, const MsimMessage *user_lookup_info, gpointer data)
+-{
+- MsimMessage *contact_info, *user_lookup_info_body;
+- PurpleGroup *group;
+- PurpleBuddy *buddy;
+- MsimUser *user;
+- gchar *username, *group_name, *display_name;
+- guint uid, visibility;
+-
+- contact_info = (MsimMessage *)data;
+- purple_debug_info("msim_add_contact_from_server_cb", "contact_info addr=%p\n", contact_info);
+- uid = msim_msg_get_integer(contact_info, "ContactID");
+-
+- if (!user_lookup_info) {
+- username = g_strdup(msim_uid2username_from_blist(session->account, uid));
+- display_name = NULL;
+- g_return_if_fail(username != NULL);
+- } else {
+- user_lookup_info_body = msim_msg_get_dictionary(user_lookup_info, "body");
+- username = msim_msg_get_string(user_lookup_info_body, "UserName");
+- display_name = msim_msg_get_string(user_lookup_info_body, "DisplayName");
+- msim_msg_free(user_lookup_info_body);
+- g_return_if_fail(username != NULL);
+- }
+-
+- purple_debug_info("msim_add_contact_from_server_cb",
+- "*** about to add/update username=%s\n", username);
+-
+- /* 1. Creates a new group, or gets existing group if it exists (or so
+- * the documentation claims). */
+- group_name = msim_msg_get_string(contact_info, "GroupName");
+- if (!group_name || (*group_name == '\0')) {
+- g_free(group_name);
+- group_name = g_strdup(_("IM Friends"));
+- purple_debug_info("myspace", "No GroupName specified, defaulting to '%s'.\n", group_name);
+- }
+- group = purple_find_group(group_name);
+- if (!group) {
+- group = purple_group_new(group_name);
+- /* Add group to beginning. See #2752. */
+- purple_blist_add_group(group, NULL);
+- }
+- g_free(group_name);
+-
+- visibility = msim_msg_get_integer(contact_info, "Visibility");
+- if (visibility == 2) {
+- /* This buddy is blocked (and therefore not on our buddy list */
+- purple_privacy_deny_add(session->account, username, TRUE);
+- msim_msg_free(contact_info);
+- g_free(username);
+- g_free(display_name);
+- return;
+- }
+-
+- /* 2. Get or create buddy */
+- buddy = purple_find_buddy(session->account, username);
+- if (!buddy) {
+- purple_debug_info("msim_add_contact_from_server_cb",
+- "creating new buddy: %s\n", username);
+- buddy = purple_buddy_new(session->account, username, NULL);
+- }
+-
+- /* TODO: use 'Position' in contact_info to take into account where buddy is */
+- purple_blist_add_buddy(buddy, NULL, group, NULL /* insertion point */);
+-
+- if (strtol(username, NULL, 10) == uid) {
+- /*
+- * This user has not set their username! Set their server
+- * alias to their display name so that we don't see a bunch
+- * of numbers in the buddy list.
+- */
+- if (display_name != NULL) {
+- purple_blist_node_set_string(PURPLE_BLIST_NODE(buddy), "DisplayName", display_name);
+- serv_got_alias(session->gc, username, display_name);
+- } else {
+- serv_got_alias(session->gc, username,
+- purple_blist_node_get_string(PURPLE_BLIST_NODE(buddy), "DisplayName"));
+- }
+- }
+- g_free(display_name);
+-
+- /* 3. Update buddy information */
+- user = msim_get_user_from_buddy(buddy, TRUE);
+-
+- user->id = uid;
+- /* Keep track of the user ID across sessions */
+- purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", uid);
+-
+- /* Stores a few fields in the MsimUser, relevant to the buddy itself.
+- * AvatarURL, Headline, ContactID. */
+- msim_store_user_info(session, contact_info, NULL);
+-
+- /* TODO: other fields, store in 'user' */
+- msim_msg_free(contact_info);
+-
+- g_free(username);
+-}
+-
+-/**
+- * Add first ContactID in contact_info to buddy's list. Used to add
+- * server-side buddies to client-side list.
+- *
+- * @return TRUE if added.
+- */
+-static gboolean
+-msim_add_contact_from_server(MsimSession *session, MsimMessage *contact_info)
+-{
+- guint uid;
+- const gchar *username;
+-
+- uid = msim_msg_get_integer(contact_info, "ContactID");
+- g_return_val_if_fail(uid != 0, FALSE);
+-
+- /* Lookup the username, since NickName and IMName is unreliable */
+- username = msim_uid2username_from_blist(session->account, uid);
+- if (!username) {
+- gchar *uid_str;
+-
+- uid_str = g_strdup_printf("%d", uid);
+- purple_debug_info("msim_add_contact_from_server",
+- "contact_info addr=%p\n", contact_info);
+- msim_lookup_user(session, uid_str, msim_add_contact_from_server_cb, (gpointer)msim_msg_clone(contact_info));
+- g_free(uid_str);
+- } else {
+- msim_add_contact_from_server_cb(session, NULL, (gpointer)msim_msg_clone(contact_info));
+- }
+-
+- /* Say that the contact was added, even if we're still looking up
+- * their username. */
+- return TRUE;
+-}
+-
+-/**
+- * Called when contact list is received from server.
+- */
+-static void
+-msim_got_contact_list(MsimSession *session, const MsimMessage *reply, gpointer user_data)
+-{
+- MsimMessage *body, *body_node;
+- gchar *msg;
+- guint buddy_count;
+-
+- body = msim_msg_get_dictionary(reply, "body");
+-
+- buddy_count = 0;
+-
+- for (body_node = body;
+- body_node != NULL;
+- body_node = msim_msg_get_next_element_node(body_node))
+- {
+- MsimMessageElement *elem;
+-
+- elem = (MsimMessageElement *)body_node->data;
+-
+- if (g_str_equal(elem->name, "ContactID"))
+- {
+- /* Will look for first contact in body_node */
+- if (msim_add_contact_from_server(session, body_node)) {
+- ++buddy_count;
+- }
+- }
+- }
+-
+- switch (GPOINTER_TO_UINT(user_data)) {
+- case MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS:
+- msg = g_strdup_printf(ngettext("%d buddy was added or updated from the server (including buddies already on the server-side list)",
+- "%d buddies were added or updated from the server (including buddies already on the server-side list)",
+- buddy_count),
+- buddy_count);
+- purple_notify_info(session->account, _("Add contacts from server"), msg, NULL);
+- g_free(msg);
+- break;
+-
+- case MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS:
+- /* TODO */
+- break;
+-
+- case MSIM_CONTACT_LIST_INITIAL_FRIENDS:
+- /* The session is now set up, ready to be connected. This emits the
+- * signedOn signal, so clients can now do anything with msimprpl, and
+- * we're ready for it (session key, userid, username all setup). */
+- purple_connection_update_progress(session->gc, _("Connected"), 3, 4);
+- purple_connection_set_state(session->gc, PURPLE_CONNECTED);
+- break;
+- }
+-
+- msim_msg_free(body);
+-}
+-
+-/**
+- * Get contact list, calling msim_got_contact_list() with
+- * what_to_do_after as user_data gpointer.
+- *
+- * @param what_to_do_after should be one of the MSIM_CONTACT_LIST_* #defines.
+- */
+-static gboolean
+-msim_get_contact_list(MsimSession *session, int what_to_do_after)
+-{
+- return msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_DSN,
+- "lid", MSIM_TYPE_INTEGER, MG_LIST_ALL_CONTACTS_LID,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "rid", MSIM_TYPE_INTEGER,
+- msim_new_reply_callback(session, msim_got_contact_list, GUINT_TO_POINTER(what_to_do_after)),
+- "body", MSIM_TYPE_STRING, g_strdup(""),
+- NULL);
+-}
+-
+-/** Called after username is set, if necessary and we're open for business. */
+-gboolean msim_we_are_logged_on(MsimSession *session)
+-{
+- MsimMessage *body;
+-
+- /* Set display name to username (otherwise will show email address) */
+- purple_connection_set_display_name(session->gc, session->username);
+-
+- body = msim_msg_new(
+- "UserID", MSIM_TYPE_INTEGER, session->userid,
+- NULL);
+-
+- /* Request IM info about ourself. */
+- msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_DSN,
+- "lid", MSIM_TYPE_INTEGER, MG_OWN_MYSPACE_INFO_LID,
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- "UserID", MSIM_TYPE_INTEGER, session->userid,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL);
+-
+- /* Request MySpace info about ourself. */
+- msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_DSN,
+- "lid", MSIM_TYPE_INTEGER, MG_OWN_IM_INFO_LID,
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- "body", MSIM_TYPE_STRING, g_strdup(""),
+- NULL);
+-
+- /* TODO: set options (persist cmd=514,dsn=1,lid=10) */
+- /* TODO: set blocklist */
+-
+- /* Notify servers of our current status. */
+- purple_debug_info("msim", "msim_we_are_logged_on: notifying servers of status\n");
+- msim_set_status(session->account,
+- purple_account_get_active_status(session->account));
+-
+- /* TODO: setinfo */
+- /*
+- body = msim_msg_new(
+- "TotalFriends", MSIM_TYPE_INTEGER, 666,
+- NULL);
+- msim_send(session,
+- "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "info", MSIM_TYPE_DICTIONARY, body,
+- NULL);
+- */
+-
+- /* Disable due to problems with timeouts. TODO: fix. */
+-#ifdef MSIM_USE_KEEPALIVE
+- purple_timeout_add_seconds(MSIM_KEEPALIVE_INTERVAL_CHECK,
+- (GSourceFunc)msim_check_alive, session);
+-#endif
+-
+- /* Check mail if they want to. */
+- if (purple_account_get_check_mail(session->account)) {
+- session->inbox_handle = purple_timeout_add(MSIM_MAIL_INTERVAL_CHECK,
+- (GSourceFunc)msim_check_inbox, session);
+- msim_check_inbox(session);
+- }
+-
+- msim_get_contact_list(session, MSIM_CONTACT_LIST_INITIAL_FRIENDS);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Record the client version in the buddy list, from an incoming message.
+- */
+-static gboolean
+-msim_incoming_bm_record_cv(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *username, *cv;
+- gboolean ret;
+- MsimUser *user;
+-
+- username = msim_msg_get_string(msg, "_username");
+- cv = msim_msg_get_string(msg, "cv");
+-
+- g_return_val_if_fail(username != NULL, FALSE);
+- if (!cv) {
+- /* No client version to record, don't worry about it. */
+- g_free(username);
+- return FALSE;
+- }
+-
+- user = msim_find_user(session, username);
+-
+- if (user) {
+- user->client_cv = atol(cv);
+- ret = TRUE;
+- } else {
+- ret = FALSE;
+- }
+-
+- g_free(username);
+- g_free(cv);
+-
+- return ret;
+-}
+-
+-#ifdef MSIM_SEND_CLIENT_VERSION
+-/**
+- * Send our client version to another unofficial client that understands it.
+- */
+-static gboolean
+-msim_send_unofficial_client(MsimSession *session, gchar *username)
+-{
+- gchar *our_info;
+- gboolean ret;
+-
+- our_info = g_strdup_printf("Libpurple %d.%d.%d - msimprpl %s",
+- PURPLE_MAJOR_VERSION,
+- PURPLE_MINOR_VERSION,
+- PURPLE_MICRO_VERSION,
+- MSIM_PRPL_VERSION_STRING);
+-
+- ret = msim_send_bm(session, username, our_info, MSIM_BM_UNOFFICIAL_CLIENT);
+-
+- return ret;
+-}
+-#endif
+-/**
+- * Process incoming status mood messages.
+- *
+- * @param session
+- * @param msg Status mood update message. Caller frees.
+- *
+- * @return TRUE if successful.
+- */
+-static gboolean
+-msim_incoming_status_mood(MsimSession *session, MsimMessage *msg) {
+- /* TODO: I dont know too much about this yet,
+- * so until I see how the official client handles
+- * this and decide if libpurple should as well,
+- * well just say we used it
+- */
+- gchar *ss;
+- ss = msim_msg_get_string(msg, "msg");
+- purple_debug_info("msim", "Incoming Status Message: %s", ss ? ss : "(NULL)");
+- g_free(ss);
+- return TRUE;
+-}
+-
+-/**
+- * Process incoming status messages.
+- *
+- * @param session
+- * @param msg Status update message. Caller frees.
+- *
+- * @return TRUE if successful.
+- */
+-static gboolean
+-msim_incoming_status(MsimSession *session, MsimMessage *msg)
+-{
+- MsimUser *user;
+- GList *list;
+- gchar *status_headline, *status_headline_escaped;
+- gint status_code, purple_status_code;
+- gchar *username;
+- gchar *unrecognized_msg;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- /* Helpfully looked up by msim_incoming_resolve() for us. */
+- username = msim_msg_get_string(msg, "_username");
+- g_return_val_if_fail(username != NULL, FALSE);
+-
+- {
+- gchar *ss;
+-
+- ss = msim_msg_get_string(msg, "msg");
+- purple_debug_info("msim",
+- "msim_status: updating status for <%s> to <%s>\n",
+- username, ss ? ss : "(NULL)");
+- g_free(ss);
+- }
+-
+- /* Example fields:
+- * |s|0|ss|Offline
+- * |s|1|ss|:-)|ls||ip|0|p|0
+- */
+- list = msim_msg_get_list(msg, "msg");
+-
+- status_code = msim_msg_get_integer_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_ONLINE));
+- purple_debug_info("msim", "msim_status: %s's status code = %d\n", username, status_code);
+- status_headline = msim_msg_get_string_from_element(g_list_nth_data(list, MSIM_STATUS_ORDINAL_HEADLINE));
+-
+- /* Add buddy if not found.
+- * TODO: Could this be responsible for #3444? */
+- user = msim_find_user(session, username);
+- if (!user) {
+- PurpleBuddy *buddy;
+-
+- purple_debug_info("msim",
+- "msim_status: making new buddy for %s\n", username);
+- buddy = purple_buddy_new(session->account, username, NULL);
+- purple_blist_add_buddy(buddy, NULL, NULL, NULL);
+-
+- user = msim_get_user_from_buddy(buddy, TRUE);
+- user->id = msim_msg_get_integer(msg, "f");
+-
+- /* Keep track of the user ID across sessions */
+- purple_blist_node_set_int(PURPLE_BLIST_NODE(buddy), "UserID", user->id);
+-
+- msim_store_user_info(session, msg, NULL);
+- } else {
+- purple_debug_info("msim", "msim_status: found buddy %s\n", username);
+- }
+-
+- if (status_headline && strcmp(status_headline, "") != 0) {
+- /* The status headline is plaintext, but libpurple treats it as HTML,
+- * so escape any HTML characters to their entity equivalents. */
+- status_headline_escaped = g_markup_escape_text(status_headline, -1);
+- } else {
+- status_headline_escaped = NULL;
+- }
+-
+- g_free(status_headline);
+-
+- /* don't copy; let the MsimUser own the headline, memory-wise */
+- g_free(user->headline);
+- user->headline = status_headline_escaped;
+-
+- /* Set user status */
+- switch (status_code) {
+- case MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN:
+- purple_status_code = PURPLE_STATUS_OFFLINE;
+- break;
+-
+- case MSIM_STATUS_CODE_ONLINE:
+- purple_status_code = PURPLE_STATUS_AVAILABLE;
+- break;
+-
+- case MSIM_STATUS_CODE_AWAY:
+- purple_status_code = PURPLE_STATUS_AWAY;
+- break;
+-
+- case MSIM_STATUS_CODE_IDLE:
+- /* Treat idle as an available status. */
+- purple_status_code = PURPLE_STATUS_AVAILABLE;
+- break;
+-
+- default:
+- purple_debug_info("msim", "msim_incoming_status for %s, unknown status code %d, treating as available\n",
+- username, status_code);
+- purple_status_code = PURPLE_STATUS_AVAILABLE;
+-
+- unrecognized_msg = g_strdup_printf("msim_incoming_status, unrecognized status code: %d\n",
+- status_code);
+- msim_unrecognized(session, NULL, unrecognized_msg);
+- g_free(unrecognized_msg);
+- }
+-
+- purple_prpl_got_user_status(session->account, username, purple_primitive_get_id_from_type(purple_status_code), NULL);
+-
+- if (status_code == MSIM_STATUS_CODE_IDLE) {
+- purple_debug_info("msim", "msim_status: got idle: %s\n", username);
+- purple_prpl_got_user_idle(session->account, username, TRUE, 0);
+- } else {
+- /* All other statuses indicate going back to non-idle. */
+- purple_prpl_got_user_idle(session->account, username, FALSE, 0);
+- }
+-
+-#ifdef MSIM_SEND_CLIENT_VERSION
+- if (status_code == MSIM_STATUS_CODE_ONLINE) {
+- /* Secretly whisper to unofficial clients our own version as they come online */
+- msim_send_unofficial_client(session, username);
+- }
+-#endif
+-
+- if (status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN) {
+- /* Get information when they come online.
+- * TODO: periodically refresh?
+- */
+- purple_debug_info("msim_incoming_status", "%s came online, looking up\n", username);
+- msim_lookup_user(session, username, NULL, NULL);
+- }
+-
+- g_free(username);
+- msim_msg_list_free(list);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Handle an incoming instant message.
+- *
+- * @param session The session
+- * @param msg Message from the server, containing 'f' (userid from) and 'msg'.
+- * Should also contain username in _username from preprocessing.
+- *
+- * @return TRUE if successful.
+- */
+-static gboolean
+-msim_incoming_im(MsimSession *session, MsimMessage *msg, const gchar *username)
+-{
+- gchar *msg_msim_markup, *msg_purple_markup;
+- gchar *userid;
+- time_t time_received;
+- PurpleConversation *conv;
+-
+- /* I know this isn't really a string... but we need it to be one for
+- * purple_find_conversation_with_account(). */
+- userid = msim_msg_get_string(msg, "f");
+-
+- purple_debug_info("msim_incoming_im", "UserID is %s", userid);
+-
+- if (msim_is_userid(username)) {
+- purple_debug_info("msim", "Ignoring message from spambot (%s) on account %s\n",
+- username, purple_account_get_username(session->account));
+- return FALSE;
+- }
+-
+- /* See if a conversation with their UID already exists...*/
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, userid, session->account);
+- if (conv) {
+- /* Since the conversation exists... We need to normalize it */
+- purple_conversation_set_name(conv, username);
+- }
+-
+- msg_msim_markup = msim_msg_get_string(msg, "msg");
+- g_return_val_if_fail(msg_msim_markup != NULL, FALSE);
+-
+- msg_purple_markup = msim_markup_to_html(session, msg_msim_markup);
+- g_free(msg_msim_markup);
+-
+- time_received = msim_msg_get_integer(msg, "date");
+- if (!time_received) {
+- purple_debug_info("msim_incoming_im", "date in message not set.\n");
+- time_received = time(NULL);
+- }
+-
+- serv_got_im(session->gc, username, msg_purple_markup, PURPLE_MESSAGE_RECV, time_received);
+-
+- g_free(msg_purple_markup);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Handle an incoming action message or an IM.
+- *
+- * @param session
+- * @param msg
+- *
+- * @return TRUE if successful.
+- */
+-static gboolean
+-msim_incoming_action_or_im(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *msg_text, *username;
+- gboolean rc;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- msg_text = msim_msg_get_string(msg, "msg");
+- g_return_val_if_fail(msg_text != NULL, FALSE);
+-
+- username = msim_msg_get_string(msg, "_username");
+- g_return_val_if_fail(username != NULL, FALSE);
+-
+- purple_debug_info("msim",
+- "msim_incoming_action_or_im: action <%s> from <%s>\n",
+- msg_text, username);
+-
+- if (g_str_equal(msg_text, "%typing%")) {
+- serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
+- rc = TRUE;
+- } else if (g_str_equal(msg_text, "%stoptyping%")) {
+- serv_got_typing_stopped(session->gc, username);
+- rc = TRUE;
+- } else if (strstr(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_")) {
+- rc = msim_incoming_zap(session, msg);
+- } else if (strstr(msg_text, "!!!GroupCount=")) {
+- /* TODO: support group chats. I think the number in msg_text has
+- * something to do with the 'gid' field. */
+- purple_debug_info("msim",
+- "msim_incoming_action_or_im: "
+- "TODO: implement #4691, group chats: %s\n", msg_text);
+-
+- rc = TRUE;
+- } else if (strstr(msg_text, "!!!Offline=")) {
+- /* TODO: support group chats. This one might mean a user
+- * went offline or exited the chat. */
+- purple_debug_info("msim", "msim_incoming_action_or_im: "
+- "TODO: implement #4691, group chats: %s\n", msg_text);
+-
+- rc = TRUE;
+- } else if (msim_msg_get_integer(msg, "aid") != 0) {
+- purple_debug_info("msim", "TODO: implement #4691, group chat from %d on %d: %s\n",
+- msim_msg_get_integer(msg, "aid"),
+- msim_msg_get_integer(msg, "f"),
+- msg_text);
+-
+- rc = TRUE;
+- } else {
+- rc = msim_incoming_im(session, msg, username);
+- }
+-
+- g_free(msg_text);
+- g_free(username);
+-
+- return rc;
+-}
+-
+-/**
+- * Process an incoming media (message background?) message.
+- */
+-static gboolean
+-msim_incoming_media(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *username, *text;
+-
+- username = msim_msg_get_string(msg, "_username");
+- text = msim_msg_get_string(msg, "msg");
+-
+- g_return_val_if_fail(username != NULL, FALSE);
+- g_return_val_if_fail(text != NULL, FALSE);
+-
+- purple_debug_info("msim", "msim_incoming_media: from %s, got msg=%s\n", username, text);
+-
+- /* Media messages are sent when the user opens a window to someone.
+- * Tell libpurple they started typing and stopped typing, to inform the Psychic
+- * Mode plugin so it too can open a window to the user. */
+- serv_got_typing(session->gc, username, 0, PURPLE_TYPING);
+- serv_got_typing_stopped(session->gc, username);
+-
+- g_free(username);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Process an incoming "unofficial client" message. The plugin for
+- * Miranda IM sends this message with the plugin information.
+- */
+-static gboolean
+-msim_incoming_unofficial_client(MsimSession *session, MsimMessage *msg)
+-{
+- MsimUser *user;
+- gchar *username, *client_info;
+-
+- username = msim_msg_get_string(msg, "_username");
+- client_info = msim_msg_get_string(msg, "msg");
+-
+- g_return_val_if_fail(username != NULL, FALSE);
+- g_return_val_if_fail(client_info != NULL, FALSE);
+-
+- purple_debug_info("msim", "msim_incoming_unofficial_client: %s is using client %s\n",
+- username, client_info);
+-
+- user = msim_find_user(session, username);
+-
+- g_return_val_if_fail(user != NULL, FALSE);
+-
+- if (user->client_info) {
+- g_free(user->client_info);
+- }
+- user->client_info = client_info;
+-
+- g_free(username);
+- /* Do not free client_info - the MsimUser now owns it. */
+-
+- return TRUE;
+-}
+-
+-/**
+- * Handle an incoming buddy message.
+- */
+-static gboolean
+-msim_incoming_bm(MsimSession *session, MsimMessage *msg)
+-{
+- guint bm;
+-
+- bm = msim_msg_get_integer(msg, "bm");
+-
+- msim_incoming_bm_record_cv(session, msg);
+-
+- switch (bm) {
+- case MSIM_BM_STATUS:
+- return msim_incoming_status(session, msg);
+- case MSIM_BM_ACTION_OR_IM_DELAYABLE:
+- case MSIM_BM_ACTION_OR_IM_INSTANT:
+- return msim_incoming_action_or_im(session, msg);
+- case MSIM_BM_MEDIA:
+- return msim_incoming_media(session, msg);
+- case MSIM_BM_UNOFFICIAL_CLIENT:
+- return msim_incoming_unofficial_client(session, msg);
+- case MSIM_BM_STATUS_MOOD:
+- return msim_incoming_status_mood(session, msg);
+- default:
+- /*
+- * Unknown message type! We used to call
+- * msim_incoming_action_or_im(session, msg);
+- * for these, but that doesn't help anything, and it means
+- * we'll show broken gibberish if MySpace starts sending us
+- * other message types.
+- */
+- purple_debug_warning("myspace", "Received unknown imcoming "
+- "message, bm=%u\n", bm);
+- return TRUE;
+- }
+-}
+-
+-/**
+- * Process the initial server information from the server.
+- */
+-static gboolean
+-msim_process_server_info(MsimSession *session, MsimMessage *msg)
+-{
+- MsimMessage *body;
+-
+- body = msim_msg_get_dictionary(msg, "body");
+- g_return_val_if_fail(body != NULL, FALSE);
+-
+- /* Example body:
+-AdUnitRefreshInterval=10.
+-AlertPollInterval=360.
+-AllowChatRoomEmoticonSharing=False.
+-ChatRoomUserIDs=78744676;163733130;1300326231;123521495;142663391.
+-CurClientVersion=673.
+-EnableIMBrowse=True.
+-EnableIMStuffAvatars=False.
+-EnableIMStuffZaps=False.
+-MaxAddAllFriends=100.
+-MaxContacts=1000.
+-MinClientVersion=594.
+-MySpaceIM_ENGLISH=78744676.
+-MySpaceNowTimer=720.
+-PersistenceDataTimeout=900.
+-UseWebChallenge=1.
+-WebTicketGoHome=False
+-
+- Anything useful? TODO: use what is useful, and use it.
+-*/
+- purple_debug_info("msim_process_server_info",
+- "maximum contacts: %d\n",
+- msim_msg_get_integer(body, "MaxContacts"));
+-
+- session->server_info = body;
+- /* session->server_info freed in msim_session_destroy */
+-
+- return TRUE;
+-}
+-
+-/**
+- * Process a web challenge, used to login to the web site.
+- */
+-static gboolean
+-msim_web_challenge(MsimSession *session, MsimMessage *msg)
+-{
+- /* TODO: web challenge, store token. #2659. */
+- return FALSE;
+-}
+-
+-/**
+- * Process a persistance message reply from the server.
+- *
+- * @param session
+- * @param msg Message reply from server.
+- *
+- * @return TRUE if successful.
+- *
+- * msim_lookup_user sets callback for here
+- */
+-static gboolean
+-msim_process_reply(MsimSession *session, MsimMessage *msg)
+-{
+- MSIM_USER_LOOKUP_CB cb;
+- gpointer data;
+- guint rid, cmd, dsn, lid;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- msim_store_user_info(session, msg, NULL);
+-
+- rid = msim_msg_get_integer(msg, "rid");
+- cmd = msim_msg_get_integer(msg, "cmd");
+- dsn = msim_msg_get_integer(msg, "dsn");
+- lid = msim_msg_get_integer(msg, "lid");
+-
+- /* Unsolicited messages */
+- if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)) {
+- if (dsn == MG_SERVER_INFO_DSN && lid == MG_SERVER_INFO_LID) {
+- return msim_process_server_info(session, msg);
+- } else if (dsn == MG_WEB_CHALLENGE_DSN && lid == MG_WEB_CHALLENGE_LID) {
+- return msim_web_challenge(session, msg);
+- }
+- }
+-
+- /* If a callback is registered for this userid lookup, call it. */
+- cb = g_hash_table_lookup(session->user_lookup_cb, GUINT_TO_POINTER(rid));
+- data = g_hash_table_lookup(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
+-
+- if (cb) {
+- purple_debug_info("msim", "msim_process_reply: calling callback now\n");
+- /* Clone message, so that the callback 'cb' can use it (needs to free it also). */
+- cb(session, msg, data);
+- g_hash_table_remove(session->user_lookup_cb, GUINT_TO_POINTER(rid));
+- g_hash_table_remove(session->user_lookup_cb_data, GUINT_TO_POINTER(rid));
+- } else {
+- purple_debug_info("msim",
+- "msim_process_reply: no callback for rid %d\n", rid);
+- }
+-
+- return TRUE;
+-}
+-
+-/**
+- * Handle an error from the server.
+- *
+- * @param session
+- * @param msg The message.
+- *
+- * @return TRUE if successfully reported error.
+- */
+-static gboolean
+-msim_error(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *errmsg, *full_errmsg;
+- guint err;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- err = msim_msg_get_integer(msg, "err");
+- errmsg = msim_msg_get_string(msg, "errmsg");
+-
+- full_errmsg = g_strdup_printf(_("Protocol error, code %d: %s"), err,
+- errmsg ? errmsg : "no 'errmsg' given");
+-
+- g_free(errmsg);
+-
+- purple_debug_info("msim", "msim_error (sesskey=%d): %s\n",
+- session->sesskey, full_errmsg);
+-
+- /* Destroy session if fatal. */
+- if (msim_msg_get(msg, "fatal")) {
+- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- purple_debug_info("msim", "fatal error, closing\n");
+-
+- switch (err) {
+- case MSIM_ERROR_INCORRECT_PASSWORD: /* Incorrect password */
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- if (!purple_account_get_remember_password(session->account))
+- purple_account_set_password(session->account, NULL);
+-#ifdef MSIM_MAX_PASSWORD_LENGTH
+- if (session->account->password && (strlen(session->account->password) > MSIM_MAX_PASSWORD_LENGTH)) {
+- gchar *suggestion;
+-
+- suggestion = g_strdup_printf(_("%s Your password is "
+- "%zu characters, which is longer than the "
+- "maximum length of %d. Please shorten your "
+- "password at http://profileedit.myspace.com/index.cfm?fuseaction=accountSettings.changePassword and try again."),
+- full_errmsg,
+- strlen(session->account->password),
+- MSIM_MAX_PASSWORD_LENGTH);
+-
+- /* Replace full_errmsg. */
+- g_free(full_errmsg);
+- full_errmsg = suggestion;
+- } else {
+- g_free(full_errmsg);
+- full_errmsg = g_strdup(_("Incorrect username or password"));
+- }
+-#endif
+- break;
+- case MSIM_ERROR_LOGGED_IN_ELSEWHERE: /* Logged in elsewhere */
+- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
+- if (!purple_account_get_remember_password(session->account))
+- purple_account_set_password(session->account, NULL);
+- break;
+- }
+- purple_connection_error_reason(session->gc, reason, full_errmsg);
+- } else {
+- purple_notify_error(session->account, _("MySpaceIM Error"), full_errmsg, NULL);
+- }
+-
+- g_free(full_errmsg);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Process a message.
+- *
+- * @param session
+- * @param msg A message from the server, ready for processing (possibly with resolved username information attached). Caller frees.
+- *
+- * @return TRUE if successful. FALSE if processing failed.
+- */
+-static gboolean
+-msim_process(MsimSession *session, MsimMessage *msg)
+-{
+- g_return_val_if_fail(session != NULL, FALSE);
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- if (msim_msg_get_integer(msg, "lc") == 1) {
+- return msim_login_challenge(session, msg);
+- } else if (msim_msg_get_integer(msg, "lc") == 2) {
+- /* return msim_we_are_logged_on(session, msg); */
+- if (msim_is_username_set(session, msg)) {
+- return msim_we_are_logged_on(session);
+- } else {
+- /* No username is set... We'll wait for the callbacks to do their work */
+- /* When they're all done, the last one will call msim_we_are_logged_on() and pick up where we left off */
+- return FALSE;
+- }
+- } else if (msim_msg_get(msg, "bm")) {
+- return msim_incoming_bm(session, msg);
+- } else if (msim_msg_get(msg, "rid")) {
+- return msim_process_reply(session, msg);
+- } else if (msim_msg_get(msg, "error")) {
+- return msim_error(session, msg);
+- } else if (msim_msg_get(msg, "ka")) {
+- return TRUE;
+- } else {
+- msim_unrecognized(session, msg, "in msim_process");
+- return FALSE;
+- }
+-}
+-
+-/**
+- * After a uid is resolved to username, tag it with the username and submit for processing.
+- *
+- * @param session
+- * @param userinfo Response messsage to resolving request.
+- * @param data MsimMessage *, the message to attach information to.
+- */
+-static void
+-msim_incoming_resolved(MsimSession *session, const MsimMessage *userinfo,
+- gpointer data)
+-{
+- gchar *username;
+- MsimMessage *msg, *body;
+-
+- g_return_if_fail(userinfo != NULL);
+-
+- body = msim_msg_get_dictionary(userinfo, "body");
+- g_return_if_fail(body != NULL);
+-
+- username = msim_msg_get_string(body, "UserName");
+- g_return_if_fail(username != NULL);
+- /* Note: username will be owned by 'msg' below. */
+-
+- msg = (MsimMessage *)data;
+- g_return_if_fail(msg != NULL);
+-
+- /* TODO: more elegant solution than below. attach whole message? */
+- /* Special elements name beginning with '_', we'll use internally within the
+- * program (did not come directly from the wire). */
+- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, username); /* This makes 'msg' the owner of 'username' */
+-
+- /* TODO: attach more useful information, like ImageURL */
+-
+- msim_process(session, msg);
+-
+- msim_msg_free(msg);
+- msim_msg_free(body);
+-}
+-
+-/**
+- * Preprocess incoming messages, resolving as needed, calling
+- * msim_process() when ready to process.
+- *
+- * @param session
+- * @param msg MsimMessage *, freed by caller.
+- */
+-static gboolean
+-msim_preprocess_incoming(MsimSession *session, MsimMessage *msg)
+-{
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- if (msim_msg_get(msg, "bm") && msim_msg_get(msg, "f")) {
+- guint uid;
+- const gchar *username;
+-
+- /* 'f' = userid message is from, in buddy messages */
+- uid = msim_msg_get_integer(msg, "f");
+-
+- username = msim_uid2username_from_blist(session->account, uid);
+-
+- if (username) {
+- /* Know username already, use it. */
+- purple_debug_info("msim", "msim_preprocess_incoming: tagging with _username=%s\n",
+- username);
+- msg = msim_msg_append(msg, "_username", MSIM_TYPE_STRING, g_strdup(username));
+- return msim_process(session, msg);
+-
+- } else {
+- gchar *from;
+-
+- /* Send lookup request. */
+- /* XXX: where is msim_msg_get_string() freed? make _strdup and _nonstrdup. */
+- purple_debug_info("msim", "msim_incoming: sending lookup, setting up callback\n");
+- from = msim_msg_get_string(msg, "f");
+- msim_lookup_user(session, from, msim_incoming_resolved, msim_msg_clone(msg));
+- g_free(from);
+-
+- /* indeterminate */
+- return TRUE;
+- }
+- } else {
+- /* Nothing to resolve - send directly to processing. */
+- return msim_process(session, msg);
+- }
+-}
+-
+-/**
+- * Callback when input available.
+- *
+- * @param gc_uncasted A PurpleConnection pointer.
+- * @param source File descriptor.
+- * @param cond PURPLE_INPUT_READ
+- *
+- * Reads the input, and calls msim_preprocess_incoming() to handle it.
+- */
+-static void
+-msim_input_cb(gpointer gc_uncasted, gint source, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc;
+- MsimSession *session;
+- gchar *end;
+- int n;
+-
+- g_return_if_fail(gc_uncasted != NULL);
+- g_return_if_fail(source >= 0); /* Note: 0 is a valid fd */
+-
+- gc = (PurpleConnection *)(gc_uncasted);
+- session = gc->proto_data;
+-
+- /* libpurple/eventloop.h only defines these two */
+- if (cond != PURPLE_INPUT_READ && cond != PURPLE_INPUT_WRITE) {
+- purple_debug_info("msim_input_cb", "unknown condition=%d\n", cond);
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Invalid input condition"));
+- return;
+- }
+-
+- g_return_if_fail(cond == PURPLE_INPUT_READ);
+-
+- /* Mark down that we got data, so we don't timeout. */
+- session->last_comm = time(NULL);
+-
+- /* If approaching end of buffer, reallocate some more memory. */
+- if (session->rxsize < session->rxoff + MSIM_READ_BUF_SIZE) {
+- purple_debug_info("msim",
+- "msim_input_cb: %d-byte read buffer full, rxoff=%d, " "growing by %d bytes\n",
+- session->rxsize, session->rxoff, MSIM_READ_BUF_SIZE);
+- session->rxsize += MSIM_READ_BUF_SIZE;
+- session->rxbuf = g_realloc(session->rxbuf, session->rxsize);
+-
+- return;
+- }
+-
+- purple_debug_info("msim", "dynamic buffer at %d (max %d), reading up to %d\n",
+- session->rxoff, session->rxsize,
+- MSIM_READ_BUF_SIZE - session->rxoff - 1);
+-
+- /* Read into buffer. On Win32, need recv() not read(). session->fd also holds
+- * the file descriptor, but it sometimes differs from the 'source' parameter.
+- */
+- n = recv(session->fd,
+- session->rxbuf + session->rxoff,
+- session->rxsize - session->rxoff - 1, 0);
+-
+- if (n < 0) {
+- gchar *tmp;
+-
+- if (errno == EAGAIN)
+- /* No worries */
+- return;
+-
+- tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- } else if (n == 0) {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Server closed the connection"));
+- return;
+- }
+-
+- /* Null terminate */
+- purple_debug_info("msim", "msim_input_cb: going to null terminate "
+- "at n=%d\n", n);
+- session->rxbuf[session->rxoff + n] = 0;
+-
+-#ifdef MSIM_CHECK_EMBEDDED_NULLS
+- /* Check for embedded NULs. I don't handle them, and they shouldn't occur. */
+- if (strlen(session->rxbuf + session->rxoff) != n) {
+- /* Occurs after login, but it is not a null byte. */
+- purple_debug_info("msim", "msim_input_cb: strlen=%d, but read %d bytes"
+- "--null byte encountered?\n",
+- strlen(session->rxbuf + session->rxoff), n);
+- /*purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- "Invalid message - null byte on input"); */
+- return;
+- }
+-#endif
+-
+- session->rxoff += n;
+- purple_debug_info("msim", "msim_input_cb: read=%d\n", n);
+-
+-#ifdef MSIM_DEBUG_RXBUF
+- purple_debug_info("msim", "buf=<%s>\n", session->rxbuf);
+-#endif
+-
+- /* Look for \\final\\ end markers. If found, process message. */
+- while((end = strstr(session->rxbuf, MSIM_FINAL_STRING))) {
+- MsimMessage *msg;
+-
+-#ifdef MSIM_DEBUG_RXBUF
+- purple_debug_info("msim", "in loop: buf=<%s>\n", session->rxbuf);
+-#endif
+- *end = 0;
+- msg = msim_parse(session->rxbuf);
+- if (!msg) {
+- purple_debug_info("msim", "msim_input_cb: couldn't parse rxbuf\n");
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to parse message"));
+- break;
+- } else {
+- /* Process message and then free it (processing function should
+- * clone message if it wants to keep it afterwards.) */
+- if (!msim_preprocess_incoming(session, msg)) {
+- msim_msg_dump("msim_input_cb: preprocessing message failed on msg: %s\n", msg);
+- }
+- msim_msg_free(msg);
+- }
+-
+- /* Move remaining part of buffer to beginning. */
+- session->rxoff -= strlen(session->rxbuf) + strlen(MSIM_FINAL_STRING);
+- memmove(session->rxbuf, end + strlen(MSIM_FINAL_STRING),
+- session->rxsize - (end + strlen(MSIM_FINAL_STRING) - session->rxbuf));
+-
+- /* Clear end of buffer
+- * memset(end, 0, MSIM_READ_BUF_SIZE - (end - session->rxbuf));
+- */
+- }
+-}
+-
+-/**
+- * Callback when connected. Sets up input handlers.
+- *
+- * @param data A PurpleConnection pointer.
+- * @param source File descriptor.
+- * @param error_message
+- */
+-static void
+-msim_connect_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleConnection *gc;
+- MsimSession *session;
+-
+- g_return_if_fail(data != NULL);
+-
+- gc = (PurpleConnection *)data;
+- session = (MsimSession *)gc->proto_data;
+-
+- if (source < 0) {
+- gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
+- error_message);
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- session->fd = source;
+-
+- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, msim_input_cb, gc);
+-}
+-
+-/**
+- * Start logging in to the MSIM servers.
+- *
+- * @param acct Account information to use to login.
+- */
+-static void
+-msim_login(PurpleAccount *acct)
+-{
+- PurpleConnection *gc;
+- const gchar *host;
+- int port;
+-
+- g_return_if_fail(acct != NULL);
+- g_return_if_fail(acct->username != NULL);
+-
+- purple_debug_info("msim", "logging in %s\n", acct->username);
+-
+- gc = purple_account_get_connection(acct);
+- gc->proto_data = msim_session_new(acct);
+- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_URLDESC;
+-
+- /*
+- * Lets wipe out our local list of blocked buddies. We'll get a
+- * list of all blocked buddies from the server, and we shouldn't
+- * have stuff in the local list that isn't on the server list.
+- */
+- while (acct->deny != NULL)
+- purple_privacy_deny_remove(acct, acct->deny->data, TRUE);
+-
+- /* 1. connect to server */
+- purple_connection_update_progress(gc, _("Connecting"),
+- 0, /* which connection step this is */
+- 4); /* total number of steps */
+-
+- host = purple_account_get_string(acct, "server", MSIM_SERVER);
+- port = purple_account_get_int(acct, "port", MSIM_PORT);
+-
+- /* From purple.sf.net/api:
+- * """Note that this function name can be misleading--although it is called
+- * "proxy connect," it is used for establishing any outgoing TCP connection,
+- * whether through a proxy or not.""" */
+-
+- /* Calls msim_connect_cb when connected. */
+- if (!purple_proxy_connect(gc, acct, host, port, msim_connect_cb, gc)) {
+- /* TODO: try other ports if in auto mode, then save
+- * working port and try that first next time. */
+- purple_connection_error_reason (gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- return;
+- }
+-}
+-
+-static void
+-msim_buddy_free(PurpleBuddy *buddy)
+-{
+- msim_user_free(purple_buddy_get_protocol_data(buddy));
+- purple_buddy_set_protocol_data(buddy, NULL);
+-}
+-
+-/**
+- * Close the connection.
+- *
+- * @param gc The connection.
+- */
+-static void
+-msim_close(PurpleConnection *gc)
+-{
+- GSList *buddies;
+- MsimSession *session;
+-
+- if (gc == NULL) {
+- return;
+- }
+-
+- /*
+- * Free our protocol-specific buddy data. It almost seems like libpurple
+- * should call our buddy_free prpl callback so that we don't need to do
+- * this... but it doesn't, so we do.
+- */
+- buddies = purple_find_buddies(purple_connection_get_account(gc), NULL);
+- while (buddies != NULL) {
+- msim_buddy_free(buddies->data);
+- buddies = g_slist_delete_link(buddies, buddies);
+- }
+-
+- session = (MsimSession *)gc->proto_data;
+- if (session == NULL)
+- return;
+-
+- gc->proto_data = NULL;
+-
+- if (session->gc->inpa) {
+- purple_input_remove(session->gc->inpa);
+- }
+- if (session->fd >= 0) {
+- close(session->fd);
+- session->fd = -1;
+- }
+-
+- msim_session_destroy(session);
+-}
+-
+-/**
+- * Schedule an IM to be sent once the user ID is looked up.
+- *
+- * @param gc Connection.
+- * @param who A user id, email, or username to send the message to.
+- * @param message Instant message text to send.
+- * @param flags Flags.
+- *
+- * @return 1 if successful or postponed, -1 if failed
+- *
+- * Allows sending to a user by username, email address, or userid. If
+- * a username or email address is given, the userid must be looked up.
+- * This function does that by calling msim_postprocess_outgoing().
+- */
+-static int
+-msim_send_im(PurpleConnection *gc, const gchar *who, const gchar *message,
+- PurpleMessageFlags flags)
+-{
+- MsimSession *session;
+- gchar *message_msim;
+- int rc;
+-
+- g_return_val_if_fail(gc != NULL, -1);
+- g_return_val_if_fail(who != NULL, -1);
+- g_return_val_if_fail(message != NULL, -1);
+-
+- /* 'flags' has many options, not used here. */
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- message_msim = html_to_msim_markup(session, message);
+-
+- if (msim_send_bm(session, who, message_msim, MSIM_BM_ACTION_OR_IM_DELAYABLE)) {
+- /* Return 1 to have Purple show this IM as being sent, 0 to not. I always
+- * return 1 even if the message could not be sent, since I don't know if
+- * it has failed yet--because the IM is only sent after the userid is
+- * retrieved from the server (which happens after this function returns).
+- * If an error does occur, it should be logged to the IM window.
+- */
+- rc = 1;
+- } else {
+- rc = -1;
+- }
+-
+- g_free(message_msim);
+-
+- return rc;
+-}
+-
+-/**
+- * Handle when our user starts or stops typing to another user.
+- *
+- * @param gc
+- * @param name The buddy name to which our user is typing to
+- * @param state PURPLE_TYPING, PURPLE_TYPED, PURPLE_NOT_TYPING
+- *
+- * @return 0
+- */
+-static unsigned int
+-msim_send_typing(PurpleConnection *gc, const gchar *name,
+- PurpleTypingState state)
+-{
+- const gchar *typing_str;
+- MsimSession *session;
+-
+- g_return_val_if_fail(gc != NULL, 0);
+- g_return_val_if_fail(name != NULL, 0);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- switch (state) {
+- case PURPLE_TYPING:
+- typing_str = "%typing%";
+- break;
+-
+- case PURPLE_TYPED:
+- case PURPLE_NOT_TYPING:
+- default:
+- typing_str = "%stoptyping%";
+- break;
+- }
+-
+- purple_debug_info("msim", "msim_send_typing(%s): %d (%s)\n", name, state, typing_str);
+- msim_send_bm(session, name, typing_str, MSIM_BM_ACTION_OR_IM_INSTANT);
+- return 0;
+-}
+-
+-/**
+- * Callback for msim_get_info(), for when user info is received.
+- */
+-static void
+-msim_get_info_cb(MsimSession *session, const MsimMessage *user_info_msg,
+- gpointer data)
+-{
+- MsimMessage *msg;
+- gchar *username;
+- PurpleNotifyUserInfo *user_info;
+- MsimUser *user;
+-
+- /* Get user{name,id} from msim_get_info, passed as an MsimMessage for
+- orthogonality. */
+- msg = (MsimMessage *)data;
+- g_return_if_fail(msg != NULL);
+-
+- username = msim_msg_get_string(msg, "user");
+- if (!username) {
+- purple_debug_info("msim", "msim_get_info_cb: no 'user' in msg\n");
+- return;
+- }
+-
+- msim_msg_free(msg);
+- purple_debug_info("msim", "msim_get_info_cb: got for user: %s\n", username);
+-
+- user = msim_find_user(session, username);
+-
+- if (!user) {
+- /* User isn't on blist, create a temporary user to store info. */
+- user = g_new0(MsimUser, 1);
+- user->temporary_user = TRUE;
+- }
+-
+- /* Update user structure with new information */
+- msim_store_user_info(session, user_info_msg, user);
+-
+- user_info = purple_notify_user_info_new();
+-
+- /* Append data from MsimUser to PurpleNotifyUserInfo for display, full */
+- msim_append_user_info(session, user_info, user, TRUE);
+-
+- purple_notify_userinfo(session->gc, username, user_info, NULL, NULL);
+- purple_debug_info("msim", "msim_get_info_cb: username=%s\n", username);
+-
+- purple_notify_user_info_destroy(user_info);
+-
+- if (user->temporary_user)
+- msim_user_free(user);
+- g_free(username);
+-}
+-
+-/**
+- * Retrieve a user's profile.
+- * @param username Username, user ID, or email address to lookup.
+- */
+-static void
+-msim_get_info(PurpleConnection *gc, const gchar *username)
+-{
+- MsimSession *session;
+- MsimUser *user;
+- gchar *user_to_lookup;
+- MsimMessage *user_msg;
+-
+- g_return_if_fail(gc != NULL);
+- g_return_if_fail(username != NULL);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /* Obtain uid of buddy. */
+- user = msim_find_user(session, username);
+-
+- /* If is on buddy list, lookup by uid since it is faster. */
+- if (user && user->id) {
+- user_to_lookup = g_strdup_printf("%d", user->id);
+- } else {
+- /* Looking up buddy not on blist. Lookup by whatever user entered. */
+- user_to_lookup = g_strdup(username);
+- }
+-
+- /* Pass the username to msim_get_info_cb(), because since we lookup
+- * by userid, the userinfo message will only contain the uid (not
+- * the username) but it would be useful to display the username too.
+- */
+- user_msg = msim_msg_new(
+- "user", MSIM_TYPE_STRING, g_strdup(username),
+- NULL);
+- purple_debug_info("msim", "msim_get_info, setting up lookup, user=%s\n", username);
+-
+- msim_lookup_user(session, user_to_lookup, msim_get_info_cb, user_msg);
+-
+- g_free(user_to_lookup);
+-}
+-
+-/**
+- * Set status using an MSIM_STATUS_CODE_* value.
+- * @param status_code An MSIM_STATUS_CODE_* value.
+- * @param statstring Status string, must be a dynamic string (will be freed by msim_send).
+- */
+-static void
+-msim_set_status_code(MsimSession *session, guint status_code, gchar *statstring)
+-{
+- g_return_if_fail(statstring != NULL);
+-
+- purple_debug_info("msim", "msim_set_status_code: going to set status to code=%d,str=%s\n",
+- status_code, statstring);
+-
+- if (!msim_send(session,
+- "status", MSIM_TYPE_INTEGER, status_code,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "statstring", MSIM_TYPE_STRING, statstring,
+- "locstring", MSIM_TYPE_STRING, g_strdup(""),
+- NULL))
+- {
+- purple_debug_info("msim", "msim_set_status: failed to set status\n");
+- }
+-}
+-
+-/**
+- * Set your status - callback for when user manually sets it.
+- */
+-static void
+-msim_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleStatusType *type;
+- PurplePresence *pres;
+- MsimSession *session;
+- guint status_code;
+- const gchar *message;
+- gchar *stripped;
+- gchar *unrecognized_msg;
+-
+- session = (MsimSession *)account->gc->proto_data;
+-
+- type = purple_status_get_type(status);
+- pres = purple_status_get_presence(status);
+-
+- switch (purple_status_type_get_primitive(type)) {
+- case PURPLE_STATUS_AVAILABLE:
+- purple_debug_info("msim", "msim_set_status: available (%d->%d)\n", PURPLE_STATUS_AVAILABLE,
+- MSIM_STATUS_CODE_ONLINE);
+- status_code = MSIM_STATUS_CODE_ONLINE;
+- break;
+-
+- case PURPLE_STATUS_INVISIBLE:
+- purple_debug_info("msim", "msim_set_status: invisible (%d->%d)\n", PURPLE_STATUS_INVISIBLE,
+- MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN);
+- status_code = MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN;
+- break;
+-
+- case PURPLE_STATUS_AWAY:
+- purple_debug_info("msim", "msim_set_status: away (%d->%d)\n", PURPLE_STATUS_AWAY,
+- MSIM_STATUS_CODE_AWAY);
+- status_code = MSIM_STATUS_CODE_AWAY;
+- break;
+-
+- default:
+- purple_debug_info("msim", "msim_set_status: unknown "
+- "status interpreting as online");
+- status_code = MSIM_STATUS_CODE_ONLINE;
+-
+- unrecognized_msg = g_strdup_printf("msim_set_status, unrecognized status type: %d\n",
+- purple_status_type_get_primitive(type));
+- msim_unrecognized(session, NULL, unrecognized_msg);
+- g_free(unrecognized_msg);
+-
+- break;
+- }
+-
+- message = purple_status_get_attr_string(status, "message");
+-
+- /* Status strings are plain text. */
+- if (message != NULL)
+- stripped = purple_markup_strip_html(message);
+- else
+- stripped = g_strdup("");
+-
+- msim_set_status_code(session, status_code, stripped);
+-
+- /* If we should be idle, set that status. Time is irrelevant here. */
+- if (purple_presence_is_idle(pres) && status_code != MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN)
+- msim_set_idle(account->gc, 1);
+-}
+-
+-/**
+- * Go idle.
+- */
+-static void
+-msim_set_idle(PurpleConnection *gc, int time)
+-{
+- MsimSession *session;
+- PurpleStatus *status;
+-
+- g_return_if_fail(gc != NULL);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- status = purple_account_get_active_status(session->account);
+-
+- if (time == 0) {
+- /* Going back from idle. In msim, idle is mutually exclusive
+- * from the other states (you can only be away or idle, but not
+- * both, for example), so by going non-idle I go back to what
+- * libpurple says I should be.
+- */
+- msim_set_status(session->account, status);
+- } else {
+- const gchar *message;
+- gchar *stripped;
+-
+- /* Set the idle message to the status message from the real
+- * current status.
+- */
+- message = purple_status_get_attr_string(status, "message");
+- if (message != NULL)
+- stripped = purple_markup_strip_html(message);
+- else
+- stripped = g_strdup("");
+-
+- /* msim doesn't support idle time, so just go idle */
+- msim_set_status_code(session, MSIM_STATUS_CODE_IDLE, stripped);
+- }
+-}
+-
+-/**
+- * @return TRUE if everything was ok, FALSE if something went awry.
+- */
+-static gboolean
+-msim_update_blocklist_for_buddy(MsimSession *session, const char *name, gboolean allow, gboolean block)
+-{
+- MsimMessage *msg;
+- GList *list;
+-
+- list = NULL;
+- list = g_list_prepend(list, allow ? "a+" : "a-");
+- list = g_list_prepend(list, "<uid>");
+- list = g_list_prepend(list, block ? "b+" : "b-");
+- list = g_list_prepend(list, "<uid>");
+- list = g_list_reverse(list);
+-
+- msg = msim_msg_new(
+- "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- /* TODO: MsimMessage lists. Currently <uid> isn't replaced in lists. */
+- /* "idlist", MSIM_TYPE_STRING, g_strdup("a-|<uid>|b-|<uid>"), */
+- "idlist", MSIM_TYPE_LIST, list,
+- NULL);
+-
+- if (!msim_postprocess_outgoing(session, msg, name, "idlist", NULL)) {
+- purple_debug_error("myspace",
+- "blocklist command failed for %s, allow=%d, block=%d\n",
+- name, allow, block);
+- msim_msg_free(msg);
+- return FALSE;
+- }
+-
+- msim_msg_free(msg);
+-
+- return TRUE;
+-}
+-
+-/**
+- * Add a buddy to user's buddy list.
+- */
+-static void
+-msim_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- MsimSession *session;
+- MsimMessage *msg;
+- MsimMessage *msg_persist;
+- MsimMessage *body;
+- const char *name, *gname;
+-
+- session = (MsimSession *)gc->proto_data;
+- name = purple_buddy_get_name(buddy);
+- gname = group ? purple_group_get_name(group) : NULL;
+-
+- if (msim_get_user_from_buddy(buddy, FALSE) != NULL)
+- return;
+-
+- purple_debug_info("msim", "msim_add_buddy: want to add %s to %s\n",
+- name, gname ? gname : "(no group)");
+-
+- msg = msim_msg_new(
+- "addbuddy", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- /* "newprofileid" will be inserted here with uid. */
+- "reason", MSIM_TYPE_STRING, g_strdup(""),
+- NULL);
+-
+- if (!msim_postprocess_outgoing(session, msg, name, "newprofileid", "reason")) {
+- purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("'addbuddy' command failed."));
+- msim_msg_free(msg);
+- return;
+- }
+- msim_msg_free(msg);
+-
+- /* TODO: if addbuddy fails ('error' message is returned), delete added buddy from
+- * buddy list since Purple adds it locally. */
+-
+- body = msim_msg_new(
+- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
+- "GroupName", MSIM_TYPE_STRING, g_strdup(gname),
+- "Position", MSIM_TYPE_INTEGER, 1000,
+- "Visibility", MSIM_TYPE_INTEGER, 1,
+- "NickName", MSIM_TYPE_STRING, g_strdup(""),
+- "NameSelect", MSIM_TYPE_INTEGER, 0,
+- NULL);
+-
+- /* TODO: Update blocklist. */
+-
+- msg_persist = msim_msg_new(
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
+- "dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
+- /* TODO: Use msim_new_reply_callback to get rid. */
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL);
+-
+- if (!msim_postprocess_outgoing(session, msg_persist, name, "body", NULL))
+- {
+- purple_notify_error(NULL, NULL, _("Failed to add buddy"), _("persist command failed"));
+- msim_msg_free(msg_persist);
+- return;
+- }
+- msim_msg_free(msg_persist);
+-
+- /* Add to allow list, remove from block list */
+- msim_update_blocklist_for_buddy(session, name, TRUE, FALSE);
+-}
+-
+-/**
+- * Remove a buddy from the user's buddy list.
+- */
+-static void
+-msim_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- MsimSession *session;
+- MsimMessage *delbuddy_msg;
+- MsimMessage *persist_msg;
+- const char *name;
+-
+- session = (MsimSession *)gc->proto_data;
+- name = purple_buddy_get_name(buddy);
+-
+- delbuddy_msg = msim_msg_new(
+- "delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- /* 'delprofileid' with uid will be inserted here. */
+- NULL);
+-
+- if (!msim_postprocess_outgoing(session, delbuddy_msg, name, "delprofileid", NULL)) {
+- purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("'delbuddy' command failed"));
+- msim_msg_free(delbuddy_msg);
+- return;
+- }
+- msim_msg_free(delbuddy_msg);
+-
+- persist_msg = msim_msg_new(
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
+- "dsn", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_DSN,
+- "lid", MSIM_TYPE_INTEGER, MD_DELETE_BUDDY_LID,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- /* <uid> will be replaced by postprocessing */
+- "body", MSIM_TYPE_STRING, g_strdup("ContactID=<uid>"),
+- NULL);
+-
+- if (!msim_postprocess_outgoing(session, persist_msg, name, "body", NULL)) {
+- purple_notify_error(NULL, NULL, _("Failed to remove buddy"), _("persist command failed"));
+- msim_msg_free(persist_msg);
+- return;
+- }
+- msim_msg_free(persist_msg);
+-
+- /*
+- * Remove from our approve list and from our block list (this
+- * doesn't seem like it would be necessary, but the official client
+- * does it)
+- */
+- if (!msim_update_blocklist_for_buddy(session, name, FALSE, FALSE)) {
+- purple_notify_error(NULL, NULL,
+- _("Failed to remove buddy"), _("blocklist command failed"));
+- return;
+- }
+- msim_buddy_free(buddy);
+-}
+-
+-/**
+- * Remove a buddy from the user's buddy list and add them to the block list.
+- */
+-static void
+-msim_add_deny(PurpleConnection *gc, const char *name)
+-{
+- MsimSession *session;
+- MsimMessage *msg, *body;
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /* Remove from buddy list */
+- msg = msim_msg_new(
+- "delbuddy", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- /* 'delprofileid' with uid will be inserted here. */
+- NULL);
+- if (!msim_postprocess_outgoing(session, msg, name, "delprofileid", NULL))
+- purple_debug_error("myspace", "delbuddy command failed\n");
+- msim_msg_free(msg);
+-
+- /* Remove from our approve list and add to our block list */
+- msim_update_blocklist_for_buddy(session, name, FALSE, TRUE);
+-
+- /*
+- * Add the buddy to our list of blocked contacts, so we know they
+- * are blocked if we log in with another client
+- */
+- body = msim_msg_new(
+- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
+- "Visibility", MSIM_TYPE_INTEGER, 2,
+- NULL);
+- msg = msim_msg_new(
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_PUT,
+- "dsn", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_DSN,
+- "lid", MSIM_TYPE_INTEGER, MC_CONTACT_INFO_LID,
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL);
+- if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
+- purple_debug_error("myspace", "add to block list command failed\n");
+- msim_msg_free(msg);
+-
+- /*
+- * TODO: MySpace doesn't allow blocked buddies on our buddy list,
+- * do they? If not then we need to remove the buddy from
+- * libpurple's buddy list.
+- */
+-}
+-
+-/**
+- * Remove a buddy from the user's block list.
+- */
+-static void
+-msim_rem_deny(PurpleConnection *gc, const char *name)
+-{
+- MsimSession *session;
+- MsimMessage *msg, *body;
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /*
+- * Remove from our list of blocked contacts, so we know they
+- * are no longer blocked if we log in with another client
+- */
+- body = msim_msg_new(
+- "ContactID", MSIM_TYPE_STRING, g_strdup("<uid>"),
+- NULL);
+- msg = msim_msg_new(
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_BIT_ACTION | MSIM_CMD_DELETE,
+- "dsn", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_DSN,
+- "lid", MSIM_TYPE_INTEGER, MC_DELETE_CONTACT_INFO_LID,
+- "rid", MSIM_TYPE_INTEGER, session->next_rid++,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL);
+- if (!msim_postprocess_outgoing(session, msg, name, "body", NULL))
+- purple_debug_error("myspace", "remove from block list command failed\n");
+- msim_msg_free(msg);
+-
+- /* Remove from our approve list and our block list */
+- msim_update_blocklist_for_buddy(session, name, FALSE, FALSE);
+-}
+-
+-/**
+- * Returns a string of a username in canonical form. Basically removes all the
+- * spaces, lowercases the string, and looks up user IDs to usernames.
+- * Normalizing tom, TOM, Tom, and 6221 wil all return 'tom'.
+- *
+- * Borrowed this code from oscar_normalize. Added checking for
+- * "if userid, get name before normalizing"
+- */
+-static const char *msim_normalize(const PurpleAccount *account, const char *str) {
+- static char normalized[BUF_LEN];
+- char *tmp1, *tmp2;
+- int i, j;
+- guint id;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+-
+- if (msim_is_userid(str)) {
+- /* Have user ID, we need to get their username first :) */
+- const char *username;
+-
+- /* If the account does not exist, we can't look up the user. */
+- if (!account || !account->gc)
+- return str;
+-
+- id = atol(str);
+- username = msim_uid2username_from_blist((PurpleAccount *)account, id);
+- if (!username) {
+- /* Not in buddy list... scheisse... TODO: Manual Lookup! Bug #4631 */
+- /* Note: manual lookup using msim_lookup_user() is a problem inside
+- * msim_normalize(), because msim_lookup_user() calls a callback function
+- * when the user information has been looked up, but msim_normalize() expects
+- * the result immediately. */
+- strncpy(normalized, str, BUF_LEN);
+- } else {
+- strncpy(normalized, username, BUF_LEN);
+- }
+- } else {
+- /* Have username. */
+- strncpy(normalized, str, BUF_LEN);
+- }
+-
+- /* Strip spaces. */
+- for (i=0, j=0; normalized[j]; j++) {
+- if (normalized[j] != ' ')
+- normalized[i++] = normalized[j];
+- }
+- normalized[i] = '\0';
+-
+- /* Lowercase and perform UTF-8 normalization. */
+- tmp1 = g_utf8_strdown(normalized, -1);
+- tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
+- g_snprintf(normalized, sizeof(normalized), "%s", tmp2);
+- g_free(tmp2);
+- g_free(tmp1);
+-
+- /* TODO: re-add caps and spacing back to what the user wanted.
+- * User can format their own names, for example 'msimprpl' is shown
+- * as 'MsIm PrPl' in the official client.
+- *
+- * TODO: file a ticket to add this enhancement.
+- */
+-
+- return normalized;
+-}
+-
+-/**
+- * Return whether the buddy can be messaged while offline.
+- *
+- * The protocol supports offline messages in just the same way as online
+- * messages.
+- */
+-static gboolean
+-msim_offline_message(const PurpleBuddy *buddy)
+-{
+- return TRUE;
+-}
+-
+-/**
+- * Send raw data to the server, possibly with embedded NULs.
+- *
+- * Used in prpl_info struct, so that plugins can have the most possible
+- * control of what is sent over the connection. Inside this prpl,
+- * msim_send_raw() is used, since it sends NUL-terminated strings (easier).
+- *
+- * @param gc PurpleConnection
+- * @param buf Buffer to send
+- * @param total_bytes Size of buffer to send
+- *
+- * @return Bytes successfully sent, or -1 on error.
+- */
+-/*
+- * TODO: This needs to do non-blocking writes and use a watcher to check
+- * when the fd is available to be written to.
+- */
+-static int
+-msim_send_really_raw(PurpleConnection *gc, const char *buf, int total_bytes)
+-{
+- int total_bytes_sent;
+- MsimSession *session;
+-
+- g_return_val_if_fail(gc != NULL, -1);
+- g_return_val_if_fail(buf != NULL, -1);
+- g_return_val_if_fail(total_bytes >= 0, -1);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /* Loop until all data is sent, or a failure occurs. */
+- total_bytes_sent = 0;
+- do {
+- int bytes_sent;
+-
+- bytes_sent = send(session->fd, buf + total_bytes_sent,
+- total_bytes - total_bytes_sent, 0);
+-
+- if (bytes_sent < 0) {
+- purple_debug_info("msim", "msim_send_raw(%s): send() failed: %s\n",
+- buf, g_strerror(errno));
+- return total_bytes_sent;
+- }
+- total_bytes_sent += bytes_sent;
+-
+- } while(total_bytes_sent < total_bytes);
+-
+- return total_bytes_sent;
+-}
+-
+-/**
+- * Send raw data (given as a NUL-terminated string) to the server.
+- *
+- * @param session
+- * @param msg The raw data to send, in a NUL-terminated string.
+- *
+- * @return TRUE if succeeded, FALSE if not.
+- *
+- */
+-gboolean
+-msim_send_raw(MsimSession *session, const gchar *msg)
+-{
+- size_t len;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- purple_debug_info("msim", "msim_send_raw: writing <%s>\n", msg);
+- len = strlen(msg);
+-
+- return msim_send_really_raw(session->gc, msg, len) == len;
+-}
+-
+-static GHashTable *
+-msim_get_account_text_table(PurpleAccount *unused)
+-{
+- GHashTable *table;
+-
+- table = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- g_hash_table_insert(table, "login_label", (gpointer)_("Email Address..."));
+-
+- return table;
+-}
+-
+-/**
+- * Callbacks called by Purple, to access this plugin.
+- */
+-static PurplePluginProtocolInfo prpl_info = {
+- /* options */
+- OPT_PROTO_USE_POINTSIZE /* specify font size in sane point size */
+- | OPT_PROTO_MAIL_CHECK,
+-
+- /* | OPT_PROTO_IM_IMAGE - TODO: direct images. */
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- NO_BUDDY_ICONS, /* icon_spec - TODO: eventually should add this */
+- msim_list_icon, /* list_icon */
+- NULL, /* list_emblems */
+- msim_status_text, /* status_text */
+- msim_tooltip_text, /* tooltip_text */
+- msim_status_types, /* status_types */
+- msim_blist_node_menu, /* blist_node_menu */
+- NULL, /* chat_info */
+- NULL, /* chat_info_defaults */
+- msim_login, /* login */
+- msim_close, /* close */
+- msim_send_im, /* send_im */
+- NULL, /* set_info */
+- msim_send_typing, /* send_typing */
+- msim_get_info, /* get_info */
+- msim_set_status, /* set_status */
+- msim_set_idle, /* set_idle */
+- NULL, /* change_passwd */
+- msim_add_buddy, /* add_buddy */
+- NULL, /* add_buddies */
+- msim_remove_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- msim_add_deny, /* add_deny */
+- NULL, /* rem_permit */
+- msim_rem_deny, /* rem_deny */
+- NULL, /* set_permit_deny */
+- NULL, /* join_chat */
+- NULL, /* reject chat invite */
+- NULL, /* get_chat_name */
+- NULL, /* chat_invite */
+- NULL, /* chat_leave */
+- NULL, /* chat_whisper */
+- NULL, /* chat_send */
+- NULL, /* keepalive */
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- NULL, /* alias_buddy */
+- NULL, /* group_buddy */
+- NULL, /* rename_group */
+- msim_buddy_free, /* buddy_free */
+- NULL, /* convo_closed */
+- msim_normalize, /* normalize */
+- NULL, /* set_buddy_icon */
+- NULL, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- NULL, /* can_receive_file */
+- NULL, /* send_file */
+- NULL, /* new_xfer */
+- msim_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- msim_send_really_raw, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- msim_send_attention, /* send_attention */
+- msim_attention_types, /* attention_types */
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- msim_get_account_text_table, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- NULL, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-/**
+- * Load the plugin.
+- */
+-static gboolean
+-msim_load(PurplePlugin *plugin)
+-{
+- /* If compiled to use RC4 from libpurple, check if it is really there. */
+- if (!purple_ciphers_find_cipher("rc4")) {
+- purple_debug_error("msim", "rc4 not in libpurple, but it is required - not loading MySpaceIM plugin!\n");
+- purple_notify_error(plugin, _("Missing Cipher"),
+- _("The RC4 cipher could not be found"),
+- _("Upgrade "
+- "to a libpurple with RC4 support (>= 2.0.1). MySpaceIM "
+- "plugin will not be loaded."));
+- return FALSE;
+- }
+- return TRUE;
+-}
+-
+-/**
+- * Called when friends have been imported to buddy list on server.
+- */
+-static void
+-msim_import_friends_cb(MsimSession *session, const MsimMessage *reply, gpointer user_data)
+-{
+- MsimMessage *body;
+- gchar *completed;
+-
+- /* Check if the friends were imported successfully. */
+- body = msim_msg_get_dictionary(reply, "body");
+- g_return_if_fail(body != NULL);
+- completed = msim_msg_get_string(body, "Completed");
+- msim_msg_free(body);
+- g_return_if_fail(completed != NULL);
+- if (!g_str_equal(completed, "True"))
+- {
+- purple_debug_info("msim_import_friends_cb",
+- "failed to import friends: %s", completed);
+- purple_notify_error(session->account, _("Add friends from MySpace.com"),
+- _("Importing friends failed"), NULL);
+- g_free(completed);
+- return;
+- }
+- g_free(completed);
+-
+- purple_debug_info("msim_import_friends_cb",
+- "added friends to server-side buddy list, requesting new contacts from server");
+-
+- msim_get_contact_list(session, MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS);
+-
+- /* TODO: show, X friends have been added */
+-}
+-
+-/**
+- * Import friends from myspace.com.
+- */
+-static void msim_import_friends(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- MsimSession *session;
+- gchar *group_name;
+-
+- gc = (PurpleConnection *)action->context;
+- session = (MsimSession *)gc->proto_data;
+-
+- group_name = "MySpace Friends";
+-
+- g_return_if_fail(msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
+- "dsn", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_DSN,
+- "lid", MSIM_TYPE_INTEGER, MC_IMPORT_ALL_FRIENDS_LID,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "rid", MSIM_TYPE_INTEGER,
+- msim_new_reply_callback(session, msim_import_friends_cb, NULL),
+- "body", MSIM_TYPE_STRING,
+- g_strdup_printf("GroupName=%s", group_name),
+- NULL));
+-}
+-
+-/**
+- * Actions menu for account.
+- */
+-static GList *
+-msim_actions(PurplePlugin *plugin, gpointer context /* PurpleConnection* */)
+-{
+- GList *menu;
+- PurplePluginAction *act;
+-
+- menu = NULL;
+-
+-#if 0
+- /* TODO: find out how */
+- act = purple_plugin_action_new(_("Find people..."), msim_);
+- menu = g_list_append(menu, act);
+-
+- act = purple_plugin_action_new(_("Change IM name..."), NULL);
+- menu = g_list_append(menu, act);
+-#endif
+-
+- act = purple_plugin_action_new(_("Add friends from MySpace.com"), msim_import_friends);
+- menu = g_list_append(menu, act);
+-
+- return menu;
+-}
+-
+-/**
+- * Based on MSN's plugin info comments.
+- */
+-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-myspace", /**< id */
+- "MySpaceIM", /**< name */
+- MSIM_PRPL_VERSION_STRING, /**< version */
+- /** summary */
+- "MySpaceIM Protocol Plugin",
+- /** description */
+- "MySpaceIM Protocol Plugin",
+- "Jeff Connelly <jeff2@soc.pidgin.im>", /**< author */
+- "http://developer.pidgin.im/wiki/MySpaceIM/", /**< homepage */
+-
+- msim_load, /**< load */
+- NULL, /**< unload */
+- NULL, /**< destroy */
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL, /**< prefs_info */
+- msim_actions, /**< msim_actions */
+- NULL, /**< reserved1 */
+- NULL, /**< reserved2 */
+- NULL, /**< reserved3 */
+- NULL /**< reserved4 */
+-};
+-
+-#ifdef MSIM_SELF_TEST
+-/*
+- * Test functions.
+- * Used to test or try out the internal workings of msimprpl. If you're reading
+- * this code for the first time, these functions can be instructive in learning
+- * how msimprpl is architected.
+- */
+-
+-/**
+- * Test MsimMessage for basic functionality.
+- */
+-static int
+-msim_test_msg(void)
+-{
+- MsimMessage *msg, *msg_cloned, *msg2;
+- GList *list;
+- gchar *packed, *packed_expected, *packed_cloned;
+- guint failures;
+-
+- failures = 0;
+-
+- purple_debug_info("msim", "\n\nTesting MsimMessage\n");
+- msg = msim_msg_new(NULL); /* Create a new, empty message. */
+-
+- /* Append some new elements. */
+- msg = msim_msg_append(msg, "bx", MSIM_TYPE_BINARY, g_string_new_len("XXX", 3));
+- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v1"));
+- msg = msim_msg_append(msg, "k1", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(42));
+- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v43"));
+- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v52/xxx\\yyy"));
+- msg = msim_msg_append(msg, "k1", MSIM_TYPE_STRING, g_strdup("v7"));
+- msim_msg_dump("msg debug str=%s\n", msg);
+- packed = msim_msg_pack(msg);
+-
+- purple_debug_info("msim", "msg packed=%s\n", packed);
+-
+- packed_expected = "\\bx\\WFhY\\k1\\v1\\k1\\42\\k1"
+- "\\v43\\k1\\v52/1xxx/2yyy\\k1\\v7\\final\\";
+-
+- if (!g_str_equal(packed, packed_expected)) {
+- purple_debug_info("msim", "!!!(%d), msim_msg_pack not what expected: %s != %s\n",
+- ++failures, packed, packed_expected);
+- }
+-
+-
+- msg_cloned = msim_msg_clone(msg);
+- packed_cloned = msim_msg_pack(msg_cloned);
+-
+- purple_debug_info("msim", "msg cloned=%s\n", packed_cloned);
+- if (!g_str_equal(packed, packed_cloned)) {
+- purple_debug_info("msim", "!!!(%d), msim_msg_pack on cloned message not equal to original: %s != %s\n",
+- ++failures, packed_cloned, packed);
+- }
+-
+- g_free(packed);
+- g_free(packed_cloned);
+- msim_msg_free(msg_cloned);
+- msim_msg_free(msg);
+-
+- /* Try some of the more advanced functionality */
+- list = NULL;
+-
+- list = g_list_prepend(list, "item3");
+- list = g_list_prepend(list, "item2");
+- list = g_list_prepend(list, "item1");
+- list = g_list_prepend(list, "item0");
+-
+- msg = msim_msg_new(NULL);
+- msg = msim_msg_append(msg, "string", MSIM_TYPE_STRING, g_strdup("string value"));
+- msg = msim_msg_append(msg, "raw", MSIM_TYPE_RAW, g_strdup("raw value"));
+- msg = msim_msg_append(msg, "integer", MSIM_TYPE_INTEGER, GUINT_TO_POINTER(3140));
+- msg = msim_msg_append(msg, "boolean", MSIM_TYPE_BOOLEAN, GUINT_TO_POINTER(FALSE));
+- msg = msim_msg_append(msg, "list", MSIM_TYPE_LIST, list);
+-
+- msim_msg_dump("msg with list=%s\n", msg);
+- purple_debug_info("msim", "msg with list packed=%s\n", msim_msg_pack(msg));
+-
+- msg2 = msim_msg_new(NULL);
+- msg2 = msim_msg_append(msg2, "outer", MSIM_TYPE_STRING, g_strdup("outer value"));
+- msg2 = msim_msg_append(msg2, "body", MSIM_TYPE_DICTIONARY, msg);
+- msim_msg_dump("msg with dict=%s\n", msg2); /* msg2 now 'owns' msg */
+- purple_debug_info("msim", "msg with dict packed=%s\n", msim_msg_pack(msg2));
+-
+- msim_msg_free(msg2);
+-
+- return failures;
+-}
+-
+-/**
+- * Test protocol-level escaping/unescaping.
+- */
+-static int
+-msim_test_escaping(void)
+-{
+- guint failures;
+- gchar *raw, *escaped, *unescaped, *expected;
+-
+- failures = 0;
+-
+- purple_debug_info("msim", "\n\nTesting escaping\n");
+-
+- raw = "hello/world\\hello/world";
+-
+- escaped = msim_escape(raw);
+- purple_debug_info("msim", "msim_test_escaping: raw=%s, escaped=%s\n", raw, escaped);
+- expected = "hello/1world/2hello/1world";
+- if (!g_str_equal(escaped, expected)) {
+- purple_debug_info("msim", "!!!(%d), msim_escape failed: %s != %s\n",
+- ++failures, escaped, expected);
+- }
+-
+-
+- unescaped = msim_unescape(escaped);
+- g_free(escaped);
+- purple_debug_info("msim", "msim_test_escaping: unescaped=%s\n", unescaped);
+- if (!g_str_equal(raw, unescaped)) {
+- purple_debug_info("msim", "!!!(%d), msim_unescape failed: %s != %s\n",
+- ++failures, raw, unescaped);
+- }
+-
+- return failures;
+-}
+-
+-static void
+-msim_test_all(void)
+-{
+- guint failures;
+-
+- failures = 0;
+- failures += msim_test_msg();
+- failures += msim_test_escaping();
+-
+- if (failures) {
+- purple_debug_info("msim", "msim_test_all HAD FAILURES: %d\n", failures);
+- } else {
+- purple_debug_info("msim", "msim_test_all - all tests passed!\n");
+- }
+- exit(0);
+-}
+-#endif
+-
+-#ifdef MSIM_CHECK_NEWER_VERSION
+-/**
+- * Callback for when a currentversion.txt has been downloaded.
+- */
+-static void
+-msim_check_newer_version_cb(PurpleUtilFetchUrlData *url_data,
+- gpointer user_data,
+- const gchar *url_text,
+- gsize len,
+- const gchar *error_message)
+-{
+- GKeyFile *keyfile;
+- GError *error;
+- GString *data;
+- gchar *newest_filever;
+-
+- if (!url_text) {
+- purple_debug_info("msim_check_newer_version_cb",
+- "got error: %s\n", error_message);
+- return;
+- }
+-
+- purple_debug_info("msim_check_newer_version_cb",
+- "url_text=%s\n", url_text ? url_text : "(NULL)");
+-
+- /* Prepend [group] so that GKeyFile can parse it (requires a group). */
+- data = g_string_new(url_text);
+- purple_debug_info("msim", "data=%s\n", data->str
+- ? data->str : "(NULL)");
+- data = g_string_prepend(data, "[group]\n");
+-
+- purple_debug_info("msim", "data=%s\n", data->str
+- ? data->str : "(NULL)");
+-
+- /* url_text is variable=data\n...†*/
+-
+- /* Check FILEVER, 1.0.716.0. 716 is build, MSIM_CLIENT_VERSION */
+- /* New (english) version can be downloaded from SETUPURL+SETUPFILE */
+-
+- error = NULL;
+- keyfile = g_key_file_new();
+-
+- /* Default list seperator is ;, but currentversion.txt doesn't have
+- * these, so set to an unused character to avoid parsing problems. */
+- g_key_file_set_list_separator(keyfile, '\0');
+-
+- g_key_file_load_from_data(keyfile, data->str, data->len,
+- G_KEY_FILE_NONE, &error);
+- g_string_free(data, TRUE);
+-
+- if (error != NULL) {
+- purple_debug_info("msim_check_newer_version_cb",
+- "couldn't parse, error: %d %d %s\n",
+- error->domain, error->code, error->message);
+- g_error_free(error);
+- return;
+- }
+-
+- gchar **ks;
+- guint n;
+- ks = g_key_file_get_keys(keyfile, "group", &n, NULL);
+- purple_debug_info("msim", "n=%d\n", n);
+- guint i;
+- for (i = 0; ks[i] != NULL; ++i)
+- {
+- purple_debug_info("msim", "%d=%s\n", i, ks[i]);
+- }
+-
+- newest_filever = g_key_file_get_string(keyfile, "group",
+- "FILEVER", &error);
+-
+- purple_debug_info("msim_check_newer_version_cb",
+- "newest filever: %s\n", newest_filever ?
+- newest_filever : "(NULL)");
+- if (error != NULL) {
+- purple_debug_info("msim_check_newer_version_cb",
+- "error: %d %d %s\n",
+- error->domain, error->code, error->message);
+- g_error_free(error);
+- }
+-
+- g_key_file_free(keyfile);
+-
+- exit(0);
+-}
+-#endif
+-
+-/**
+- Handle a myim:addContact command, after username has been looked up.
+- */
+-static void
+-msim_uri_handler_addContact_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
+-{
+- MsimMessage *body;
+- gchar *username;
+-
+- body = msim_msg_get_dictionary(userinfo, "body");
+- username = msim_msg_get_string(body, "UserName");
+- msim_msg_free(body);
+-
+- if (!username) {
+- guint uid;
+-
+- uid = msim_msg_get_integer(userinfo, "UserID");
+- g_return_if_fail(uid != 0);
+-
+- username = g_strdup_printf("%d", uid);
+- }
+-
+- purple_blist_request_add_buddy(session->account, username, _("Buddies"), NULL);
+-
+- g_free(username);
+-}
+-
+-/* TODO: move uid->username resolving to IM sending and buddy adding functions,
+- * so that user can manually add or IM by userid and username automatically
+- * looked up if possible? */
+-
+-/**
+- * Handle a myim:sendIM URI command, after username has been looked up.
+- */
+-static void
+-msim_uri_handler_sendIM_cb(MsimSession *session, MsimMessage *userinfo, gpointer data)
+-{
+- PurpleConversation *conv;
+- MsimMessage *body;
+- gchar *username;
+-
+- body = msim_msg_get_dictionary(userinfo, "body");
+- username = msim_msg_get_string(body, "UserName");
+- msim_msg_free(body);
+-
+- if (!username) {
+- guint uid;
+-
+- uid = msim_msg_get_integer(userinfo, "UserID");
+- g_return_if_fail(uid != 0);
+-
+- username = g_strdup_printf("%d", uid);
+- }
+-
+-
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, username, session->account);
+- if (!conv) {
+- purple_debug_info("msim_uri_handler", "creating new conversation for %s\n", username);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, session->account, username);
+- }
+-
+- /* Just open the window so the user can send an IM. */
+- purple_conversation_present(conv);
+-
+- g_free(username);
+-}
+-
+-static gboolean
+-msim_uri_handler(const gchar *proto, const gchar *cmd, GHashTable *params)
+-{
+- PurpleAccount *account;
+- MsimSession *session;
+- GList *l;
+- gchar *uid_str, *cid_str;
+- guint uid, cid;
+-
+- if (g_ascii_strcasecmp(proto, "myim"))
+- return FALSE;
+-
+- /* Parameters are case-insensitive. */
+- uid_str = g_hash_table_lookup(params, "uid");
+- cid_str = g_hash_table_lookup(params, "cid");
+-
+- uid = uid_str ? atol(uid_str) : 0;
+- cid = cid_str ? atol(cid_str) : 0;
+-
+- /* Need a contact. */
+- g_return_val_if_fail(cid != 0, FALSE);
+-
+- /* TODO: if auto=true, "Add all the people on this page to my IM List!", on
+- * http://collect.myspace.com/index.cfm?fuseaction=im.friendslist. Don't need a cid. */
+-
+- /* Convert numeric contact ID back to a string. Needed for looking up. Don't just
+- * directly use cid directly from parameters, because it might not be numeric.
+- * It is trivial to change this to allow cID to be a username, but that's not how
+- * the official MySpaceIM client works, so don't provide that functionality. */
+- cid_str = g_strdup_printf("%d", cid);
+-
+-
+- /* Find our account with specified user id, or use first connected account if uid=0. */
+- account = NULL;
+- l = purple_accounts_get_all();
+- while (l) {
+- if (purple_account_is_connected(l->data) &&
+- (uid == 0 || purple_account_get_int(l->data, "uid", 0) == uid)) {
+- account = l->data;
+- break;
+- }
+- l = l->next;
+- }
+-
+- if (!account) {
+- purple_notify_error(NULL, _("myim URL handler"),
+- _("No suitable MySpaceIM account could be found to open this myim URL."),
+- _("Enable the proper MySpaceIM account and try again."));
+- g_free(cid_str);
+- return FALSE;
+- }
+-
+- session = (MsimSession *)account->gc->proto_data;
+- g_return_val_if_fail(session != NULL, FALSE);
+-
+- /* Lookup userid to username. TODO: push this down, to IM sending/contact
+- * adding functions. */
+-
+- /* myim:sendIM?uID=USERID&cID=CONTACTID */
+- if (!g_ascii_strcasecmp(cmd, "sendIM")) {
+- msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_sendIM_cb, NULL);
+- g_free(cid_str);
+- return TRUE;
+-
+- /* myim:addContact?uID=USERID&cID=CONTACTID */
+- } else if (!g_ascii_strcasecmp(cmd, "addContact")) {
+- msim_lookup_user(session, cid_str, (MSIM_USER_LOOKUP_CB)msim_uri_handler_addContact_cb, NULL);
+- g_free(cid_str);
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-/**
+- * Initialize plugin.
+- */
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+-#ifdef MSIM_SELF_TEST
+- msim_test_all();
+- exit(0);
+-#endif /* MSIM_SELF_TEST */
+-
+- PurpleAccountOption *option;
+- static gboolean initialized = FALSE;
+-
+-#ifdef MSIM_CHECK_NEWER_VERSION
+- /* PROBLEM: MySpace's servers always return Content-Location, and
+- * libpurple redirects to it, infinitely, even though it is the same
+- * location we requested! */
+- purple_util_fetch_url("http://im.myspace.com/nsis/currentversion.txt",
+- FALSE, /* not full URL */
+- "MSIMAutoUpdateAgent", /* user agent */
+- TRUE, /* use HTTP/1.1 */
+- msim_check_newer_version_cb, NULL);
+-#endif
+-
+- /* TODO: default to automatically try different ports. Make the user be
+- * able to set the first port to try (like LastConnectedPort in Windows client). */
+- option = purple_account_option_string_new(_("Connect server"), "server", MSIM_SERVER);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_int_new(_("Connect port"), "port", MSIM_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+-#ifdef MSIM_USER_WANTS_TO_CONFIGURE_STATUS_TEXT
+- option = purple_account_option_bool_new(_("Show display name in status text"), "show_display_name", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Show headline in status text"), "show_headline", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-#endif
+-
+-#ifdef MSIM_USER_WANTS_TO_DISABLE_EMOTICONS
+- option = purple_account_option_bool_new(_("Send emoticons"), "emoticons", TRUE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-#endif
+-
+-#ifdef MSIM_USER_REALLY_CARES_ABOUT_PRECISE_FONT_SIZES
+- option = purple_account_option_int_new(_("Screen resolution (dots per inch)"), "dpi", MSIM_DEFAULT_DPI);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_int_new(_("Base font size (points)"), "base_font_size", MSIM_BASE_FONT_POINT_SIZE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-#endif
+-
+- /* Code below only runs once. Based on oscar.c's oscar_init(). */
+- if (initialized)
+- return;
+-
+- initialized = TRUE;
+-
+- purple_signal_connect(purple_get_core(), "uri-handler", &initialized,
+- PURPLE_CALLBACK(msim_uri_handler), NULL);
+-}
+-
+-PURPLE_INIT_PLUGIN(myspace, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/myspace.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/myspace.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/myspace.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,203 +0,0 @@
+-/* MySpaceIM Protocol Plugin, header file
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_MYSPACE_H
+-#define _MYSPACE_MYSPACE_H
+-
+-#include "internal.h"
+-
+-/* Other includes */
+-#include <string.h>
+-#include <errno.h>/* for EAGAIN */
+-#include <stdarg.h>
+-#include <math.h>
+-
+-#include <glib.h>
+-
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#else
+-/* For recv() and send(); needed to match Win32 */
+-#include <sys/types.h>
+-#include <sys/socket.h>
+-#endif
+-
+-#include "notify.h"
+-#include "plugin.h"
+-#include "accountopt.h"
+-#include "version.h"
+-#include "cipher.h" /* for SHA-1 */
+-#include "util.h" /* for base64 */
+-#include "debug.h" /* for purple_debug_info */
+-#include "request.h" /* For dialogs used in setting the username */
+-#include "xmlnode.h"
+-#include "core.h"
+-#include "conversation.h" /* For late normalization */
+-
+-/* MySpaceIM includes */
+-#include "persist.h"
+-#include "message.h"
+-#include "session.h"
+-#include "zap.h"
+-#include "markup.h"
+-#include "user.h"
+-
+-/* Conditional compilation options */
+-/* Send third-party client version? (Recognized by us and Miranda's plugin) */
+-/*#define MSIM_SEND_CLIENT_VERSION */
+-
+-/* Debugging options */
+-/* Low-level and rarely needed */
+-/*#define MSIM_DEBUG_PARSE */
+-/*#define MSIM_DEBUG_LOGIN_CHALLENGE*/
+-/*#define MSIM_DEBUG_RXBUF */
+-
+-/* Encode unknown HTML tags from IM clients in messages as [tag], instead of
+- * ignoring. Useful for debugging */
+-/*#define MSIM_MARKUP_SHOW_UNKNOWN_TAGS */
+-
+-/* Define to cause init_plugin() to run some tests and print
+- * the results to the Purple debug log, then exit. Useful to
+- * run with 'pidgin -d' to see the output. Don't define if
+- * you want to actually use the plugin! */
+-/*#define MSIM_SELF_TEST */
+-
+-/* Constants */
+-
+-/* Maximum length of a password that is acceptable. This is the limit
+- * on the official client (build 679) and on the 'new password' field at
+- * http://settings.myspace.com/index.cfm?fuseaction=user.changepassword
+- * (though curiously, not on the 'current password' field). */
+-
+-/* After login fails, if password is greater than this many characters,
+- * warn user that it may be too long. */
+-#define MSIM_MAX_PASSWORD_LENGTH 10
+-
+-/* Maximum length of usernames, when setting. */
+-#define MSIM_MAX_USERNAME_LENGTH 25
+-
+-/* Build version of MySpaceIM to report to servers (1.0.xxx.0) */
+-#define MSIM_CLIENT_VERSION 697
+-
+-/* Check for a newer official MySpaceIM client on startup?
+- * (Mostly useful for developers) */
+-/*#define MSIM_CHECK_NEWER_VERSION*/
+-
+-/* Language codes from http://www.microsoft.com/globaldev/reference/oslocversion.mspx */
+-#define MSIM_LANGUAGE_ID_ENGLISH 1033
+-#define MSIM_LANGUAGE_NAME_ENGLISH "ENGLISH"
+-
+-/* msimprpl version string of this plugin */
+-#define MSIM_PRPL_VERSION_STRING "0.18"
+-
+-/* Default server */
+-#define MSIM_SERVER "im.myspace.akadns.net"
+-#define MSIM_PORT 1863 /* TODO: alternate ports and automatic */
+-
+-/* Time between keepalives (seconds) - if no data within this time, is dead. */
+-#define MSIM_KEEPALIVE_INTERVAL (3 * 60)
+-/*#define MSIM_USE_KEEPALIVE*/
+-
+-/* Time to check if alive (seconds) */
+-#define MSIM_KEEPALIVE_INTERVAL_CHECK 30
+-
+-/* Time to check for new mail (milliseconds) */
+-#define MSIM_MAIL_INTERVAL_CHECK (60 * 1000)
+-
+-/* Constants */
+-#define HASH_SIZE 0x14 /**< Size of SHA-1 hash for login */
+-#define NONCE_SIZE 0x20 /**< Half of decoded 'nc' field */
+-#define MSIM_READ_BUF_SIZE (15 * 1024) /**< Receive buffer size */
+-#define MSIM_FINAL_STRING "\\final\\" /**< Message end marker */
+-
+-/* Messages */
+-#define MSIM_BM_ACTION_OR_IM_DELAYABLE 1
+-#define MSIM_BM_STATUS 100
+-#define MSIM_BM_ACTION_OR_IM_INSTANT 121
+-#define MSIM_BM_MEDIA 122
+-#define MSIM_BM_PROFILE 124
+-#define MSIM_BM_STATUS_MOOD 126
+-#define MSIM_BM_UNOFFICIAL_CLIENT 200
+-
+-/* Authentication algorithm for login2 */
+-#define MSIM_AUTH_ALGORITHM 196610
+-
+-/* Recognized challenge length */
+-#define MSIM_AUTH_CHALLENGE_LENGTH 0x40
+-
+-#ifdef SEND_OUR_IP_ADDRESSES
+-/* TODO: obtain IPs of network interfaces from user's machine, instead of
+- * hardcoding these values below (used in msim_compute_login_response).
+- * This is not immediately
+- * important because you can still connect and perform basic
+- * functions of the protocol. There is also a high chance that the addreses
+- * are RFC1918 private, so the servers couldn't do anything with them
+- * anyways except make note of that fact. Probably important for any
+- * kind of direct connection, or file transfer functionality.
+- */
+-
+-#define MSIM_LOGIN_IP_LIST "\x00\x00\x00\x00\x05\x7f\x00\x00\x01\x00\x00\x00\x00\x0a\x00\x00\x40\xc0\xa8\x58\x01\xc0\xa8\x3c\x01"
+-#define MSIM_LOGIN_IP_LIST_LEN 25
+-#endif /* SEND_OUR_IP_ADDRESSES */
+-
+-/* Indexes into status string (0|1|2|3|..., but 0 always empty) */
+-#define MSIM_STATUS_ORDINAL_EMPTY 0
+-#define MSIM_STATUS_ORDINAL_UNKNOWNs 1
+-#define MSIM_STATUS_ORDINAL_ONLINE 2
+-#define MSIM_STATUS_ORDINAL_UNKNOWNss 3
+-#define MSIM_STATUS_ORDINAL_HEADLINE 4
+-#define MSIM_STATUS_ORDINAL_UNKNOWNls 5
+-#define MSIM_STATUS_ORDINAL_UNKNOWN 6
+-#define MSIM_STATUS_ORDINAL_UNKNOWN1 7
+-#define MSIM_STATUS_ORDINAL_UNKNOWNp 8
+-#define MSIM_STATUS_ORDINAL_UNKNOWN2 9
+-
+-/* Status codes - states a buddy (or you!) can be in. */
+-#define MSIM_STATUS_CODE_OFFLINE_OR_HIDDEN 0
+-#define MSIM_STATUS_CODE_ONLINE 1
+-#define MSIM_STATUS_CODE_IDLE 2
+-#define MSIM_STATUS_CODE_AWAY 5
+-
+-/* Inbox status bitfield values for MsimSession.inbox_status. */
+-#define MSIM_INBOX_MAIL (1 << 0)
+-#define MSIM_INBOX_BLOG_COMMENT (1 << 1)
+-#define MSIM_INBOX_PROFILE_COMMENT (1 << 2)
+-#define MSIM_INBOX_FRIEND_REQUEST (1 << 3)
+-#define MSIM_INBOX_PICTURE_COMMENT (1 << 4)
+-
+-/* Codes for msim_got_contact_list(), to tell what to do afterwards. */
+-#define MSIM_CONTACT_LIST_INITIAL_FRIENDS 0
+-#define MSIM_CONTACT_LIST_IMPORT_ALL_FRIENDS 1
+-#define MSIM_CONTACT_LIST_IMPORT_TOP_FRIENDS 2
+-
+-/* Error codes */
+-#define MSIM_ERROR_INCORRECT_PASSWORD 260
+-#define MSIM_ERROR_LOGGED_IN_ELSEWHERE 6
+-
+-/* Functions */
+-gboolean msim_send_raw(MsimSession *session, const gchar *msg);
+-
+-gboolean msim_send_bm(MsimSession *session, const gchar *who, const gchar *text, int type);
+-
+-gboolean msim_we_are_logged_on(MsimSession *session);
+-
+-void msim_unrecognized(MsimSession *session, MsimMessage *msg, gchar *note);
+-guint msim_new_reply_callback(MsimSession *session, MSIM_USER_LOOKUP_CB cb, gpointer data);
+-
+-#endif /* !_MYSPACE_MYSPACE_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/persist.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/persist.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/persist.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/persist.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,92 +0,0 @@
+-/* MySpaceIM Protocol Plugin, persist commands
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_PERSIST_H
+-#define _MYSPACE_PERSIST_H
+-
+-/** Command codes */
+-#define MSIM_CMD_GET 1
+-#define MSIM_CMD_PUT 2
+-#define MSIM_CMD_DELETE 3
+-
+-/** Command bit fields */
+-#define MSIM_CMD_BIT_CODE 255 /*< Bits specifying command code */
+-#define MSIM_CMD_BIT_REPLY 256 /**< 1=reply, 0=request */
+-#define MSIM_CMD_BIT_ACTION 512 /**< 1=action, 0=information */
+-#define MSIM_CMD_BIT_ERROR 1024 /**< 1=error, 0=normal */
+-
+-/** Macros to read cmd bitfield. */
+-#define MSIM_CMD_GET_CODE(x) (x & MSIM_CMD_BIT_CODE)
+-#define MSIM_CMD_IS_REPLY(x) (x & MSIM_CMD_BIT_REPLY)
+-#define MSIM_CMD_IS_REQUEST(x) !(x & MSIM_CMD_BIT_REPLY)
+-#define MSIM_CMD_IS_ACTION(x) (x & MSIM_CMD_BIT_ACTION)
+-#define MSIM_CMD_IS_INFO(x) !(x & MSIM_CMD_BIT_ACTION)
+-#define MSIM_CMD_IS_ERROR(x) (x & MSIM_CMD_BIT_ERROR)
+-#define MSIM_CMD_IS_NORMAL(x) !(x & MSIM_CMD_BIT_ERROR)
+-
+-/** Define a set of _DSN and _LID constants for a persistance request. */
+-#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \
+- static const int name##_DSN = dsn; \
+- static const int name##_LID = lid;
+-
+-/* Can't do this, errors:
+- * persist.h:51:3: error: '#' is not followed by a macro parameter
+- * In file included from myspace.c:37:
+- * persist.h:56: error: expected ')' before numeric constant
+- * So instead, I define const ints above.
+-#define MSIM_PERSIST_DSN_LID(name,dsn,lid) \
+- #define name##_DSN dsn \
+- #define name##_LID lid
+-#endif
+-*/
+-
+-/** Messages to Get information dsn lid */
+-MSIM_PERSIST_DSN_LID(MG_LIST_ALL_CONTACTS, 0, 1)
+-MSIM_PERSIST_DSN_LID(MG_USER_INFO_BY_ID, 0, 2)
+-MSIM_PERSIST_DSN_LID(MG_OWN_IM_INFO, 1, 4)
+-MSIM_PERSIST_DSN_LID(MG_IM_INFO_BY_ID, 1, 17)
+-MSIM_PERSIST_DSN_LID(MG_LIST_ALL_GROUPS, 2, 6)
+-MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_ID, 4, 3)
+-MSIM_PERSIST_DSN_LID(MG_OWN_MYSPACE_INFO, 4, 5)
+-MSIM_PERSIST_DSN_LID(MG_MYSPACE_INFO_BY_STRING, 5, 7)
+-MSIM_PERSIST_DSN_LID(MG_CHECK_MAIL, 7, 18)
+-MSIM_PERSIST_DSN_LID(MG_WEB_CHALLENGE, 17, 26)
+-MSIM_PERSIST_DSN_LID(MG_USER_SONG, 21, 28)
+-MSIM_PERSIST_DSN_LID(MG_SERVER_INFO, 101, 20)
+-
+-/** Messages to Change/send information */
+-MSIM_PERSIST_DSN_LID(MC_USER_PREFERENCES, 1, 10)
+-MSIM_PERSIST_DSN_LID(MC_DELETE_CONTACT_INFO, 0, 8)
+-MSIM_PERSIST_DSN_LID(MC_CONTACT_INFO, 0, 9)
+-MSIM_PERSIST_DSN_LID(MC_SET_USERNAME, 9, 14)
+-MSIM_PERSIST_DSN_LID(MC_IMPORT_ALL_FRIENDS, 14, 21)
+-MSIM_PERSIST_DSN_LID(MC_INVITE, 16, 25)
+-
+-/** Messages to Delete information */
+-MSIM_PERSIST_DSN_LID(MD_DELETE_BUDDY, 0, 8)
+-
+-/** Error codes */
+-#define MERR_PARSE 1
+-#define MERR_NOT_LOGGED_IN 2
+-#define MERR_ANOTHER_LOGIN 6
+-#define MERR_BAD_EMAIL 259
+-#define MERR_BAD_PASSWORD 260
+-#define MERR_BAD_UID_IN_PERSISTR 4352
+-
+-#endif /* !_MYSPACE_PERSIST_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/README pidgin-2.10.7-nonprism/libpurple/protocols/myspace/README
+--- pidgin-2.10.7/libpurple/protocols/myspace/README 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/README 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-MySpaceIM Protocol Plugin for libpurple by Jeff Connelly 2007-08-07
+-
+-Greetings. This package contains a plugin for libpurple (as used in
+-Pidgin, formerly Gaim) to connect to the new MySpaceIM instant messaging
+-network and send/receive messages. Functionality is only basic as of yet,
+-and this code should be considered alpha quality.
+-
+-This code was initially developed under Google Summer of Code 2007.
+-
+-For features and TODO, see http://developer.pidgin.im/wiki/MySpaceIM
+-
+-Usage:
+-
+-Login using your _email address_ you use to login to myspace.com. You can't
+-login using your numeric ID or alias.
+-
+-To test it out, send a message to yourself (by your username or numeric
+-uid (email not yet supported)) or tom (6221). In either case you should
+-get a reply. You should also be able to talk to other MySpaceIM users if
+-you desire. Replies will always be shown as coming from a user's username,
+-even if you IM by email or userid.
+-
+-Feedback welcome. You can IM my test account at "msimprpl" if you feel like it.
+-
+-Enjoy,
+--Jeff Connelly
+-msimprpl@xyzzy.cjb.net
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/session.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/session.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,98 +0,0 @@
+-/* MySpaceIM Protocol Plugin, session
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "myspace.h"
+-
+-/* Session methods */
+-
+-/**
+- * Create a new MSIM session.
+- *
+- * @param acct The account to create the session from.
+- *
+- * @return Pointer to a new session. Free with msim_session_destroy.
+- */
+-MsimSession *
+-msim_session_new(PurpleAccount *acct)
+-{
+- MsimSession *session;
+-
+- g_return_val_if_fail(acct != NULL, NULL);
+-
+- session = g_new0(MsimSession, 1);
+-
+- session->magic = MSIM_SESSION_STRUCT_MAGIC;
+- session->account = acct;
+- session->gc = purple_account_get_connection(acct);
+- session->sesskey = 0;
+- session->userid = 0;
+- session->username = NULL;
+- session->fd = -1;
+-
+- /* TODO: Remove. */
+- session->user_lookup_cb = g_hash_table_new_full(g_direct_hash,
+- g_direct_equal, NULL, NULL); /* do NOT free function pointers! (values) */
+- session->user_lookup_cb_data = g_hash_table_new_full(g_direct_hash,
+- g_direct_equal, NULL, NULL);/* TODO: we don't know what the values are,
+- they could be integers inside gpointers
+- or strings, so I don't freed them.
+- Figure this out, once free cache. */
+-
+- /* Created in msim_process_server_info() */
+- session->server_info = NULL;
+-
+- session->rxoff = 0;
+- session->rxsize = MSIM_READ_BUF_SIZE;
+- session->rxbuf = g_new0(gchar, session->rxsize);
+- session->next_rid = 1;
+- session->last_comm = time(NULL);
+- session->inbox_status = 0;
+- session->inbox_handle = 0;
+-
+- return session;
+-}
+-
+-/**
+- * Free a session.
+- *
+- * @param session The session to destroy.
+- */
+-void
+-msim_session_destroy(MsimSession *session)
+-{
+- session->magic = -1;
+-
+- g_free(session->rxbuf);
+- g_free(session->username);
+-
+- /* TODO: Remove. */
+- g_hash_table_destroy(session->user_lookup_cb);
+- g_hash_table_destroy(session->user_lookup_cb_data);
+-
+- if (session->server_info) {
+- msim_msg_free(session->server_info);
+- }
+-
+- /* Stop checking the inbox at the end of the session. */
+- if (session->inbox_handle) {
+- purple_timeout_remove(session->inbox_handle);
+- }
+-
+- g_free(session);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/session.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/session.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/session.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,60 +0,0 @@
+-/* MySpaceIM Protocol Plugin, session
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_SESSION_H
+-#define _MYSPACE_SESSION_H
+-
+-#include "account.h"
+-
+-/* Random number in every MsimSession, to ensure it is valid. */
+-#define MSIM_SESSION_STRUCT_MAGIC 0xe4a6752b
+-
+-/* Everything needed to keep track of a session (proto_data field in PurpleConnection) */
+-typedef struct _MsimSession
+-{
+- guint magic; /**< MSIM_SESSION_STRUCT_MAGIC */
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- guint sesskey; /**< Session key from server */
+- guint userid; /**< This user's numeric user ID */
+- gchar *username; /**< This user's unique username */
+- gboolean show_only_to_list;
+- int privacy_mode; /**< This is a bitmask */
+- int offline_message_mode;
+- gint fd; /**< File descriptor to/from server */
+-
+- /* TODO: Remove. */
+- GHashTable *user_lookup_cb; /**< Username -> userid lookup callback */
+- GHashTable *user_lookup_cb_data; /**< Username -> userid lookup callback data */
+-
+- MsimMessage *server_info; /**< Parameters from server */
+-
+- gchar *rxbuf; /**< Receive buffer */
+- guint rxoff; /**< Receive buffer offset */
+- guint rxsize; /**< Receive buffer size */
+- guint next_rid; /**< Next request/response ID */
+- time_t last_comm; /**< Time received last communication */
+- guint inbox_status; /**< Bit field of inbox notifications */
+- guint inbox_handle; /**< The handle for the mail check timer */
+-} MsimSession;
+-
+-MsimSession *msim_session_new(PurpleAccount *acct);
+-void msim_session_destroy(MsimSession *session);
+-
+-#endif /* !_MYSPACE_SESSION_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/user.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/user.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,890 +0,0 @@
+-/* MySpaceIM Protocol Plugin, header file
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "myspace.h"
+-
+-static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check);
+-
+-static char *msim_username_to_set;
+-
+-/**
+- * Format the "now playing" indicator, showing the artist and song.
+- *
+- * @return Return a new string (must be g_free()'d), or NULL.
+- */
+-static gchar *
+-msim_format_now_playing(const gchar *band, const gchar *song)
+-{
+- if ((band && *band) || (song && *song)) {
+- return g_strdup_printf("%s - %s",
+- (band && *band) ? band : "Unknown Artist",
+- (song && *song) ? song : "Unknown Song");
+- } else {
+- return NULL;
+- }
+-}
+-
+-/**
+- * Get the MsimUser from a PurpleBuddy, optionally creating it if needed.
+- */
+-MsimUser *
+-msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create)
+-{
+- MsimUser *user;
+-
+- if (!buddy) {
+- return NULL;
+- }
+-
+- user = purple_buddy_get_protocol_data(buddy);
+- if (create && !user) {
+- PurpleBlistNode *node = PURPLE_BLIST_NODE(buddy);
+-
+- /* No MsimUser for this buddy; make one. */
+-
+- user = g_new0(MsimUser, 1);
+- user->buddy = buddy;
+- user->id = purple_blist_node_get_int(node, "UserID");
+- purple_buddy_set_protocol_data(buddy, user);
+- }
+-
+- return user;
+-}
+-
+-void msim_user_free(MsimUser *user)
+-{
+- if (!user)
+- return;
+-
+- if (user->url_data != NULL)
+- purple_util_fetch_url_cancel(user->url_data);
+-
+- g_free(user->client_info);
+- g_free(user->gender);
+- g_free(user->location);
+- g_free(user->headline);
+- g_free(user->display_name);
+- g_free(user->username);
+- g_free(user->band_name);
+- g_free(user->song_name);
+- g_free(user->image_url);
+- g_free(user);
+-}
+-
+-/**
+- * Find and return an MsimUser * representing a user on the buddy list, or NULL.
+- */
+-MsimUser *
+-msim_find_user(MsimSession *session, const gchar *username)
+-{
+- PurpleBuddy *buddy;
+-
+- buddy = purple_find_buddy(session->account, username);
+- if (!buddy) {
+- return NULL;
+- }
+-
+- return msim_get_user_from_buddy(buddy, TRUE);
+-}
+-
+-/**
+- * Append user information to a PurpleNotifyUserInfo, given an MsimUser.
+- * Used by msim_tooltip_text() and msim_get_info_cb() to show a user's profile.
+- */
+-void
+-msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full)
+-{
+- PurplePresence *presence;
+- gchar *str;
+- guint cv;
+-
+- /* Useful to identify the account the tooltip refers to.
+- * Other prpls show this. */
+- if (user->username) {
+- purple_notify_user_info_add_pair(user_info, _("User"), user->username);
+- }
+-
+- /* a/s/l...the vitals */
+- if (user->age) {
+- char age[16];
+- g_snprintf(age, sizeof(age), "%d", user->age);
+- purple_notify_user_info_add_pair(user_info, _("Age"), age);
+- }
+-
+- if (user->gender && *user->gender) {
+- purple_notify_user_info_add_pair(user_info, _("Gender"), user->gender);
+- }
+-
+- if (user->location && *user->location) {
+- purple_notify_user_info_add_pair(user_info, _("Location"), user->location);
+- }
+-
+- /* Other information */
+- if (user->headline && *user->headline) {
+- purple_notify_user_info_add_pair(user_info, _("Headline"), user->headline);
+- }
+-
+- if (user->buddy != NULL) {
+- presence = purple_buddy_get_presence(user->buddy);
+-
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+- PurpleStatus *status;
+- const char *artist, *title;
+-
+- status = purple_presence_get_status(presence, "tune");
+- title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+- artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+-
+- str = msim_format_now_playing(artist, title);
+- if (str && *str) {
+- purple_notify_user_info_add_pair(user_info, _("Song"), str);
+- }
+- g_free(str);
+- }
+- }
+-
+- /* Note: total friends only available if looked up by uid, not username. */
+- if (user->total_friends) {
+- char friends[16];
+- g_snprintf(friends, sizeof(friends), "%d", user->total_friends);
+- purple_notify_user_info_add_pair(user_info, _("Total Friends"), friends);
+- }
+-
+- if (full) {
+- /* Client information */
+- char *client = NULL;
+-
+- str = user->client_info;
+- cv = user->client_cv;
+-
+- if (str && cv != 0) {
+- client = g_strdup_printf("%s (build %d)", str, cv);
+- } else if (str) {
+- client = g_strdup(str);
+- } else if (cv) {
+- client = g_strdup_printf("Build %d", cv);
+- }
+- if (client && *client)
+- purple_notify_user_info_add_pair(user_info, _("Client Version"), client);
+- g_free(client);
+- }
+-
+- if (full && user->id) {
+- /* TODO: link to username, if available */
+- char *profile;
+- purple_notify_user_info_add_section_break(user_info);
+- if (user->buddy != NULL)
+- profile = g_strdup_printf("<a href=\"http://myspace.com/%s\">%s</a>",
+- purple_buddy_get_name(user->buddy), _("View web profile"));
+- else
+- profile = g_strdup_printf("<a href=\"http://myspace.com/%d\">%s</a>",
+- user->id, _("View web profile"));
+- purple_notify_user_info_add_pair(user_info, NULL, profile);
+- g_free(profile);
+- }
+-}
+-
+-/**
+- * Callback for when a buddy icon finished being downloaded.
+- */
+-static void
+-msim_downloaded_buddy_icon(PurpleUtilFetchUrlData *url_data,
+- gpointer user_data,
+- const gchar *url_text,
+- gsize len,
+- const gchar *error_message)
+-{
+- MsimUser *user = (MsimUser *)user_data;
+- const char *name = purple_buddy_get_name(user->buddy);
+- PurpleAccount *account;
+-
+- user->url_data = NULL;
+-
+- purple_debug_info("msim_downloaded_buddy_icon",
+- "Downloaded %" G_GSIZE_FORMAT " bytes\n", len);
+-
+- if (!url_text) {
+- purple_debug_info("msim_downloaded_buddy_icon",
+- "failed to download icon for %s",
+- name);
+- return;
+- }
+-
+- account = purple_buddy_get_account(user->buddy);
+- purple_buddy_icons_set_for_user(account, name,
+- g_memdup((gchar *)url_text, len), len,
+- /* Use URL itself as buddy icon "checksum" (TODO: ETag) */
+- user->image_url); /* checksum */
+-}
+-
+-/**
+- * Set the currently playing song artist and or title.
+- *
+- * @param user User associated with the now playing information.
+- *
+- * @param new_artist New artist to set, or NULL/empty to not change artist.
+- *
+- * @param new_title New title to set, or NULL/empty to not change title.
+- *
+- * If new_artist and new_title are NULL/empty, deactivate PURPLE_STATUS_TUNE.
+- *
+- * This function is useful because it lets you set the artist or title
+- * individually, which purple_prpl_got_user_status() doesn't do.
+- */
+-static void msim_set_artist_or_title(MsimUser *user, const char *new_artist, const char *new_title)
+-{
+- PurplePresence *presence;
+- PurpleAccount *account;
+- const char *prev_artist, *prev_title;
+- const char *name;
+-
+- if (user->buddy == NULL)
+- /* User not on buddy list so nothing to do */
+- return;
+-
+- prev_artist = NULL;
+- prev_title = NULL;
+-
+- if (new_artist && !*new_artist)
+- new_artist = NULL;
+- if (new_title && !*new_title)
+- new_title = NULL;
+-
+- account = purple_buddy_get_account(user->buddy);
+- name = purple_buddy_get_name(user->buddy);
+-
+- if (!new_artist && !new_title) {
+- purple_prpl_got_user_status_deactive(account, name, "tune");
+- return;
+- }
+-
+- presence = purple_buddy_get_presence(user->buddy);
+-
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_TUNE)) {
+- PurpleStatus *status;
+-
+- status = purple_presence_get_status(presence, "tune");
+- prev_title = purple_status_get_attr_string(status, PURPLE_TUNE_TITLE);
+- prev_artist = purple_status_get_attr_string(status, PURPLE_TUNE_ARTIST);
+- }
+-
+- if (!new_artist)
+- new_artist = prev_artist;
+-
+- if (!new_title)
+- new_title = prev_title;
+-
+- purple_prpl_got_user_status(account, name, "tune",
+- PURPLE_TUNE_TITLE, new_title,
+- PURPLE_TUNE_ARTIST, new_artist,
+- NULL);
+-}
+-
+-/**
+- * Store a field of information about a buddy.
+- *
+- * @param key_str Key to store.
+- * @param value_str Value string, either user takes ownership of this string
+- * or it is freed if MsimUser doesn't store the string.
+- * @param user User to store data in. Existing data will be replaced.
+- */
+-static void
+-msim_store_user_info_each(const gchar *key_str, gchar *value_str, MsimUser *user)
+-{
+- const char *name = user->buddy ? purple_buddy_get_name(user->buddy) : NULL;
+-
+- if (g_str_equal(key_str, "UserID") || g_str_equal(key_str, "ContactID")) {
+- /* Save to buddy list, if it exists, for quick cached uid lookup with msim_uid2username_from_blist(). */
+- user->id = atol(value_str);
+- g_free(value_str);
+- if (user->buddy)
+- {
+- purple_debug_info("msim", "associating uid %s with username %s\n", key_str, name);
+- purple_blist_node_set_int(PURPLE_BLIST_NODE(user->buddy), "UserID", user->id);
+- }
+- /* Need to store in MsimUser, too? What if not on blist? */
+- } else if (g_str_equal(key_str, "Age")) {
+- user->age = atol(value_str);
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "Gender")) {
+- g_free(user->gender);
+- user->gender = value_str;
+- } else if (g_str_equal(key_str, "Location")) {
+- g_free(user->location);
+- user->location = value_str;
+- } else if (g_str_equal(key_str, "TotalFriends")) {
+- user->total_friends = atol(value_str);
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "DisplayName")) {
+- g_free(user->display_name);
+- user->display_name = value_str;
+- } else if (g_str_equal(key_str, "BandName")) {
+- msim_set_artist_or_title(user, value_str, NULL);
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "SongName")) {
+- msim_set_artist_or_title(user, NULL, value_str);
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "UserName") || g_str_equal(key_str, "IMName") || g_str_equal(key_str, "NickName")) {
+- /* Ignore because PurpleBuddy knows this already */
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "ImageURL") || g_str_equal(key_str, "AvatarURL")) {
+- const gchar *previous_url;
+-
+- if (user->temporary_user) {
+- /* This user will be destroyed soon; don't try to look up its image or avatar,
+- * since that won't return immediately and we will end up accessing freed data.
+- */
+- g_free(value_str);
+- return;
+- }
+-
+- g_free(user->image_url);
+-
+- user->image_url = value_str;
+-
+- /* Instead of showing 'no photo' picture, show nothing. */
+- if (g_str_equal(user->image_url, "http://x.myspace.com/images/no_pic.gif"))
+- {
+- purple_buddy_icons_set_for_user(purple_buddy_get_account(user->buddy),
+- name, NULL, 0, NULL);
+- return;
+- }
+-
+- /* TODO: use ETag for checksum */
+- previous_url = purple_buddy_icons_get_checksum_for_user(user->buddy);
+-
+- /* Only download if URL changed */
+- if (!previous_url || !g_str_equal(previous_url, user->image_url)) {
+- if (user->url_data != NULL)
+- purple_util_fetch_url_cancel(user->url_data);
+- user->url_data = purple_util_fetch_url(user->image_url, TRUE, NULL, TRUE, msim_downloaded_buddy_icon, (gpointer)user);
+- }
+- } else if (g_str_equal(key_str, "LastImageUpdated")) {
+- /* TODO: use somewhere */
+- user->last_image_updated = atol(value_str);
+- g_free(value_str);
+- } else if (g_str_equal(key_str, "Headline")) {
+- g_free(user->headline);
+- user->headline = value_str;
+- } else {
+- /* TODO: other fields in MsimUser */
+- gchar *msg;
+-
+- msg = g_strdup_printf("msim_store_user_info_each: unknown field %s=%s",
+- key_str, value_str);
+- g_free(value_str);
+-
+- msim_unrecognized(NULL, NULL, msg);
+-
+- g_free(msg);
+- }
+-}
+-
+-/**
+- * Save buddy information to the buddy list from a user info reply message.
+- *
+- * @param session
+- * @param msg The user information reply, with any amount of information.
+- * @param user The structure to save to, or NULL to save in PurpleBuddy->proto_data.
+- *
+- * Variable information is saved to the passed MsimUser structure. Permanent
+- * information (UserID) is stored in the blist node of the buddy list (and
+- * ends up in blist.xml, persisted to disk) if it exists.
+- *
+- * If the function has no buddy information, this function
+- * is a no-op (and returns FALSE).
+- */
+-gboolean
+-msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user)
+-{
+- gchar *username;
+- MsimMessage *body, *body_node;
+-
+- g_return_val_if_fail(msg != NULL, FALSE);
+-
+- body = msim_msg_get_dictionary(msg, "body");
+- if (!body) {
+- return FALSE;
+- }
+-
+- if (msim_msg_get_integer(msg, "dsn") == MG_OWN_IM_INFO_DSN &&
+- msim_msg_get_integer(msg, "lid") == MG_OWN_IM_INFO_LID)
+- {
+- /*
+- * Some of this info will be available on the buddy list if the
+- * user has themselves as their own buddy.
+- *
+- * Much of the info is already available in MsimSession,
+- * stored in msim_we_are_logged_on().
+- */
+- gchar *tmpstr;
+-
+- tmpstr = msim_msg_get_string(body, "ShowOnlyToList");
+- if (tmpstr != NULL) {
+- session->show_only_to_list = g_str_equal(tmpstr, "True");
+- g_free(tmpstr);
+- }
+-
+- session->privacy_mode = msim_msg_get_integer(body, "PrivacyMode");
+- session->offline_message_mode = msim_msg_get_integer(body, "OfflineMessageMode");
+-
+- msim_send(session,
+- "blocklist", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "idlist", MSIM_TYPE_STRING,
+- g_strdup_printf("w%d|c%d",
+- session->show_only_to_list ? 1 : 0,
+- session->privacy_mode & 1),
+- NULL);
+- } else if (msim_msg_get_integer(msg, "dsn") == MG_OWN_MYSPACE_INFO_DSN &&
+- msim_msg_get_integer(msg, "lid") == MG_OWN_MYSPACE_INFO_LID) {
+- /* TODO: same as above, but for MySpace info. */
+- }
+-
+- username = msim_msg_get_string(body, "UserName");
+-
+- if (!username) {
+- purple_debug_info("msim",
+- "msim_process_reply: not caching body, no UserName\n");
+- msim_msg_free(body);
+- g_free(username);
+- return FALSE;
+- }
+-
+- /* Null user = find and store in PurpleBuddy's proto_data */
+- if (!user) {
+- user = msim_find_user(session, username);
+- if (!user) {
+- msim_msg_free(body);
+- g_free(username);
+- return FALSE;
+- }
+- }
+-
+- /* TODO: make looping over MsimMessage's easier. */
+- for (body_node = body;
+- body_node != NULL;
+- body_node = msim_msg_get_next_element_node(body_node))
+- {
+- const gchar *key_str;
+- gchar *value_str;
+- MsimMessageElement *elem;
+-
+- elem = (MsimMessageElement *)body_node->data;
+- key_str = elem->name;
+-
+- value_str = msim_msg_get_string_from_element(elem);
+- msim_store_user_info_each(key_str, value_str, user);
+- }
+-
+- msim_msg_free(body);
+- g_free(username);
+-
+- return TRUE;
+-}
+-
+-#if 0
+-/**
+- * Return whether a given username is syntactically valid.
+- * Note: does not actually check that the user exists.
+- */
+-static gboolean
+-msim_is_valid_username(const gchar *user)
+-{
+- return !msim_is_userid(user) && /* Not all numeric */
+- strlen(user) <= MSIM_MAX_USERNAME_LENGTH
+- && strspn(user, "0123456789"
+- "abcdefghijklmnopqrstuvwxyz"
+- "_"
+- "ABCDEFGHIJKLMNOPQRSTUVWXYZ") == strlen(user);
+-}
+-#endif
+-
+-/**
+- * Check if a string is a userid (all numeric).
+- *
+- * @param user The user id, email, or name.
+- *
+- * @return TRUE if is userid, FALSE if not.
+- */
+-gboolean
+-msim_is_userid(const gchar *user)
+-{
+- g_return_val_if_fail(user != NULL, FALSE);
+-
+- return strspn(user, "0123456789") == strlen(user);
+-}
+-
+-/**
+- * Check if a string is an email address (contains an @).
+- *
+- * @param user The user id, email, or name.
+- *
+- * @return TRUE if is an email, FALSE if not.
+- *
+- * This function is not intended to be used as a generic
+- * means of validating email addresses, but to distinguish
+- * between a user represented by an email address from
+- * other forms of identification.
+- */
+-static gboolean
+-msim_is_email(const gchar *user)
+-{
+- g_return_val_if_fail(user != NULL, FALSE);
+-
+- return strchr(user, '@') != NULL;
+-}
+-
+-/**
+- * Asynchronously lookup user information, calling callback when receive result.
+- *
+- * @param session
+- * @param user The user id, email address, or username. Not freed.
+- * @param cb Callback, called with user information when available.
+- * @param data An arbitray data pointer passed to the callback.
+- */
+-/* TODO: change to not use callbacks */
+-void
+-msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data)
+-{
+- MsimMessage *body;
+- gchar *field_name;
+- guint rid, dsn, lid;
+-
+- g_return_if_fail(user != NULL);
+- /* Callback can be null to not call anything, just lookup & store information. */
+- /*g_return_if_fail(cb != NULL);*/
+-
+- purple_debug_info("msim", "msim_lookup_userid: "
+- "asynchronously looking up <%s>\n", user);
+-
+- /* Setup callback. Response will be associated with request using 'rid'. */
+- rid = msim_new_reply_callback(session, cb, data);
+-
+- /* Send request */
+-
+- if (msim_is_userid(user)) {
+- field_name = "UserID";
+- dsn = MG_MYSPACE_INFO_BY_ID_DSN;
+- lid = MG_MYSPACE_INFO_BY_ID_LID;
+- } else if (msim_is_email(user)) {
+- field_name = "Email";
+- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
+- lid = MG_MYSPACE_INFO_BY_STRING_LID;
+- } else {
+- field_name = "UserName";
+- dsn = MG_MYSPACE_INFO_BY_STRING_DSN;
+- lid = MG_MYSPACE_INFO_BY_STRING_LID;
+- }
+-
+- body = msim_msg_new(
+- field_name, MSIM_TYPE_STRING, g_strdup(user),
+- NULL);
+-
+- g_return_if_fail(msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, dsn,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "lid", MSIM_TYPE_INTEGER, lid,
+- "rid", MSIM_TYPE_INTEGER, rid,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL));
+-}
+-
+-/**
+- * Called after username is set.
+- */
+-static void msim_username_is_set_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
+-{
+- gchar *username;
+- const gchar *errmsg;
+- MsimMessage *body;
+-
+- guint rid;
+- gint cmd,dsn,uid,lid,code;
+- /* \persistr\\cmd\258\dsn\9\uid\204084363\lid\14\rid\369\body\UserName=TheAlbinoRhino1.Code=0\final\ */
+-
+- purple_debug_info("msim","username_is_set made\n");
+-
+- cmd = msim_msg_get_integer(userinfo, "cmd");
+- dsn = msim_msg_get_integer(userinfo, "dsn");
+- uid = msim_msg_get_integer(userinfo, "uid");
+- lid = msim_msg_get_integer(userinfo, "lid");
+- body = msim_msg_get_dictionary(userinfo, "body");
+- errmsg = _("An error occurred while trying to set the username. "
+- "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
+- "fuseaction=profile.username to set your username.");
+-
+- if (!body) {
+- purple_debug_info("msim_username_is_set_cb", "No body");
+- /* Error: No body! */
+- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+- }
+- username = msim_msg_get_string(body, "UserName");
+- code = msim_msg_get_integer(body,"Code");
+-
+- msim_msg_free(body);
+-
+- purple_debug_info("msim_username_is_set_cb",
+- "cmd = %d, dsn = %d, lid = %d, code = %d, username = %s\n",
+- cmd, dsn, lid, code, username);
+-
+- if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_PUT)
+- && dsn == MC_SET_USERNAME_DSN
+- && lid == MC_SET_USERNAME_LID)
+- {
+- purple_debug_info("msim_username_is_set_cb", "Proper cmd,dsn,lid for username_is_set!\n");
+- purple_debug_info("msim_username_is_set_cb", "Username Set with return code %d\n",code);
+- if (code == 0) {
+- /* Good! */
+- session->username = username;
+- msim_we_are_logged_on(session);
+- } else {
+- purple_debug_info("msim_username_is_set", "code is %d",code);
+- /* TODO: what to do here? */
+- }
+- } else if (cmd == (MSIM_CMD_BIT_REPLY | MSIM_CMD_GET)
+- && dsn == MG_MYSPACE_INFO_BY_STRING_DSN
+- && lid == MG_MYSPACE_INFO_BY_STRING_LID) {
+- /* Not quite done... ONE MORE STEP :) */
+- rid = msim_new_reply_callback(session, msim_username_is_set_cb, data);
+- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username), NULL);
+- if (!msim_send(session, "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_PUT,
+- "dsn", MSIM_TYPE_INTEGER, MC_SET_USERNAME_DSN,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "lid", MSIM_TYPE_INTEGER, MC_SET_USERNAME_LID,
+- "rid", MSIM_TYPE_INTEGER, rid,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL)) {
+- /* Error! */
+- /* Can't set... Disconnect */
+- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+- }
+-
+- } else {
+- /* Error! */
+- purple_debug_info("msim","username_is_set Error: Invalid cmd/dsn/lid combination");
+- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, errmsg);
+- }
+-}
+-
+-/**
+- * Asynchronously set new username, calling callback when receive result.
+- *
+- * @param session
+- * @param username The username we're setting for ourselves. Not freed.
+- * @param cb Callback, called with user information when available.
+- * @param data An arbitray data pointer passed to the callback.
+- */
+-static void
+-msim_set_username(MsimSession *session, const gchar *username,
+- MSIM_USER_LOOKUP_CB cb, gpointer data)
+-{
+- MsimMessage *body;
+- guint rid;
+-
+- g_return_if_fail(username != NULL);
+- g_return_if_fail(cb != NULL);
+-
+- purple_debug_info("msim", "msim_set_username: "
+- "Setting username %s\n", username);
+-
+- /* Setup callback. Response will be associated with request using 'rid'. */
+- rid = msim_new_reply_callback(session, cb, data);
+-
+- /* TODO: I dont know if the ContactType is -/ALWAYS/- 1 */
+-
+- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
+-/* \setinfo\\sesskey\469958979\info\Age=21.AvatarUrl=.BandName=.ContactType=1.DisplayName=Msim.Gender=M.ImageURL=http:/1/1x.myspace.com/1images/1no_pic.gif.LastLogin=128335268400000000.Location=US.ShowAvatar=False.SongName=.TotalFriends=1.UserName=msimprpl2\final\
+-*/
+-
+- /* Send request */
+- g_return_if_fail(msim_send(session,
+- "setinfo", MSIM_TYPE_BOOLEAN, TRUE,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "info", MSIM_TYPE_DICTIONARY, body,
+- NULL));
+- body = msim_msg_new("UserName", MSIM_TYPE_STRING, g_strdup(username),NULL);
+- g_return_if_fail(msim_send(session,
+- "persist", MSIM_TYPE_INTEGER, 1,
+- "sesskey", MSIM_TYPE_INTEGER, session->sesskey,
+- "cmd", MSIM_TYPE_INTEGER, MSIM_CMD_GET,
+- "dsn", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_DSN,
+- "uid", MSIM_TYPE_INTEGER, session->userid,
+- "lid", MSIM_TYPE_INTEGER, MG_MYSPACE_INFO_BY_STRING_LID,
+- "rid", MSIM_TYPE_INTEGER, rid,
+- "body", MSIM_TYPE_DICTIONARY, body,
+- NULL));
+-}
+-
+-/**
+- * They've confirmed that username that was available, Lets make the call to set it
+- */
+-static void msim_set_username_confirmed_cb(PurpleConnection *gc)
+-{
+- MsimMessage *user_msg;
+- MsimSession *session;
+-
+- g_return_if_fail(gc != NULL);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- user_msg = msim_msg_new(
+- "user", MSIM_TYPE_STRING, g_strdup(msim_username_to_set),
+- NULL);
+-
+- purple_debug_info("msim_set_username_confirmed_cb", "Setting username to %s\n", msim_username_to_set);
+-
+- /* Sets our username... keep your fingers crossed :) */
+- msim_set_username(session, msim_username_to_set, msim_username_is_set_cb, user_msg);
+- g_free(msim_username_to_set);
+-}
+-
+-/**
+- * This is where we do a bit more than merely prompt the user.
+- * Now we have some real data to tell us the state of their requested username
+- * \persistr\\cmd\257\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=TheAlbinoRhino1\final\
+- */
+-static void msim_username_is_available_cb(MsimSession *session, const MsimMessage *userinfo, gpointer data)
+-{
+- MsimMessage *msg;
+- gchar *username;
+- MsimMessage *body;
+- gint userid;
+-
+- purple_debug_info("msim_username_is_available_cb", "Look up username callback made\n");
+-
+- msg = (MsimMessage *)data;
+- g_return_if_fail(msg != NULL);
+-
+- username = msim_msg_get_string(msg, "user");
+- body = msim_msg_get_dictionary(userinfo, "body");
+-
+- if (!body) {
+- purple_debug_info("msim_username_is_available_cb", "No body for %s?!\n", username);
+- purple_connection_error_reason(session->gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+- _("An error occurred while trying to set the username. "
+- "Please try again, or visit http://editprofile.myspace.com/index.cfm?"
+- "fuseaction=profile.username to set your username."));
+- return;
+- }
+-
+- userid = msim_msg_get_integer(body, "UserID");
+-
+- purple_debug_info("msim_username_is_available_cb", "Returned username is %s and userid is %d\n", username, userid);
+- msim_msg_free(body);
+- msim_msg_free(msg);
+-
+- /* The response for a free username will ONLY have the UserName in it..
+- * thus making UserID return 0 when we msg_get_integer it */
+- if (userid == 0) {
+- /* This username is currently unused */
+- purple_debug_info("msim_username_is_available_cb", "Username available. Prompting to Confirm.\n");
+- msim_username_to_set = g_strdup(username);
+- g_free(username);
+- purple_request_yes_no(session->gc,
+- _("MySpaceIM - Username Available"),
+- _("This username is available. Would you like to set it?"),
+- _("ONCE SET, THIS CANNOT BE CHANGED!"),
+- 0,
+- session->account,
+- NULL,
+- NULL,
+- session->gc,
+- G_CALLBACK(msim_set_username_confirmed_cb),
+- G_CALLBACK(msim_do_not_set_username_cb));
+- } else {
+- /* Looks like its in use or we have an invalid response */
+- purple_debug_info("msim_username_is_available_cb", "Username unavaiable. Prompting for new entry.\n");
+- purple_request_input(session->gc, _("MySpaceIM - Please Set a Username"),
+- _("This username is unavailable."),
+- _("Please try another username:"),
+- "", FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msim_check_username_availability_cb),
+- _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
+- session->account,
+- NULL,
+- NULL,
+- session->gc);
+- }
+-}
+-
+-/**
+- * Once they've submitted their desired new username,
+- * check if it is available here.
+- */
+-static void msim_check_username_availability_cb(PurpleConnection *gc, const char *username_to_check)
+-{
+- MsimMessage *user_msg;
+- MsimSession *session;
+-
+- g_return_if_fail(gc != NULL);
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- purple_debug_info("msim_check_username_availability_cb", "Checking username: %s\n", username_to_check);
+-
+- user_msg = msim_msg_new(
+- "user", MSIM_TYPE_STRING, g_strdup(username_to_check),
+- NULL);
+-
+- /* 25 characters: letters, numbers, underscores */
+- /* TODO: VERIFY ABOVE */
+-
+- /* \persist\1\sesskey\288500516\cmd\1\dsn\5\uid\204084363\lid\7\rid\367\body\UserName=Jaywalker\final\ */
+- /* Official client uses a standard lookup... So do we! */
+- msim_lookup_user(session, username_to_check, msim_username_is_available_cb, user_msg);
+-}
+-
+-/***
+- * If they hit cancel or no at any point in the Setting Username process,
+- * we come here. Currently we're safe letting them get by without
+- * setting it, unless we hear otherwise. So for now give them a menu.
+- * If this becomes an issue with the official client then boot them here.
+- */
+-void msim_do_not_set_username_cb(PurpleConnection *gc)
+-{
+- purple_debug_info("msim", "Don't set username");
+-
+- /* Protocol won't log in now without a username set.. Disconnect */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("No username set"));
+-}
+-
+-/**
+- * They've decided to set a username! Yay!
+- */
+-void msim_set_username_cb(PurpleConnection *gc)
+-{
+- g_return_if_fail(gc != NULL);
+- purple_debug_info("msim","Set username\n");
+- purple_request_input(gc, _("MySpaceIM - Please Set a Username"),
+- _("Please enter a username to check its availability:"),
+- NULL,
+- "", FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(msim_check_username_availability_cb),
+- _("Cancel"), G_CALLBACK(msim_do_not_set_username_cb),
+- purple_connection_get_account(gc),
+- NULL,
+- NULL,
+- gc);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/user.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/user.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/user.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,60 +0,0 @@
+-/* MySpaceIM Protocol Plugin, header file
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_USER_H
+-#define _MYSPACE_USER_H
+-
+-/* Hold ephemeral information about buddies, for proto_data of PurpleBuddy. */
+-/* GHashTable? */
+-typedef struct _MsimUser
+-{
+- PurpleBuddy *buddy;
+- /* Note: id is also &buddy->node (set_blist_node_int), when buddy is non-NULL */
+- int id;
+- guint client_cv;
+- gchar *client_info;
+- guint age;
+- gchar *gender;
+- gchar *location;
+- guint total_friends;
+- gchar *headline;
+- gchar *display_name;
+- gchar *username;
+- gchar *band_name, *song_name;
+- gchar *image_url;
+- guint last_image_updated;
+- gboolean temporary_user;
+- PurpleUtilFetchUrlData *url_data;
+-} MsimUser;
+-
+-/* Callback function pointer type for when a user's information is received,
+- * initiated from a user lookup. */
+-typedef void (*MSIM_USER_LOOKUP_CB)(MsimSession *session, const MsimMessage *userinfo, gpointer data);
+-
+-MsimUser *msim_get_user_from_buddy(PurpleBuddy *buddy, gboolean create);
+-void msim_user_free(MsimUser *user);
+-MsimUser *msim_find_user(MsimSession *session, const gchar *username);
+-void msim_append_user_info(MsimSession *session, PurpleNotifyUserInfo *user_info, MsimUser *user, gboolean full);
+-gboolean msim_store_user_info(MsimSession *session, const MsimMessage *msg, MsimUser *user);
+-gboolean msim_is_userid(const gchar *user);
+-void msim_lookup_user(MsimSession *session, const gchar *user, MSIM_USER_LOOKUP_CB cb, gpointer data);
+-void msim_set_username_cb(PurpleConnection *gc);
+-void msim_do_not_set_username_cb(PurpleConnection *gc);
+-
+-#endif /* !_MYSPACE_USER_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/zap.c pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.c
+--- pidgin-2.10.7/libpurple/protocols/myspace/zap.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,246 +0,0 @@
+-/* MySpaceIM Protocol Plugin - zap support
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "myspace.h"
+-#include "zap.h"
+-
+-/** Get zap types. */
+-GList *
+-msim_attention_types(PurpleAccount *acct)
+-{
+- static GList *types = NULL;
+- PurpleAttentionType* attn;
+-
+- if (!types) {
+-#define _MSIM_ADD_NEW_ATTENTION(icn, ulname, nme, incoming, outgoing) \
+- attn = purple_attention_type_new(ulname, nme, incoming, outgoing); \
+- purple_attention_type_set_icon_name(attn, icn); \
+- types = g_list_append(types, attn);
+-
+- /* TODO: icons for each zap */
+-
+- /* Lots of comments for translators: */
+-
+- /* Zap means "to strike suddenly and forcefully as if with a
+- * projectile or weapon." This term often has an electrical
+- * connotation, for example, "he was zapped by electricity when
+- * he put a fork in the toaster." */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Zap", _("Zap"), _("%s has zapped you!"),
+- _("Zapping %s..."));
+-
+- /* Whack means "to hit or strike someone with a sharp blow" */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Whack", _("Whack"),
+- _("%s has whacked you!"), _("Whacking %s..."));
+-
+- /* Torch means "to set on fire." Don't worry, this doesn't
+- * make a whole lot of sense in English, either. Feel free
+- * to translate it literally. */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Torch", _("Torch"),
+- _("%s has torched you!"), _("Torching %s..."));
+-
+- /* Smooch means "to kiss someone, often enthusiastically" */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Smooch", _("Smooch"),
+- _("%s has smooched you!"), _("Smooching %s..."));
+-
+- /* A hug is a display of affection; wrapping your arms around someone */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Hug", _("Hug"), _("%s has hugged you!"),
+- _("Hugging %s..."));
+-
+- /* Slap means "to hit someone with an open/flat hand" */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Slap", _("Slap"),
+- _("%s has slapped you!"), _("Slapping %s..."));
+-
+- /* Goose means "to pinch someone on their butt" */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Goose", _("Goose"),
+- _("%s has goosed you!"), _("Goosing %s..."));
+-
+- /* A high-five is when two people's hands slap each other
+- * in the air above their heads. It is done to celebrate
+- * something, often a victory, or to congratulate someone. */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "High-five", _("High-five"),
+- _("%s has high-fived you!"), _("High-fiving %s..."));
+-
+- /* We're not entirely sure what the MySpace people mean by
+- * this... but we think it's the equivalent of "prank." Or, for
+- * someone to perform a mischievous trick or practical joke. */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Punk", _("Punk"),
+- _("%s has punk'd you!"), _("Punking %s..."));
+-
+- /* Raspberry is a slang term for the vibrating sound made
+- * when you stick your tongue out of your mouth with your
+- * lips closed and blow. It is typically done when
+- * gloating or bragging. Nowadays it's a pretty silly
+- * gesture, so it does not carry a harsh negative
+- * connotation. It is generally used in a playful tone
+- * with friends. */
+- _MSIM_ADD_NEW_ATTENTION(NULL, "Raspberry", _("Raspberry"),
+- _("%s has raspberried you!"), _("Raspberrying %s..."));
+- }
+-
+- return types;
+-}
+-
+-/** Send a zap to a user. */
+-static gboolean
+-msim_send_zap(MsimSession *session, const gchar *username, guint code)
+-{
+- gchar *zap_string;
+- gboolean rc;
+-
+- g_return_val_if_fail(session != NULL, FALSE);
+- g_return_val_if_fail(username != NULL, FALSE);
+-
+- /* Construct and send the actual zap command. */
+- zap_string = g_strdup_printf("!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", code);
+-
+- if (!msim_send_bm(session, username, zap_string, MSIM_BM_ACTION_OR_IM_INSTANT)) {
+- purple_debug_info("msim_send_zap",
+- "msim_send_bm failed: zapping %s with %s\n",
+- username, zap_string);
+- rc = FALSE;
+- } else {
+- rc = TRUE;
+- }
+-
+- g_free(zap_string);
+-
+- return rc;
+-}
+-
+-/** Send a zap */
+-gboolean
+-msim_send_attention(PurpleConnection *gc, const gchar *username, guint code)
+-{
+- GList *types;
+- MsimSession *session;
+- PurpleAttentionType *attn;
+- PurpleBuddy *buddy;
+-
+- session = (MsimSession *)gc->proto_data;
+-
+- /* Look for this attention type, by the code index given. */
+- types = msim_attention_types(gc->account);
+- attn = (PurpleAttentionType *)g_list_nth_data(types, code);
+-
+- if (!attn) {
+- purple_debug_info("msim_send_attention", "got invalid zap code %d\n", code);
+- return FALSE;
+- }
+-
+- buddy = purple_find_buddy(session->account, username);
+- if (!buddy) {
+- return FALSE;
+- }
+-
+- msim_send_zap(session, username, code);
+-
+- return TRUE;
+-}
+-
+-/** Zap someone. Callback from msim_blist_node_menu zap menu. */
+-static void
+-msim_send_zap_from_menu(PurpleBlistNode *node, gpointer zap_num_ptr)
+-{
+- PurpleBuddy *buddy;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- MsimSession *session;
+- guint zap;
+-
+- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+- /* Only know about buddies for now. */
+- return;
+- }
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *)node;
+-
+- /* Find the session */
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- session = (MsimSession *)gc->proto_data;
+-
+- zap = GPOINTER_TO_INT(zap_num_ptr);
+-
+- purple_prpl_send_attention(session->gc, purple_buddy_get_name(buddy), zap);
+-}
+-
+-/** Return menu, if any, for a buddy list node. */
+-GList *
+-msim_blist_node_menu(PurpleBlistNode *node)
+-{
+- GList *menu, *zap_menu;
+- GList *types;
+- PurpleMenuAction *act;
+- guint i;
+-
+- if (!PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+- /* Only know about buddies for now. */
+- return NULL;
+- }
+-
+- zap_menu = NULL;
+-
+- /* TODO: get rid of once is accessible directly in GUI */
+- types = msim_attention_types(NULL);
+- i = 0;
+- do
+- {
+- PurpleAttentionType *attn;
+-
+- attn = (PurpleAttentionType *)types->data;
+-
+- act = purple_menu_action_new(purple_attention_type_get_name(attn),
+- PURPLE_CALLBACK(msim_send_zap_from_menu), GUINT_TO_POINTER(i), NULL);
+- zap_menu = g_list_append(zap_menu, act);
+-
+- ++i;
+- } while ((types = g_list_next(types)));
+-
+- act = purple_menu_action_new(_("Zap"), NULL, NULL, zap_menu);
+- menu = g_list_append(NULL, act);
+-
+- return menu;
+-}
+-
+-/** Process an incoming zap. */
+-gboolean
+-msim_incoming_zap(MsimSession *session, MsimMessage *msg)
+-{
+- gchar *msg_text, *username;
+- gint zap;
+-
+- msg_text = msim_msg_get_string(msg, "msg");
+- username = msim_msg_get_string(msg, "_username");
+-
+- g_return_val_if_fail(msg_text != NULL, FALSE);
+- g_return_val_if_fail(username != NULL, FALSE);
+-
+- g_return_val_if_fail(sscanf(msg_text, "!!!ZAP_SEND!!!=RTE_BTN_ZAPS_%d", &zap) == 1, FALSE);
+-
+- zap = CLAMP(zap, 0, 9);
+-
+- purple_prpl_got_attention(session->gc, username, zap);
+-
+- g_free(msg_text);
+- g_free(username);
+-
+- return TRUE;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/myspace/zap.h pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.h
+--- pidgin-2.10.7/libpurple/protocols/myspace/zap.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/myspace/zap.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,28 +0,0 @@
+-/* MySpaceIM Protocol Plugin - zap support
+- *
+- * Copyright (C) 2007, Jeff Connelly <jeff2@soc.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., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _MYSPACE_ZAP_H
+-#define _MYSPACE_ZAP_H
+-
+-GList *msim_attention_types(PurpleAccount *acct);
+-gboolean msim_send_attention(PurpleConnection *gc, const gchar *username, guint code);
+-GList *msim_blist_node_menu(PurpleBlistNode *node);
+-gboolean msim_incoming_zap(MsimSession *session, MsimMessage *msg);
+-
+-#endif /* !_MYSPACE_ZAP_H */
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/novell/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,53 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-NOVELLSOURCES = \
+- nmfield.h \
+- nmfield.c \
+- nmconn.h \
+- nmconn.c \
+- nmconference.h \
+- nmconference.c \
+- nmcontact.h \
+- nmcontact.c \
+- nmevent.h \
+- nmevent.c \
+- nmmessage.h \
+- nmmessage.c \
+- nmrequest.h \
+- nmrequest.c \
+- nmrtf.h \
+- nmrtf.c \
+- nmuser.h \
+- nmuser.c \
+- nmuserrecord.h \
+- nmuserrecord.c \
+- novell.c
+-
+-AM_CFLAGS = $(st)
+-
+-libnovell_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_NOVELL
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libnovell.la
+-libnovell_la_SOURCES = $(NOVELLSOURCES)
+-libnovell_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libnovell.la
+-libnovell_la_SOURCES = $(NOVELLSOURCES)
+-libnovell_la_LIBADD = $(GLIB_LIBS)
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(DEBUG_CFLAGS) \
+- $(GLIB_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/novell/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,857 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/novell
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-@STATIC_NOVELL_FALSE@libnovell_la_DEPENDENCIES = \
+-@STATIC_NOVELL_FALSE@ $(am__DEPENDENCIES_1)
+-am__libnovell_la_SOURCES_DIST = nmfield.h nmfield.c nmconn.h nmconn.c \
+- nmconference.h nmconference.c nmcontact.h nmcontact.c \
+- nmevent.h nmevent.c nmmessage.h nmmessage.c nmrequest.h \
+- nmrequest.c nmrtf.h nmrtf.c nmuser.h nmuser.c nmuserrecord.h \
+- nmuserrecord.c novell.c
+-am__objects_1 = libnovell_la-nmfield.lo libnovell_la-nmconn.lo \
+- libnovell_la-nmconference.lo libnovell_la-nmcontact.lo \
+- libnovell_la-nmevent.lo libnovell_la-nmmessage.lo \
+- libnovell_la-nmrequest.lo libnovell_la-nmrtf.lo \
+- libnovell_la-nmuser.lo libnovell_la-nmuserrecord.lo \
+- libnovell_la-novell.lo
+-@STATIC_NOVELL_FALSE@am_libnovell_la_OBJECTS = $(am__objects_1)
+-@STATIC_NOVELL_TRUE@am_libnovell_la_OBJECTS = $(am__objects_1)
+-libnovell_la_OBJECTS = $(am_libnovell_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libnovell_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libnovell_la_CFLAGS) \
+- $(CFLAGS) $(libnovell_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_NOVELL_FALSE@am_libnovell_la_rpath = -rpath $(pkgdir)
+-@STATIC_NOVELL_TRUE@am_libnovell_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libnovell_la_SOURCES)
+-DIST_SOURCES = $(am__libnovell_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-NOVELLSOURCES = \
+- nmfield.h \
+- nmfield.c \
+- nmconn.h \
+- nmconn.c \
+- nmconference.h \
+- nmconference.c \
+- nmcontact.h \
+- nmcontact.c \
+- nmevent.h \
+- nmevent.c \
+- nmmessage.h \
+- nmmessage.c \
+- nmrequest.h \
+- nmrequest.c \
+- nmrtf.h \
+- nmrtf.c \
+- nmuser.h \
+- nmuser.c \
+- nmuserrecord.h \
+- nmuserrecord.c \
+- novell.c
+-
+-AM_CFLAGS = $(st)
+-libnovell_la_LDFLAGS = -module -avoid-version
+-@STATIC_NOVELL_FALSE@st =
+-@STATIC_NOVELL_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_NOVELL_TRUE@noinst_LTLIBRARIES = libnovell.la
+-@STATIC_NOVELL_FALSE@libnovell_la_SOURCES = $(NOVELLSOURCES)
+-@STATIC_NOVELL_TRUE@libnovell_la_SOURCES = $(NOVELLSOURCES)
+-@STATIC_NOVELL_TRUE@libnovell_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_NOVELL_FALSE@pkg_LTLIBRARIES = libnovell.la
+-@STATIC_NOVELL_FALSE@libnovell_la_LIBADD = $(GLIB_LIBS)
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(DEBUG_CFLAGS) \
+- $(GLIB_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/novell/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/novell/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libnovell.la: $(libnovell_la_OBJECTS) $(libnovell_la_DEPENDENCIES) $(EXTRA_libnovell_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libnovell_la_LINK) $(am_libnovell_la_rpath) $(libnovell_la_OBJECTS) $(libnovell_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmconference.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmconn.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmcontact.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmevent.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmfield.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmmessage.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmrequest.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmrtf.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmuser.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-nmuserrecord.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libnovell_la-novell.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libnovell_la-nmfield.lo: nmfield.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmfield.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmfield.Tpo -c -o libnovell_la-nmfield.lo `test -f 'nmfield.c' || echo '$(srcdir)/'`nmfield.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmfield.Tpo $(DEPDIR)/libnovell_la-nmfield.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmfield.c' object='libnovell_la-nmfield.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmfield.lo `test -f 'nmfield.c' || echo '$(srcdir)/'`nmfield.c
+-
+-libnovell_la-nmconn.lo: nmconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmconn.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmconn.Tpo -c -o libnovell_la-nmconn.lo `test -f 'nmconn.c' || echo '$(srcdir)/'`nmconn.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmconn.Tpo $(DEPDIR)/libnovell_la-nmconn.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmconn.c' object='libnovell_la-nmconn.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmconn.lo `test -f 'nmconn.c' || echo '$(srcdir)/'`nmconn.c
+-
+-libnovell_la-nmconference.lo: nmconference.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmconference.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmconference.Tpo -c -o libnovell_la-nmconference.lo `test -f 'nmconference.c' || echo '$(srcdir)/'`nmconference.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmconference.Tpo $(DEPDIR)/libnovell_la-nmconference.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmconference.c' object='libnovell_la-nmconference.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmconference.lo `test -f 'nmconference.c' || echo '$(srcdir)/'`nmconference.c
+-
+-libnovell_la-nmcontact.lo: nmcontact.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmcontact.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmcontact.Tpo -c -o libnovell_la-nmcontact.lo `test -f 'nmcontact.c' || echo '$(srcdir)/'`nmcontact.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmcontact.Tpo $(DEPDIR)/libnovell_la-nmcontact.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmcontact.c' object='libnovell_la-nmcontact.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmcontact.lo `test -f 'nmcontact.c' || echo '$(srcdir)/'`nmcontact.c
+-
+-libnovell_la-nmevent.lo: nmevent.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmevent.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmevent.Tpo -c -o libnovell_la-nmevent.lo `test -f 'nmevent.c' || echo '$(srcdir)/'`nmevent.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmevent.Tpo $(DEPDIR)/libnovell_la-nmevent.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmevent.c' object='libnovell_la-nmevent.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmevent.lo `test -f 'nmevent.c' || echo '$(srcdir)/'`nmevent.c
+-
+-libnovell_la-nmmessage.lo: nmmessage.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmmessage.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmmessage.Tpo -c -o libnovell_la-nmmessage.lo `test -f 'nmmessage.c' || echo '$(srcdir)/'`nmmessage.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmmessage.Tpo $(DEPDIR)/libnovell_la-nmmessage.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmmessage.c' object='libnovell_la-nmmessage.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmmessage.lo `test -f 'nmmessage.c' || echo '$(srcdir)/'`nmmessage.c
+-
+-libnovell_la-nmrequest.lo: nmrequest.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmrequest.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmrequest.Tpo -c -o libnovell_la-nmrequest.lo `test -f 'nmrequest.c' || echo '$(srcdir)/'`nmrequest.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmrequest.Tpo $(DEPDIR)/libnovell_la-nmrequest.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmrequest.c' object='libnovell_la-nmrequest.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmrequest.lo `test -f 'nmrequest.c' || echo '$(srcdir)/'`nmrequest.c
+-
+-libnovell_la-nmrtf.lo: nmrtf.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmrtf.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmrtf.Tpo -c -o libnovell_la-nmrtf.lo `test -f 'nmrtf.c' || echo '$(srcdir)/'`nmrtf.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmrtf.Tpo $(DEPDIR)/libnovell_la-nmrtf.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmrtf.c' object='libnovell_la-nmrtf.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmrtf.lo `test -f 'nmrtf.c' || echo '$(srcdir)/'`nmrtf.c
+-
+-libnovell_la-nmuser.lo: nmuser.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmuser.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmuser.Tpo -c -o libnovell_la-nmuser.lo `test -f 'nmuser.c' || echo '$(srcdir)/'`nmuser.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmuser.Tpo $(DEPDIR)/libnovell_la-nmuser.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmuser.c' object='libnovell_la-nmuser.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmuser.lo `test -f 'nmuser.c' || echo '$(srcdir)/'`nmuser.c
+-
+-libnovell_la-nmuserrecord.lo: nmuserrecord.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-nmuserrecord.lo -MD -MP -MF $(DEPDIR)/libnovell_la-nmuserrecord.Tpo -c -o libnovell_la-nmuserrecord.lo `test -f 'nmuserrecord.c' || echo '$(srcdir)/'`nmuserrecord.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-nmuserrecord.Tpo $(DEPDIR)/libnovell_la-nmuserrecord.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='nmuserrecord.c' object='libnovell_la-nmuserrecord.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-nmuserrecord.lo `test -f 'nmuserrecord.c' || echo '$(srcdir)/'`nmuserrecord.c
+-
+-libnovell_la-novell.lo: novell.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -MT libnovell_la-novell.lo -MD -MP -MF $(DEPDIR)/libnovell_la-novell.Tpo -c -o libnovell_la-novell.lo `test -f 'novell.c' || echo '$(srcdir)/'`novell.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libnovell_la-novell.Tpo $(DEPDIR)/libnovell_la-novell.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='novell.c' object='libnovell_la-novell.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libnovell_la_CFLAGS) $(CFLAGS) -c -o libnovell_la-novell.lo `test -f 'novell.c' || echo '$(srcdir)/'`novell.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/novell/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,88 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libnovell
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libnovell
+-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 = \
+- nmfield.c \
+- nmconn.c \
+- nmconference.c \
+- nmcontact.c \
+- nmevent.c \
+- nmmessage.c \
+- nmrequest.c \
+- nmrtf.c \
+- nmuser.c \
+- nmuserrecord.c \
+- novell.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconference.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmconference.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,232 +0,0 @@
+-/*
+- * nmconference.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <string.h>
+-#include "nmconference.h"
+-
+-static int conf_count = 0;
+-
+-struct _NMConference
+-{
+-
+- /* The conference identifier */
+- char *guid;
+-
+- /* The list of participants for the conference */
+- GSList *participants;
+-
+- /* Flags for the conference */
+- guint32 flags;
+-
+- /* User defined data */
+- gpointer data;
+-
+- /* Reference count for this object */
+- int ref_count;
+-
+-};
+-
+-
+-/*******************************************************************************
+- * Conference API -- see header file for comments
+- ******************************************************************************/
+-
+-NMConference *
+-nm_create_conference(const char *guid)
+-{
+- NMConference *conf = g_new0(NMConference, 1);
+-
+- if (guid) {
+- conf->guid = g_strdup(guid);
+- } else {
+- conf->guid = g_strdup(BLANK_GUID);
+- }
+- conf->ref_count = 1;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Creating a conference %p, total=%d\n",
+- conf, conf_count++);
+-
+- return conf;
+-}
+-
+-void
+-nm_release_conference(NMConference * conference)
+-{
+- GSList *node;
+-
+- g_return_if_fail(conference != NULL);
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "In release conference %p, refs=%d\n",
+- conference, conference->ref_count);
+- if (--conference->ref_count == 0) {
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Releasing conference %p, total=%d\n",
+- conference, --conf_count);
+-
+- if (conference->guid)
+- g_free(conference->guid);
+-
+- if (conference->participants) {
+- for (node = conference->participants; node; node = node->next) {
+- if (node->data) {
+- NMUserRecord *user_record = node->data;
+-
+- nm_release_user_record(user_record);
+- node->data = NULL;
+- }
+- }
+-
+- g_slist_free(conference->participants);
+- }
+-
+- g_free(conference);
+- }
+-}
+-
+-gboolean
+-nm_conference_is_instantiated(NMConference * conference)
+-{
+- if (conference == NULL)
+- return FALSE;
+-
+- return (strncmp(conference->guid, BLANK_GUID, CONF_GUID_END) != 0);
+-}
+-
+-int
+-nm_conference_get_participant_count(NMConference * conference)
+-{
+- if (conference == NULL)
+- return 0;
+-
+- return g_slist_length(conference->participants);
+-}
+-
+-NMUserRecord *
+-nm_conference_get_participant(NMConference * conference, int index)
+-{
+- if (conference == NULL)
+- return NULL;
+-
+- return (NMUserRecord *) g_slist_nth_data(conference->participants, index);
+-}
+-
+-void
+-nm_conference_add_participant(NMConference * conference,
+- NMUserRecord * user_record)
+-{
+- if (conference == NULL || user_record == NULL) {
+- return;
+- }
+-
+- nm_user_record_add_ref(user_record);
+- conference->participants = g_slist_append(conference->participants, user_record);
+-}
+-
+-void
+-nm_conference_remove_participant(NMConference * conference, const char *dn)
+-{
+- GSList *node, *element = NULL;
+-
+- if (conference == NULL || dn == NULL) {
+- return;
+- }
+-
+- for (node = conference->participants; node; node = node->next) {
+- NMUserRecord *user_record = node->data;
+-
+- if (user_record) {
+- if (nm_utf8_str_equal(dn, nm_user_record_get_dn(user_record))) {
+- element = node;
+- break;
+- }
+- }
+- }
+-
+- if (element) {
+- nm_release_user_record((NMUserRecord *) element->data);
+- element->data = NULL;
+- conference->participants =
+- g_slist_remove_link(conference->participants, element);
+- g_slist_free_1(element);
+- }
+-}
+-
+-void
+-nm_conference_add_ref(NMConference * conference)
+-{
+- if (conference)
+- conference->ref_count++;
+-}
+-
+-void
+-nm_conference_set_flags(NMConference * conference, guint32 flags)
+-{
+- if (conference) {
+- conference->flags = flags;
+- }
+-}
+-
+-void
+-nm_conference_set_guid(NMConference * conference, const char *guid)
+-{
+- if (conference) {
+-
+- /* Release memory for old guid */
+- if (conference->guid) {
+- g_free(conference->guid);
+- }
+-
+- /* Set the new guid */
+- if (guid)
+- conference->guid = g_strdup(guid);
+- else
+- conference->guid = g_strdup(BLANK_GUID);
+- }
+-}
+-
+-void
+-nm_conference_set_data(NMConference * conference, gpointer data)
+-{
+- if (conference == NULL)
+- return;
+-
+- conference->data = data;
+-}
+-
+-gpointer
+-nm_conference_get_data(NMConference * conference)
+-{
+- if (conference == NULL)
+- return NULL;
+-
+- return conference->data;
+-}
+-
+-const char *
+-nm_conference_get_guid(NMConference * conference)
+-{
+- if (conference == NULL)
+- return NULL;
+-
+- return conference->guid;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconference.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmconference.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconference.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,167 +0,0 @@
+-/*
+- * nmconference.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_CONFERENCE_H__
+-#define __NM_CONFERENCE_H__
+-
+-typedef struct _NMConference NMConference;
+-
+-#include "nmuserrecord.h"
+-
+-/* A blank GUID -- represents an uninstatiated conference */
+-#define BLANK_GUID "[00000000-00000000-00000000-0000-0000]"
+-
+-/* This is how much of the conference GUIDs to compare when testing
+- * to see if two conferences are the same. We cannot compare the
+- * entire GUID because the last part is the session count.
+- */
+-#define CONF_GUID_END 27
+-
+-/**
+- * Creates an conference object.
+- *
+- * The conference should be released by calling
+- * nm_release_conference
+- *
+- * @param guid The GUID for the conference.
+- *
+- * @return The new NMConference
+- */
+-NMConference *nm_create_conference(const char *guid);
+-
+-/**
+- * Increments the reference count for the conference.
+- *
+- * The reference to the conference should be released
+- * by calling nm_release_conference
+- *
+- * @param conference The conference to reference
+- */
+-void nm_conference_add_ref(NMConference * conference);
+-
+-/**
+- * Releases the resources associated with the conference
+- * if there are no more references to it, otherwise just
+- * decrements the reference count.
+- *
+- * @param conf The conference to release
+- *
+- */
+-void nm_release_conference(NMConference * conf);
+-
+-/**
+- * Set the GUID for the conference.
+- *
+- * @param conference The conference
+- * @param guid The new conference GUID
+- *
+- */
+-void nm_conference_set_guid(NMConference * conference, const char *guid);
+-
+-/**
+- * Return the GUID for the conference.
+- *
+- * @param conference The conference
+- *
+- * @return The GUID for the conference
+- */
+-const char *nm_conference_get_guid(NMConference * conference);
+-
+-/**
+- * Add a participant to the conference.
+- *
+- * @param conference The conference
+- * @param user_record The user record to add as a participant
+- *
+- * @return
+- */
+-void nm_conference_add_participant(NMConference * conference,
+- NMUserRecord * user_record);
+-
+-/**
+- * Remove a participant to the conference.
+- *
+- * @param conference The conference
+- * @param dn The dn of the participant to remove
+- *
+- */
+-void nm_conference_remove_participant(NMConference * conference, const char *dn);
+-
+-/**
+- * Return the total number of participants in the conference.
+- *
+- * @param conference The conference
+- *
+- * @return The number of participants for the conference
+- *
+- */
+-int nm_conference_get_participant_count(NMConference * conference);
+-
+-/**
+- * Return a participant given an index.
+- *
+- * @param conference The conference
+- * @param index The index of the participant to get
+- *
+- * @return The participant or NULL if the index is out of range.
+- *
+- */
+-NMUserRecord *nm_conference_get_participant(NMConference * conference, int index);
+-
+-/**
+- * Check to see if the conference has been instantiated
+- *
+- * @param conference The conference
+- *
+- * @return TRUE if the conference has been instantiated,
+- * FALSE otherwise.
+- *
+- */
+-gboolean nm_conference_is_instantiated(NMConference * conf);
+-
+-/**
+- * Set the flags for the conference.
+- *
+- * @param conference The conference
+- * @param flags The conference flags.
+- *
+- */
+-void nm_conference_set_flags(NMConference * conference, guint32 flags);
+-
+-/**
+- * Set the user defined data for the conference.
+- *
+- * @param conference The conference
+- * @param data User defined data
+- *
+- */
+-void nm_conference_set_data(NMConference * conference, gpointer data);
+-
+-/**
+- * Get the user defined data for the conference.
+- *
+- * @param conference The conference
+- *
+- * @return The data if it has been set, NULL otherwise.
+- *
+- */
+-gpointer nm_conference_get_data(NMConference * conference);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconn.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmconn.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,701 +0,0 @@
+-/*
+- * nmconn.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <glib.h>
+-#include <unistd.h>
+-#include <errno.h>
+-#include <string.h>
+-#include <ctype.h>
+-#include <time.h>
+-#include "nmconn.h"
+-
+-#ifdef _WIN32
+-#include <windows.h>
+-#endif
+-
+-#define NO_ESCAPE(ch) ((ch == 0x20) || (ch >= 0x30 && ch <= 0x39) || \
+- (ch >= 0x41 && ch <= 0x5a) || (ch >= 0x61 && ch <= 0x7a))
+-
+-/* Read data from conn until the end of a line */
+-static NMERR_T
+-read_line(NMConn * conn, char *buff, int len)
+-{
+- NMERR_T rc = NM_OK;
+- int total_bytes = 0;
+-
+- while ((rc == NM_OK) && (total_bytes < (len - 1))) {
+- rc = nm_read_all(conn, &buff[total_bytes], 1);
+- if (rc == NM_OK) {
+- total_bytes += 1;
+- if (buff[total_bytes - 1] == '\n') {
+- break;
+- }
+- }
+- }
+- buff[total_bytes] = '\0';
+-
+- return rc;
+-}
+-
+-static char *
+-url_escape_string(char *src)
+-{
+- guint32 escape = 0;
+- char *p;
+- char *q;
+- char *encoded = NULL;
+- int ch;
+-
+- static const char hex_table[16] = "0123456789abcdef";
+-
+- if (src == NULL) {
+- return NULL;
+- }
+-
+- /* Find number of chars to escape */
+- for (p = src; *p != '\0'; p++) {
+- ch = (guchar) *p;
+- if (!NO_ESCAPE(ch)) {
+- escape++;
+- }
+- }
+-
+- encoded = g_malloc((p - src) + (escape * 2) + 1);
+-
+- /* Escape the string */
+- for (p = src, q = encoded; *p != '\0'; p++) {
+- ch = (guchar) * p;
+- if (NO_ESCAPE(ch)) {
+- if (ch != 0x20) {
+- *q = ch;
+- q++;
+- } else {
+- *q = '+';
+- q++;
+- }
+- } else {
+- *q = '%';
+- q++;
+-
+- *q = hex_table[ch >> 4];
+- q++;
+-
+- *q = hex_table[ch & 15];
+- q++;
+- }
+- }
+- *q = '\0';
+-
+- return encoded;
+-}
+-
+-static char *
+-encode_method(guint8 method)
+-{
+- char *str;
+-
+- switch (method) {
+- case NMFIELD_METHOD_EQUAL:
+- str = "G";
+- break;
+- case NMFIELD_METHOD_UPDATE:
+- str = "F";
+- break;
+- case NMFIELD_METHOD_GTE:
+- str = "E";
+- break;
+- case NMFIELD_METHOD_LTE:
+- str = "D";
+- break;
+- case NMFIELD_METHOD_NE:
+- str = "C";
+- break;
+- case NMFIELD_METHOD_EXIST:
+- str = "B";
+- break;
+- case NMFIELD_METHOD_NOTEXIST:
+- str = "A";
+- break;
+- case NMFIELD_METHOD_SEARCH:
+- str = "9";
+- break;
+- case NMFIELD_METHOD_MATCHBEGIN:
+- str = "8";
+- break;
+- case NMFIELD_METHOD_MATCHEND:
+- str = "7";
+- break;
+- case NMFIELD_METHOD_NOT_ARRAY:
+- str = "6";
+- break;
+- case NMFIELD_METHOD_OR_ARRAY:
+- str = "5";
+- break;
+- case NMFIELD_METHOD_AND_ARRAY:
+- str = "4";
+- break;
+- case NMFIELD_METHOD_DELETE_ALL:
+- str = "3";
+- break;
+- case NMFIELD_METHOD_DELETE:
+- str = "2";
+- break;
+- case NMFIELD_METHOD_ADD:
+- str = "1";
+- break;
+- default: /* NMFIELD_METHOD_VALID */
+- str = "0";
+- break;
+- }
+-
+- return str;
+-}
+-
+-NMConn *
+-nm_create_conn(const char *addr, int port)
+-{
+- NMConn *conn = g_new0(NMConn, 1);
+- conn->addr = g_strdup(addr);
+- conn->port = port;
+- return conn;
+-}
+-
+-void nm_release_conn(NMConn *conn)
+-{
+- if (conn) {
+- GSList *node;
+- for (node = conn->requests; node; node = node->next) {
+- if (node->data)
+- nm_release_request(node->data);
+- }
+- g_slist_free(conn->requests);
+- conn->requests = NULL;
+- if (conn->ssl_conn) {
+- g_free(conn->ssl_conn);
+- conn->ssl_conn = NULL;
+- }
+- g_free(conn->addr);
+- conn->addr = NULL;
+- g_free(conn);
+- }
+-}
+-
+-int
+-nm_tcp_write(NMConn * conn, const void *buff, int len)
+-{
+- if (conn == NULL || buff == NULL)
+- return -1;
+-
+- if (!conn->use_ssl)
+- return (write(conn->fd, buff, len));
+- else if (conn->ssl_conn && conn->ssl_conn->write)
+- return (conn->ssl_conn->write(conn->ssl_conn->data, buff, len));
+- else
+- return -1;
+-}
+-
+-int
+-nm_tcp_read(NMConn * conn, void *buff, int len)
+-{
+- if (conn == NULL || buff == NULL)
+- return -1;
+-
+- if (!conn->use_ssl)
+- return (read(conn->fd, buff, len));
+- else if (conn->ssl_conn && conn->ssl_conn->read)
+- return ((conn->ssl_conn->read)(conn->ssl_conn->data, buff, len));
+- else
+- return -1;
+-}
+-
+-NMERR_T
+-nm_read_all(NMConn * conn, char *buff, int len)
+-{
+- NMERR_T rc = NM_OK;
+- int bytes_left = len;
+- int bytes_read;
+- int total_bytes = 0;
+- int retry = 1000;
+-
+- if (conn == NULL || buff == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Keep reading until buffer is full */
+- while (bytes_left) {
+- bytes_read = nm_tcp_read(conn, &buff[total_bytes], bytes_left);
+- if (bytes_read > 0) {
+- bytes_left -= bytes_read;
+- total_bytes += bytes_read;
+- } else {
+- if (errno == EAGAIN) {
+- if (--retry == 0) {
+- rc = NMERR_TCP_READ;
+- break;
+- }
+-#ifdef _WIN32
+- Sleep(1);
+-#else
+- usleep(1000);
+-#endif
+- } else {
+- rc = NMERR_TCP_READ;
+- break;
+- }
+- }
+- }
+- return rc;
+-}
+-
+-NMERR_T
+-nm_read_uint32(NMConn *conn, guint32 *val)
+-{
+- NMERR_T rc = NM_OK;
+-
+- rc = nm_read_all(conn, (char *)val, sizeof(*val));
+- if (rc == NM_OK) {
+- *val = GUINT32_FROM_LE(*val);
+- }
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_read_uint16(NMConn *conn, guint16 *val)
+-{
+- NMERR_T rc = NM_OK;
+-
+- rc = nm_read_all(conn, (char *)val, sizeof(*val));
+- if (rc == NM_OK) {
+- *val = GUINT16_FROM_LE(*val);
+- }
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_write_fields(NMConn * conn, NMField * fields)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *field;
+- char *value = NULL;
+- char *method = NULL;
+- char buffer[4096];
+- int ret;
+- int bytes_to_send;
+- int val = 0;
+-
+- if (conn == NULL || fields == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Format each field as valid "post" data and write it out */
+- for (field = fields; (rc == NM_OK) && (field->tag); field++) {
+-
+- /* We don't currently handle binary types */
+- if (field->method == NMFIELD_METHOD_IGNORE ||
+- field->type == NMFIELD_TYPE_BINARY) {
+- continue;
+- }
+-
+- /* Write the field tag */
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&tag=%s", field->tag);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+-
+- /* Write the field method */
+- if (rc == NM_OK) {
+- method = encode_method(field->method);
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "&cmd=%s", method);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+- }
+-
+- /* Write the field value */
+- if (rc == NM_OK) {
+- switch (field->type) {
+- case NMFIELD_TYPE_UTF8:
+- case NMFIELD_TYPE_DN:
+-
+- value = url_escape_string((char *) field->ptr_value);
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "&val=%s", value);
+- if (bytes_to_send > (int)sizeof(buffer)) {
+- ret = nm_tcp_write(conn, buffer, sizeof(buffer));
+- } else {
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- }
+-
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+-
+- g_free(value);
+-
+- break;
+-
+- case NMFIELD_TYPE_ARRAY:
+- case NMFIELD_TYPE_MV:
+-
+- val = nm_count_fields((NMField *) field->ptr_value);
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "&val=%u", val);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+-
+- break;
+-
+- default:
+-
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "&val=%u", field->value);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+-
+- break;
+- }
+- }
+-
+- /* Write the field type */
+- if (rc == NM_OK) {
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "&type=%u", field->type);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+- }
+-
+- /* If the field is a sub array then post its fields */
+- if (rc == NM_OK && val > 0) {
+- if (field->type == NMFIELD_TYPE_ARRAY ||
+- field->type == NMFIELD_TYPE_MV) {
+-
+- rc = nm_write_fields(conn, (NMField *) field->ptr_value);
+-
+- }
+- }
+- }
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_request(NMConn *conn, char *cmd, NMField *fields,
+- nm_response_cb cb, gpointer data, NMRequest **request)
+-{
+- NMERR_T rc = NM_OK;
+- char buffer[512];
+- int bytes_to_send;
+- int ret;
+- NMField *request_fields = NULL;
+- char *str = NULL;
+-
+- if (conn == NULL || cmd == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Write the post */
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "POST /%s HTTP/1.0\r\n", cmd);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+-
+- /* Write headers */
+- if (rc == NM_OK) {
+- if (strcmp("login", cmd) == 0) {
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer),
+- "Host: %s:%d\r\n\r\n", conn->addr, conn->port);
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+- } else {
+- bytes_to_send = g_snprintf(buffer, sizeof(buffer), "\r\n");
+- ret = nm_tcp_write(conn, buffer, bytes_to_send);
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+- }
+- }
+-
+- /* Add the transaction id to the request fields */
+- if (rc == NM_OK) {
+- if (fields)
+- request_fields = nm_copy_field_array(fields);
+-
+- str = g_strdup_printf("%d", ++(conn->trans_id));
+- request_fields = nm_field_add_pointer(request_fields, NM_A_SZ_TRANSACTION_ID, 0,
+- NMFIELD_METHOD_VALID, 0,
+- str, NMFIELD_TYPE_UTF8);
+- }
+-
+- /* Send the request to the server */
+- if (rc == NM_OK) {
+- rc = nm_write_fields(conn, request_fields);
+- }
+-
+- /* Write the CRLF to terminate the data */
+- if (rc == NM_OK) {
+- ret = nm_tcp_write(conn, "\r\n", strlen("\r\n"));
+- if (ret < 0) {
+- rc = NMERR_TCP_WRITE;
+- }
+- }
+-
+- /* Create a request struct, add it to our queue, and return it */
+- if (rc == NM_OK) {
+- NMRequest *new_request = nm_create_request(cmd, conn->trans_id,
+- time(0), cb, NULL, data);
+- nm_conn_add_request_item(conn, new_request);
+-
+- /* Set the out param if it was sent in, otherwise release the request */
+- if (request)
+- *request = new_request;
+- else
+- nm_release_request(new_request);
+- }
+-
+- if (request_fields != NULL)
+- nm_free_fields(&request_fields);
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_read_header(NMConn * conn)
+-{
+- NMERR_T rc = NM_OK;
+- char buffer[512];
+- char *ptr = NULL;
+- int i;
+- char rtn_buf[8];
+- int rtn_code = 0;
+-
+- if (conn == NULL)
+- return NMERR_BAD_PARM;
+-
+- *buffer = '\0';
+- rc = read_line(conn, buffer, sizeof(buffer));
+- if (rc == NM_OK) {
+-
+- /* Find the return code */
+- ptr = strchr(buffer, ' ');
+- if (ptr != NULL) {
+- ptr++;
+-
+- i = 0;
+- while (isdigit(*ptr) && (i < 3)) {
+- rtn_buf[i] = *ptr;
+- i++;
+- ptr++;
+- }
+- rtn_buf[i] = '\0';
+-
+- if (i > 0)
+- rtn_code = atoi(rtn_buf);
+- }
+- }
+-
+- /* Finish reading header, in the future we might want to do more processing here */
+- /* TODO: handle more general redirects in the future */
+- while ((rc == NM_OK) && (strcmp(buffer, "\r\n") != 0)) {
+- rc = read_line(conn, buffer, sizeof(buffer));
+- }
+-
+- if (rc == NM_OK && rtn_code == 301)
+- rc = NMERR_SERVER_REDIRECT;
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_read_fields(NMConn * conn, int count, NMField ** fields)
+-{
+- NMERR_T rc = NM_OK;
+- guint8 type;
+- guint8 method;
+- guint32 val;
+- char tag[64];
+- NMField *sub_fields = NULL;
+- char *str = NULL;
+-
+- if (conn == NULL || fields == NULL)
+- return NMERR_BAD_PARM;
+-
+- do {
+- if (count > 0) {
+- count--;
+- }
+-
+- /* Read the field type, method, and tag */
+- rc = nm_read_all(conn, (char *)&type, sizeof(type));
+- if (rc != NM_OK || type == 0)
+- break;
+-
+- rc = nm_read_all(conn, (char *)&method, sizeof(method));
+- if (rc != NM_OK)
+- break;
+-
+- rc = nm_read_uint32(conn, &val);
+- if (rc != NM_OK)
+- break;
+-
+- if (val > sizeof(tag)) {
+- rc = NMERR_PROTOCOL;
+- break;
+- }
+-
+- rc = nm_read_all(conn, tag, val);
+- if (rc != NM_OK)
+- break;
+-
+- if (type == NMFIELD_TYPE_MV || type == NMFIELD_TYPE_ARRAY) {
+-
+- /* Read the subarray (first read the number of items in the array) */
+- rc = nm_read_uint32(conn, &val);
+- if (rc != NM_OK)
+- break;
+-
+- if (val > 0) {
+- rc = nm_read_fields(conn, val, &sub_fields);
+- if (rc != NM_OK)
+- break;
+- }
+-
+- *fields = nm_field_add_pointer(*fields, tag, 0, method,
+- 0, sub_fields, type);
+-
+- sub_fields = NULL;
+-
+- } else if (type == NMFIELD_TYPE_UTF8 || type == NMFIELD_TYPE_DN) {
+-
+- /* Read the string (first read the length) */
+- rc = nm_read_uint32(conn, &val);
+- if (rc != NM_OK)
+- break;
+-
+- if (val >= NMFIELD_MAX_STR_LENGTH) {
+- rc = NMERR_PROTOCOL;
+- break;
+- }
+-
+- if (val > 0) {
+- str = g_new0(char, val + 1);
+-
+- rc = nm_read_all(conn, str, val);
+- if (rc != NM_OK)
+- break;
+-
+- *fields = nm_field_add_pointer(*fields, tag, 0, method,
+- 0, str, type);
+- str = NULL;
+- }
+-
+- } else {
+-
+- /* Read the numerical value */
+- rc = nm_read_uint32(conn, &val);
+- if (rc != NM_OK)
+- break;
+-
+- *fields = nm_field_add_number(*fields, tag, 0, method,
+- 0, val, type);
+- }
+-
+- } while ((type != 0) && (count != 0));
+-
+-
+- if (str != NULL) {
+- g_free(str);
+- }
+-
+- if (sub_fields != NULL) {
+- nm_free_fields(&sub_fields);
+- }
+-
+- return rc;
+-}
+-
+-void
+-nm_conn_add_request_item(NMConn * conn, NMRequest * request)
+-{
+- if (conn == NULL || request == NULL)
+- return;
+-
+- nm_request_add_ref(request);
+- conn->requests = g_slist_append(conn->requests, request);
+-}
+-
+-void
+-nm_conn_remove_request_item(NMConn * conn, NMRequest * request)
+-{
+- if (conn == NULL || request == NULL)
+- return;
+-
+- conn->requests = g_slist_remove(conn->requests, request);
+- nm_release_request(request);
+-}
+-
+-NMRequest *
+-nm_conn_find_request(NMConn * conn, int trans_id)
+-{
+- NMRequest *req = NULL;
+- GSList *itr = NULL;
+-
+- if (conn == NULL)
+- return NULL;
+-
+- itr = conn->requests;
+- while (itr) {
+- req = (NMRequest *) itr->data;
+- if (req != NULL && nm_request_get_trans_id(req) == trans_id) {
+- return req;
+- }
+- itr = g_slist_next(itr);
+- }
+- return NULL;
+-}
+-
+-const char *
+-nm_conn_get_addr(NMConn * conn)
+-{
+- if (conn == NULL)
+- return NULL;
+- else
+- return conn->addr;
+-}
+-
+-int
+-nm_conn_get_port(NMConn * conn)
+-{
+- if (conn == NULL)
+- return -1;
+- else
+- return conn->port;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmconn.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmconn.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmconn.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,246 +0,0 @@
+-/*
+- * nmconn.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_CONN_H__
+-#define __NM_CONN_H__
+-
+-typedef struct _NMConn NMConn;
+-typedef struct _NMSSLConn NMSSLConn;
+-
+-#include "nmfield.h"
+-#include "nmuser.h"
+-
+-typedef int (*nm_ssl_read_cb) (gpointer ssl_data, void *buff, int len);
+-typedef int (*nm_ssl_write_cb) (gpointer ssl_data, const void *buff, int len);
+-
+-struct _NMConn
+-{
+-
+- /* The address of the server that we are connecting to. */
+- char *addr;
+-
+- /* The port that we are connecting to. */
+- int port;
+-
+- /* The file descriptor of the socket for the connection. */
+- int fd;
+-
+- /* The transaction counter. */
+- int trans_id;
+-
+- /* A list of requests currently awaiting a response. */
+- GSList *requests;
+-
+- /* Are we connected? TRUE if so, FALSE if not. */
+- gboolean connected;
+-
+- /* Are we running in secure mode? */
+- gboolean use_ssl;
+-
+- /* Have we been redirected? */
+- gboolean redirect;
+-
+- /* SSL connection */
+- NMSSLConn *ssl_conn;
+-
+-};
+-
+-struct _NMSSLConn
+-{
+-
+- /* Data to pass to the callbacks */
+- gpointer data;
+-
+- /* Callbacks for reading/writing */
+- nm_ssl_read_cb read;
+- nm_ssl_write_cb write;
+-
+-};
+-
+-/**
+- * Allocate a new NMConn struct
+- *
+- * @param The address of the server that we are connecting to.
+- * @param The port that we are connecting to.
+- *
+- * @return A pointer to a newly allocated NMConn struct, should
+- * be freed by calling nm_release_conn()
+- */
+-NMConn *nm_create_conn(const char *addr, int port);
+-
+-/**
+- * Release an NMConn
+- *
+- * @param Pointer to the NMConn to release.
+- *
+- */
+-void nm_release_conn(NMConn *conn);
+-
+-/**
+- * Write len bytes from the given buffer.
+- *
+- * @param conn The connection to write to.
+- * @param buff The buffer to write from.
+- * @param len The number of bytes to write.
+- *
+- * @return The number of bytes written.
+- */
+-int nm_tcp_write(NMConn * conn, const void *buff, int len);
+-
+-/**
+- * Read at most len bytes into the given buffer.
+- *
+- * @param conn The connection to read from.
+- * @param buff The buffer to write to.
+- * @param len The maximum number of bytes to read.
+- *
+- * @return The number of bytes read.
+- */
+-int nm_tcp_read(NMConn * conn, void *buff, int len);
+-
+-/**
+- * Read exactly len bytes into the given buffer.
+- *
+- * @param conn The connection to read from.
+- * @param buff The buffer to write to.
+- * @param len The number of bytes to read.
+- *
+- * @return NM_OK on success, NMERR_TCP_READ if read fails.
+- */
+-NMERR_T nm_read_all(NMConn * conn, char *buf, int len);
+-
+-/**
+- * Read a 32 bit value and convert it to the host byte order.
+- *
+- * @param conn The connection to read from.
+- * @param val A pointer to unsigned 32 bit integer
+- *
+- * @return NM_OK on success, NMERR_TCP_READ if read fails.
+- */
+-NMERR_T
+-nm_read_uint32(NMConn *conn, guint32 *val);
+-
+-/**
+- * Read a 16 bit value and convert it to the host byte order.
+- *
+- * @param conn The connection to read from.
+- * @param val A pointer to unsigned 16 bit integer
+- *
+- * @return NM_OK on success, NMERR_TCP_READ if read fails.
+- */
+-NMERR_T
+-nm_read_uint16(NMConn *conn, guint16 *val);
+-
+-/**
+- * Dispatch a request to the server.
+- *
+- * @param conn The connection.
+- * @param cmd The request to dispatch.
+- * @param fields The field list for the request.
+- * @param cb The response callback for the new request object.
+- * @param data The user defined data for the request (to be passed to the resp cb).
+- * @param req The request. Should be freed with nm_release_request.
+- *
+- * @return NM_OK on success.
+- */
+-NMERR_T
+-nm_send_request(NMConn *conn, char *cmd, NMField *fields,
+- nm_response_cb cb, gpointer data, NMRequest **request);
+-
+-/**
+- * Write out the given field list.
+- *
+- * @param conn The connection to write to.
+- * @param fields The field list to write.
+- *
+- * @return NM_OK on success.
+- */
+-NMERR_T nm_write_fields(NMConn * conn, NMField * fields);
+-
+-/**
+- * Read the headers for a response.
+- *
+- * @param conn The connection to read from.
+- *
+- * @return NM_OK on success.
+- */
+-NMERR_T nm_read_header(NMConn * conn);
+-
+-/**
+- * Read a field list from the connection.
+- *
+- * @param conn The connection to read from.
+- * @param count The maximum number of fields to read (or -1 for no max).
+- * @param fields The field list. This is an out param. It
+- * should be freed by calling nm_free_fields
+- * when finished.
+- *
+- * @return NM_OK on success.
+- */
+-NMERR_T nm_read_fields(NMConn * conn, int count, NMField ** fields);
+-
+-/**
+- * Add a request to the connections request list.
+- *
+- * @param conn The connection.
+- * @param request The request to add to the list.
+- */
+-void nm_conn_add_request_item(NMConn * conn, NMRequest * request);
+-
+-/**
+- * Remove a request from the connections list.
+- *
+- * @param conn The connection.
+- * @param request The request to remove from the list.
+- */
+-void nm_conn_remove_request_item(NMConn * conn, NMRequest * request);
+-
+-/**
+- * Find the request with the given transaction id in the connections
+- * request list.
+- *
+- * @param conn The connection.
+- * @param trans_id The transaction id of the request to return.
+- *
+- * @return The request, or NULL if a matching request is not
+- * found.
+- */
+-NMRequest *nm_conn_find_request(NMConn * conn, int trans_id);
+-
+-/**
+- * Get the server address for the connection.
+- *
+- * @param conn The connection.
+- *
+- * @return The server address for the connection.
+- *
+- */
+-const char *nm_conn_get_addr(NMConn * conn);
+-
+-/**
+- * Get the port for the connection.
+- *
+- * @param conn The connection.
+- *
+- * @return The port that we are connected to.
+- */
+-int nm_conn_get_port(NMConn * conn);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmcontact.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmcontact.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,972 +0,0 @@
+-/*
+- * nmcontact.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <glib.h>
+-#include <string.h>
+-#include "nmcontact.h"
+-#include "nmfield.h"
+-#include "nmuser.h"
+-
+-struct _NMContact
+-{
+- int id;
+- int parent_id;
+- int seq;
+- char *dn;
+- char *display_name;
+- NMUserRecord *user_record;
+- gpointer data;
+- int ref_count;
+-};
+-
+-struct _NMFolder
+-{
+- int id;
+- int seq;
+- char *name;
+- GSList *folders;
+- GSList *contacts;
+- int ref_count;
+-};
+-
+-static int count = 0;
+-
+-static void _release_folder_contacts(NMFolder * folder);
+-static void _release_folder_folders(NMFolder * folder);
+-static void _add_contacts(NMUser * user, NMFolder * folder, NMField * fields);
+-static void _add_folders(NMFolder * root, NMField * fields);
+-
+-/*********************************************************************
+- * Contact API
+- *********************************************************************/
+-
+-NMContact *
+-nm_create_contact()
+-{
+- NMContact *contact = g_new0(NMContact, 1);
+-
+- contact->ref_count = 1;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell", "Creating contact, total=%d\n",
+- count++);
+-
+- return contact;
+-}
+-
+-/*
+- * This creates a contact for the contact list. The
+- * field array that is passed in should be a
+- * NM_A_FA_CONTACT array.
+- *
+- */
+-NMContact *
+-nm_create_contact_from_fields(NMField * fields)
+-{
+- NMContact *contact;
+- NMField *field;
+-
+- if ( fields == NULL || fields->tag == NULL || fields->ptr_value == 0 ||
+- strcmp(fields->tag, NM_A_FA_CONTACT) )
+- {
+- return NULL;
+- }
+-
+- contact = nm_create_contact();
+-
+- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->id = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->parent_id = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->seq = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->display_name = g_strdup((char *) field->ptr_value);
+-
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->dn = g_strdup((char *) field->ptr_value);
+-
+- }
+-
+- return contact;
+-}
+-
+-void
+-nm_contact_update_list_properties(NMContact * contact, NMField * fields)
+-{
+- NMField *field;
+-
+- if (contact == NULL || fields == NULL || fields->ptr_value == 0)
+- return;
+-
+- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->id = atoi((char *)field->ptr_value);
+-
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_PARENT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->parent_id = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- contact->seq = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value) {
+- if (contact->display_name)
+- g_free(contact->display_name);
+-
+- contact->display_name = g_strdup((char *) field->ptr_value);
+- }
+-
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_DN, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value) {
+- if (contact->dn)
+- g_free(contact->dn);
+-
+- contact->dn = g_strdup((char *) field->ptr_value);
+- }
+-
+- }
+-}
+-
+-NMField *
+-nm_contact_to_fields(NMContact * contact)
+-{
+- NMField *fields = NULL;
+-
+- if (contact == NULL)
+- return NULL;
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", contact->id), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", contact->parent_id), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", contact->seq), NMFIELD_TYPE_UTF8);
+-
+- if (contact->display_name != NULL) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(contact->display_name), NMFIELD_TYPE_UTF8);
+- }
+-
+- if (contact->dn != NULL) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(contact->dn), NMFIELD_TYPE_UTF8);
+- }
+-
+- return fields;
+-}
+-
+-void
+-nm_contact_add_ref(NMContact * contact)
+-{
+- if (contact)
+- contact->ref_count++;
+-}
+-
+-void
+-nm_release_contact(NMContact * contact)
+-{
+- if (contact == NULL)
+- return;
+-
+- if (--(contact->ref_count) == 0) {
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Releasing contact, total=%d\n", --count);
+-
+- if (contact->display_name) {
+- g_free(contact->display_name);
+- }
+-
+- if (contact->dn) {
+- g_free(contact->dn);
+- }
+-
+- if (contact->user_record) {
+- nm_release_user_record(contact->user_record);
+- }
+-
+- g_free(contact);
+- }
+-
+-}
+-
+-const char *
+-nm_contact_get_display_name(NMContact * contact)
+-{
+- if (contact == NULL)
+- return NULL;
+-
+- if (contact->user_record != NULL && contact->display_name == NULL) {
+- const char *full_name, *lname, *fname, *cn, *display_id;
+-
+- full_name = nm_user_record_get_full_name(contact->user_record);
+- fname = nm_user_record_get_first_name(contact->user_record);
+- lname = nm_user_record_get_last_name(contact->user_record);
+- cn = nm_user_record_get_userid(contact->user_record);
+- display_id = nm_user_record_get_display_id(contact->user_record);
+-
+- /* Try to build a display name. */
+- if (full_name) {
+-
+- contact->display_name = g_strdup(full_name);
+-
+- } else if (fname && lname) {
+-
+- contact->display_name = g_strdup_printf("%s %s", fname, lname);
+-
+- } else {
+-
+- /* If auth attribute is set use it */
+- if (nm_user_record_get_auth_attr(contact->user_record) &&
+- display_id != NULL) {
+-
+- contact->display_name = g_strdup(display_id);
+-
+- } else {
+-
+- /* Use CN or display id */
+- if (cn) {
+-
+- contact->display_name = g_strdup(cn);
+-
+- } else if (display_id) {
+-
+- contact->display_name = g_strdup(display_id);
+-
+- }
+-
+- }
+-
+- }
+- }
+-
+- return contact->display_name;
+-}
+-
+-void
+-nm_contact_set_display_name(NMContact * contact, const char *display_name)
+-{
+- if (contact == NULL)
+- return;
+-
+- if (contact->display_name) {
+- g_free(contact->display_name);
+- contact->display_name = NULL;
+- }
+-
+- if (display_name)
+- contact->display_name = g_strdup(display_name);
+-}
+-
+-void
+-nm_contact_set_dn(NMContact * contact, const char *dn)
+-{
+- if (contact == NULL)
+- return;
+-
+- if (contact->dn) {
+- g_free(contact->dn);
+- contact->dn = NULL;
+- }
+-
+- if (dn)
+- contact->dn = g_strdup(dn);
+-}
+-
+-const char *
+-nm_contact_get_dn(NMContact * contact)
+-{
+- if (contact == NULL)
+- return NULL;
+-
+- return contact->dn;
+-}
+-
+-gpointer
+-nm_contact_get_data(NMContact * contact)
+-{
+- if (contact == NULL)
+- return NULL;
+-
+- return contact->data;
+-}
+-
+-int
+-nm_contact_get_id(NMContact * contact)
+-{
+- if (contact == NULL)
+- return -1;
+-
+- return contact->id;
+-}
+-
+-int
+-nm_contact_get_parent_id(NMContact * contact)
+-{
+- if (contact == NULL)
+- return -1;
+-
+- return contact->parent_id;
+-}
+-
+-void
+-nm_contact_set_data(NMContact * contact, gpointer data)
+-{
+- if (contact == NULL)
+- return;
+-
+- contact->data = data;
+-}
+-
+-void
+-nm_contact_set_user_record(NMContact * contact, NMUserRecord * user_record)
+-{
+- if (contact == NULL)
+- return;
+-
+- if (contact->user_record) {
+- nm_release_user_record(contact->user_record);
+- }
+-
+- nm_user_record_add_ref(user_record);
+- contact->user_record = user_record;
+-}
+-
+-NMUserRecord *
+-nm_contact_get_user_record(NMContact * contact)
+-{
+- if (contact == NULL)
+- return NULL;
+-
+- return contact->user_record;
+-}
+-
+-const char *
+-nm_contact_get_userid(NMContact * contact)
+-{
+- NMUserRecord *user_record;
+- const char *userid = NULL;
+-
+- if (contact == NULL)
+- return NULL;
+-
+- user_record = nm_contact_get_user_record(contact);
+- if (user_record) {
+- userid = nm_user_record_get_userid(user_record);
+- }
+-
+- return userid;
+-}
+-
+-const char *
+-nm_contact_get_display_id(NMContact * contact)
+-{
+- NMUserRecord *user_record;
+- const char *id = NULL;
+-
+- if (contact == NULL)
+- return NULL;
+-
+- user_record = nm_contact_get_user_record(contact);
+- if (user_record) {
+- id = nm_user_record_get_display_id(user_record);
+- }
+-
+- return id;
+-}
+-
+-
+-/*********************************************************************
+- * Folder API
+- *********************************************************************/
+-
+-NMFolder *
+-nm_create_folder(const char *name)
+-{
+- NMFolder *folder = g_new0(NMFolder, 1);
+-
+- if (name)
+- folder->name = g_strdup(name);
+-
+- folder->ref_count = 1;
+-
+- return folder;
+-}
+-
+-NMFolder *
+-nm_create_folder_from_fields(NMField * fields)
+-{
+- NMField *field;
+- NMFolder *folder;
+-
+- if (fields == NULL || fields->ptr_value == 0)
+- return NULL;
+-
+- folder = g_new0(NMFolder, 1);
+-
+- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- folder->id = atoi((char *) field->ptr_value);
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- folder->seq = atoi((char *) field->ptr_value);
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- folder->name = g_strdup((char *) field->ptr_value);
+- }
+-
+- folder->ref_count = 1;
+- return folder;
+-}
+-
+-NMField *
+-nm_folder_to_fields(NMFolder * folder)
+-{
+- NMField *fields = NULL;
+-
+- if (folder == NULL)
+- return NULL;
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", folder->id), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup("0"), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_TYPE, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup("1"), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", folder->seq), NMFIELD_TYPE_UTF8);
+-
+- if (folder->name != NULL) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(folder->name), NMFIELD_TYPE_UTF8);
+- }
+-
+-
+- return fields;
+-}
+-
+-void
+-nm_folder_update_list_properties(NMFolder * folder, NMField * fields)
+-{
+- NMField *field;
+-
+- if (folder == NULL || fields == NULL || fields->ptr_value == 0)
+- return;
+-
+- if ((field = nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- folder->id = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_SEQUENCE_NUMBER, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value)
+- folder->seq = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field =
+- nm_locate_field(NM_A_SZ_DISPLAY_NAME, (NMField *) fields->ptr_value))) {
+-
+- if (field->ptr_value) {
+- if (folder->name)
+- g_free(folder->name);
+-
+- folder->name = g_strdup((char *) field->ptr_value);
+- }
+-
+- }
+-
+-}
+-
+-void
+-nm_release_folder(NMFolder * folder)
+-{
+- if (folder == NULL)
+- return;
+-
+- if (--(folder->ref_count) == 0) {
+- if (folder->name) {
+- g_free(folder->name);
+- }
+-
+- if (folder->folders) {
+- _release_folder_folders(folder);
+- }
+-
+- if (folder->contacts) {
+- _release_folder_contacts(folder);
+- }
+-
+- g_free(folder);
+- }
+-}
+-
+-
+-void
+-nm_folder_add_ref(NMFolder * folder)
+-{
+- if (folder)
+- folder->ref_count++;
+-}
+-
+-int
+-nm_folder_get_subfolder_count(NMFolder * folder)
+-{
+- if (folder == NULL)
+- return 0;
+-
+- if (folder->folders)
+- return g_slist_length(folder->folders);
+- else
+- return 0;
+-}
+-
+-NMFolder *
+-nm_folder_get_subfolder(NMFolder * folder, int index)
+-{
+- if (folder == NULL)
+- return NULL;
+-
+- if (folder->folders)
+- return (NMFolder *) g_slist_nth_data(folder->folders, index);
+- else
+- return NULL;
+-}
+-
+-int
+-nm_folder_get_contact_count(NMFolder * folder)
+-{
+- if (folder == NULL)
+- return 0;
+-
+- if (folder->contacts != NULL)
+- return g_slist_length(folder->contacts);
+- else
+- return 0;
+-}
+-
+-NMContact *
+-nm_folder_get_contact(NMFolder * folder, int index)
+-{
+- if (folder == NULL)
+- return NULL;
+-
+- if (folder->contacts)
+- return (NMContact *) g_slist_nth_data(folder->contacts, index);
+- else
+- return NULL;
+-}
+-
+-const char *
+-nm_folder_get_name(NMFolder * folder)
+-{
+- if (folder == NULL)
+- return NULL;
+-
+- return folder->name;
+-}
+-
+-void
+-nm_folder_set_name(NMFolder * folder, const char *name)
+-{
+- if (folder == NULL || name == NULL)
+- return;
+-
+- if (folder->name)
+- g_free(folder->name);
+-
+- folder->name = g_strdup(name);
+-}
+-
+-int
+-nm_folder_get_id(NMFolder * folder)
+-{
+- if (folder == NULL) {
+- return -1;
+- }
+-
+- return folder->id;
+-}
+-
+-void
+-nm_folder_add_folder_to_list(NMFolder * root, NMFolder * folder)
+-{
+- GSList *node;
+-
+- if (root == NULL || folder == NULL)
+- return;
+-
+- node = root->folders;
+- while (node) {
+- if (folder->seq <= ((NMFolder *) node->data)->seq) {
+- nm_folder_add_ref(folder);
+- root->folders = g_slist_insert_before(root->folders, node, folder);
+- break;
+- }
+- node = g_slist_next(node);
+- }
+- if (node == NULL) {
+- nm_folder_add_ref(folder);
+- root->folders = g_slist_append(root->folders, folder);
+- }
+-}
+-
+-void
+-nm_folder_remove_contact(NMFolder * folder, NMContact * contact)
+-{
+- GSList *node;
+-
+- if (folder == NULL || contact == NULL)
+- return;
+-
+- node = folder->contacts;
+- while (node) {
+- if (contact->id == ((NMContact *) (node->data))->id) {
+- folder->contacts = g_slist_remove(folder->contacts, node->data);
+- nm_release_contact(contact);
+- break;
+- }
+- node = g_slist_next(node);
+- }
+-}
+-
+-void
+-nm_folder_add_contact_to_list(NMFolder * root_folder, NMContact * contact)
+-{
+- GSList *node = NULL;
+- NMFolder *folder = root_folder;
+-
+- if (folder == NULL || contact == NULL)
+- return;
+-
+- /* Find folder to add contact to */
+- if (contact->parent_id != 0) {
+- node = folder->folders;
+- while (node) {
+- folder = (NMFolder *) node->data;
+- if (contact->parent_id == folder->id) {
+- break;
+- }
+- folder = NULL;
+- node = g_slist_next(node);
+- }
+- }
+-
+- /* Add contact to list */
+- if (folder) {
+- node = folder->contacts;
+- while (node) {
+- if (contact->seq <= ((NMContact *) (node->data))->seq) {
+- nm_contact_add_ref(contact);
+- folder->contacts =
+- g_slist_insert_before(folder->contacts, node, contact);
+- break;
+- }
+- node = g_slist_next(node);
+- }
+-
+- if (node == NULL) {
+- nm_contact_add_ref(contact);
+- folder->contacts = g_slist_append(folder->contacts, contact);
+- }
+- }
+-}
+-
+-void
+-nm_folder_add_contacts_and_folders(NMUser * user, NMFolder * root,
+- NMField * fields)
+-{
+- /* Add the contacts and folders from the field array */
+- if (user && root && fields) {
+- _add_folders(root, fields);
+- _add_contacts(user, root, fields);
+- }
+-}
+-
+-gpointer
+-nm_folder_find_item_by_object_id(NMFolder * root_folder, int object_id)
+-{
+- int cnt, cnt2, i, j;
+- gpointer item = NULL;
+- NMFolder *folder;
+- NMContact *contact;
+-
+- if (root_folder == NULL)
+- return NULL;
+-
+- /* Check all contacts for the top level folder */
+- cnt = nm_folder_get_contact_count(root_folder);
+- for (i = 0; i < cnt; i++) {
+- contact = nm_folder_get_contact(root_folder, i);
+- if (contact && (contact->id == object_id)) {
+- item = contact;
+- break;
+- }
+- }
+-
+- /* If we haven't found the item yet, check the subfolders */
+- if (item == NULL) {
+- cnt = nm_folder_get_subfolder_count(root_folder);
+- for (i = 0; (i < cnt) && (item == NULL); i++) {
+- folder = nm_folder_get_subfolder(root_folder, i);
+-
+- /* Check the id of this folder */
+- if (folder && (folder->id == object_id)) {
+- item = folder;
+- break;
+- }
+-
+- /* Check all contacts for this folder */
+- cnt2 = nm_folder_get_contact_count(folder);
+- for (j = 0; j < cnt2; j++) {
+- contact = nm_folder_get_contact(folder, j);
+- if (contact && (contact->id == object_id)) {
+- item = contact;
+- break;
+- }
+- }
+- }
+- }
+-
+- return item;
+-}
+-
+-NMContact *
+-nm_folder_find_contact_by_userid(NMFolder * folder, const char *userid)
+-{
+- int cnt, i;
+- NMContact *tmp, *contact = NULL;
+-
+- if (folder == NULL || userid == NULL)
+- return NULL;
+-
+- cnt = nm_folder_get_contact_count(folder);
+- for (i = 0; i < cnt; i++) {
+- tmp = nm_folder_get_contact(folder, i);
+- if (tmp && nm_utf8_str_equal(nm_contact_get_userid(tmp), userid)) {
+- contact = tmp;
+- break;
+- }
+- }
+-
+- return contact;
+-}
+-
+-NMContact *
+-nm_folder_find_contact_by_display_id(NMFolder * folder, const char *display_id)
+-{
+- int cnt, i;
+- NMContact *tmp, *contact = NULL;
+-
+- if (folder == NULL || display_id == NULL)
+- return NULL;
+-
+- cnt = nm_folder_get_contact_count(folder);
+- for (i = 0; i < cnt; i++) {
+- tmp = nm_folder_get_contact(folder, i);
+- if (tmp && nm_utf8_str_equal(nm_contact_get_display_id(tmp), display_id)) {
+- contact = tmp;
+- break;
+- }
+- }
+-
+- return contact;
+-}
+-
+-NMContact *
+-nm_folder_find_contact(NMFolder * folder, const char *dn)
+-{
+- int cnt, i;
+- NMContact *tmp, *contact = NULL;
+-
+- if (folder == NULL || dn == NULL)
+- return NULL;
+-
+- cnt = nm_folder_get_contact_count(folder);
+- for (i = 0; i < cnt; i++) {
+- tmp = nm_folder_get_contact(folder, i);
+- if (tmp && nm_utf8_str_equal(nm_contact_get_dn(tmp), dn)) {
+- contact = tmp;
+- break;
+- }
+- }
+-
+- return contact;
+-}
+-
+-
+-/*********************************************************************
+- * Utility functions
+- *********************************************************************/
+-
+-static void
+-_release_folder_contacts(NMFolder * folder)
+-{
+- GSList *cnode;
+- NMContact *contact;
+-
+- for (cnode = folder->contacts; cnode; cnode = cnode->next) {
+- contact = cnode->data;
+- cnode->data = NULL;
+- nm_release_contact(contact);
+- }
+-
+- g_slist_free(folder->contacts);
+- folder->contacts = NULL;
+-}
+-
+-static void
+-_release_folder_folders(NMFolder * folder)
+-{
+- GSList *fnode;
+- NMFolder *subfolder;
+-
+- if (folder == NULL)
+- return;
+-
+- for (fnode = folder->folders; fnode; fnode = fnode->next) {
+- subfolder = fnode->data;
+- fnode->data = NULL;
+- nm_release_folder(subfolder);
+- }
+-
+- g_slist_free(folder->folders);
+- folder->folders = NULL;
+-}
+-
+-static void
+-_add_folders(NMFolder * root, NMField * fields)
+-{
+- NMFolder *folder = NULL;
+- NMField *locate = NULL;
+-
+- locate = nm_locate_field(NM_A_FA_FOLDER, fields);
+- while (locate != NULL) {
+-
+- /* Create a new folder */
+- folder = nm_create_folder_from_fields(locate);
+-
+- /* Add subfolder to roots folder list */
+- nm_folder_add_folder_to_list(root, folder);
+-
+- /* Decrement the ref count */
+- nm_release_folder(folder);
+-
+- /* Find the next folder */
+- locate = nm_locate_field(NM_A_FA_FOLDER, locate+1);
+-
+- }
+-}
+-
+-static void
+-_add_contacts(NMUser * user, NMFolder * folder, NMField * fields)
+-{
+- NMContact *contact = NULL;
+- NMField *locate = NULL, *details;
+- NMUserRecord *user_record = NULL;
+-
+- locate = nm_locate_field(NM_A_FA_CONTACT, fields);
+- while (locate != NULL) {
+-
+- /* Create a new contact from the fields */
+- contact = nm_create_contact_from_fields(locate);
+-
+- /* Add it to our contact list */
+- nm_folder_add_contact_to_list(folder, contact);
+-
+- /* Update the contact cache */
+- nm_user_add_contact(user, contact);
+-
+- /* Update the user record cache */
+- if ((details = nm_locate_field(NM_A_FA_USER_DETAILS,
+- (NMField *) locate->ptr_value))) {
+- user_record = nm_find_user_record(user, nm_contact_get_dn(contact));
+- if (user_record == NULL) {
+- user_record = nm_create_user_record_from_fields(details);
+- nm_user_record_set_dn(user_record, nm_contact_get_dn(contact));
+- nm_user_add_user_record(user, user_record);
+- nm_release_user_record(user_record);
+- }
+- nm_contact_set_user_record(contact, user_record);
+- }
+-
+- nm_release_contact(contact);
+-
+- locate = nm_locate_field(NM_A_FA_CONTACT, locate+1);
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmcontact.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmcontact.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmcontact.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,425 +0,0 @@
+-/*
+- * nmcontact.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_CONTACT_H__
+-#define __NM_CONTACT_H__
+-
+-#include <glib.h>
+-
+-typedef struct _NMContact NMContact;
+-typedef struct _NMContactProperty NMContactProperty;
+-typedef struct _NMFolder NMFolder;
+-
+-#include "nmfield.h"
+-#include "nmuser.h"
+-
+-/**
+- * Creates a contact
+- *
+- * Should be released by calling nm_release_contact
+- *
+- * @return The new NMContact
+- *
+- */
+-NMContact *nm_create_contact(void);
+-
+-/**
+- * Creates a contact from a field array representing the
+- * contact
+- *
+- * Should be released by calling nm_release_contact
+- *
+- * @param fields Should be the NM_A_FA_CONTACT for
+- * the contact
+- *
+- * @return The new contact
+- *
+- */
+-NMContact *nm_create_contact_from_fields(NMField * fields);
+-
+-/**
+- * Add a reference to an existing contact
+- *
+- * The reference should be released by calling
+- * nm_release_contact
+- *
+- * @param contact The contact
+- *
+- */
+-void nm_contact_add_ref(NMContact * contact);
+-
+-/**
+- * Update the contact list properties of the contact (sequence, parent id, etc.)
+- *
+- * @param contact The contact to update
+- * @param fields The fields to update from (should be a NM_A_FA_CONTACT array)
+- *
+- */
+-void nm_contact_update_list_properties(NMContact * contact, NMField * fields);
+-
+-/**
+- * Release a contact reference
+- *
+- * @param contact The contact to release.
+- *
+- */
+-void nm_release_contact(NMContact * contact);
+-
+-/**
+- * Get the display name of a contact
+- *
+- * @param contact The contact
+- *
+- * @return The display name of a contact
+- *
+- */
+-const char *nm_contact_get_display_name(NMContact * contact);
+-
+-/**
+- * Get the DN of a contact
+- *
+- * @param contact The contact
+- *
+- * @return The DN of the contact
+- */
+-const char *nm_contact_get_dn(NMContact * contact);
+-
+-/**
+- * Set the display name for a contact. This is called
+- * by nm_send_rename_contact. It should not be called
+- * directly (it does not change the display name on the
+- * server side list -- nm_send_rename_conact does).
+- *
+- * @param contact The contact
+- * @param display_name The new display name
+- *
+- */
+-void nm_contact_set_display_name(NMContact * contact, const char * display_name);
+-
+-/**
+- * Set the DN for the contact
+- *
+- * @param contact The contact
+- * @param dn The new DN for the contact
+- *
+- */
+-void nm_contact_set_dn(NMContact * contact, const char * dn);
+-
+-/**
+- * Return a field array (NM_A_FA_CONTACT) representing the contact
+- *
+- * @param contact The contact
+- *
+- * @return A field array representing the contact
+- */
+-NMField *nm_contact_to_fields(NMContact * contact);
+-
+-/**
+- * Set the user record for the contact
+- *
+- * @param contact The contact
+- * @param user_record The user record
+- *
+- */
+-void nm_contact_set_user_record(NMContact * contact, NMUserRecord * user_record);
+-
+-/**
+- * Get the user record for the contact
+- *
+- * @param contact The contact
+- *
+- * @return The user record associated with the contact
+- *
+- */
+-NMUserRecord *nm_contact_get_user_record(NMContact * contact);
+-
+-/**
+- * Get the user defined data for the contact
+- *
+- * @param contact The contact
+- *
+- * @return The user defined data for the contact
+- *
+- */
+-gpointer nm_contact_get_data(NMContact * contact);
+-
+-/**
+- * Get the Object ID for the contact
+- *
+- * @param contact The contact
+- *
+- * @return The ID for the contact
+- */
+-int nm_contact_get_id(NMContact * contact);
+-
+-/**
+- * Get the ID for the folder that the contact is in
+- *
+- * @param contact The contact
+- *
+- * @return The ID of the folder that contains the contact
+- *
+- */
+-int nm_contact_get_parent_id(NMContact * contact);
+-
+-/**
+- * Get The userid of the contact.
+- *
+- * @param contact The contact
+- *
+- * @return The userid of the contact
+- *
+- */
+-const char *nm_contact_get_userid(NMContact * contact);
+-
+-/**
+- * Get the display id of the contact
+- *
+- * @param contact The contact
+- *
+- * @return The display id of the contact
+- */
+-const char *nm_contact_get_display_id(NMContact * contact);
+-
+-/**
+- * Set the user defined data for the contact
+- *
+- * @param contact The contact
+- * @param data The user defined data
+- *
+- */
+-void nm_contact_set_data(NMContact * contact, gpointer data);
+-
+-/**
+- * Create a folder with the given name
+- *
+- * @param name The name of the folder
+- *
+- * @return The new folder
+- *
+- */
+-NMFolder *nm_create_folder(const char *name);
+-
+-/**
+- * Create a folder from a NM_A_FA_FOLDER field array
+- *
+- * @param fields The NM_A_FA_FOLDER field array
+- *
+- * @return The new folder
+- *
+- */
+-NMFolder *nm_create_folder_from_fields(NMField * fields);
+-
+-/**
+- * Add a reference to an existing folder
+- *
+- * The reference should be released by calling
+- * nm_release_folder
+- *
+- * @param folder The folder
+- *
+- */
+-void nm_folder_add_ref(NMFolder * folder);
+-
+-/**
+- * Release a reference to a folder.
+- *
+- * @param folder The folder to release
+- *
+- */
+-void nm_release_folder(NMFolder * folder);
+-
+-/**
+- * Return the number of subfolders for the given
+- * folder
+- *
+- * @param folder The folder
+- *
+- * @return The number of subfolders contained by folder
+- */
+-int nm_folder_get_subfolder_count(NMFolder * folder);
+-
+-/**
+- * Get a subfolder
+- *
+- * @param folder The root folder
+- * @param index The index of the folder to get
+- *
+- * @return The subfolder at the given index
+- *
+- */
+-NMFolder *nm_folder_get_subfolder(NMFolder * folder, int index);
+-
+-/**
+- * Get the number of contacts in the given folder
+- *
+- * @param folder The folder
+- *
+- * @return The number of contacts contained by folder
+- *
+- */
+-int nm_folder_get_contact_count(NMFolder * folder);
+-
+-/**
+- * Get a contact in the given folder
+- *
+- * @param folder The folder
+- * @param index The index of the contact to get
+- *
+- * @return The contact at the given index
+- *
+- */
+-NMContact *nm_folder_get_contact(NMFolder * folder, int index);
+-
+-/**
+- * Get the name of the folder
+- *
+- * @param folder The folder
+- *
+- * @return The name of the folder.
+- *
+- */
+-const char *nm_folder_get_name(NMFolder * folder);
+-
+-/**
+- * Set the name of a folder. Do not call this directly.
+- * It does not change the name of the folder in the
+- * server side contact list. You must call
+- * nm_send_set_folder_name().
+- *
+- * @param folder The folder
+- * @param name The new name for the folder
+- *
+- */
+-void nm_folder_set_name(NMFolder * folder, const char *name);
+-
+-/**
+- * Get Object ID for folder
+- *
+- * @param folder The folder
+- *
+- * @return The ID of the folder
+- *
+- */
+-int nm_folder_get_id(NMFolder * folder);
+-
+-/**
+- * Add contacts and folders from fields into root
+- *
+- * @param user The logged in user
+- * @param root The root folder
+- * @param fields The contact list field array
+- *
+- */
+-void nm_folder_add_contacts_and_folders(NMUser * user, NMFolder * root,
+- NMField * fields);
+-/**
+- * Add a contact to the contact list.
+- *
+- * @param root_folder The root folder of the contact list
+- * @param contact The contact to add
+- *
+- */
+-void nm_folder_add_contact_to_list(NMFolder * root_folder,
+- NMContact * contact);
+-
+-/**
+- * Update the contact list properties of the folder (sequence, parent id, etc.)
+- *
+- * @param folder The folder to update
+- * @param fields The fields to update from (should be a NM_A_FA_FOLDER array)
+- *
+- */
+-void nm_folder_update_list_properties(NMFolder * folder, NMField * fields);
+-
+-/**
+- * Add folder to the contact list
+- *
+- * @param root_folder The root folder of the contact list
+- * @param folder The folder to add to the contact list
+- *
+- */
+-void nm_folder_add_folder_to_list(NMFolder * root_folder, NMFolder * folder);
+-
+-/**
+- * Find the object with the given id
+- *
+- * @param root_folder The root folder of the contact list
+- * @param object_id The object id of the object to find
+- *
+- * @return The object with object id (either a contact or a folder)
+- */
+-gpointer nm_folder_find_item_by_object_id(NMFolder * root_folder,
+- int object_id);
+-
+-/**
+- * Remove a contact from the folder
+- *
+- * @param folder The folder
+- * @param contact The contact to remove
+- *
+- */
+-void nm_folder_remove_contact(NMFolder * folder, NMContact * contact);
+-
+-/**
+- * Find a contact in a folder by DN
+- *
+- * @param folder The folder to search
+- * @param dn The DN of the contact to find
+- *
+- * @return The contact if found, NULL otherwise
+- *
+- */
+-NMContact *nm_folder_find_contact(NMFolder * folder, const char *dn);
+-
+-/**
+- * Find a contact in a folder by userid
+- *
+- * @param folder The folder to search
+- * @param userid The userid of the contact to find
+- *
+- * @return The contact if found, NULL otherwise
+- *
+- */
+-NMContact *nm_folder_find_contact_by_userid(NMFolder * folder,
+- const char *userid);
+-
+-/**
+- * Find a contact in a folder by display id
+- *
+- * @param folder The folder to search
+- * @param display_id The userid of the contact to find
+- *
+- * @return The contact if found, NULL otherwise
+- *
+- */
+-NMContact *
+-nm_folder_find_contact_by_display_id(NMFolder * folder, const char *display_id);
+-
+-/**
+- * Return a field array (NM_A_FA_FOLDER) representing the folder
+- *
+- * @param folder The folder
+- *
+- * @return A field array representing the folder
+- */
+-NMField *nm_folder_to_fields(NMFolder * folder);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmevent.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmevent.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,940 +0,0 @@
+-/*
+- * nmevent.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <glib.h>
+-#include <string.h>
+-#include <time.h>
+-#include "nmevent.h"
+-#include "nmfield.h"
+-#include "nmconn.h"
+-#include "nmuserrecord.h"
+-#include "nmrtf.h"
+-
+-#define MAX_UINT32 0xFFFFFFFF
+-
+-struct _NMEvent
+-{
+-
+- /* Event type */
+- int type;
+-
+- /* The DN of the event source */
+- char *source;
+-
+- /* Timestamp of the event */
+- guint32 gmt;
+-
+- /* Conference to associate with the event */
+- NMConference *conference;
+-
+- /* User record to associate with the event */
+- NMUserRecord *user_record;
+-
+- /* Text associated with the event */
+- char *text;
+-
+- /* Reference count for event structure */
+- int ref_count;
+-
+-};
+-
+-/* Handle getdetails response and set the new user record into the event */
+-static void
+-_got_user_for_event(NMUser * user, NMERR_T ret_val,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMUserRecord *user_record;
+- NMEvent *event;
+- nm_event_cb cb;
+-
+- if (user == NULL)
+- return;
+-
+- user_record = resp_data;
+- event = user_data;
+-
+- if (ret_val == NM_OK) {
+- if (event && user_record) {
+-
+- /* Add the user record to the event structure
+- * and make the callback.
+- */
+- nm_event_set_user_record(event, user_record);
+- if ((cb = nm_user_get_event_callback(user))) {
+- cb(user, event);
+- }
+- }
+-
+- } else {
+- /* Cleanup resp_data */
+-
+- }
+-
+- /* Clean up */
+- if (event)
+- nm_release_event(event);
+-
+-}
+-
+-/* Handle getdetails response, set the new user record into the event
+- * and add the user record as a participant in the conference
+- */
+-static void
+-_got_user_for_conference(NMUser * user, NMERR_T ret_val,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMUserRecord *user_record = resp_data;
+- NMEvent *event = user_data;
+- NMConference *conference;
+- nm_event_cb cb;
+-
+- if (user == NULL)
+- return;
+-
+- if (event && user_record) {
+-
+- conference = nm_event_get_conference(event);
+- if (conference) {
+-
+- /* Add source of event as recip of the conference */
+- nm_conference_add_participant(conference, user_record);
+-
+- /* Add the user record to the event structure
+- * and make the callback.
+- */
+- nm_event_set_user_record(event, user_record);
+- if ((cb = nm_user_get_event_callback(user))) {
+- cb(user, event);
+- }
+- }
+- }
+-
+- if (event)
+- nm_release_event(event);
+-}
+-
+-/* Read the receive message event, set up the event object, and
+- * get details for the event source if we don't have them yet.
+- */
+-static NMERR_T
+-handle_receive_message(NMUser * user, NMEvent * event, gboolean autoreply)
+-{
+- NMConference *conference;
+- NMUserRecord *user_record;
+- NMConn *conn;
+- NMERR_T rc = NM_OK;
+- guint32 size = 0, flags = 0;
+- char *msg = NULL;
+- char *nortf = NULL;
+- char *guid = NULL;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- /* Read the conference flags */
+- if (rc == NM_OK) {
+- rc = nm_read_uint32(conn, &flags);
+- }
+-
+- /* Read the message text */
+- if (rc == NM_OK) {
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- msg = g_new0(char, size + 1);
+- rc = nm_read_all(conn, msg, size);
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell", "Message is %s\n", msg);
+-
+- /* Auto replies are not in RTF format! */
+- if (!autoreply) {
+- NMRtfContext *ctx;
+-
+- ctx = nm_rtf_init();
+- nortf = nm_rtf_strip_formatting(ctx, msg);
+- nm_rtf_deinit(ctx);
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Message without RTF is %s\n", nortf);
+-
+- /* Store the event data */
+- nm_event_set_text(event, nortf);
+-
+- } else {
+-
+- /* Store the event data */
+- nm_event_set_text(event, msg);
+- }
+- }
+- }
+-
+- /* Check to see if we already know about the conference */
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+-
+- nm_conference_set_flags(conference, flags);
+- nm_event_set_conference(event, conference);
+-
+- /* Add a reference to the user record in our event object */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- nm_event_set_user_record(event, user_record);
+- }
+-
+- } else {
+-
+- /* This is a new conference, so create one and add it to our list */
+- conference = nm_create_conference(guid);
+- nm_conference_set_flags(conference, flags);
+-
+- /* Add a reference to the conference in the event */
+- nm_event_set_conference(event, conference);
+-
+- /* Add new conference to the conference list */
+- nm_conference_list_add(user, conference);
+-
+- /* Check to see if we have details for the event source yet */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+-
+- /* We do so add the user record as a recipient of the conference */
+- nm_conference_add_participant(conference, user_record);
+-
+- /* Add a reference to the user record in our event object */
+- nm_event_set_user_record(event, user_record);
+-
+- } else {
+-
+- /* Need to go to the server to get details for the user */
+- rc = nm_send_get_details(user, nm_event_get_source(event),
+- _got_user_for_conference, event);
+- if (rc == NM_OK)
+- rc = -1; /* Not done processing the event yet! */
+- }
+-
+- nm_release_conference(conference);
+- }
+-
+- if (msg)
+- g_free(msg);
+-
+- if (nortf)
+- g_free(nortf);
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the invite event, set up the event object, and
+- * get details for the event source if we don't have them yet.
+- */
+-static NMERR_T
+-handle_conference_invite(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- char *msg = NULL;
+- NMConn *conn;
+- NMUserRecord *user_record;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- /* Read the the message */
+- if (rc == NM_OK) {
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- msg = g_new0(char, size + 1);
+- rc = nm_read_all(conn, msg, size);
+- }
+- }
+-
+- /* Store the event data */
+- if (rc == NM_OK) {
+- NMConference *conference;
+-
+- nm_event_set_text(event, msg);
+-
+- conference = nm_conference_list_find(user, guid);
+- if (conference == NULL) {
+- conference = nm_create_conference(guid);
+-
+- /* Add new conference to the list and the event */
+- nm_conference_list_add(user, conference);
+- nm_event_set_conference(event, conference);
+-
+- /* Check to see if we have details for the event source yet */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+-
+- /* Add a reference to the user record in our event object */
+- nm_event_set_user_record(event, user_record);
+-
+- } else {
+-
+- /* Need to go to the server to get details for the user */
+- rc = nm_send_get_details(user, nm_event_get_source(event),
+- _got_user_for_event, event);
+- if (rc == NM_OK)
+- rc = -1; /* Not done processing the event yet! */
+- }
+-
+- nm_release_conference(conference);
+-
+- }
+- }
+-
+- if (msg)
+- g_free(msg);
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the invite notify event, set up the event object, and
+- * get details for the event source if we don't have them yet.
+- */
+-static NMERR_T
+-handle_conference_invite_notify(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- NMConn *conn;
+- NMConference *conference;
+- NMUserRecord *user_record;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_event_set_conference(event, conference);
+-
+- /* Check to see if we have details for the event source yet */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+-
+- /* Add a reference to the user record in our event object */
+- nm_event_set_user_record(event, user_record);
+-
+- } else {
+-
+- /* Need to go to the server to get details for the user */
+- rc = nm_send_get_details(user, nm_event_get_source(event),
+- _got_user_for_event, event);
+- if (rc == NM_OK)
+- rc = -1; /* Not done processing the event yet! */
+- }
+-
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+-
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the conference reject event and set up the event object */
+-static NMERR_T
+-handle_conference_reject(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- NMConn *conn;
+- NMConference *conference;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- if (rc == NM_OK) {
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_event_set_conference(event, conference);
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the conference left event, set up the event object, and
+- * remove the conference from the list if there are no more
+- * participants
+- */
+-static NMERR_T
+-handle_conference_left(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0, flags = 0;
+- char *guid = NULL;
+- NMConference *conference;
+- NMConn *conn;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- /* Read the conference flags */
+- if (rc == NM_OK) {
+- rc = nm_read_uint32(conn, &flags);
+- }
+-
+- if (rc == NM_OK) {
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_event_set_conference(event, conference);
+- nm_conference_set_flags(conference, flags);
+-
+- nm_conference_remove_participant(conference, nm_event_get_source(event));
+- if (nm_conference_get_participant_count(conference) == 0) {
+- nm_conference_list_remove(user, conference);
+- }
+-
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the conference closed, set up the event object, and
+- * remove the conference from the list
+- */
+-static NMERR_T
+-handle_conference_closed(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- NMConference *conference;
+- NMConn *conn;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- if (rc == NM_OK) {
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_event_set_conference(event, conference);
+- nm_conference_list_remove(user, conference);
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the conference joined event, set up the event object, and
+- * get details for the event source if we don't have them yet.
+- */
+-static NMERR_T
+-handle_conference_joined(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0, flags = 0;
+- char *guid = NULL;
+- NMConn *conn;
+- NMConference *conference;
+- NMUserRecord *user_record;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- /* Read the conference flags */
+- if (rc == NM_OK) {
+- rc = nm_read_uint32(conn, &flags);
+- }
+-
+- if (rc == NM_OK) {
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_conference_set_flags(conference, flags);
+-
+- nm_event_set_conference(event, conference);
+-
+- /* Add the new user to the participants list */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- nm_conference_remove_participant(conference,
+- nm_user_record_get_dn(user_record));
+- nm_conference_add_participant(conference, user_record);
+- } else {
+-
+- /* Need to go to the server to get details for the user */
+- rc = nm_send_get_details(user, nm_event_get_source(event),
+- _got_user_for_conference, event);
+- if (rc == NM_OK)
+- rc = -1; /* Not done processing the event yet! */
+- }
+-
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the typing event and set up the event object */
+-static NMERR_T
+-handle_typing(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- NMConference *conference;
+- NMConn *conn;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- if (rc == NM_OK) {
+- conference = nm_conference_list_find(user, guid);
+- if (conference) {
+- nm_event_set_conference(event, conference);
+- } else {
+- rc = NMERR_CONFERENCE_NOT_FOUND;
+- }
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/* Read the event, set up the event object, and update
+- * the status in the user record (for the event source)
+- */
+-static NMERR_T
+-handle_status_change(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint16 status;
+- guint32 size;
+- char *text = NULL;
+- NMUserRecord *user_record;
+- NMConn *conn;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read new status */
+- rc = nm_read_uint16(conn, &status);
+- if (rc == NM_OK) {
+-
+- /* Read the status text */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- text = g_new0(char, size + 1);
+- rc = nm_read_all(conn, text, size);
+- }
+- }
+-
+- if (rc == NM_OK) {
+- nm_event_set_text(event, text);
+-
+- /* Get a reference to the user record and store the new status */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- nm_event_set_user_record(event, user_record);
+- nm_user_record_set_status(user_record, status, text);
+- }
+- }
+-
+- if (text)
+- g_free(text);
+-
+- return rc;
+-}
+-
+-/* Read the undeliverable event */
+-static NMERR_T
+-handle_undeliverable_status(NMUser * user, NMEvent * event)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- char *guid = NULL;
+- NMConn *conn;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the conference guid */
+- rc = nm_read_uint32(conn, &size);
+- if (size == MAX_UINT32) return NMERR_PROTOCOL;
+-
+- if (rc == NM_OK) {
+- guid = g_new0(char, size + 1);
+- rc = nm_read_all(conn, guid, size);
+- }
+-
+- if (guid)
+- g_free(guid);
+-
+- return rc;
+-}
+-
+-/*******************************************************************************
+- * Event API -- see header file for comments
+- ******************************************************************************/
+-
+-NMEvent *
+-nm_create_event(int type, const char *source, guint32 gmt)
+-{
+- NMEvent *event = g_new0(NMEvent, 1);
+-
+- event->type = type;
+- event->gmt = gmt;
+-
+- if (source)
+- event->source = g_strdup(source);
+-
+- event->ref_count = 1;
+-
+- return event;
+-}
+-
+-void
+-nm_release_event(NMEvent * event)
+-{
+- if (event == NULL) {
+- return;
+- }
+-
+- if (--(event->ref_count) == 0) {
+-
+- if (event->source)
+- g_free(event->source);
+-
+- if (event->conference)
+- nm_release_conference(event->conference);
+-
+- if (event->user_record)
+- nm_release_user_record(event->user_record);
+-
+- if (event->text)
+- g_free(event->text);
+-
+- g_free(event);
+- }
+-}
+-
+-
+-NMConference *
+-nm_event_get_conference(NMEvent * event)
+-{
+- if (event)
+- return event->conference;
+- else
+- return NULL;
+-}
+-
+-void
+-nm_event_set_conference(NMEvent * event, NMConference * conference)
+-{
+- if (event && conference) {
+- nm_conference_add_ref(conference);
+- event->conference = conference;
+- }
+-}
+-
+-NMUserRecord *
+-nm_event_get_user_record(NMEvent * event)
+-{
+- if (event)
+- return event->user_record;
+- else
+- return NULL;
+-}
+-
+-void
+-nm_event_set_user_record(NMEvent * event, NMUserRecord * user_record)
+-{
+- if (event && user_record) {
+- nm_user_record_add_ref(user_record);
+- event->user_record = user_record;
+- }
+-}
+-
+-const char *
+-nm_event_get_text(NMEvent * event)
+-{
+- if (event)
+- return event->text;
+- else
+- return NULL;
+-}
+-
+-void
+-nm_event_set_text(NMEvent * event, const char *text)
+-{
+- if (event) {
+- if (text)
+- event->text = g_strdup(text);
+- else
+- event->text = NULL;
+- }
+-}
+-
+-const char *
+-nm_event_get_source(NMEvent * event)
+-{
+- if (event)
+- return event->source;
+- else
+- return NULL;
+-}
+-
+-int
+-nm_event_get_type(NMEvent * event)
+-{
+- if (event)
+- return event->type;
+- else
+- return -1;
+-}
+-
+-time_t
+-nm_event_get_gmt(NMEvent * event)
+-{
+- if (event)
+- return event->gmt;
+- else
+- return (time_t)-1;
+-}
+-
+-NMERR_T
+-nm_process_event(NMUser * user, int type)
+-{
+- NMERR_T rc = NM_OK;
+- guint32 size = 0;
+- NMEvent *event = NULL;
+- char *source = NULL;
+- nm_event_cb cb;
+- NMConn *conn;
+-
+- if (user == NULL)
+- return NMERR_BAD_PARM;
+-
+- if (type < NMEVT_START || type > NMEVT_STOP)
+- return NMERR_PROTOCOL;
+-
+- conn = nm_user_get_conn(user);
+-
+- /* Read the event source */
+- rc = nm_read_uint32(conn, &size);
+- if (rc == NM_OK) {
+- if (size > 0) {
+- source = g_new0(char, size);
+-
+- rc = nm_read_all(conn, source, size);
+- }
+- }
+-
+- /* Read the event data */
+- if (rc == NM_OK) {
+- event = nm_create_event(type, source, time(0));
+-
+- if (event) {
+-
+- switch (type) {
+- case NMEVT_STATUS_CHANGE:
+- rc = handle_status_change(user, event);
+- break;
+-
+- case NMEVT_RECEIVE_MESSAGE:
+- rc = handle_receive_message(user, event, FALSE);
+- break;
+-
+- case NMEVT_RECEIVE_AUTOREPLY:
+- rc = handle_receive_message(user, event, TRUE);
+- break;
+-
+- case NMEVT_USER_TYPING:
+- case NMEVT_USER_NOT_TYPING:
+- rc = handle_typing(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_LEFT:
+- rc = handle_conference_left(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_CLOSED:
+- rc = handle_conference_closed(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_JOINED:
+- rc = handle_conference_joined(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_INVITE:
+- rc = handle_conference_invite(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_REJECT:
+- rc = handle_conference_reject(user, event);
+- break;
+-
+- case NMEVT_CONFERENCE_INVITE_NOTIFY:
+- rc = handle_conference_invite_notify(user, event);
+- break;
+-
+- case NMEVT_UNDELIVERABLE_STATUS:
+- rc = handle_undeliverable_status(user, event);
+- break;
+-
+- case NMEVT_INVALID_RECIPIENT:
+- /* Nothing else to read, just callback */
+- break;
+-
+- case NMEVT_USER_DISCONNECT:
+- /* Nothing else to read, just callback */
+- break;
+-
+- case NMEVT_SERVER_DISCONNECT:
+- /* Nothing else to read, just callback */
+- break;
+-
+- case NMEVT_RECEIVE_FILE:
+- case NMEVT_CONTACT_ADD:
+- /* Safely ignored for now */
+- break;
+-
+- default:
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Unknown event %d received.\n", type);
+- rc = NMERR_PROTOCOL;
+- break;
+- }
+- }
+- }
+-
+- if (rc == (NMERR_T)-1) {
+- /* -1 means that we are not ready to callback yet. */
+- rc = NM_OK;
+- } else if (rc == NM_OK && (cb = nm_user_get_event_callback(user))) {
+-
+- cb(user, event);
+-
+- if (event)
+- nm_release_event(event);
+- } else {
+- if (event)
+- nm_release_event(event);
+- }
+-
+- /* Cleanup */
+- if (source)
+- g_free(source);
+-
+- return rc;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmevent.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmevent.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmevent.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,178 +0,0 @@
+-/*
+- * nmevent.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_EVENT_H__
+-#define __NM_EVENT_H__
+-
+-typedef struct _NMEvent NMEvent;
+-
+-#include "nmuser.h"
+-#include <sys/types.h>
+-
+-/**
+- * Defines for the event types
+- */
+-#define NMEVT_INVALID_RECIPIENT 101
+-#define NMEVT_UNDELIVERABLE_STATUS 102
+-#define NMEVT_STATUS_CHANGE 103
+-#define NMEVT_CONTACT_ADD 104
+-#define NMEVT_CONFERENCE_CLOSED 105
+-#define NMEVT_CONFERENCE_JOINED 106
+-#define NMEVT_CONFERENCE_LEFT 107
+-#define NMEVT_RECEIVE_MESSAGE 108
+-#define NMEVT_RECEIVE_FILE 109
+-#define NMEVT_USER_TYPING 112
+-#define NMEVT_USER_NOT_TYPING 113
+-#define NMEVT_USER_DISCONNECT 114
+-#define NMEVT_SERVER_DISCONNECT 115
+-#define NMEVT_CONFERENCE_RENAME 116
+-#define NMEVT_CONFERENCE_INVITE 117
+-#define NMEVT_CONFERENCE_INVITE_NOTIFY 118
+-#define NMEVT_CONFERENCE_REJECT 119
+-#define NMEVT_RECEIVE_AUTOREPLY 121
+-#define NMEVT_START NMEVT_INVALID_RECIPIENT
+-#define NMEVT_STOP NMEVT_RECEIVE_AUTOREPLY
+-
+-/**
+- * Process the event. The event will be read, an NMEvent will
+- * be created, and the event callback will be called.
+- *
+- * @param user The main user structure.
+- * @param type The type of the event to read.
+- *
+- * @return NM_OK on success
+- */
+-NMERR_T nm_process_event(NMUser * user, int type);
+-
+-/**
+- * Creates an NMEvent
+- *
+- * The NMEvent should be released by calling
+- * nm_release_event.
+- *
+- * @param type The event type, see defines above.
+- * @param source The DN of the event source.
+- * @param gmt The time that the event occurred.
+- *
+- * @return The new NMEvent
+- */
+-NMEvent *nm_create_event(int type, const char *source, guint32 gmt);
+-
+-/**
+- * Releases an NMEvent
+- *
+- * @param event The event to release
+- *
+- */
+-void nm_release_event(NMEvent * event);
+-
+-/**
+- * Sets the conference object for the given event.
+- *
+- * @param event The event.
+- * @param conference The conference to associate with the event.
+- *
+- */
+-void nm_event_set_conference(NMEvent * event, NMConference * conference);
+-
+-/**
+- * Returns the conference object associated with the given event. This should not
+- * be released. If it needs to be kept around call nm_conference_addref().
+- *
+- * @param event The event.
+- *
+- * @return The conference associated with the event, or NULL
+- * if no conference has been set for the event.
+- */
+-NMConference *nm_event_get_conference(NMEvent * event);
+-
+-/**
+- * Sets the NMUserRecord object for the given event.
+- * The user record represents the event source.
+- *
+- * @param event The event.
+- * @param user_record The user record to associate with the event.
+- *
+- */
+-void nm_event_set_user_record(NMEvent * event, NMUserRecord * user_record);
+-
+-/**
+- * Returns the NMUserRecord object associated with the given event.
+- * The user record represents the event source. This should not
+- * be released. If it needs to be kept around call
+- * nm_user_record_add_ref().
+- *
+- * @param event The event.
+- *
+- * @return The user record associated with the event, or NULL
+- * if no user record has been set for the event.
+- */
+-NMUserRecord *nm_event_get_user_record(NMEvent * event);
+-
+-/**
+- * Sets the text to associate with the given event.
+- *
+- * @param event The event.
+- * @param text The text to associate with the event.
+- *
+- */
+-void nm_event_set_text(NMEvent * event, const char *text);
+-
+-/**
+- * Returns the text associated with the given event.
+- *
+- * @param event The event.
+- *
+- * @return The text associated with the event, or NULL
+- * if no text has been set for the event.
+- */
+-const char *nm_event_get_text(NMEvent * event);
+-
+-/**
+- * Returns the source of the event (this will be the full DN of the
+- * event source).
+- *
+- * @param event The event.
+- *
+- * @return The full DN of the event's source.
+- */
+-const char *nm_event_get_source(NMEvent * event);
+-
+-/**
+- * Returns the type of the event. See the defines above for
+- * a list of possible event types.
+- *
+- * @param event The event.
+- *
+- * @return The type of the event.
+- *
+- */
+-int nm_event_get_type(NMEvent * event);
+-
+-/**
+- * Returns the time that the event took place.
+- *
+- * @param event The event.
+- *
+- * @return The timestamp for the event.
+- */
+-time_t nm_event_get_gmt(NMEvent * event);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmfield.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmfield.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,364 +0,0 @@
+-/*
+- * nmfield.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <string.h>
+-#include <stdio.h>
+-#include "nmfield.h"
+-
+-/* Free a field value and tag */
+-static void _free_field(NMField * field);
+-
+-/* Free a field value */
+-static void _free_field_value(NMField * field);
+-
+-/* Make a deep copy of the field */
+-static void _copy_field(NMField * dest, NMField * src);
+-
+-/* Make a deep copy of the field's value */
+-static void _copy_field_value(NMField * dest, NMField * src);
+-
+-/* Create a string from a value -- for debugging */
+-static char *_value_to_string(NMField * field);
+-
+-static NMField *
+-_add_blank_field(NMField *fields, guint32 count)
+-{
+- guint32 new_len;
+-
+- if (fields == NULL) {
+- fields = g_new0(NMField, 10);
+- fields->len = 10;
+- } else {
+- if (fields->len < count + 2) {
+- new_len = count + 10;
+- fields = g_realloc(fields, new_len * sizeof(NMField));
+- fields->len = new_len;
+- }
+- }
+- return fields;
+-}
+-
+-NMField *
+-nm_field_add_number(NMField * fields, const char *tag, guint32 size, guint8 method,
+- guint8 flags, guint32 value, guint8 type)
+-{
+- guint32 count;
+- NMField *field;
+-
+- count = nm_count_fields(fields);
+- fields = _add_blank_field(fields, count);
+-
+- field = &(fields[count]);
+- field->tag = g_strdup(tag);
+- field->size = size;
+- field->method = method;
+- field->flags = flags;
+- field->value = value;
+- field->type = type;
+-
+- /* Null terminate the field array */
+- field = &((fields)[count + 1]);
+- field->tag = NULL;
+- field->value = 0;
+- field->ptr_value = NULL;
+-
+- return fields;
+-}
+-
+-NMField *
+-nm_field_add_pointer(NMField * fields, const char *tag, guint32 size, guint8 method,
+- guint8 flags, gpointer value, guint8 type)
+-{
+- guint32 count;
+- NMField *field = NULL;
+-
+- count = nm_count_fields(fields);
+- fields = _add_blank_field(fields, count);
+-
+- field = &(fields[count]);
+- field->tag = g_strdup(tag);
+- field->size = size;
+- field->method = method;
+- field->flags = flags;
+- field->ptr_value = value;
+- field->type = type;
+-
+- /* Null terminate the field array */
+- field = &((fields)[count + 1]);
+- field->tag = NULL;
+- field->value = 0;
+- field->ptr_value = NULL;
+-
+- return fields;
+-}
+-
+-guint32
+-nm_count_fields(NMField * fields)
+-{
+- guint32 count = 0;
+-
+- if (fields) {
+- while (fields->tag != NULL) {
+- count++;
+- fields++;
+- }
+- }
+-
+- return count;
+-}
+-
+-void
+-nm_free_fields(NMField ** fields)
+-{
+- NMField *field = NULL;
+-
+- if ((fields == NULL) || (*fields == NULL))
+- return;
+-
+- field = *fields;
+-
+- while (field->tag != NULL) {
+- _free_field(field);
+- field++;
+- }
+-
+- g_free(*fields);
+- *fields = NULL;
+-}
+-
+-
+-static void
+-_free_field(NMField * field)
+-{
+- if (field == NULL)
+- return;
+-
+- _free_field_value(field);
+- g_free(field->tag);
+-}
+-
+-static void
+-_free_field_value(NMField * field)
+-{
+- if (field == NULL)
+- return;
+-
+- switch (field->type) {
+- case NMFIELD_TYPE_BINARY:
+- case NMFIELD_TYPE_UTF8:
+- case NMFIELD_TYPE_DN:
+- g_free(field->ptr_value);
+- break;
+-
+- case NMFIELD_TYPE_ARRAY:
+- case NMFIELD_TYPE_MV:
+- nm_free_fields((NMField **)&field->ptr_value);
+- break;
+-
+- default:
+- break;
+- }
+-
+- field->size = 0;
+- field->ptr_value = NULL;
+-}
+-
+-NMField *
+-nm_locate_field(char *tag, NMField * fields)
+-{
+- NMField *ret_fields = NULL;
+-
+- if ((fields == NULL) || (tag == NULL)) {
+- return NULL;
+- }
+-
+- while (fields->tag != NULL) {
+- if (g_ascii_strcasecmp(fields->tag, tag) == 0) {
+- ret_fields = fields;
+- break;
+- }
+- fields++;
+- }
+-
+- return ret_fields;
+-}
+-
+-NMField *
+-nm_copy_field_array(NMField * src)
+-{
+- NMField *ptr = NULL;
+- NMField *dest = NULL;
+- int count;
+-
+- if (src != NULL) {
+- count = nm_count_fields(src) + 1;
+- dest = g_new0(NMField, count);
+- dest->len = count;
+- ptr = dest;
+- while (src->tag != NULL) {
+- _copy_field(ptr, src);
+- ptr++;
+- src++;
+- }
+- }
+-
+- return dest;
+-}
+-
+-static void
+-_copy_field(NMField * dest, NMField * src)
+-{
+- dest->type = src->type;
+- dest->flags = src->flags;
+- dest->method = src->method;
+- dest->tag = g_strdup(src->tag);
+- _copy_field_value(dest, src);
+-}
+-
+-static void
+-_copy_field_value(NMField * dest, NMField * src)
+-{
+- dest->type = src->type;
+- switch (dest->type) {
+- case NMFIELD_TYPE_UTF8:
+- case NMFIELD_TYPE_DN:
+- if (src->size == 0 && src->ptr_value != NULL) {
+- src->size = strlen((char *) src->ptr_value) + 1;
+- }
+- /* fall through */
+- case NMFIELD_TYPE_BINARY:
+- if (src->size != 0 && src->ptr_value != NULL) {
+- dest->ptr_value = g_new0(char, src->size);
+- memcpy(dest->ptr_value, src->ptr_value, src->size);
+- }
+- break;
+-
+- case NMFIELD_TYPE_ARRAY:
+- case NMFIELD_TYPE_MV:
+- dest->ptr_value = nm_copy_field_array((NMField *)src->ptr_value);
+- break;
+-
+- default:
+- /* numeric value */
+- dest->value = src->value;
+- break;
+- }
+-
+- dest->size = src->size;
+-}
+-
+-void
+-nm_remove_field(NMField * field)
+-{
+- NMField *tmp;
+- guint32 len;
+-
+- if ((field != NULL) && (field->tag != NULL)) {
+- _free_field(field);
+-
+- /* Move fields down */
+- tmp = field + 1;
+- while (1) {
+- /* Don't overwrite the size of the array */
+- len = field->len;
+-
+- *field = *tmp;
+-
+- field->len = len;
+-
+- if (tmp->tag == NULL)
+- break;
+-
+- field++;
+- tmp++;
+- }
+- }
+-}
+-
+-void
+-nm_print_fields(NMField * fields)
+-{
+- char *str = NULL;
+- NMField *field = fields;
+-
+- if (fields == NULL)
+- return;
+-
+- while (field->tag != NULL) {
+- if (field->type == NMFIELD_TYPE_ARRAY || field->type == NMFIELD_TYPE_MV) {
+- printf("Subarray START: %s Method = %d\n", field->tag, field->method);
+- nm_print_fields((NMField *) field->ptr_value);
+- printf("Subarray END: %s\n", field->tag);
+- } else {
+- str = _value_to_string(field);
+- printf("Tag=%s;Value=%s\n", field->tag, str);
+- g_free(str);
+- str = NULL;
+- }
+- field++;
+- }
+-
+-}
+-
+-static char *
+-_value_to_string(NMField * field)
+-{
+- char *value = NULL;
+-
+- if (field == NULL)
+- return NULL;
+-
+- /* This is a single value attribute */
+- if (((field->type == NMFIELD_TYPE_UTF8) ||
+- (field->type == NMFIELD_TYPE_DN)) && (field->ptr_value != NULL)) {
+- value = g_strdup((const char *) field->ptr_value);
+- } else if (field->type == NMFIELD_TYPE_BINARY && field->ptr_value != NULL) {
+- value = g_new0(char, field->size);
+- memcpy(value, (const char *) field->ptr_value, field->size);
+- } else if (field->type == NMFIELD_TYPE_BOOL) {
+- if (field->value) {
+- value = g_strdup(NM_FIELD_TRUE);
+- } else {
+- value = g_strdup(NM_FIELD_FALSE);
+- }
+- } else {
+- /* assume it is a number */
+- value = g_new0(char, 20);
+-
+- switch (field->type) {
+- case NMFIELD_TYPE_BYTE:
+- case NMFIELD_TYPE_WORD:
+- case NMFIELD_TYPE_DWORD:
+- value = g_strdup_printf("%ld", (long) field->value);
+- break;
+-
+- case NMFIELD_TYPE_UBYTE:
+- case NMFIELD_TYPE_UWORD:
+- case NMFIELD_TYPE_UDWORD:
+- value = g_strdup_printf("%lu", (unsigned long) field->value);
+- break;
+- }
+- }
+-
+- if (value == NULL)
+- value = g_strdup("NULL");
+-
+- return value;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmfield.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmfield.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmfield.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,225 +0,0 @@
+-/*
+- * nmfield.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef NMFIELD_H
+-#define NMFIELD_H
+-
+-#include <glib.h>
+-
+-typedef struct NMField_t
+-{
+- char *tag; /* Field tag */
+- guint8 method; /* Method of the field */
+- guint8 flags; /* Flags */
+- guint8 type; /* Type of value */
+- guint32 size; /* Size of value if binary */
+- guint32 value; /* Value of a numeric field */
+- gpointer ptr_value; /* Value of a string or sub array field */
+- guint32 len; /* Length of the array */
+-} NMField;
+-
+-/* Field types */
+-#define NMFIELD_TYPE_INVALID 0
+-#define NMFIELD_TYPE_NUMBER 1
+-#define NMFIELD_TYPE_BINARY 2
+-#define NMFIELD_TYPE_BYTE 3
+-#define NMFIELD_TYPE_UBYTE 4
+-#define NMFIELD_TYPE_WORD 5
+-#define NMFIELD_TYPE_UWORD 6
+-#define NMFIELD_TYPE_DWORD 7
+-#define NMFIELD_TYPE_UDWORD 8
+-#define NMFIELD_TYPE_ARRAY 9
+-#define NMFIELD_TYPE_UTF8 10
+-#define NMFIELD_TYPE_BOOL 11
+-#define NMFIELD_TYPE_MV 12
+-#define NMFIELD_TYPE_DN 13
+-
+-/* Field methods */
+-#define NMFIELD_METHOD_VALID 0
+-#define NMFIELD_METHOD_IGNORE 1
+-#define NMFIELD_METHOD_DELETE 2
+-#define NMFIELD_METHOD_DELETE_ALL 3
+-#define NMFIELD_METHOD_EQUAL 4
+-#define NMFIELD_METHOD_ADD 5
+-#define NMFIELD_METHOD_UPDATE 6
+-#define NMFIELD_METHOD_GTE 10
+-#define NMFIELD_METHOD_LTE 12
+-#define NMFIELD_METHOD_NE 14
+-#define NMFIELD_METHOD_EXIST 15
+-#define NMFIELD_METHOD_NOTEXIST 16
+-#define NMFIELD_METHOD_SEARCH 17
+-#define NMFIELD_METHOD_MATCHBEGIN 19
+-#define NMFIELD_METHOD_MATCHEND 20
+-#define NMFIELD_METHOD_NOT_ARRAY 40
+-#define NMFIELD_METHOD_OR_ARRAY 41
+-#define NMFIELD_METHOD_AND_ARRAY 42
+-
+-/* Attribute Names (field tags) */
+-#define NM_A_IP_ADDRESS "nnmIPAddress"
+-#define NM_A_PORT "nnmPort"
+-#define NM_A_FA_FOLDER "NM_A_FA_FOLDER"
+-#define NM_A_FA_CONTACT "NM_A_FA_CONTACT"
+-#define NM_A_FA_CONVERSATION "NM_A_FA_CONVERSATION"
+-#define NM_A_FA_MESSAGE "NM_A_FA_MESSAGE"
+-#define NM_A_FA_CONTACT_LIST "NM_A_FA_CONTACT_LIST"
+-#define NM_A_FA_RESULTS "NM_A_FA_RESULTS"
+-#define NM_A_FA_INFO_DISPLAY_ARRAY "NM_A_FA_INFO_DISPLAY_ARRAY"
+-#define NM_A_FA_USER_DETAILS "NM_A_FA_USER_DETAILS"
+-#define NM_A_SZ_OBJECT_ID "NM_A_SZ_OBJECT_ID"
+-#define NM_A_SZ_PARENT_ID "NM_A_SZ_PARENT_ID"
+-#define NM_A_SZ_SEQUENCE_NUMBER "NM_A_SZ_SEQUENCE_NUMBER"
+-#define NM_A_SZ_TYPE "NM_A_SZ_TYPE"
+-#define NM_A_SZ_STATUS "NM_A_SZ_STATUS"
+-#define NM_A_SZ_STATUS_TEXT "NM_A_SZ_STATUS_TEXT"
+-#define NM_A_SZ_DN "NM_A_SZ_DN"
+-#define NM_A_SZ_DISPLAY_NAME "NM_A_SZ_DISPLAY_NAME"
+-#define NM_A_SZ_USERID "NM_A_SZ_USERID"
+-#define NM_A_SZ_CREDENTIALS "NM_A_SZ_CREDENTIALS"
+-#define NM_A_SZ_MESSAGE_BODY "NM_A_SZ_MESSAGE_BODY"
+-#define NM_A_SZ_MESSAGE_TEXT "NM_A_SZ_MESSAGE_TEXT"
+-#define NM_A_UD_MESSAGE_TYPE "NM_A_UD_MESSAGE_TYPE"
+-#define NM_A_FA_PARTICIPANTS "NM_A_FA_PARTICIPANTS"
+-#define NM_A_FA_INVITES "NM_A_FA_INVITES"
+-#define NM_A_FA_EVENT "NM_A_FA_EVENT"
+-#define NM_A_UD_COUNT "NM_A_UD_COUNT"
+-#define NM_A_UD_DATE "NM_A_UD_DATE"
+-#define NM_A_UD_EVENT "NM_A_UD_EVENT"
+-#define NM_A_B_NO_CONTACTS "NM_A_B_NO_CONTACTS"
+-#define NM_A_B_NO_CUSTOMS "NM_A_B_NO_CUSTOMS"
+-#define NM_A_B_NO_PRIVACY "NM_A_B_NO_PRIVACY"
+-#define NM_A_UW_STATUS "NM_A_UW_STATUS"
+-#define NM_A_UD_OBJECT_ID "NM_A_UD_OBJECT_ID"
+-#define NM_A_SZ_TRANSACTION_ID "NM_A_SZ_TRANSACTION_ID"
+-#define NM_A_SZ_RESULT_CODE "NM_A_SZ_RESULT_CODE"
+-#define NM_A_UD_BUILD "NM_A_UD_BUILD"
+-#define NM_A_SZ_AUTH_ATTRIBUTE "NM_A_SZ_AUTH_ATTRIBUTE"
+-#define NM_A_UD_KEEPALIVE "NM_A_UD_KEEPALIVE"
+-#define NM_A_SZ_USER_AGENT "NM_A_SZ_USER_AGENT"
+-#define NM_A_BLOCKING "nnmBlocking"
+-#define NM_A_BLOCKING_DENY_LIST "nnmBlockingDenyList"
+-#define NM_A_BLOCKING_ALLOW_LIST "nnmBlockingAllowList"
+-#define NM_A_SZ_BLOCKING_ALLOW_ITEM "NM_A_SZ_BLOCKING_ALLOW_ITEM"
+-#define NM_A_SZ_BLOCKING_DENY_ITEM "NM_A_SZ_BLOCKING_DENY_ITEM"
+-#define NM_A_LOCKED_ATTR_LIST "nnmLockedAttrList"
+-
+-#define NM_PROTOCOL_VERSION 2
+-
+-#define NM_FIELD_TRUE "1"
+-#define NM_FIELD_FALSE "0"
+-
+-#define NMFIELD_MAX_STR_LENGTH 32768
+-
+-/**
+- * Count the number of fields
+- *
+- * @param fields Field array
+- *
+- * @return The number of fields in the array.
+- *
+- */
+-guint32 nm_count_fields(NMField * fields);
+-
+-/**
+- * Add a field to the field array. The field should be of type NMFIELD_TYPE_UTF8,
+- * NMFIELD_TYPE_DN, NMFIELD_TYPE_ARRAY, or NMFIELD_TYPE_MV
+- *
+- * NOTE: field array that is passed in may be realloc'd so you should use
+- * the returned field array pointer not the passed in pointer after calling
+- * this function.
+- *
+- * @param fields Field array
+- * @param tag Tag for the new field
+- * @param size Size of the field value (if type = binary)
+- * @param method Field method (see method defines above)
+- * @param flags Flags for new field
+- * @param value The value of the field
+- * @param type The type of the field value
+- *
+- * @return Pointer to the updated field array
+- *
+- */
+-NMField *nm_field_add_pointer(NMField *fields, const char *tag, guint32 size, guint8 method,
+- guint8 flags, gpointer value, guint8 type);
+-
+-/**
+- * Add a numeric field to the field array.
+- *
+- * NOTE: field array that is passed in may be realloc'd so you should use
+- * the returned field array pointer not the passed in pointer after calling
+- * this function.
+- *
+- * @param fields Field array
+- * @param tag Tag for the new field
+- * @param size Size of the field value (if type = binary)
+- * @param method Field method (see method defines above)
+- * @param flags Flags for new field
+- * @param value The value of the field
+- * @param type The type of the field value
+- *
+- * @return Pointer to the updated field array
+- *
+- */
+-NMField *nm_field_add_number(NMField *fields, const char *tag, guint32 size, guint8 method,
+- guint8 flags, guint32 value, guint8 type);
+-
+-/**
+- * Recursively free an array of fields and set pointer to NULL.
+- *
+- * @param fields Pointer to a field array
+- *
+- */
+-void nm_free_fields(NMField ** fields);
+-
+-/**
+- * Find first field with given tag in field array.
+- *
+- * Note: this will only work for 7-bit ascii tags (which is all that
+- * we use currently).
+- *
+- * @param tag Tag to search for
+- * @param fields Field array
+- *
+- * @return The first matching field, or NULL if no fields match.
+- *
+- */
+-NMField *nm_locate_field(char *tag, NMField * fields);
+-
+-/**
+- * Make a deep copy of a field array
+- *
+- * @param src The array to copy
+- *
+- * @return The new (copied) array, which must be freed.
+- *
+- */
+-NMField *nm_copy_field_array(NMField * src);
+-
+-/**
+- * Remove a field and move other fields up to fill the gap
+- *
+- * @param field The field to remove
+- *
+- */
+-void nm_remove_field(NMField * field);
+-
+-/* Print a field array (for debugging purposes) */
+-void nm_print_fields(NMField * fields);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmmessage.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmmessage.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,96 +0,0 @@
+-/*
+- * nmmessage.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "nmmessage.h"
+-
+-struct _NMMessage
+-{
+- NMConference *conference;
+- char *text;
+- guint32 ref_count;
+-};
+-
+-
+-/** Message API **/
+-
+-NMMessage *
+-nm_create_message(const char *text)
+-{
+- NMMessage *msg = g_new0(NMMessage, 1);
+-
+- if (text)
+- msg->text = g_strdup(text);
+-
+- msg->ref_count = 1;
+- return msg;
+-}
+-
+-void
+-nm_message_add_ref(NMMessage * msg)
+-{
+- if (msg)
+- msg->ref_count++;
+-}
+-
+-void
+-nm_release_message(NMMessage * msg)
+-{
+- if (msg && (--(msg->ref_count) == 0)) {
+- if (msg->text)
+- g_free(msg->text);
+-
+- if (msg->conference)
+- nm_release_conference(msg->conference);
+-
+- g_free(msg);
+- }
+-}
+-
+-const char *
+-nm_message_get_text(NMMessage * msg)
+-{
+- if (msg == NULL)
+- return NULL;
+-
+- return msg->text;
+-}
+-
+-void
+-nm_message_set_conference(NMMessage * msg, NMConference * conf)
+-{
+- if (msg == NULL || conf == NULL)
+- return;
+-
+- /* Need to ref the conference first so that it doesn't
+- * get released out from under us
+- */
+- nm_conference_add_ref(conf);
+-
+- msg->conference = conf;
+-}
+-
+-NMConference *
+-nm_message_get_conference(NMMessage * msg)
+-{
+- if (msg == NULL)
+- return NULL;
+-
+- return msg->conference;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmmessage.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmmessage.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmmessage.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,83 +0,0 @@
+-/*
+- * nmmessage.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_MESSAGE_H__
+-#define __NM_MESSAGE_H__
+-
+-typedef struct _NMMessage NMMessage;
+-
+-#include "nmconference.h"
+-
+-/**
+- * Creates a new message.
+- *
+- * The returned message should be released by calling
+- * nm_release_message
+- *
+- * @param text The message text
+- * @return A newly allocated message
+- */
+-NMMessage *nm_create_message(const char *text);
+-
+-/**
+- * Increment the reference count for the message object.
+- *
+- * @param msg The message
+- */
+-void nm_message_add_ref(NMMessage * msg);
+-
+-/**
+- * Releases a message.
+- *
+- * @param msg The message
+- */
+-void nm_release_message(NMMessage * msg);
+-
+-/**
+- * Returns the message text
+- *
+- * @param msg The message
+- * @return The message text
+- */
+-const char *nm_message_get_text(NMMessage * msg);
+-
+-/**
+- * Sets the conference object for a message
+- *
+- * @param msg The message
+- * @param conf The conference to associate with the message
+- * @return RVALUE_OK on success
+- */
+-void nm_message_set_conference(NMMessage * msg, NMConference * conf);
+-
+-/**
+- * Returns the conference object associated with the message
+- *
+- * Note: this does not increment the reference count for the
+- * conference and the conference should NOT be released with
+- * nm_release_conference. If the reference needs to be kept
+- * around nm_conference_add_ref should be called.
+- *
+- * @param msg The message
+- * @return The conference associated with this message
+- */
+-NMConference *nm_message_get_conference(NMMessage * msg);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrequest.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmrequest.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,161 +0,0 @@
+-/*
+- * nmrequest.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "nmrequest.h"
+-
+-static int count = 0;
+-
+-struct _NMRequest
+-{
+- int trans_id;
+- char *cmd;
+- int gmt;
+- gpointer data;
+- gpointer user_define;
+- nm_response_cb callback;
+- int ref_count;
+- NMERR_T ret_code;
+-};
+-
+-NMRequest *nm_create_request(const char *cmd, int trans_id, int gmt, nm_response_cb cb,
+- gpointer resp_data, gpointer user_define)
+-{
+- NMRequest *req;
+-
+- if (cmd == NULL)
+- return NULL;
+-
+- req = g_new0(NMRequest, 1);
+- req->cmd = g_strdup(cmd);
+- req->trans_id = trans_id;
+- req->gmt = gmt;
+- req->callback = cb;
+- req->data = resp_data;
+- req->user_define = user_define;
+- req->ref_count = 1;
+-
+- purple_debug_info("novell", "Creating NMRequest instance, total=%d\n", ++count);
+-
+- return req;
+-}
+-
+-void
+-nm_release_request(NMRequest * req)
+-{
+- if (req && (--req->ref_count == 0)) {
+- if (req->cmd)
+- g_free(req->cmd);
+- g_free(req);
+-
+- purple_debug_info("novell",
+- "Releasing NMRequest instance, total=%d\n", --count);
+- }
+-
+-}
+-
+-void
+-nm_request_add_ref(NMRequest * req)
+-{
+- if (req)
+- req->ref_count++;
+-}
+-
+-void
+-nm_request_set_callback(NMRequest * req, nm_response_cb callback)
+-{
+- if (req)
+- req->callback = callback;
+-}
+-
+-void
+-nm_request_set_data(NMRequest * req, gpointer data)
+-{
+- if (req)
+- req->data = data;
+-}
+-
+-void
+-nm_request_set_user_define(NMRequest * req, gpointer user_define)
+-{
+- if (req)
+- req->user_define = user_define;
+-}
+-
+-int
+-nm_request_get_trans_id(NMRequest * req)
+-{
+- if (req)
+- return req->trans_id;
+- else
+- return -1;
+-}
+-
+-const char *
+-nm_request_get_cmd(NMRequest * req)
+-{
+- if (req == NULL)
+- return NULL;
+-
+- return req->cmd;
+-}
+-
+-gpointer
+-nm_request_get_data(NMRequest * req)
+-{
+- if (req == NULL)
+- return NULL;
+-
+- return req->data;
+-}
+-
+-gpointer
+-nm_request_get_user_define(NMRequest * req)
+-{
+- if (req == NULL)
+- return NULL;
+-
+- return req->user_define;
+-}
+-
+-nm_response_cb
+-nm_request_get_callback(NMRequest * req)
+-{
+- if (req == NULL)
+- return NULL;
+-
+- return req->callback;
+-}
+-
+-
+-void
+-nm_request_set_ret_code(NMRequest * req, NMERR_T rc)
+-{
+- if (req)
+- req->ret_code = rc;
+-}
+-
+-NMERR_T
+-nm_request_get_ret_code(NMRequest * req)
+-{
+- if (req)
+- return req->ret_code;
+- else
+- return (NMERR_T) - 1;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrequest.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmrequest.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrequest.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,150 +0,0 @@
+-/*
+- * nmrequest.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_REQUEST_H__
+-#define __NM_REQUEST_H__
+-
+-typedef struct _NMRequest NMRequest;
+-
+-#include "nmuser.h"
+-
+-/**
+- * Create a new request object. Object must be release with nm_release_object.
+- *
+- * @param cmd The request command string (e.g. "login")
+- * @param trans_id The request transaction id
+- * @param gmt The time in seconds that the request was created
+- *
+- * @return The new request object
+- */
+-NMRequest *nm_create_request(const char *cmd, int trans_id, int gmt, nm_response_cb cb,
+- gpointer resp_data, gpointer user_define);
+-
+-/**
+- * Release a request object.
+- *
+- * @param req The request to release
+- */
+-void nm_release_request(NMRequest * req);
+-
+-/**
+- * Add a new reference to this object. This reference must be released by
+- * a call to nm_release_object.
+- *
+- * @param req The request object
+- */
+-void nm_request_add_ref(NMRequest * req);
+-
+-/**
+- * Set the response callback for this request object. This is the callback
+- * that will be made when we get a response from the server.
+- *
+- * @param req The request object
+- * @param callback The response callback
+- *
+- */
+-void nm_request_set_callback(NMRequest * req, nm_response_cb callback);
+-
+-/**
+- * Set the response data. This will be set differently depending on
+- * the request type (for example to nm_send_get_details will set this
+- * to be the newly create NMUserRecord object).
+- *
+- * @param req The request object
+- * @param data Pointer to some data
+- *
+- */
+-void nm_request_set_data(NMRequest * req, gpointer data);
+-
+-/**
+- * Set the user defined data. This is the data that the client
+- * passes to the various nm_send_* functions. We will pass it
+- * back when we make the callback.
+- *
+- * @param req The request object
+- * @param user_define Pointer to some data
+- *
+- */
+-void nm_request_set_user_define(NMRequest * req, gpointer user_define);
+-
+-/**
+- * Set the return code. This is the return code that we received in
+- * the server response fields.
+- *
+- * @param req The request object
+- * @param rc The return code to set
+- */
+-void nm_request_set_ret_code(NMRequest * req, NMERR_T rc);
+-
+-/**
+- * Get the transaction id for this request.
+- *
+- * @param req The request object
+- *
+- * @return The transaction id.
+- */
+-int nm_request_get_trans_id(NMRequest * req);
+-
+-/**
+- * Get the command (request type) for this request.
+- *
+- * @param req The request object
+- *
+- * @return The request cmd
+- */
+-const char *nm_request_get_cmd(NMRequest * req);
+-
+-/**
+- * Get the response data for this request
+- *
+- * @param req The request object
+- *
+- * @return The response data
+- */
+-gpointer nm_request_get_data(NMRequest * req);
+-
+-/**
+- * Get the user defined data for this request
+- *
+- * @param req The request object
+- *
+- * @return The user defined data
+- */
+-gpointer nm_request_get_user_define(NMRequest * req);
+-
+-/**
+- * Get the response callback for this request
+- *
+- * @param req The request object
+- *
+- * @return The response callback
+- */
+-nm_response_cb nm_request_get_callback(NMRequest * req);
+-
+-/**
+- * Get the return code
+- *
+- * @param req The request object
+- *
+- * @return The return code (from the response fields)
+- */
+-NMERR_T nm_request_get_ret_code(NMRequest * req);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrtf.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmrtf.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,829 +0,0 @@
+-/*
+- * nmrtf.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/* This code was adapted from the sample RTF reader found here:
+- * http://msdn.microsoft.com/library/default.asp?url=/library/en-us/dnrtfspec/html/rtfspec.asp
+- */
+-
+-#include <glib.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <stddef.h>
+-#include <ctype.h>
+-#include <string.h>
+-#include "nmrtf.h"
+-#include "debug.h"
+-
+-/* Internal RTF parser error codes */
+-#define NMRTF_OK 0 /* Everything's fine! */
+-#define NMRTF_STACK_UNDERFLOW 1 /* Unmatched '}' */
+-#define NMRTF_STACK_OVERFLOW 2 /* Too many '{' -- memory exhausted */
+-#define NMRTF_UNMATCHED_BRACE 3 /* RTF ended during an open group. */
+-#define NMRTF_INVALID_HEX 4 /* invalid hex character found in data */
+-#define NMRTF_BAD_TABLE 5 /* RTF table (sym or prop) invalid */
+-#define NMRTF_ASSERTION 6 /* Assertion failure */
+-#define NMRTF_EOF 7 /* End of file reached while reading RTF */
+-#define NMRTF_CONVERT_ERROR 8 /* Error converting text */
+-
+-#define NMRTF_MAX_DEPTH 256
+-
+-typedef enum
+-{
+- NMRTF_STATE_NORMAL,
+- NMRTF_STATE_SKIP,
+- NMRTF_STATE_FONTTABLE,
+- NMRTF_STATE_BIN,
+- NMRTF_STATE_HEX
+-} NMRtfState; /* Rtf State */
+-
+-/* Property types that we care about */
+-typedef enum
+-{
+- NMRTF_PROP_FONT_IDX,
+- NMRTF_PROP_FONT_CHARSET,
+- NMRTF_PROP_MAX
+-} NMRtfProperty;
+-
+-typedef enum
+-{
+- NMRTF_SPECIAL_BIN,
+- NMRTF_SPECIAL_HEX,
+- NMRTF_SPECIAL_UNICODE,
+- NMRTF_SPECIAL_SKIP
+-} NMRtfSpecialKwd;
+-
+-typedef enum
+-{
+- NMRTF_DEST_FONTTABLE,
+- NMRTF_DEST_SKIP
+-} NMRtfDestinationType;
+-
+-typedef enum
+-{
+- NMRTF_KWD_CHAR,
+- NMRTF_KWD_DEST,
+- NMRTF_KWD_PROP,
+- NMRTF_KWD_SPEC
+-} NMRtfKeywordType;
+-
+-typedef struct _NMRTFCharProp
+-{
+- /* All we care about for now is the font.
+- * bold, italic, underline, etc. should be
+- * added here
+- */
+- int font_idx;
+- int font_charset;
+-} NMRtfCharProp;
+-
+-typedef struct _NMRtfStateSave
+-{
+- NMRtfCharProp chp;
+- NMRtfState rds;
+- NMRtfState ris;
+-} NMRtfStateSave;
+-
+-typedef struct _NMRtfSymbol
+-{
+- char *keyword; /* RTF keyword */
+- int default_val; /* default value to use */
+- gboolean pass_default; /* true to use default value from this table */
+- NMRtfKeywordType kwd_type; /* the type of the keyword */
+- int action; /* property type if the keyword represents a property */
+- /* destination type if the keyword represents a destination */
+- /* character to print if the keyword represents a character */
+-} NMRtfSymbol;
+-
+-
+-typedef struct _NMRtfFont
+-{
+- int number;
+- char *name;
+- int charset;
+-} NMRtfFont;
+-
+-/* RTF Context */
+-struct _NMRtfContext
+-{
+- NMRtfState rds; /* destination state */
+- NMRtfState ris; /* internal state */
+- NMRtfCharProp chp; /* current character properties (ie. font, bold, italic, etc.) */
+- GSList *font_table; /* the font table */
+- GSList *saved; /* saved state stack */
+- int param; /* numeric parameter for the current keyword */
+- long bytes_to_skip; /* number of bytes to skip (after encountering \bin) */
+- int depth; /* how many groups deep are we */
+- gboolean skip_unknown; /* if true, skip any unknown destinations (this is set after encountering '\*') */
+- char *input; /* input string */
+- char nextch; /* next char in input */
+- GString *ansi; /* Temporary ansi text, will be convert/flushed to the output string */
+- GString *output; /* The plain text UTF8 string */
+-};
+-
+-static int rtf_parse(NMRtfContext *ctx);
+-static int rtf_push_state(NMRtfContext *ctx);
+-static int rtf_pop_state(NMRtfContext *ctx);
+-static NMRtfFont *rtf_get_font(NMRtfContext *ctx, int index);
+-static int rtf_get_char(NMRtfContext *ctx, guchar *ch);
+-static int rtf_unget_char(NMRtfContext *ctx, guchar ch);
+-static int rtf_flush_data(NMRtfContext *ctx);
+-static int rtf_parse_keyword(NMRtfContext *ctx);
+-static int rtf_dispatch_control(NMRtfContext *ctx, char *keyword, int param, gboolean param_set);
+-static int rtf_dispatch_char(NMRtfContext *ctx, guchar ch);
+-static int rtf_dispatch_unicode_char(NMRtfContext *ctx, gunichar ch);
+-static int rtf_print_char(NMRtfContext *ctx, guchar ch);
+-static int rtf_print_unicode_char(NMRtfContext *ctx, gunichar ch);
+-static int rtf_change_destination(NMRtfContext *ctx, NMRtfDestinationType dest);
+-static int rtf_dispatch_special(NMRtfContext *ctx, NMRtfSpecialKwd special);
+-static int rtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val);
+-
+-/* RTF parser tables */
+-
+-/* Keyword descriptions */
+-NMRtfSymbol rtf_symbols[] = {
+- /* keyword, default, pass_default, keyword_type, action */
+- {"fonttbl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_FONTTABLE},
+- {"f", 0, FALSE, NMRTF_KWD_PROP, NMRTF_PROP_FONT_IDX},
+- {"fcharset", 0, FALSE, NMRTF_KWD_PROP, NMRTF_PROP_FONT_CHARSET},
+- {"par", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
+- {"line", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
+- {"\0x0a", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
+- {"\0x0d", 0, FALSE, NMRTF_KWD_CHAR, 0x0a},
+- {"tab", 0, FALSE, NMRTF_KWD_CHAR, 0x09},
+- {"\r", 0, FALSE, NMRTF_KWD_CHAR, '\r'},
+- {"\n", 0, FALSE, NMRTF_KWD_CHAR, '\n'},
+- {"ldblquote",0, FALSE, NMRTF_KWD_CHAR, '"'},
+- {"rdblquote",0, FALSE, NMRTF_KWD_CHAR, '"'},
+- {"{", 0, FALSE, NMRTF_KWD_CHAR, '{'},
+- {"}", 0, FALSE, NMRTF_KWD_CHAR, '}'},
+- {"\\", 0, FALSE, NMRTF_KWD_CHAR, '\\'},
+- {"bin", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_BIN},
+- {"*", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_SKIP},
+- {"'", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_HEX},
+- {"u", 0, FALSE, NMRTF_KWD_SPEC, NMRTF_SPECIAL_UNICODE},
+- {"colortbl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"author", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"buptim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"comment", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"creatim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"doccomm", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"footer", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"footerf", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"footerl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"footerr", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"footnote", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"ftncn", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"ftnsep", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"ftnsepc", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"header", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"headerf", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"headerl", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"headerr", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"info", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"keywords", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"operator", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"pict", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"printim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"private1", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"revtim", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"rxe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"stylesheet", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"subject", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"tc", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"title", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"txe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP},
+- {"xe", 0, FALSE, NMRTF_KWD_DEST, NMRTF_DEST_SKIP}
+-};
+-int table_size = sizeof(rtf_symbols) / sizeof(NMRtfSymbol);
+-
+-NMRtfContext *
+-nm_rtf_init()
+-{
+- NMRtfContext *ctx = g_new0(NMRtfContext, 1);
+- ctx->nextch = -1;
+- ctx->ansi = g_string_new("");
+- ctx->output = g_string_new("");
+- return ctx;
+-}
+-
+-char *
+-nm_rtf_strip_formatting(NMRtfContext *ctx, const char *input)
+-{
+- int status;
+-
+- ctx->input = (char *)input;
+- status = rtf_parse(ctx);
+- if (status == NMRTF_OK)
+- return g_strdup(ctx->output->str);
+-
+- purple_debug_info("novell", "RTF parser failed with error code %d\n", status);
+- return NULL;
+-}
+-
+-void
+-nm_rtf_deinit(NMRtfContext *ctx)
+-{
+- GSList *node;
+- NMRtfFont *font;
+- NMRtfStateSave *save;
+-
+- if (ctx) {
+- for (node = ctx->font_table; node; node = node->next) {
+- font = node->data;
+- g_free(font->name);
+- g_free(font);
+- node->data = NULL;
+- }
+- g_slist_free(ctx->font_table);
+- for (node = ctx->saved; node; node = node->next) {
+- save = node->data;
+- g_free(save);
+- node->data = NULL;
+- }
+- g_slist_free(ctx->saved);
+- g_string_free(ctx->ansi, TRUE);
+- g_string_free(ctx->output, TRUE);
+- g_free(ctx);
+- }
+-}
+-
+-static const char *
+-get_current_encoding(NMRtfContext *ctx)
+-{
+- NMRtfFont *font;
+-
+- font = rtf_get_font(ctx, ctx->chp.font_idx);
+-
+- switch (font->charset) {
+- case 0:
+- return "CP1252";
+- case 77:
+- return "MACINTOSH";
+- case 78:
+- return "SJIS";
+- case 128:
+- return "CP932";
+- case 129:
+- return "CP949";
+- case 130:
+- return "CP1361";
+- case 134:
+- return "CP936";
+- case 136:
+- return "CP950";
+- case 161:
+- return "CP1253";
+- case 162:
+- return "CP1254";
+- case 163:
+- return "CP1258";
+- case 181:
+- case 177:
+- return "CP1255";
+- case 178:
+- case 179:
+- case 180:
+- return "CP1256";
+- case 186:
+- return "CP1257";
+- case 204:
+- return "CP1251";
+- case 222:
+- return "CP874";
+- case 238:
+- return "CP1250";
+- case 254:
+- return "CP437";
+- default:
+- purple_debug_info("novell", "Unhandled font charset %d\n", font->charset);
+- return "CP1252";
+- }
+- return "CP1252";
+-}
+-
+-
+-/*
+- * Add an entry to the font table
+- */
+-static int
+-rtf_add_font_entry(NMRtfContext *ctx, int number, const char *name, int charset)
+-{
+- NMRtfFont *font = g_new0(NMRtfFont, 1);
+-
+- font->number = number;
+- font->name = g_strdup(name);
+- font->charset = charset;
+-
+- purple_debug_info("novell", "Adding font to table: #%d\t%s\t%d\n",
+- font->number, font->name, font->charset);
+-
+- ctx->font_table = g_slist_append(ctx->font_table, font);
+-
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Return the nth entry in the font table
+- */
+-static NMRtfFont *
+-rtf_get_font(NMRtfContext *ctx, int nth)
+-{
+- NMRtfFont *font;
+-
+- font = g_slist_nth_data(ctx->font_table, nth);
+-
+- return font;
+-}
+-
+-/*
+- * Step 1:
+- * Isolate RTF keywords and send them to rtf_parse_keyword;
+- * Push and pop state at the start and end of RTF groups;
+- * Send text to rtf_dispatch_char for further processing.
+- */
+-static int
+-rtf_parse(NMRtfContext *ctx)
+-{
+- int status;
+- guchar ch;
+- guchar hex_byte = 0;
+- int hex_count = 2;
+- int len;
+-
+- if (ctx->input == NULL)
+- return NMRTF_OK;
+-
+- while (rtf_get_char(ctx, &ch) == NMRTF_OK) {
+- if (ctx->depth < 0)
+- return NMRTF_STACK_UNDERFLOW;
+-
+- /* if we're parsing binary data, handle it directly */
+- if (ctx->ris == NMRTF_STATE_BIN) {
+- if ((status = rtf_dispatch_char(ctx, ch)) != NMRTF_OK)
+- return status;
+- } else {
+- switch (ch) {
+- case '{':
+- if (ctx->depth > NMRTF_MAX_DEPTH)
+- return NMRTF_STACK_OVERFLOW;
+- rtf_flush_data(ctx);
+- if ((status = rtf_push_state(ctx)) != NMRTF_OK)
+- return status;
+- break;
+- case '}':
+- rtf_flush_data(ctx);
+-
+- /* for some reason there is always an unwanted '\par' at the end */
+- if (ctx->rds == NMRTF_STATE_NORMAL) {
+- len = ctx->output->len;
+- if (ctx->output->str[len-1] == '\n')
+- ctx->output = g_string_truncate(ctx->output, len-1);
+- }
+-
+- if ((status = rtf_pop_state(ctx)) != NMRTF_OK)
+- return status;
+-
+- if (ctx->depth < 0)
+- return NMRTF_STACK_OVERFLOW;
+- break;
+- case '\\':
+- if ((status = rtf_parse_keyword(ctx)) != NMRTF_OK)
+- return status;
+- break;
+- case 0x0d:
+- case 0x0a: /* cr and lf are noise characters... */
+- break;
+- default:
+- if (ctx->ris == NMRTF_STATE_NORMAL) {
+- if ((status = rtf_dispatch_char(ctx, ch)) != NMRTF_OK)
+- return status;
+- } else { /* parsing a hex encoded character */
+- if (ctx->ris != NMRTF_STATE_HEX)
+- return NMRTF_ASSERTION;
+-
+- hex_byte = hex_byte << 4;
+- if (isdigit(ch))
+- hex_byte += (char) ch - '0';
+- else {
+- if (islower(ch)) {
+- if (ch < 'a' || ch > 'f')
+- return NMRTF_INVALID_HEX;
+- hex_byte += (char) ch - 'a' + 10;
+- } else {
+- if (ch < 'A' || ch > 'F')
+- return NMRTF_INVALID_HEX;
+- hex_byte += (char) ch - 'A' + 10;
+- }
+- }
+- hex_count--;
+- if (hex_count == 0) {
+- if ((status = rtf_dispatch_char(ctx, hex_byte)) != NMRTF_OK)
+- return status;
+- hex_count = 2;
+- hex_byte = 0;
+- ctx->ris = NMRTF_STATE_NORMAL;
+- }
+- }
+- break;
+- }
+- }
+- }
+- if (ctx->depth < 0)
+- return NMRTF_STACK_OVERFLOW;
+- if (ctx->depth > 0)
+- return NMRTF_UNMATCHED_BRACE;
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Push the current state onto stack
+- */
+-static int
+-rtf_push_state(NMRtfContext *ctx)
+-{
+- NMRtfStateSave *save = g_new0(NMRtfStateSave, 1);
+- save->chp = ctx->chp;
+- save->rds = ctx->rds;
+- save->ris = ctx->ris;
+- ctx->saved = g_slist_prepend(ctx->saved, save);
+- ctx->ris = NMRTF_STATE_NORMAL;
+- (ctx->depth)++;
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Restore the state at the top of the stack
+- */
+-static int
+-rtf_pop_state(NMRtfContext *ctx)
+-{
+- NMRtfStateSave *save_old;
+- GSList *link_old;
+-
+- if (ctx->saved == NULL)
+- return NMRTF_STACK_UNDERFLOW;
+-
+- save_old = ctx->saved->data;
+- ctx->chp = save_old->chp;
+- ctx->rds = save_old->rds;
+- ctx->ris = save_old->ris;
+- (ctx->depth)--;
+-
+- g_free(save_old);
+- link_old = ctx->saved;
+- ctx->saved = g_slist_remove_link(ctx->saved, link_old);
+- g_slist_free_1(link_old);
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Step 2:
+- * Get a control word (and its associated value) and
+- * dispatch the control.
+- */
+-static int
+-rtf_parse_keyword(NMRtfContext *ctx)
+-{
+- int status = NMRTF_OK;
+- guchar ch;
+- gboolean param_set = FALSE;
+- gboolean is_neg = FALSE;
+- int param = 0;
+- char keyword[30];
+- char parameter[20];
+- int i;
+-
+- keyword[0] = '\0';
+- parameter[0] = '\0';
+- if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK)
+- return status;
+-
+- if (!isalpha(ch)) {
+- /* a control symbol; no delimiter. */
+- keyword[0] = (char) ch;
+- keyword[1] = '\0';
+- return rtf_dispatch_control(ctx, keyword, 0, param_set);
+- }
+-
+- /* parse keyword */
+- for (i = 0; isalpha(ch) && (i < sizeof(keyword) - 1); rtf_get_char(ctx, &ch)) {
+- keyword[i] = (char) ch;
+- i++;
+- }
+- keyword[i] = '\0';
+-
+- /* check for '-' indicated a negative parameter value */
+- if (ch == '-') {
+- is_neg = TRUE;
+- if ((status = rtf_get_char(ctx, &ch)) != NMRTF_OK)
+- return status;
+- }
+-
+- /* check for numerical param */
+- if (isdigit(ch)) {
+-
+- param_set = TRUE;
+- for (i = 0; isdigit(ch) && (i < sizeof(parameter) - 1); rtf_get_char(ctx, &ch)) {
+- parameter[i] = (char) ch;
+- i++;
+- }
+- parameter[i] = '\0';
+-
+- ctx->param = param = atoi(parameter);
+- if (is_neg)
+- ctx->param = param = -param;
+- }
+-
+- /* space after control is optional, put character back if it is not a space */
+- if (ch != ' ')
+- rtf_unget_char(ctx, ch);
+-
+- return rtf_dispatch_control(ctx, keyword, param, param_set);
+-}
+-
+-/*
+- * Route the character to the appropriate destination
+- */
+-static int
+-rtf_dispatch_char(NMRtfContext *ctx, guchar ch)
+-{
+- if (ctx->ris == NMRTF_STATE_BIN && --(ctx->bytes_to_skip) <= 0)
+- ctx->ris = NMRTF_STATE_NORMAL;
+-
+- switch (ctx->rds) {
+- case NMRTF_STATE_SKIP:
+- return NMRTF_OK;
+- case NMRTF_STATE_NORMAL:
+- return rtf_print_char(ctx, ch);
+- case NMRTF_STATE_FONTTABLE:
+- if (ch == ';') {
+- rtf_add_font_entry(ctx, ctx->chp.font_idx,
+- ctx->ansi->str, ctx->chp.font_charset);
+- g_string_truncate(ctx->ansi, 0);
+- }
+- else {
+- return rtf_print_char(ctx, ch);
+- }
+- return NMRTF_OK;
+- default:
+- return NMRTF_OK;
+- }
+-}
+-
+-/* Handle a unicode character */
+-static int
+-rtf_dispatch_unicode_char(NMRtfContext *ctx, gunichar ch)
+-{
+- switch (ctx->rds) {
+- case NMRTF_STATE_SKIP:
+- return NMRTF_OK;
+- case NMRTF_STATE_NORMAL:
+- case NMRTF_STATE_FONTTABLE:
+- return rtf_print_unicode_char(ctx, ch);
+- default:
+- return NMRTF_OK;
+- }
+-}
+-
+-/*
+- * Output a character
+- */
+-static int
+-rtf_print_char(NMRtfContext *ctx, guchar ch)
+-{
+-
+- ctx->ansi = g_string_append_c(ctx->ansi, ch);
+-
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Output a unicode character
+- */
+-static int
+-rtf_print_unicode_char(NMRtfContext *ctx, gunichar ch)
+-{
+- char buf[7];
+- int num;
+-
+- /* convert and flush the ansi buffer to the utf8 buffer */
+- rtf_flush_data(ctx);
+-
+- /* convert the unicode character to utf8 and add directly to the output buffer */
+- num = g_unichar_to_utf8((gunichar) ch, buf);
+- buf[num] = 0;
+- purple_debug_info("novell", "converted unichar 0x%X to utf8 char %s\n", ch, buf);
+-
+- ctx->output = g_string_append(ctx->output, buf);
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Flush the output text
+- */
+-static int
+-rtf_flush_data(NMRtfContext *ctx)
+-{
+- int status = NMRTF_OK;
+- char *conv_data = NULL;
+- const char *enc = NULL;
+- GError *gerror = NULL;
+-
+- if (ctx->rds == NMRTF_STATE_NORMAL && ctx->ansi->len > 0) {
+- enc = get_current_encoding(ctx);
+- conv_data = g_convert(ctx->ansi->str, ctx->ansi->len, "UTF-8", enc,
+- NULL, NULL, &gerror);
+- if (conv_data) {
+- ctx->output = g_string_append(ctx->output, conv_data);
+- g_free(conv_data);
+- ctx->ansi = g_string_truncate(ctx->ansi, 0);
+- } else {
+- status = NMRTF_CONVERT_ERROR;
+- purple_debug_info("novell", "failed to convert data! error code = %d msg = %s\n",
+- gerror->code, gerror->message);
+- g_free(gerror);
+- }
+- }
+-
+- return status;
+-}
+-
+-/*
+- * Handle a property change
+- */
+-static int
+-rtf_apply_property(NMRtfContext *ctx, NMRtfProperty prop, int val)
+-{
+- if (ctx->rds == NMRTF_STATE_SKIP) /* If we're skipping text, */
+- return NMRTF_OK; /* don't do anything. */
+-
+- /* Need to flush any temporary data before a property change*/
+- rtf_flush_data(ctx);
+-
+- switch (prop) {
+- case NMRTF_PROP_FONT_IDX:
+- ctx->chp.font_idx = val;
+- break;
+- case NMRTF_PROP_FONT_CHARSET:
+- ctx->chp.font_charset = val;
+- break;
+- default:
+- return NMRTF_BAD_TABLE;
+- }
+-
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Step 3.
+- * Search the table for keyword and evaluate it appropriately.
+- *
+- * Inputs:
+- * keyword: The RTF control to evaluate.
+- * param: The parameter of the RTF control.
+- * param_set: TRUE if the control had a parameter; (that is, if param is valid)
+- * FALSE if it did not.
+- */
+-static int
+-rtf_dispatch_control(NMRtfContext *ctx, char *keyword, int param, gboolean param_set)
+-{
+- int idx;
+-
+- for (idx = 0; idx < table_size; idx++) {
+- if (strcmp(keyword, rtf_symbols[idx].keyword) == 0)
+- break;
+- }
+-
+- if (idx == table_size) {
+- if (ctx->skip_unknown)
+- ctx->rds = NMRTF_STATE_SKIP;
+- ctx->skip_unknown = FALSE;
+- return NMRTF_OK;
+- }
+-
+- /* found it! use kwd_type and action to determine what to do with it. */
+- ctx->skip_unknown = FALSE;
+- switch (rtf_symbols[idx].kwd_type) {
+- case NMRTF_KWD_PROP:
+- if (rtf_symbols[idx].pass_default || !param_set)
+- param = rtf_symbols[idx].default_val;
+- return rtf_apply_property(ctx, rtf_symbols[idx].action, param);
+- case NMRTF_KWD_CHAR:
+- return rtf_dispatch_char(ctx, rtf_symbols[idx].action);
+- case NMRTF_KWD_DEST:
+- return rtf_change_destination(ctx, rtf_symbols[idx].action);
+- case NMRTF_KWD_SPEC:
+- return rtf_dispatch_special(ctx, rtf_symbols[idx].action);
+- default:
+- return NMRTF_BAD_TABLE;
+- }
+- return NMRTF_BAD_TABLE;
+-}
+-
+-/*
+- * Change to the destination specified.
+- */
+-static int
+-rtf_change_destination(NMRtfContext *ctx, NMRtfDestinationType type)
+-{
+- /* if we're skipping text, don't do anything */
+- if (ctx->rds == NMRTF_STATE_SKIP)
+- return NMRTF_OK;
+-
+- switch (type) {
+- case NMRTF_DEST_FONTTABLE:
+- ctx->rds = NMRTF_STATE_FONTTABLE;
+- g_string_truncate(ctx->ansi, 0);
+- break;
+- default:
+- ctx->rds = NMRTF_STATE_SKIP; /* when in doubt, skip it... */
+- break;
+- }
+- return NMRTF_OK;
+-}
+-
+-/*
+- * Dispatch an RTF control that needs special processing
+- */
+-static int
+-rtf_dispatch_special(NMRtfContext *ctx, NMRtfSpecialKwd type)
+-{
+- int status = NMRTF_OK;
+- guchar ch;
+-
+- if (ctx->rds == NMRTF_STATE_SKIP && type != NMRTF_SPECIAL_BIN) /* if we're skipping, and it's not */
+- return NMRTF_OK; /* the \bin keyword, ignore it. */
+-
+- switch (type) {
+- case NMRTF_SPECIAL_BIN:
+- ctx->ris = NMRTF_STATE_BIN;
+- ctx->bytes_to_skip = ctx->param;
+- break;
+- case NMRTF_SPECIAL_SKIP:
+- ctx->skip_unknown = TRUE;
+- break;
+- case NMRTF_SPECIAL_HEX:
+- ctx->ris = NMRTF_STATE_HEX;
+- break;
+- case NMRTF_SPECIAL_UNICODE:
+- purple_debug_info("novell", "parsing unichar\n");
+- status = rtf_dispatch_unicode_char(ctx, ctx->param);
+- /* Skip next char */
+- if (status == NMRTF_OK)
+- status = rtf_get_char(ctx, &ch);
+- break;
+- default:
+- status = NMRTF_BAD_TABLE;
+- break;
+- }
+-
+- return status;
+-}
+-
+-/*
+- * Get the next character from the input stream
+- */
+-static int
+-rtf_get_char(NMRtfContext *ctx, guchar *ch)
+-{
+- if (ctx->nextch >= 0) {
+- *ch = ctx->nextch;
+- ctx->nextch = -1;
+- }
+- else {
+- *ch = *(ctx->input);
+- ctx->input++;
+- }
+-
+- if (*ch)
+- return NMRTF_OK;
+- else
+- return NMRTF_EOF;
+-}
+-
+-/*
+- * Move a character back into the input stream
+- */
+-static int
+-rtf_unget_char(NMRtfContext *ctx, guchar ch)
+-{
+- ctx->nextch = ch;
+- return NMRTF_OK;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmrtf.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmrtf.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmrtf.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,30 +0,0 @@
+-/*
+- * nmrtf.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NMRTF_H__
+-#define __NMRTF_H__
+-
+-typedef struct _NMRtfContext NMRtfContext;
+-
+-NMRtfContext *nm_rtf_init(void);
+-char *nm_rtf_strip_formatting(NMRtfContext *ctx, const char *input);
+-void nm_rtf_deinit(NMRtfContext *ctx);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuser.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmuser.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2137 +0,0 @@
+-/*
+- * nmuser.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-#include <string.h>
+-#include "nmfield.h"
+-#include "nmuser.h"
+-#include "nmconn.h"
+-#include "nmcontact.h"
+-#include "nmuserrecord.h"
+-#include "util.h"
+-
+-/* This is the template that we wrap outgoing messages in, since the other
+- * GW Messenger clients expect messages to be in RTF.
+- */
+-#define RTF_TEMPLATE "{\\rtf1\\ansi\n"\
+- "{\\fonttbl{\\f0\\fnil Unknown;}}\n"\
+- "{\\colortbl ;\\red0\\green0\\blue0;}\n"\
+- "\\uc1\\cf1\\f0\\fs24 %s\\par\n}"
+-#define NM_MAX_MESSAGE_SIZE 2048
+-
+-static NMERR_T nm_process_response(NMUser * user);
+-static void _update_contact_list(NMUser * user, NMField * fields);
+-static void _handle_multiple_get_details_login_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data);
+-static char * nm_rtfize_text(char *text);
+-
+-/**
+- * See header for comments on on "public" functions
+- */
+-
+-NMUser *
+-nm_initialize_user(const char *name, const char *server_addr,
+- int port, gpointer data, nm_event_cb event_callback)
+-{
+- NMUser *user;
+- if (name == NULL || server_addr == NULL || event_callback == NULL)
+- return NULL;
+-
+- user = g_new0(NMUser, 1);
+-
+-
+-
+- user->contacts =
+- g_hash_table_new_full(g_str_hash, nm_utf8_str_equal,
+- g_free, (GDestroyNotify) nm_release_contact);
+-
+- user->user_records =
+- g_hash_table_new_full(g_str_hash, nm_utf8_str_equal, g_free,
+- (GDestroyNotify) nm_release_user_record);
+-
+- user->display_id_to_dn = g_hash_table_new_full(g_str_hash, nm_utf8_str_equal,
+- g_free, g_free);
+-
+- user->name = g_strdup(name);
+- user->conn = nm_create_conn(server_addr, port);
+- user->conn->addr = g_strdup(server_addr);
+- user->conn->port = port;
+- user->evt_callback = event_callback;
+- user->client_data = data;
+-
+- return user;
+-}
+-
+-
+-void
+-nm_deinitialize_user(NMUser * user)
+-{
+- nm_release_conn(user->conn);
+-
+- if (user->contacts) {
+- g_hash_table_destroy(user->contacts);
+- }
+-
+- if (user->user_records) {
+- g_hash_table_destroy(user->user_records);
+- }
+-
+- if (user->display_id_to_dn) {
+- g_hash_table_destroy(user->display_id_to_dn);
+- }
+-
+- if (user->name) {
+- g_free(user->name);
+- }
+-
+- if (user->user_record) {
+- nm_release_user_record(user->user_record);
+- }
+-
+- nm_conference_list_free(user);
+- nm_destroy_contact_list(user);
+-
+- g_free(user);
+-}
+-
+-NMERR_T
+-nm_send_login(NMUser * user, const char *pwd, const char *my_addr,
+- const char *user_agent, nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+-
+- if (user == NULL || pwd == NULL || user_agent == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(user->name), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_CREDENTIALS, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(pwd), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_USER_AGENT, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(user_agent), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_number(fields, NM_A_UD_BUILD, 0, NMFIELD_METHOD_VALID, 0,
+- NM_PROTOCOL_VERSION, NMFIELD_TYPE_UDWORD);
+- if (my_addr) {
+- fields = nm_field_add_pointer(fields, NM_A_IP_ADDRESS, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(my_addr), NMFIELD_TYPE_UTF8);
+- }
+-
+- /* Send the login */
+- rc = nm_send_request(user->conn, "login", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_set_status(NMUser * user, int status, const char *text,
+- const char *auto_resp, nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+-
+- if (user == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add the status */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_STATUS, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", status), NMFIELD_TYPE_UTF8);
+-
+- /* Add the status text and auto reply text if there is any */
+- if (text) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_STATUS_TEXT, 0,
+- NMFIELD_METHOD_VALID, 0, g_strdup(text),
+- NMFIELD_TYPE_UTF8);
+- }
+-
+- if (auto_resp) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_MESSAGE_BODY, 0,
+- NMFIELD_METHOD_VALID, 0, g_strdup(auto_resp),
+- NMFIELD_TYPE_UTF8);
+- }
+-
+- rc = nm_send_request(user->conn, "setstatus", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_multiple_get_details(NMUser * user, GSList *names,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- GSList *node;
+-
+- if (user == NULL || names == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in DN or display id */
+- for (node = names; node; node = node->next) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(node->data), NMFIELD_TYPE_UTF8);
+- }
+-
+- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_get_details(NMUser * user, const char *name,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+-
+- if (user == NULL || name == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in DN or display id */
+- if (strstr("=", name)) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_DN);
+- } else {
+-
+- const char *dn = nm_lookup_dn(user, name);
+- if (dn) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_DN);
+- } else {
+- fields =
+- nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_UTF8);
+- }
+-
+- }
+-
+- rc = nm_send_request(user->conn, "getdetails", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_create_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMField *tmp = NULL;
+- NMField *field = NULL;
+- NMRequest *req = NULL;
+- int count, i;
+-
+- if (user == NULL || conference == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in a blank guid */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(BLANK_GUID), NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
+- NMFIELD_METHOD_VALID, 0, tmp,
+- NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+-
+- /* Add participants in */
+- count = nm_conference_get_participant_count(conference);
+- for (i = 0; i < count; i++) {
+- NMUserRecord *user_record = nm_conference_get_participant(conference, i);
+-
+- if (user_record) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN,
+- 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_user_record_get_dn(user_record)),
+- NMFIELD_TYPE_DN);
+- }
+- }
+-
+- /* Add our user in */
+- field = nm_locate_field(NM_A_SZ_DN, user->fields);
+- if (field) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN,
+- 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup((char *) field->ptr_value),
+- NMFIELD_TYPE_DN);
+- }
+-
+- rc = nm_send_request(user->conn, "createconf", fields, callback, data, &req);
+- if (rc == NM_OK && req) {
+- nm_conference_add_ref(conference);
+- nm_request_set_data(req, conference);
+- }
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_leave_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMField *tmp = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || conference == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in the conference guid */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conference)),
+- NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
+- NMFIELD_METHOD_VALID, 0, tmp,
+- NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Send the request to the server */
+- rc = nm_send_request(user->conn, "leaveconf", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, conference);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_join_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL, *tmp = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || conference == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in the conference guid */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conference)),
+- NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
+- NMFIELD_METHOD_VALID, 0, tmp,
+- NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Send the request to the server */
+- rc = nm_send_request(user->conn, "joinconf", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, conference);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_reject_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMField *tmp = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || conference == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in the conference guid */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conference)),
+- NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
+- NMFIELD_METHOD_VALID, 0, tmp,
+- NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Send the request to the server */
+- rc = nm_send_request(user->conn, "rejectconf", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, conference);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_conference_invite(NMUser *user, NMConference *conference, NMUserRecord *user_record,
+- const char *message, nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMField *tmp = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || conference == NULL || user_record == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add in the conference guid */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conference)),
+- NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0,
+- NMFIELD_METHOD_VALID, 0, tmp,
+- NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Add in DN of user to invite */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_user_record_get_dn(user_record)),
+- NMFIELD_TYPE_DN);
+-
+- /* Add the invite message if there is one */
+- if (message)
+- fields = nm_field_add_pointer(fields, NM_A_SZ_MESSAGE_BODY, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(message), NMFIELD_TYPE_UTF8);
+-
+- /* Send the request to the server */
+- rc = nm_send_request(user->conn, "sendinvite", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, conference);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_message(NMUser * user, NMMessage * message, nm_response_cb callback)
+-{
+- NMERR_T rc = NM_OK;
+- char *text, *rtfized;
+- NMField *fields = NULL, *tmp = NULL;
+- NMConference *conf;
+- NMUserRecord *user_record;
+- int count, i;
+-
+- if (user == NULL || message == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- conf = nm_message_get_conference(message);
+- if (!nm_conference_is_instantiated(conf)) {
+- rc = NMERR_CONFERENCE_NOT_INSTANTIATED;
+- } else {
+-
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conf)),
+- NMFIELD_TYPE_UTF8);
+-
+- fields =
+- nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0, NMFIELD_METHOD_VALID, 0,
+- tmp, NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Add RTF and plain text versions of the message */
+- text = g_strdup(nm_message_get_text(message));
+-
+- /* Truncate if necessary */
+- if (strlen(text) > NM_MAX_MESSAGE_SIZE)
+- text[NM_MAX_MESSAGE_SIZE] = 0;
+-
+- rtfized = nm_rtfize_text(text);
+-
+- purple_debug_info("novell", "message text is: %s\n", text);
+- purple_debug_info("novell", "message rtf is: %s\n", rtfized);
+-
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_MESSAGE_BODY, 0, NMFIELD_METHOD_VALID, 0,
+- rtfized, NMFIELD_TYPE_UTF8);
+-
+- tmp = nm_field_add_number(tmp, NM_A_UD_MESSAGE_TYPE, 0, NMFIELD_METHOD_VALID, 0,
+- 0, NMFIELD_TYPE_UDWORD);
+-
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_MESSAGE_TEXT, 0, NMFIELD_METHOD_VALID, 0,
+- text, NMFIELD_TYPE_UTF8);
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_MESSAGE, 0, NMFIELD_METHOD_VALID, 0,
+- tmp, NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- /* Add participants */
+- count = nm_conference_get_participant_count(conf);
+- for (i = 0; i < count; i++) {
+- user_record = nm_conference_get_participant(conf, i);
+- if (user_record) {
+- fields =
+- nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_user_record_get_dn(user_record)),
+- NMFIELD_TYPE_DN);
+- }
+- }
+-
+- /* Send the request */
+- rc = nm_send_request(user->conn, "sendmessage", fields, callback, NULL, NULL);
+- }
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_typing(NMUser * user, NMConference * conf,
+- gboolean typing, nm_response_cb callback)
+-{
+- NMERR_T rc = NM_OK;
+- char *str = NULL;
+- NMField *fields = NULL, *tmp = NULL;
+-
+- if (user == NULL || conf == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- if (!nm_conference_is_instantiated(conf)) {
+- rc = NMERR_CONFERENCE_NOT_INSTANTIATED;
+- } else {
+- /* Add the conference GUID */
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(nm_conference_get_guid(conf)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Add typing type */
+- str = g_strdup_printf("%d",
+- (typing ? NMEVT_USER_TYPING :
+- NMEVT_USER_NOT_TYPING));
+-
+- tmp = nm_field_add_pointer(tmp, NM_A_SZ_TYPE, 0, NMFIELD_METHOD_VALID, 0,
+- str, NMFIELD_TYPE_UTF8);
+-
+- fields =
+- nm_field_add_pointer(fields, NM_A_FA_CONVERSATION, 0, NMFIELD_METHOD_VALID, 0,
+- tmp, NMFIELD_TYPE_ARRAY);
+- tmp = NULL;
+-
+- rc = nm_send_request(user->conn, "sendtyping", fields, callback, NULL, NULL);
+- }
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_create_contact(NMUser * user, NMFolder * folder,
+- NMContact * contact, nm_response_cb callback,
+- gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMRequest *req = NULL;
+- const char *name = NULL;
+- const char *display_name = NULL;
+-
+- if (user == NULL || folder == NULL || contact == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Add parent ID */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", nm_folder_get_id(folder)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Check to see if userid is current user and return an error? */
+-
+- /* Check to see if contact already exists and return an error? */
+-
+- /* Add userid or dn */
+- name = nm_contact_get_dn(contact);
+- if (name == NULL)
+- return NMERR_BAD_PARM;
+-
+- if (strstr("=", name)) {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_DN);
+- } else {
+- fields = nm_field_add_pointer(fields, NM_A_SZ_USERID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_UTF8);
+- }
+-
+- /* Add display name */
+- display_name = nm_contact_get_display_name(contact);
+- if (display_name)
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(display_name), NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "createcontact", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, contact);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_remove_contact(NMUser * user, NMFolder * folder,
+- NMContact * contact, nm_response_cb callback,
+- gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || folder == NULL || contact == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Add parent id */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", nm_folder_get_id(folder)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Add object id */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", nm_contact_get_id(contact)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, contact);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_create_folder(NMUser * user, const char *name,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || name == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Add parent ID */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup("0"), NMFIELD_TYPE_UTF8);
+-
+- /* Add name of the folder to add */
+- fields =
+- nm_field_add_pointer(fields, NM_A_SZ_DISPLAY_NAME, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(name), NMFIELD_TYPE_UTF8);
+-
+- /* Add sequence, for now just put it at the bottom */
+- fields =
+- nm_field_add_pointer(fields, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup("-1"), NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "createfolder", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, g_strdup(name));
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_remove_folder(NMUser * user, NMFolder * folder,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || folder == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Add the object id */
+- fields = nm_field_add_pointer(fields, NM_A_SZ_OBJECT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", nm_folder_get_id(folder)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "deletecontact", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, folder);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_get_status(NMUser * user, NMUserRecord * user_record,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMRequest *req = NULL;
+- const char *dn;
+-
+- if (user == NULL || user_record == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Add DN to field list */
+- dn = nm_user_record_get_dn(user_record);
+- if (dn == NULL)
+- return (NMERR_T) -1;
+-
+- fields = nm_field_add_pointer(fields, NM_A_SZ_DN, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup(dn), NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "getstatus", fields, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, user_record);
+-
+- if (req)
+- nm_release_request(req);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_rename_contact(NMUser * user, NMContact * contact,
+- const char *new_name, nm_response_cb callback,
+- gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *field = NULL, *fields = NULL, *list = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || contact == NULL || new_name == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Create field list for current contact */
+- field = nm_contact_to_fields(contact);
+- if (field) {
+-
+- fields =
+- nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_DELETE, 0,
+- field, NMFIELD_TYPE_ARRAY);
+- field = NULL;
+-
+- /* Update the contacts display name locally */
+- nm_contact_set_display_name(contact, new_name);
+-
+- /* Create field list for updated contact */
+- field = nm_contact_to_fields(contact);
+- if (field) {
+- fields =
+- nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_ADD, 0,
+- field, NMFIELD_TYPE_ARRAY);
+- field = NULL;
+-
+- /* Package it up */
+- list =
+- nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID,
+- 0, fields, NMFIELD_TYPE_ARRAY);
+- fields = NULL;
+-
+- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, contact);
+- }
+- }
+-
+- if (req)
+- nm_release_request(req);
+-
+- if (list)
+- nm_free_fields(&list);
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_rename_folder(NMUser * user, NMFolder * folder, const char *new_name,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *field = NULL, *fields = NULL, *list = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || folder == NULL || new_name == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Make sure folder does not already exist!? */
+- if (nm_find_folder(user, new_name))
+- return NMERR_FOLDER_EXISTS;
+-
+- /* Create field list for current folder */
+- field = nm_folder_to_fields(folder);
+- if (field) {
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_FOLDER, 0, NMFIELD_METHOD_DELETE, 0,
+- field, NMFIELD_TYPE_ARRAY);
+- field = NULL;
+-
+- /* Update the folders display name locally */
+- nm_folder_set_name(folder, new_name);
+-
+- /* Create field list for updated folder */
+- field = nm_folder_to_fields(folder);
+- if (field) {
+- fields = nm_field_add_pointer(fields, NM_A_FA_FOLDER, 0, NMFIELD_METHOD_ADD, 0,
+- field, NMFIELD_TYPE_ARRAY);
+- field = NULL;
+-
+- /* Package it up */
+- list = nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID,
+- 0, fields, NMFIELD_TYPE_ARRAY);
+- fields = NULL;
+-
+- rc = nm_send_request(user->conn, "updateitem", list, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, folder);
+- }
+- }
+-
+- if (req)
+- nm_release_request(req);
+-
+- if (list)
+- nm_free_fields(&list);
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_move_contact(NMUser * user, NMContact * contact, NMFolder * folder,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *field = NULL, *fields = NULL, *list = NULL;
+- NMRequest *req = NULL;
+-
+- if (user == NULL || contact == NULL || folder == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Create field list for the contact */
+- field = nm_contact_to_fields(contact);
+- if (field) {
+-
+- fields = nm_field_add_pointer(fields, NM_A_FA_CONTACT, 0, NMFIELD_METHOD_DELETE, 0,
+- field, NMFIELD_TYPE_ARRAY);
+- field = NULL;
+-
+- /* Wrap the contact up and add it to the request field list */
+- list = nm_field_add_pointer(list, NM_A_FA_CONTACT_LIST, 0, NMFIELD_METHOD_VALID, 0,
+- fields, NMFIELD_TYPE_ARRAY);
+- fields = NULL;
+-
+- /* Add sequence number */
+- list = nm_field_add_pointer(list, NM_A_SZ_SEQUENCE_NUMBER, 0, NMFIELD_METHOD_VALID,
+- 0, g_strdup("-1"), NMFIELD_TYPE_UTF8);
+-
+- /* Add parent ID */
+- list = nm_field_add_pointer(list, NM_A_SZ_PARENT_ID, 0, NMFIELD_METHOD_VALID, 0,
+- g_strdup_printf("%d", nm_folder_get_id(folder)),
+- NMFIELD_TYPE_UTF8);
+-
+- /* Dispatch the request */
+- rc = nm_send_request(user->conn, "movecontact", list, callback, data, &req);
+- if (rc == NM_OK && req)
+- nm_request_set_data(req, contact);
+-
+- }
+-
+- if (req)
+- nm_release_request(req);
+-
+- if (list)
+- nm_free_fields(&list);
+-
+- return rc;
+-}
+-
+-
+-NMERR_T
+-nm_send_create_privacy_item(NMUser *user, const char *who, gboolean allow_list,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- const char *tag;
+-
+- if (user == NULL || who == NULL)
+- return NMERR_BAD_PARM;
+-
+- if (allow_list)
+- tag = NM_A_SZ_BLOCKING_ALLOW_ITEM;
+- else
+- tag = NM_A_SZ_BLOCKING_DENY_ITEM;
+-
+- fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_ADD, 0,
+- g_strdup(who), NMFIELD_TYPE_UTF8);
+-
+- rc = nm_send_request(user->conn, "createblock", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_remove_privacy_item(NMUser *user, const char *dn, gboolean allow_list,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- const char *tag;
+- GSList **list_ptr, *node;
+-
+- if (user == NULL || dn == NULL)
+- return NMERR_BAD_PARM;
+-
+- if (allow_list) {
+- tag = NM_A_BLOCKING_ALLOW_LIST;
+- list_ptr = &user->allow_list;
+- } else {
+- tag = NM_A_BLOCKING_DENY_LIST;
+- list_ptr = &user->deny_list;
+- }
+-
+- /* Remove item from the cached list */
+- if ((node = g_slist_find_custom(*list_ptr, dn, (GCompareFunc)purple_utf8_strcasecmp))) {
+- *list_ptr = g_slist_remove_link(*list_ptr, node);
+- g_slist_free_1(node);
+- }
+-
+- fields = nm_field_add_pointer(fields, tag, 0, NMFIELD_METHOD_DELETE, 0,
+- g_strdup(dn), NMFIELD_TYPE_DN);
+-
+- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-
+-}
+-
+-NMERR_T
+-nm_send_set_privacy_default(NMUser *user, gboolean default_deny,
+- nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+-
+- if (user == NULL)
+- return NMERR_BAD_PARM;
+-
+- fields = nm_field_add_pointer(fields, NM_A_BLOCKING, 0, NMFIELD_METHOD_UPDATE, 0,
+- (default_deny ? g_strdup("1") : g_strdup("0")),
+- NMFIELD_TYPE_UTF8);
+-
+- rc = nm_send_request(user->conn, "updateblocks", fields, callback, data, NULL);
+-
+- nm_free_fields(&fields);
+- return rc;
+-}
+-
+-NMERR_T
+-nm_send_keepalive(NMUser *user, nm_response_cb callback, gpointer data)
+-{
+- NMERR_T rc = NM_OK;
+-
+- if (user == NULL)
+- return NMERR_BAD_PARM;
+-
+- rc = nm_send_request(user->conn, "ping", NULL, callback, data, NULL);
+-
+- return rc;
+-}
+-
+-NMERR_T
+-nm_process_new_data(NMUser * user)
+-{
+- NMConn *conn;
+- NMERR_T rc = NM_OK;
+- guint32 val;
+-
+- if (user == NULL)
+- return NMERR_BAD_PARM;
+-
+- conn = user->conn;
+-
+- /* Check to see if this is an event or a response */
+- rc = nm_read_all(conn, (char *) &val, sizeof(val));
+- if (rc == NM_OK) {
+- if (strncmp((char *) &val, "HTTP", strlen("HTTP")) == 0)
+- rc = nm_process_response(user);
+- else
+- rc = nm_process_event(user, GUINT32_FROM_LE(val));
+-
+- } else {
+- if (errno == EAGAIN)
+- rc = NM_OK;
+- else
+- rc = NMERR_PROTOCOL;
+- }
+-
+- return rc;
+-}
+-
+-NMConference *
+-nm_find_conversation(NMUser * user, const char *who)
+-{
+- NMConference *conference = NULL;
+- NMConference *tmp;
+- GSList *cnode;
+-
+- if (user && user->conferences) {
+- for (cnode = user->conferences; cnode; cnode = cnode->next) {
+- tmp = cnode->data;
+- if (nm_conference_get_participant_count(tmp) == 1) {
+- NMUserRecord *ur = nm_conference_get_participant(tmp, 0);
+-
+- if (ur) {
+- if (nm_utf8_str_equal(nm_user_record_get_dn(ur), who)) {
+- conference = tmp;
+- break;
+- }
+- }
+- }
+- }
+- }
+-
+- return conference;
+-}
+-
+-void
+-nm_conference_list_add(NMUser * user, NMConference * conf)
+-{
+- if (user == NULL || conf == NULL)
+- return;
+-
+- nm_conference_add_ref(conf);
+- user->conferences = g_slist_append(user->conferences, conf);
+-}
+-
+-void
+-nm_conference_list_remove(NMUser * user, NMConference * conf)
+-{
+- if (user == NULL || conf == NULL)
+- return;
+-
+- if (g_slist_find(user->conferences, conf)) {
+- user->conferences = g_slist_remove(user->conferences, conf);
+- nm_release_conference(conf);
+- }
+-}
+-
+-void
+-nm_conference_list_free(NMUser * user)
+-{
+- GSList *cnode;
+- NMConference *conference;
+-
+- if (user == NULL)
+- return;
+-
+- if (user->conferences) {
+- for (cnode = user->conferences; cnode; cnode = cnode->next) {
+- conference = cnode->data;
+- cnode->data = NULL;
+- nm_release_conference(conference);
+- }
+-
+- g_slist_free(user->conferences);
+- user->conferences = NULL;
+- }
+-}
+-
+-NMConference *
+-nm_conference_list_find(NMUser * user, const char *guid)
+-{
+- GSList *cnode;
+- NMConference *conference = NULL, *tmp;
+-
+- if (user == NULL || guid == NULL)
+- return NULL;
+-
+- if (user->conferences) {
+- for (cnode = user->conferences; cnode; cnode = cnode->next) {
+- tmp = cnode->data;
+- if (nm_are_guids_equal(nm_conference_get_guid(tmp), guid)) {
+- conference = tmp;
+- break;
+- }
+- }
+- }
+-
+- return conference;
+-}
+-
+-gboolean
+-nm_are_guids_equal(const char *guid1, const char *guid2)
+-{
+- if (guid1 == NULL || guid2 == NULL)
+- return FALSE;
+-
+- return (strncmp(guid1, guid2, CONF_GUID_END) == 0);
+-}
+-
+-void
+-nm_user_add_contact(NMUser * user, NMContact * contact)
+-{
+- if (user == NULL || contact == NULL)
+- return;
+-
+- nm_contact_add_ref(contact);
+-
+- g_hash_table_insert(user->contacts,
+- g_utf8_strdown(nm_contact_get_dn(contact), -1), contact);
+-}
+-
+-void
+-nm_user_add_user_record(NMUser * user, NMUserRecord * user_record)
+-{
+- const char *display_id;
+- const char *dn;
+-
+- if (!user || !user_record)
+- return;
+-
+- display_id = nm_user_record_get_display_id(user_record);
+- dn = nm_user_record_get_dn(user_record);
+-
+- if (!dn || !display_id)
+- return;
+-
+- nm_user_record_add_ref(user_record);
+-
+- g_hash_table_insert(user->user_records,
+- g_utf8_strdown(dn, -1),
+- user_record);
+-
+- g_hash_table_insert(user->display_id_to_dn,
+- g_utf8_strdown(display_id, -1),
+- g_utf8_strdown(dn, -1));
+-}
+-
+-nm_event_cb
+-nm_user_get_event_callback(NMUser * user)
+-{
+- if (user == NULL)
+- return NULL;
+-
+- return user->evt_callback;
+-}
+-
+-NMConn *
+-nm_user_get_conn(NMUser * user)
+-{
+- if (user == NULL)
+- return NULL;
+-
+- return user->conn;
+-}
+-
+-NMERR_T
+-nm_create_contact_list(NMUser * user)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *locate = NULL;
+-
+- if (user == NULL || user->fields == NULL) {
+- return NMERR_BAD_PARM;
+- }
+-
+- /* Create the root folder */
+- user->root_folder = nm_create_folder("");
+-
+- /* Find the contact list in the login fields */
+- locate = nm_locate_field(NM_A_FA_CONTACT_LIST, user->fields);
+- if (locate != NULL) {
+-
+- /* Add the folders and then the contacts */
+- nm_folder_add_contacts_and_folders(user, user->root_folder,
+- (NMField *) (locate->ptr_value));
+-
+- }
+-
+- return rc;
+-}
+-
+-gboolean nm_user_is_privacy_locked(NMUser *user)
+-{
+- if (user) {
+- return user->privacy_locked;
+- }
+-
+- return FALSE;
+-}
+-
+-static gboolean
+-_create_privacy_list(NMUser * user, NMRequest *request)
+-{
+- NMField *locate = NULL;
+- GSList *need_details = NULL;
+-
+- /* Are the privacy settings locked */
+- locate = nm_locate_field(NM_A_LOCKED_ATTR_LIST, user->fields);
+- if (locate && locate->ptr_value) {
+- if (locate->type == NMFIELD_TYPE_UTF8 &&
+- (purple_utf8_strcasecmp(locate->ptr_value, NM_A_BLOCKING) == 0)) {
+- user->privacy_locked = TRUE;
+- } else if (locate->type == NMFIELD_TYPE_MV ||
+- locate->type == NMFIELD_TYPE_ARRAY) {
+- NMField *tmp = (NMField *)locate->ptr_value;
+- while (tmp && tmp->tag) {
+- if (purple_utf8_strcasecmp(tmp->ptr_value, NM_A_BLOCKING) == 0) {
+- user->privacy_locked = TRUE;
+- break;
+- }
+- tmp++;
+- }
+- }
+- }
+-
+- /* Set default deny flag */
+- locate = nm_locate_field(NM_A_BLOCKING, user->fields);
+- if (locate && locate->ptr_value) {
+- user->default_deny = atoi((char *)locate->ptr_value);
+- }
+-
+- /* Read internal blocking allow list */
+- locate = nm_locate_field(NM_A_BLOCKING_ALLOW_LIST, user->fields);
+- if (locate && locate->ptr_value) {
+-
+- if (locate->type == NMFIELD_TYPE_MV) {
+- locate = (NMField *)locate->ptr_value;
+- for (; locate->tag != NULL; locate++) {
+- if (locate->ptr_value) {
+-
+- user->allow_list = g_slist_append(user->allow_list, (char *)locate->ptr_value);
+-
+- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
+- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
+-
+- }
+- }
+- } else {
+-
+- user->allow_list = g_slist_append(user->allow_list, (char *)locate->ptr_value);
+-
+- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
+- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
+-
+- }
+- }
+-
+- /* Read internal blocking deny list */
+- locate = nm_locate_field(NM_A_BLOCKING_DENY_LIST, user->fields);
+- if (locate && locate->ptr_value) {
+-
+- if (locate->type == NMFIELD_TYPE_MV) {
+- locate = (NMField *)locate->ptr_value;
+- for (; locate->tag != NULL; locate++) {
+- if (locate->ptr_value) {
+-
+- user->deny_list = g_slist_append(user->deny_list, (char *)locate->ptr_value);
+-
+- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
+- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
+-
+- }
+- }
+- } else {
+-
+- user->deny_list = g_slist_append(user->deny_list, (char *)locate->ptr_value);
+-
+- if (nm_find_user_record(user, (char *)locate->ptr_value) == NULL)
+- need_details = g_slist_append(need_details, (char *)locate->ptr_value);
+-
+- }
+- }
+-
+- if (need_details) {
+-
+- nm_request_add_ref(request);
+- nm_send_multiple_get_details(user, need_details,
+- _handle_multiple_get_details_login_cb, request);
+-
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-void
+-nm_destroy_contact_list(NMUser * user)
+-{
+- if (user == NULL)
+- return;
+-
+- if (user->root_folder) {
+- nm_release_folder(user->root_folder);
+- user->root_folder = NULL;
+- }
+-}
+-
+-NMFolder *
+-nm_get_root_folder(NMUser * user)
+-{
+- if (user == NULL)
+- return NULL;
+-
+- if (user->root_folder == NULL)
+- nm_create_contact_list(user);
+-
+- return user->root_folder;
+-}
+-
+-NMContact *
+-nm_find_contact(NMUser * user, const char *name)
+-{
+- char *str;
+- const char *dn = NULL;
+- NMContact *contact = NULL;
+-
+- if (user == NULL || name == NULL)
+- return NULL;
+-
+- str = g_utf8_strdown(name, -1);
+- if (strstr(str, "=")) {
+- dn = str;
+- } else {
+- /* Assume that we have a display id instead of a dn */
+- dn = (const char *) g_hash_table_lookup(user->display_id_to_dn, str);
+- }
+-
+- /* Find contact object in reference table */
+- if (dn) {
+- contact = (NMContact *) g_hash_table_lookup(user->contacts, dn);
+- }
+-
+- g_free(str);
+- return contact;
+-}
+-
+-GList *
+-nm_find_contacts(NMUser * user, const char *dn)
+-{
+- guint32 i, cnt;
+- NMFolder *folder;
+- NMContact *contact;
+- GList *contacts = NULL;
+-
+- if (user == NULL || dn == NULL)
+- return NULL;
+-
+- /* Check for contact at the root */
+- contact = nm_folder_find_contact(user->root_folder, dn);
+- if (contact) {
+- contacts = g_list_append(contacts, contact);
+- contact = NULL;
+- }
+-
+- /* Check for contact in each subfolder */
+- cnt = nm_folder_get_subfolder_count(user->root_folder);
+- for (i = 0; i < cnt; i++) {
+- folder = nm_folder_get_subfolder(user->root_folder, i);
+- contact = nm_folder_find_contact(folder, dn);
+- if (contact) {
+- contacts = g_list_append(contacts, contact);
+- contact = NULL;
+- }
+- }
+-
+- return contacts;
+-}
+-
+-NMUserRecord *
+-nm_find_user_record(NMUser * user, const char *name)
+-{
+- char *str = NULL;
+- const char *dn = NULL;
+- NMUserRecord *user_record = NULL;
+-
+- if (user == NULL || name == NULL)
+- return NULL;
+-
+- str = g_utf8_strdown(name, -1);
+- if (strstr(str, "=")) {
+- dn = str;
+- } else {
+- /* Assume that we have a display id instead of a dn */
+- dn = (const char *) g_hash_table_lookup(user->display_id_to_dn, str);
+- }
+-
+- /* Find user record in reference table */
+- if (dn) {
+- user_record =
+- (NMUserRecord *) g_hash_table_lookup(user->user_records, dn);
+- }
+-
+- g_free(str);
+- return user_record;
+-}
+-
+-const char *
+-nm_lookup_dn(NMUser * user, const char *display_id)
+-{
+- const char *dn;
+- char *lower;
+-
+- if (user == NULL || display_id == NULL)
+- return NULL;
+-
+- lower = g_utf8_strdown(display_id, -1);
+- dn = g_hash_table_lookup(user->display_id_to_dn, lower);
+- g_free(lower);
+-
+- return dn;
+-}
+-
+-NMFolder *
+-nm_find_folder(NMUser * user, const char *name)
+-{
+- NMFolder *folder = NULL, *temp;
+- int i, num_folders;
+- const char *tname = NULL;
+-
+- if (user == NULL || name == NULL)
+- return NULL;
+-
+- if (*name == '\0')
+- return user->root_folder;
+-
+- num_folders = nm_folder_get_subfolder_count(user->root_folder);
+- for (i = 0; i < num_folders; i++) {
+- temp = nm_folder_get_subfolder(user->root_folder, i);
+- tname = nm_folder_get_name(temp);
+- if (tname && (strcmp(tname, name) == 0)) {
+- folder = temp;
+- break;
+- }
+- }
+-
+- return folder;
+-}
+-
+-NMFolder *
+-nm_find_folder_by_id(NMUser * user, int object_id)
+-{
+- NMFolder *folder = NULL, *temp;
+- int i, num_folders;
+-
+- if (user == NULL)
+- return NULL;
+-
+- if (object_id == 0)
+- return user->root_folder;
+-
+- num_folders = nm_folder_get_subfolder_count(user->root_folder);
+- for (i = 0; i < num_folders; i++) {
+- temp = nm_folder_get_subfolder(user->root_folder, i);
+- if (nm_folder_get_id(temp) == object_id) {
+- folder = temp;
+- break;
+- }
+- }
+-
+- return folder;
+-}
+-
+-static void
+-_handle_multiple_get_details_login_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- nm_response_cb cb;
+- NMRequest *request = user_data;
+-
+- if (user == NULL || request == NULL)
+- return;
+-
+- if ((cb = nm_request_get_callback(request))) {
+- cb(user, ret_code, nm_request_get_data(request),
+- nm_request_get_user_define(request));
+- nm_release_request(request);
+- }
+-}
+-
+-static void
+-_handle_multiple_get_details_joinconf_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMRequest *request = user_data;
+- NMUserRecord *user_record = resp_data;
+- NMConference *conference;
+- GSList *list, *node;
+-
+- if (user == NULL || resp_data == NULL || user_data == NULL)
+- return;
+-
+- conference = nm_request_get_data(request);
+- list = nm_request_get_user_define(request);
+-
+- if (ret_code == 0 && conference && list) {
+-
+- /* Add the user to the conference */
+- nm_conference_add_participant(conference, user_record);
+-
+- /* Find the user in the list and remove it */
+- for (node = list; node; node = node->next) {
+- if (nm_utf8_str_equal(nm_user_record_get_dn(user_record),
+- (const char *) node->data)) {
+- g_free(node->data);
+- list = g_slist_remove(list, node->data);
+- nm_request_set_user_define(request, list);
+- break;
+- }
+- }
+-
+- /* Time to callback? */
+- if (list == NULL) {
+- nm_response_cb cb = nm_request_get_callback(request);
+-
+- if (cb) {
+- cb(user, 0, conference, conference);
+- }
+- nm_release_request(request);
+- }
+- }
+-}
+-
+-static NMERR_T
+-nm_call_handler(NMUser * user, NMRequest * request, NMField * fields)
+-{
+- NMERR_T rc = NM_OK, ret_code = NM_OK;
+- NMConference *conf = NULL;
+- NMUserRecord *user_record = NULL;
+- NMField *locate = NULL;
+- NMField *field = NULL;
+- const char *cmd;
+- nm_response_cb cb;
+- gboolean done = TRUE;
+-
+- if (user == NULL || request == NULL || fields == NULL)
+- return NMERR_BAD_PARM;
+-
+- /* Get the return code */
+- field = nm_locate_field(NM_A_SZ_RESULT_CODE, fields);
+- if (field) {
+- ret_code = atoi((char *) field->ptr_value);
+- } else {
+- ret_code = NMERR_PROTOCOL;
+- }
+-
+- cmd = nm_request_get_cmd(request);
+- if (ret_code == NM_OK && cmd != NULL) {
+-
+- if (strcmp("login", cmd) == 0) {
+-
+- user->user_record = nm_create_user_record_from_fields(fields);
+-
+- /* Save the users fields */
+- user->fields = nm_copy_field_array(fields);
+-
+- nm_create_contact_list(user);
+- done = _create_privacy_list(user, request);
+-
+- } else if (strcmp("setstatus", cmd) == 0) {
+-
+- /* Nothing to do */
+-
+- } else if (strcmp("createconf", cmd) == 0) {
+-
+- conf = (NMConference *) nm_request_get_data(request);
+-
+- /* get the convo guid */
+- locate = nm_locate_field(NM_A_FA_CONVERSATION, fields);
+- if (locate) {
+- field =
+- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value);
+- if (field) {
+- nm_conference_set_guid(conf, (char *) field->ptr_value);
+- }
+- }
+-
+- nm_conference_list_add(user, conf);
+- nm_release_conference(conf);
+-
+- } else if (strcmp("leaveconf", cmd) == 0) {
+-
+- conf = (NMConference *) nm_request_get_data(request);
+- nm_conference_list_remove(user, conf);
+-
+- } else if (strcmp("joinconf", cmd) == 0) {
+- GSList *list = NULL, *node;
+-
+- conf = nm_request_get_data(request);
+-
+- locate = nm_locate_field(NM_A_FA_CONTACT_LIST, fields);
+- if (locate && locate->ptr_value != 0) {
+-
+- field = (NMField *) locate->ptr_value;
+- while ((field = nm_locate_field(NM_A_SZ_DN, field))) {
+- if (field && field->ptr_value != 0) {
+-
+- if (nm_utf8_str_equal
+- (nm_user_record_get_dn(user->user_record),
+- (const char *) field->ptr_value)) {
+- field++;
+- continue;
+- }
+-
+- user_record =
+- nm_find_user_record(user,
+- (const char *) field->ptr_value);
+- if (user_record == NULL) {
+- list =
+- g_slist_append(list,
+- g_strdup((char *) field->ptr_value));
+- } else {
+- nm_conference_add_participant(conf, user_record);
+- }
+- }
+- field++;
+- }
+-
+- if (list != NULL) {
+-
+- done = FALSE;
+- nm_request_set_user_define(request, list);
+- nm_request_add_ref(request);
+- for (node = list; node; node = node->next) {
+-
+- nm_send_get_details(user, (const char *) node->data,
+- _handle_multiple_get_details_joinconf_cb,
+- request);
+- }
+- }
+- }
+-
+- } else if (strcmp("getdetails", cmd) == 0) {
+-
+- locate = nm_locate_field(NM_A_FA_RESULTS, fields);
+- while (locate && locate->ptr_value != 0) {
+-
+- user_record = nm_create_user_record_from_fields(locate);
+- if (user_record) {
+- NMUserRecord *tmp;
+-
+- tmp =
+- nm_find_user_record(user,
+- nm_user_record_get_dn(user_record));
+- if (tmp) {
+-
+- /* Update the existing user record */
+- nm_user_record_copy(tmp, user_record);
+- nm_release_user_record(user_record);
+- user_record = tmp;
+-
+- } else {
+- nm_user_add_user_record(user, user_record);
+- nm_release_user_record(user_record);
+- }
+-
+- /* Response data is new user record */
+- nm_request_set_data(request, (gpointer) user_record);
+- }
+-
+- locate = nm_locate_field(NM_A_FA_RESULTS, locate+1);
+- }
+-
+- } else if (strcmp("createfolder", cmd) == 0) {
+-
+- _update_contact_list(user, fields);
+-
+- } else if (strcmp("createcontact", cmd) == 0) {
+-
+- _update_contact_list(user, fields);
+-
+- locate =
+- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) fields->ptr_value);
+- if (locate) {
+-
+- NMContact *new_contact =
+- nm_folder_find_item_by_object_id(user->root_folder,
+- atoi((char *)locate->ptr_value));
+-
+- if (new_contact) {
+-
+- /* Add the contact to our cache */
+- nm_user_add_contact(user, new_contact);
+-
+- /* Set the contact as the response data */
+- nm_request_set_data(request, (gpointer) new_contact);
+-
+- }
+-
+- }
+-
+- } else if (strcmp("deletecontact", cmd) == 0) {
+-
+- _update_contact_list(user, fields);
+-
+- } else if (strcmp("movecontact", cmd) == 0) {
+-
+- _update_contact_list(user, fields);
+-
+- } else if (strcmp("getstatus", cmd) == 0) {
+-
+- locate = nm_locate_field(NM_A_SZ_STATUS, fields);
+- if (locate) {
+- nm_user_record_set_status((NMUserRecord *)
+- nm_request_get_data(request),
+- atoi((char *) locate->ptr_value), NULL);
+- }
+-
+- } else if (strcmp("updateitem", cmd) == 0) {
+-
+- /* Nothing extra to do here */
+-
+- } else if (strcmp("createblock", cmd) == 0) {
+- if ((locate = nm_locate_field(NM_A_BLOCKING_DENY_LIST, fields))) {
+- if (locate->ptr_value) {
+- user->deny_list = g_slist_append(user->deny_list, g_strdup((char *)locate->ptr_value));
+- }
+- } else if ((locate = nm_locate_field(NM_A_BLOCKING_ALLOW_LIST, fields))) {
+- if (locate->ptr_value) {
+- user->allow_list = g_slist_append(user->allow_list, g_strdup((char *)locate->ptr_value));
+- }
+- }
+- } else if (strcmp("updateblocks", cmd) == 0) {
+- /* nothing to do here */
+- } else {
+-
+- /* Nothing to do, just print debug message */
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "nm_call_handler(): Unknown request command, %s\n", cmd);
+-
+- }
+- }
+-
+- if (done && (cb = nm_request_get_callback(request))) {
+-
+- cb(user, ret_code, nm_request_get_data(request),
+- nm_request_get_user_define(request));
+- }
+-
+- return rc;
+-}
+-
+-static NMERR_T
+-nm_process_response(NMUser * user)
+-{
+- NMERR_T rc = NM_OK;
+- NMField *fields = NULL;
+- NMField *field = NULL;
+- NMConn *conn = user->conn;
+- NMRequest *req = NULL;
+-
+- rc = nm_read_header(conn);
+- if (rc == NM_OK) {
+- rc = nm_read_fields(conn, -1, &fields);
+- }
+-
+- if (rc == NM_OK) {
+- field = nm_locate_field(NM_A_SZ_TRANSACTION_ID, fields);
+- if (field != NULL && field->ptr_value != 0) {
+- req = nm_conn_find_request(conn, atoi((char *) field->ptr_value));
+- if (req != NULL) {
+- rc = nm_call_handler(user, req, fields);
+- nm_conn_remove_request_item(conn, req);
+- }
+-
+- }
+- }
+-
+- if (fields)
+- nm_free_fields(&fields);
+-
+- return rc;
+-}
+-
+-/*
+- * Some utility functions...haven't figured out where
+- * they belong yet.
+- */
+-
+-gboolean
+-nm_utf8_str_equal(gconstpointer str1, gconstpointer str2)
+-{
+- return (purple_utf8_strcasecmp(str1, str2) == 0);
+-}
+-
+-char *
+-nm_typed_to_dotted(const char *typed)
+-{
+- unsigned i = 0, j = 0;
+- char *dotted;
+-
+- if (typed == NULL)
+- return NULL;
+-
+- dotted = g_new0(char, strlen(typed));
+-
+- do {
+-
+- /* replace comma with a dot */
+- if (j != 0) {
+- dotted[j] = '.';
+- j++;
+- }
+-
+- /* skip the type */
+- while (typed[i] != '\0' && typed[i] != '=')
+- i++;
+-
+- /* verify that we aren't running off the end */
+- if (typed[i] == '\0') {
+- dotted[j] = '\0';
+- break;
+- }
+-
+- i++;
+-
+- /* copy the object name to context */
+- while (typed[i] != '\0' && typed[i] != ',') {
+- dotted[j] = typed[i];
+- j++;
+- i++;
+- }
+-
+- } while (typed[i] != '\0');
+-
+- return dotted;
+-}
+-
+-const char *
+-nm_error_to_string(NMERR_T err)
+-{
+- static char *unknown_msg = NULL;
+-
+- g_free(unknown_msg);
+- unknown_msg = NULL;
+-
+- switch (err) {
+-
+- case NMERR_BAD_PARM:
+- return _("Required parameters not passed in");
+-
+- case NMERR_TCP_WRITE:
+- return _("Unable to write to network");
+-
+- case NMERR_TCP_READ:
+- return _("Unable to read from network");
+-
+- case NMERR_PROTOCOL:
+- return _("Error communicating with server");
+-
+- case NMERR_CONFERENCE_NOT_FOUND:
+- case NMERR_CONFERENCE_NOT_FOUND_2:
+- return _("Conference not found");
+-
+- case NMERR_CONFERENCE_NOT_INSTANTIATED:
+- return _("Conference does not exist");
+-
+- case NMERR_DUPLICATE_FOLDER:
+- case NMERR_FOLDER_EXISTS:
+- return _("A folder with that name already exists");
+-
+- case NMERR_NOT_SUPPORTED:
+- return _("Not supported");
+-
+- case NMERR_PASSWORD_EXPIRED:
+- case NMERR_PASSWORD_EXPIRED_2:
+- return _("Password has expired");
+-
+- case NMERR_PASSWORD_INVALID:
+- return _("Incorrect password");
+-
+- case NMERR_USER_NOT_FOUND:
+- return _("User not found");
+-
+- case NMERR_USER_DISABLED:
+- return _("Account has been disabled");
+-
+- case NMERR_DIRECTORY_FAILURE:
+- return _("The server could not access the directory");
+-
+- case NMERR_ADMIN_LOCKED:
+- return _("Your system administrator has disabled this operation");
+-
+- case NMERR_SERVER_BUSY:
+- return _("The server is unavailable; try again later");
+-
+- case NMERR_DUPLICATE_CONTACT:
+- return _("Cannot add a contact to the same folder twice");
+-
+- case NMERR_USER_NOT_ALLOWED:
+- return _("Cannot add yourself");
+-
+- case NMERR_MASTER_ARCHIVE_MISSING:
+- return _("Master archive is misconfigured");
+-
+- case NMERR_AUTHENTICATION_FAILED:
+- case NMERR_CREDENTIALS_MISSING:
+- return _("Incorrect username or password");
+-
+- case NMERR_HOST_NOT_FOUND:
+- return _("Could not recognize the host of the username you entered");
+-
+- case NMERR_ACCESS_DENIED:
+- return _("Your account has been disabled because too many incorrect passwords were entered");
+-
+- case NMERR_DUPLICATE_PARTICIPANT:
+- return _("You cannot add the same person twice to a conversation");
+-
+- case NMERR_TOO_MANY_CONTACTS:
+- case NMERR_TOO_MANY_FOLDERS:
+- return _("You have reached your limit for the number of contacts allowed");
+-
+- case NMERR_OBJECT_NOT_FOUND:
+- return _("You have entered an incorrect username");
+-
+- case NMERR_DIRECTORY_UPDATE:
+- return _("An error occurred while updating the directory");
+-
+- case NMERR_SERVER_PROTOCOL:
+- return _("Incompatible protocol version");
+-
+- case NMERR_USER_BLOCKED:
+- return _("The user has blocked you");
+-
+- case NMERR_EVAL_CONNECTION_LIMIT:
+- return _("This evaluation version does not allow more than ten users to log in at one time");
+-
+- case NMERR_CONVERSATION_INVITE:
+- return _("The user is either offline or you are blocked");
+-
+- default:
+- unknown_msg = g_strdup_printf (_("Unknown error: 0x%X"), err);
+-
+- return unknown_msg;
+- }
+-}
+-
+-static void
+-_update_contact_list(NMUser * user, NMField * fields)
+-{
+- NMField *list, *cursor, *locate;
+- gint objid1;
+- NMContact *contact;
+- NMFolder *folder;
+- gpointer item;
+-
+- if (user == NULL || fields == NULL)
+- return;
+-
+- /* Is it wrapped in a RESULTS array? */
+- if (strcmp(fields->tag, NM_A_FA_RESULTS) == 0) {
+- list = (NMField *) fields->ptr_value;
+- } else {
+- list = fields;
+- }
+-
+- /* Update the cached contact list */
+- cursor = (NMField *) list->ptr_value;
+- while (cursor->tag != NULL) {
+- if ((g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) ||
+- (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER) == 0)) {
+-
+- locate =
+- nm_locate_field(NM_A_SZ_OBJECT_ID, (NMField *) cursor->ptr_value);
+- if (locate != NULL && locate->ptr_value != 0) {
+- objid1 = atoi((char *) locate->ptr_value);
+- item =
+- nm_folder_find_item_by_object_id(user->root_folder, objid1);
+- if (item != NULL) {
+- if (cursor->method == NMFIELD_METHOD_ADD) {
+- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
+- contact = (NMContact *) item;
+- nm_contact_update_list_properties(contact, cursor);
+- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
+- == 0) {
+- folder = (NMFolder *) item;
+- nm_folder_update_list_properties(folder, cursor);
+- }
+- } else if (cursor->method == NMFIELD_METHOD_DELETE) {
+- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
+- contact = (NMContact *) item;
+- folder =
+- nm_find_folder_by_id(user,
+- nm_contact_get_parent_id
+- (contact));
+- if (folder) {
+- nm_folder_remove_contact(folder, contact);
+- }
+- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
+- == 0) {
+- /* TODO: write nm_folder_remove_folder */
+- /* ignoring for now, should not be a big deal */
+-/* folder = (NMFolder *) item;*/
+-/* nm_folder_remove_folder(user->root_folder, folder);*/
+- }
+- }
+- } else {
+-
+- if (cursor->method == NMFIELD_METHOD_ADD) {
+-
+- /* Not found, so we need to add it */
+- if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_CONTACT) == 0) {
+-
+- const char *dn = NULL;
+-
+- locate =
+- nm_locate_field(NM_A_SZ_DN,
+- (NMField *) cursor->ptr_value);
+- if (locate != NULL && locate->ptr_value != 0) {
+- dn = (const char *) locate->ptr_value;
+- if (dn != NULL) {
+- contact =
+- nm_create_contact_from_fields(cursor);
+- if (contact) {
+- nm_folder_add_contact_to_list(user->
+- root_folder,
+- contact);
+- nm_release_contact(contact);
+- }
+- }
+- }
+- } else if (g_ascii_strcasecmp(cursor->tag, NM_A_FA_FOLDER)
+- == 0) {
+- folder = nm_create_folder_from_fields(cursor);
+- nm_folder_add_folder_to_list(user->root_folder,
+- folder);
+- nm_release_folder(folder);
+- }
+- }
+- }
+- }
+- }
+- cursor++;
+- }
+-}
+-
+-static char *
+-nm_rtfize_text(char *text)
+-{
+- GString *gstr = NULL;
+- unsigned char *pch;
+- char *uni_str = NULL, *rtf = NULL;
+- int bytes;
+- gunichar uc;
+-
+- gstr = g_string_sized_new(strlen(text)*2);
+- pch = (unsigned char *)text;
+- while (*pch) {
+- if ((*pch) <= 0x7F) {
+- switch (*pch) {
+- case '{':
+- case '}':
+- case '\\':
+- gstr = g_string_append_c(gstr, '\\');
+- gstr = g_string_append_c(gstr, *pch);
+- break;
+- case '\n':
+- gstr = g_string_append(gstr, "\\par ");
+- break;
+- default:
+- gstr = g_string_append_c(gstr, *pch);
+- break;
+- }
+- pch++;
+- } else {
+- /* convert the utf-8 character to ucs-4 for rtf encoding */
+- if(*pch <= 0xDF) {
+- uc = ((((gunichar)pch[0]) & 0x001F) << 6) |
+- (((gunichar)pch[1]) & 0x003F);
+- bytes = 2;
+- } else if(*pch <= 0xEF) {
+- uc = ((((gunichar)pch[0]) & 0x000F) << 12) |
+- ((((gunichar)pch[1]) & 0x003F) << 6) |
+- (((gunichar)pch[2]) & 0x003F);
+- bytes = 3;
+- } else if (*pch <= 0xF7) {
+- uc = ((((gunichar)pch[0]) & 0x0007) << 18) |
+- ((((gunichar)pch[1]) & 0x003F) << 12) |
+- ((((gunichar)pch[2]) & 0x003F) << 6) |
+- (((gunichar)pch[3]) & 0x003F);
+- bytes = 4;
+- } else if (*pch <= 0xFB) {
+- uc = ((((gunichar)pch[0]) & 0x0003) << 24) |
+- ((((gunichar)pch[1]) & 0x003F) << 18) |
+- ((((gunichar)pch[2]) & 0x003F) << 12) |
+- ((((gunichar)pch[3]) & 0x003F) << 6) |
+- (((gunichar)pch[4]) & 0x003F);
+- bytes = 5;
+- } else if (*pch <= 0xFD) {
+- uc = ((((gunichar)pch[0]) & 0x0001) << 30) |
+- ((((gunichar)pch[1]) & 0x003F) << 24) |
+- ((((gunichar)pch[2]) & 0x003F) << 18) |
+- ((((gunichar)pch[3]) & 0x003F) << 12) |
+- ((((gunichar)pch[4]) & 0x003F) << 6) |
+- (((gunichar)pch[5]) & 0x003F);
+- bytes = 6;
+- } else {
+- /* should never happen ... bogus utf-8! */
+- purple_debug_info("novell", "bogus utf-8 lead byte: 0x%X\n", pch[0]);
+- uc = 0x003F;
+- bytes = 1;
+- }
+- uni_str = g_strdup_printf("\\u%d?", uc);
+- purple_debug_info("novell", "unicode escaped char %s\n", uni_str);
+- gstr = g_string_append(gstr, uni_str);
+- pch += bytes;
+- g_free(uni_str);
+- }
+- }
+-
+- rtf = g_strdup_printf(RTF_TEMPLATE, gstr->str);
+- g_string_free(gstr, TRUE);
+- return rtf;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuser.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmuser.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuser.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,680 +0,0 @@
+-/*
+- * nmuser.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_USER_H__
+-#define __NM_USER_H__
+-
+-#include <glib.h>
+-#include <stdio.h>
+-#include <stdlib.h>
+-
+-typedef guint32 NMERR_T;
+-typedef int NMSTATUS_T;
+-
+-typedef struct _NMUser NMUser;
+-
+-typedef enum
+-{
+- NMREQUEST_TYPE_LOGIN = 0,
+- NMREQUEST_TYPE_LOGOUT,
+- NMREQUEST_TYPE_SETSTATUS,
+- NMREQUEST_TYPE_GETDETAILS,
+- NMREQUEST_TYPE_CREATECONF,
+- NMREQUEST_TYPE_SENDMESSAGE,
+- NMREQUEST_TYPE_JOINCONF,
+- NMREQUEST_TYPE_LEAVECONF,
+- NMREQUEST_TYPE_REJECTCONF,
+- NMREQUEST_TYPE_SENDTYPING,
+- NMREQUEST_TYPE_CREATECONTACT,
+- NMREQUEST_TYPE_DELETECONTACT
+-
+-} NMRequestType;
+-
+-#include "debug.h"
+-#include "nmmessage.h"
+-#include "nmconference.h"
+-#include "nmcontact.h"
+-#include "nmuserrecord.h"
+-#include "nmfield.h"
+-#include "nmevent.h"
+-
+-/* Callback typedefs */
+-typedef void (*nm_response_cb) (NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data);
+-
+-typedef void (*nm_event_cb) (NMUser * user, NMEvent * event);
+-
+-#include "nmrequest.h"
+-#include "nmconn.h"
+-
+-/* This represents user that we are currently logged in as */
+-struct _NMUser
+-{
+-
+- char *name;
+-
+- NMSTATUS_T status;
+-
+- /* A copy of the login response fields */
+- NMField *fields;
+-
+- /* The user record for this user */
+- NMUserRecord *user_record;
+-
+- /* Our connection information */
+- NMConn *conn;
+-
+- /* Our public IP address */
+- char *address;
+-
+- /* This is the contact list */
+- NMFolder *root_folder;
+-
+- /* All contacts that we know about hashed by dn */
+- GHashTable *contacts;
+-
+- /* All user records hashed by dn */
+- GHashTable *user_records;
+-
+- /* DN lookup */
+- GHashTable *display_id_to_dn;
+-
+- /* One on one conversations indexed by recipient's dn */
+- GSList *conferences;
+-
+- guint32 conference_count;
+-
+- /* Called when we receive an event */
+- nm_event_cb evt_callback;
+-
+- /* Privacy settings */
+- gboolean privacy_locked;
+- gboolean default_deny;
+- GSList *allow_list;
+- GSList *deny_list;
+-
+- /* Pending requests. If we need to go to the server to more info
+- * before processing a request we will queue it up and process when
+- * we get a response
+- */
+- GSList *pending_requests;
+-
+- /* Pending events. Same as above except for events. */
+- GSList *pending_events;
+-
+- /* Generic pointer to data needed by the client
+- * using the API
+- */
+- gpointer client_data;
+-
+- /* Have the privacy lists been synched yet */
+- gboolean privacy_synched;
+-
+- /* Has the contact list been synched */
+- gboolean clist_synched;
+-};
+-
+-#define NM_STATUS_UNKNOWN 0
+-#define NM_STATUS_OFFLINE 1
+-#define NM_STATUS_AVAILABLE 2
+-#define NM_STATUS_BUSY 3
+-#define NM_STATUS_AWAY 4
+-#define NM_STATUS_AWAY_IDLE 5
+-#define NM_STATUS_INVALID 6
+-
+-#define NMERR_BASE 0x2000L
+-#define NM_OK 0L
+-#define NMERR_BAD_PARM (NMERR_BASE + 0x0001)
+-#define NMERR_TCP_WRITE (NMERR_BASE + 0x0002)
+-#define NMERR_TCP_READ (NMERR_BASE + 0x0003)
+-#define NMERR_PROTOCOL (NMERR_BASE + 0x0004)
+-#define NMERR_SERVER_REDIRECT (NMERR_BASE + 0x0005)
+-#define NMERR_CONFERENCE_NOT_FOUND (NMERR_BASE + 0x0006)
+-#define NMERR_CONFERENCE_NOT_INSTANTIATED (NMERR_BASE + 0x0007)
+-#define NMERR_FOLDER_EXISTS (NMERR_BASE + 0x0008)
+-
+-/* Errors that are returned from the server */
+-#define NMERR_SERVER_BASE 0xD100L
+-#define NMERR_ACCESS_DENIED (NMERR_SERVER_BASE + 0x0006)
+-#define NMERR_NOT_SUPPORTED (NMERR_SERVER_BASE + 0x000A)
+-#define NMERR_PASSWORD_EXPIRED (NMERR_SERVER_BASE + 0x000B)
+-#define NMERR_PASSWORD_INVALID (NMERR_SERVER_BASE + 0x000C)
+-#define NMERR_USER_NOT_FOUND (NMERR_SERVER_BASE + 0x000D)
+-#define NMERR_USER_DISABLED (NMERR_SERVER_BASE + 0x0010)
+-#define NMERR_DIRECTORY_FAILURE (NMERR_SERVER_BASE + 0x0011)
+-#define NMERR_HOST_NOT_FOUND (NMERR_SERVER_BASE + 0x0019)
+-#define NMERR_ADMIN_LOCKED (NMERR_SERVER_BASE + 0x001C)
+-#define NMERR_DUPLICATE_PARTICIPANT (NMERR_SERVER_BASE + 0x001F)
+-#define NMERR_SERVER_BUSY (NMERR_SERVER_BASE + 0x0023)
+-#define NMERR_OBJECT_NOT_FOUND (NMERR_SERVER_BASE + 0x0024)
+-#define NMERR_DIRECTORY_UPDATE (NMERR_SERVER_BASE + 0x0025)
+-#define NMERR_DUPLICATE_FOLDER (NMERR_SERVER_BASE + 0x0026)
+-#define NMERR_DUPLICATE_CONTACT (NMERR_SERVER_BASE + 0x0027)
+-#define NMERR_USER_NOT_ALLOWED (NMERR_SERVER_BASE + 0x0028)
+-#define NMERR_TOO_MANY_CONTACTS (NMERR_SERVER_BASE + 0x0029)
+-#define NMERR_CONFERENCE_NOT_FOUND_2 (NMERR_SERVER_BASE + 0x002B)
+-#define NMERR_TOO_MANY_FOLDERS (NMERR_SERVER_BASE + 0x002C)
+-#define NMERR_SERVER_PROTOCOL (NMERR_SERVER_BASE + 0x0030)
+-#define NMERR_CONVERSATION_INVITE (NMERR_SERVER_BASE + 0x0035)
+-#define NMERR_USER_BLOCKED (NMERR_SERVER_BASE + 0x0039)
+-#define NMERR_MASTER_ARCHIVE_MISSING (NMERR_SERVER_BASE + 0x003A)
+-#define NMERR_PASSWORD_EXPIRED_2 (NMERR_SERVER_BASE + 0x0042)
+-#define NMERR_CREDENTIALS_MISSING (NMERR_SERVER_BASE + 0x0046)
+-#define NMERR_AUTHENTICATION_FAILED (NMERR_SERVER_BASE + 0x0049)
+-#define NMERR_EVAL_CONNECTION_LIMIT (NMERR_SERVER_BASE + 0x004A)
+-
+-/**
+- * Initialize the user that we are going to login to the system as.
+- *
+- * @param name The userid of the user
+- * @param server IP Address of server
+- * @param port Port to connect to on the server
+- * @param data Client data to associate with the user
+- * @param event_callback Function to call when we receive an event
+- *
+- * @return The initialized user object. Must be freed by calling
+- * nm_deinitialize_user
+- */
+-NMUser *nm_initialize_user(const char *name, const char *server, int port,
+- gpointer data, nm_event_cb event_callback);
+-
+-
+-/**
+- * Free up resources associated with the user object.
+- *
+- * @param user The user to deinitialize
+- */
+-void nm_deinitialize_user(NMUser * user);
+-
+-/**
+- * Send a login request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The User to login -- must be initialized
+- * @param pwd The password of the user
+- * @param my_addr The address of the client machine
+- * @param user_agent String describing the client (eg. "Purple/0.76 (Linux; 2.4.20)")
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- *
+- * @return NM_OK if login is sent successfully, error otherwise.
+- */
+-NMERR_T nm_send_login(NMUser * user, const char *pwd, const char *my_addr,
+- const char *user_agent, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a set status request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param dn The DN of the user (if known, or NULL if not known)
+- * @param address IP Address of server
+- * @param callback Function to call when we get the response from the server
+- *
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_set_status(NMUser * user, int status, const char *text,
+- const char *auto_resp, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a create conference to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conference Conference to create
+- * @param add_participants Add participant list on create?
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_create_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Tell server we have left the conference.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conference Conference the user is leaving
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_leave_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a join conference request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conference Conference the user is joining
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_join_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a conference reject request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conference Conference the user is rejecting
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_reject_conference(NMUser * user, NMConference * conference,
+- nm_response_cb callback, gpointer data);
+-
+-
+-/**
+- * Send a conference invitation to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conference Conference the user is rejecting
+- * @param user_record The user to invite
+- * @param message The invite message if there is one, NULL otherwise
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_conference_invite(NMUser *user, NMConference *conference, NMUserRecord *user_record,
+- const char *message, nm_response_cb callback, gpointer data);
+-
+-/**
+- * Get details for a more than one user from the server.
+- *
+- * The response data sent to the callback will be an NMUserRecord which should be
+- * freed with nm_release_user_record
+- *
+- * @param user The logged in User
+- * @param names Link list of user id's or dn's
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_multiple_get_details(NMUser * user, GSList *names,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Get details for a user from the server.
+- *
+- * The response data sent to the callback will be an NMUserRecord which should be
+- * freed with nm_release_user_record
+- *
+- * @param user The logged in User
+- * @param name Userid or DN of the user to look up
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data to be passed to the callback function
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_get_details(NMUser * user, const char *name,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a message.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param message The message to send.
+- * @param callback Function to call when we get the response from the server
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_message(NMUser * user, NMMessage * message,
+- nm_response_cb callback);
+-
+-/**
+- * Sends a typing event to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param conf The conference that corresponds to the typing event
+- * @param typing TRUE if the user is typing
+- * FALSE if the user has stopped typing
+- * @param callback Function to call when we get the response from the server
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_typing(NMUser * user, NMConference * conf,
+- gboolean typing, nm_response_cb callback);
+-
+-/**
+- * Send a create contact request to the server.
+- *
+- * The given folder should already exist on the server. If not,
+- * the call will fail.
+- *
+- * The response data sent to the callback will be a NMContact which should
+- * be released with nm_release_contact
+- *
+- * @param user The logged in User
+- * @param folder The folder that the contact should be created in
+- * @param contact The contact to add
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_create_contact(NMUser * user, NMFolder * folder,
+- NMContact * contact, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a remove contact request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param folder The folder to remove contact from
+- * @param contact The contact to remove
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_remove_contact(NMUser * user, NMFolder * folder,
+- NMContact * contact, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a create folder request to the server.
+- *
+- * The response data sent to the callback will be a NMFolder which should be
+- * released with nm_release_folder
+- *
+- * @param user The logged in User
+- * @param name The name of the folder to create
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_create_folder(NMUser * user, const char *name,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a delete folder request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param folder The name of the folder to remove
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_remove_folder(NMUser * user, NMFolder * folder,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a rename contact request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param contact The contact to rename
+- * @param new_name The new display name for the contact
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_rename_contact(NMUser * user, NMContact * contact,
+- const char *new_name, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a rename folder request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param folder The folder to rename
+- * @param new_name The new name of the folder
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_rename_folder(NMUser * user, NMFolder * folder,
+- const char *new_name, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a move contact request to the server.
+- *
+- * The response data sent to the callback will be NULL.
+- *
+- * @param user The logged in User
+- * @param contact The contact to move
+- * @param folder The folder to move the contact to
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_move_contact(NMUser * user, NMContact * contact,
+- NMFolder * folder, nm_response_cb callback,
+- gpointer data);
+-
+-/**
+- * Send a get status request to the server.
+- *
+- * The response data sent to the callback will be a NMUserRecord.
+- *
+- * @param user The logged in User
+- * @param contact The contact to move
+- * @param folder The folder to move the contact to
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T nm_send_get_status(NMUser * user, NMUserRecord * user_record,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a request to add an item to the allow or deny list.
+- *
+- * @param user The logged in User
+- * @param who The userid or DN of the user to add to list
+- * @param allow_list TRUE if adding to allow list, FALSE if adding to deny list
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T
+-nm_send_create_privacy_item(NMUser *user, const char *who, gboolean is_allowed,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a request to remove an item from the allow or deny list.
+- *
+- * @param user The logged in User
+- * @param who The userid or DN of the user to add to list
+- * @param allow_list TRUE if removing from allow list, FALSE if removing from deny list
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T
+-nm_send_remove_privacy_item(NMUser *user, const char *dn, gboolean allow_list,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a request to change the default privacy setting to deny all or allow all
+- *
+- * @param user The logged in User
+- * @param default_deny TRUE if default should be changed to deny all
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T
+-nm_send_set_privacy_default(NMUser *user, gboolean default_deny,
+- nm_response_cb callback, gpointer data);
+-
+-/**
+- * Send a ping to the server
+- *
+- * @param user The logged in User
+- * @param callback Function to call when we get the response from the server
+- * @param data User defined data
+- *
+- * @return NM_OK if successfully sent, error otherwise
+- */
+-NMERR_T
+-nm_send_keepalive(NMUser *user, nm_response_cb callback, gpointer data);
+-
+-/**
+- * Reads a response/event from the server and processes it.
+- *
+- * @param user The logged in User
+- */
+-NMERR_T nm_process_new_data(NMUser * user);
+-
+-/**
+- * Return the root folder of the contact list
+- *
+- * @param user The logged in User
+- *
+- * @return Root folder
+- */
+-NMFolder *nm_get_root_folder(NMUser * user);
+-
+-/**
+- * Create the contact list based on the login fields
+- *
+- * @param user The logged in User
+- *
+- */
+-NMERR_T nm_create_contact_list(NMUser * user);
+-
+-void nm_destroy_contact_list(NMUser * user);
+-
+-void nm_user_add_contact(NMUser * user, NMContact * contact);
+-
+-void nm_user_add_user_record(NMUser * user, NMUserRecord * user_record);
+-
+-NMContact *nm_find_contact(NMUser * user, const char *dn);
+-
+-GList *nm_find_contacts(NMUser * user, const char *dn);
+-
+-NMUserRecord *nm_find_user_record(NMUser * user, const char *dn);
+-
+-NMFolder *nm_find_folder(NMUser * user, const char *name);
+-
+-NMFolder *nm_find_folder_by_id(NMUser * user, int object_id);
+-
+-NMConference *nm_find_conversation(NMUser * user, const char *who);
+-
+-void nm_conference_list_add(NMUser * user, NMConference * conf);
+-
+-void nm_conference_list_remove(NMUser * user, NMConference * conf);
+-
+-void nm_conference_list_free(NMUser * user);
+-
+-NMConference *nm_conference_list_find(NMUser * user, const char *guid);
+-
+-const char *nm_lookup_dn(NMUser * user, const char *display_id);
+-
+-nm_event_cb nm_user_get_event_callback(NMUser * user);
+-
+-NMConn *nm_user_get_conn(NMUser * user);
+-
+-gboolean nm_user_is_privacy_locked(NMUser *user);
+-
+-/** Some utility functions **/
+-
+-/**
+- * Check to see if the conference GUIDs are equivalent.
+- *
+- * @param guid1 First guid to compare
+- * @param guid2 Second guid to compare
+- *
+- * @return TRUE if conference GUIDs are equivalent, FALSE otherwise.
+- *
+- */
+-gboolean nm_are_guids_equal(const char *guid1, const char *guid2);
+-
+-/**
+- * Compare UTF8 strings for equality only (case insensitive)
+- *
+- * @param guid1 First string to compare
+- * @param guid2 Second string to compare
+- *
+- * @return TRUE if strings are equal, FALSE otherwise
+- *
+- */
+-gboolean nm_utf8_str_equal(gconstpointer str1, gconstpointer str2);
+-
+-/**
+- * Convert a fully typed LDAP DN to dotted, untype notation
+- * e.g. cn=mike,o=novell -> mike.novell
+- *
+- * @param typed Fully typed dn
+- *
+- * @return Dotted equivalent of typed (must be freed).
+- *
+- */
+-char *nm_typed_to_dotted(const char *typed);
+-
+-/**
+- * Return a string representation of the error code.
+- *
+- * @param error NMERR_T to convert to string
+- *
+- * @return String representation.
+- */
+-const char *nm_error_to_string (NMERR_T err);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.c
+--- pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,561 +0,0 @@
+-/*
+- * nmuserrecord.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include <glib.h>
+-#include <string.h>
+-#include "nmuserrecord.h"
+-#include "nmfield.h"
+-#include "nmuser.h"
+-
+-struct _NMUserRecord
+-{
+- NMSTATUS_T status;
+- char *status_text;
+- char *dn;
+- char *cn;
+- char *display_id;
+- char *fname;
+- char *lname;
+- char *full_name;
+- NMField *fields;
+- gboolean auth_attr;
+- gpointer data;
+- int ref_count;
+-};
+-
+-struct _NMProperty
+-{
+- char *tag;
+- char *value;
+-};
+-
+-static int count = 0;
+-
+-/* API functions */
+-
+-NMUserRecord *
+-nm_create_user_record()
+-{
+- NMUserRecord *user_record = g_new0(NMUserRecord, 1);
+-
+- user_record->ref_count = 1;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell", "Creating user_record, total=%d\n",
+- count++);
+-
+- return user_record;
+-}
+-
+-static char *
+-_get_attribute_value(NMField *field)
+-{
+- char *value = NULL;
+-
+- if (field->ptr_value == NULL)
+- return NULL;
+-
+- if (field->type == NMFIELD_TYPE_UTF8 || field->type == NMFIELD_TYPE_DN) {
+-
+- value = (char *)field->ptr_value;
+-
+- } else if (field->type == NMFIELD_TYPE_MV) {
+-
+- /* Need to handle multi-valued returns, for now
+- * just pick the first value and return it
+- */
+- NMField *tmp = (NMField *)field->ptr_value;
+- if ((tmp != NULL) &&
+- ((tmp->type == NMFIELD_TYPE_UTF8) ||
+- (tmp->type == NMFIELD_TYPE_DN))) {
+-
+- value = (char *)tmp->ptr_value;
+-
+- } else {
+- return NULL;
+- }
+-
+- } else {
+- return NULL;
+- }
+-
+- return g_strdup(value);
+-}
+-/*
+- * This creates a user_record for the reference list the
+- * field array that is passed in should be a
+- * NM_A_FA_USER_DETAILS array.
+- */
+-NMUserRecord *
+-nm_create_user_record_from_fields(NMField * details)
+-{
+- NMUserRecord *user_record;
+- NMField *field, *fields = details;
+-
+- if (details == NULL) {
+- return NULL;
+- }
+-
+- if (details->type == NMFIELD_TYPE_ARRAY) {
+- if (details->ptr_value == NULL)
+- return NULL;
+- fields = (NMField *) details->ptr_value;
+- }
+-
+- user_record = nm_create_user_record();
+-
+- if ((field = nm_locate_field(NM_A_SZ_AUTH_ATTRIBUTE, fields))) {
+-
+- if (field->ptr_value) {
+- user_record->display_id = _get_attribute_value(field);
+- user_record->auth_attr = TRUE;
+- }
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_DN, fields))) {
+-
+- if (field->ptr_value) {
+- user_record->dn = _get_attribute_value(field);
+- }
+- }
+-
+- if ((field = nm_locate_field("CN", fields))) {
+-
+- if (field->ptr_value) {
+- user_record->cn = _get_attribute_value(field);
+- }
+- }
+-
+- if ((field = nm_locate_field("Given Name", fields))) {
+-
+- if (field->ptr_value) {
+- user_record->fname = _get_attribute_value(field);
+- }
+- }
+-
+- if ((field = nm_locate_field("Surname", fields))) {
+-
+- if (field->ptr_value) {
+- user_record->lname = _get_attribute_value(field);
+- }
+- }
+-
+- if ((field = nm_locate_field("Full Name", fields))) {
+-
+- if (field->ptr_value) {
+- user_record->full_name = _get_attribute_value(field);
+- }
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_STATUS, fields))) {
+-
+- if (field->ptr_value)
+- user_record->status = atoi((char *) field->ptr_value);
+-
+- }
+-
+- if ((field = nm_locate_field(NM_A_SZ_MESSAGE_BODY, fields))) {
+-
+- if (field->ptr_value)
+- user_record->status_text = g_strdup((char *) field->ptr_value);
+-
+- }
+-
+- user_record->fields = nm_copy_field_array(fields);
+-
+- return user_record;
+-}
+-
+-void
+-nm_user_record_copy(NMUserRecord * dest, NMUserRecord * src)
+-{
+- if (dest == NULL || src == NULL)
+- return;
+-
+- dest->status = src->status;
+-
+- /* Copy status text */
+- if (dest->status_text) {
+- g_free(dest->status_text);
+- dest->status_text = NULL;
+- }
+-
+- if (src->status_text)
+- dest->status_text = g_strdup(src->status_text);
+-
+- /* Copy DN */
+- if (dest->dn) {
+- g_free(dest->dn);
+- dest->dn = NULL;
+- }
+-
+- if (src->dn)
+- dest->dn = g_strdup(src->dn);
+-
+- /* Copy CN */
+- if (dest->cn) {
+- g_free(dest->cn);
+- dest->cn = NULL;
+- }
+-
+- if (src->cn)
+- dest->cn = g_strdup(src->cn);
+-
+- /* Copy display id */
+- if (dest->display_id) {
+- g_free(dest->display_id);
+- dest->display_id = NULL;
+- }
+-
+- if (src->display_id)
+- dest->display_id = g_strdup(src->display_id);
+-
+- /* Copy first name */
+- if (dest->fname) {
+- g_free(dest->fname);
+- dest->fname = NULL;
+- }
+-
+- if (src->fname)
+- dest->fname = g_strdup(src->fname);
+-
+- /* Copy last name */
+- if (dest->lname) {
+- g_free(dest->lname);
+- dest->lname = NULL;
+- }
+-
+- if (src->lname)
+- dest->lname = g_strdup(src->lname);
+-
+- /* Copy full name */
+- if (dest->full_name) {
+- g_free(dest->full_name);
+- dest->full_name = NULL;
+- }
+-
+- if (src->full_name)
+- dest->full_name = g_strdup(src->full_name);
+-
+- /* Copy fields */
+- if (src->fields) {
+-
+- if (dest->fields) {
+- nm_free_fields(&dest->fields);
+- }
+-
+- dest->fields = nm_copy_field_array(src->fields);
+- }
+-
+- /* Copy data */
+- dest->data = src->data;
+-}
+-
+-void
+-nm_user_record_add_ref(NMUserRecord * user_record)
+-{
+- if (user_record)
+- user_record->ref_count++;
+-}
+-
+-void
+-nm_release_user_record(NMUserRecord * user_record)
+-{
+- if (--(user_record->ref_count) == 0) {
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Releasing user_record, total=%d\n", --count);
+-
+- if (user_record->dn) {
+- g_free(user_record->dn);
+- }
+-
+- if (user_record->cn) {
+- g_free(user_record->cn);
+- }
+-
+- if (user_record->display_id) {
+- g_free(user_record->display_id);
+- }
+-
+- if (user_record->fname) {
+- g_free(user_record->fname);
+- }
+-
+- if (user_record->lname) {
+- g_free(user_record->lname);
+- }
+-
+- if (user_record->full_name) {
+- g_free(user_record->full_name);
+- }
+-
+- if (user_record->status_text) {
+- g_free(user_record->status_text);
+- }
+-
+- nm_free_fields(&user_record->fields);
+-
+- g_free(user_record);
+- }
+-}
+-
+-/* UserRecord API */
+-
+-NMSTATUS_T
+-nm_user_record_get_status(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return (NMSTATUS_T) - 1;
+-
+- return user_record->status;
+-
+-}
+-
+-const char *
+-nm_user_record_get_status_text(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->status_text;
+-}
+-
+-void
+-nm_user_record_set_dn(NMUserRecord * user_record, const char *dn)
+-{
+- if (user_record != NULL && dn != NULL) {
+- if (user_record->dn)
+- g_free(user_record->dn);
+-
+- user_record->dn = g_strdup(dn);
+- }
+-}
+-
+-const char *
+-nm_user_record_get_dn(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->dn;
+-}
+-
+-void
+-nm_user_record_set_userid(NMUserRecord * user_record, const char *userid)
+-{
+- if (user_record != NULL && userid != NULL) {
+- if (user_record->cn)
+- g_free(user_record->cn);
+-
+- user_record->cn = g_strdup(userid);
+- }
+-}
+-
+-const char *
+-nm_user_record_get_userid(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->cn;
+-}
+-
+-void
+-nm_user_record_set_display_id(NMUserRecord * user_record, const char *display_id)
+-{
+- if (user_record != NULL && display_id != NULL) {
+- if (user_record->display_id)
+- g_free(user_record->display_id);
+-
+- user_record->display_id = g_strdup(display_id);
+- }
+-}
+-
+-const char *
+-nm_user_record_get_display_id(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- if (user_record->display_id == NULL) {
+- user_record->display_id = nm_typed_to_dotted(user_record->dn);
+- }
+-
+- return user_record->display_id;
+-}
+-
+-const char *
+-nm_user_record_get_full_name(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- if (user_record->full_name == NULL) {
+- if (user_record->fname && user_record->lname) {
+- user_record->full_name = g_strdup_printf("%s %s",
+- user_record->fname,
+- user_record->lname);
+-
+- }
+- }
+-
+- return user_record->full_name;
+-}
+-
+-const char *
+-nm_user_record_get_first_name(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->fname;
+-
+-}
+-
+-const char *
+-nm_user_record_get_last_name(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->lname;
+-}
+-
+-gpointer
+-nm_user_record_get_data(NMUserRecord * user_record)
+-{
+- if (user_record == NULL)
+- return NULL;
+-
+- return user_record->data;
+-}
+-
+-void
+-nm_user_record_set_data(NMUserRecord * user_record, gpointer data)
+-{
+- if (user_record == NULL)
+- return;
+-
+- user_record->data = data;
+-}
+-
+-void
+-nm_user_record_set_status(NMUserRecord * user_record,
+- int status, const char *text)
+-{
+- if (user_record == NULL)
+- return;
+-
+- user_record->status = status;
+-
+- if (user_record->status_text) {
+- g_free(user_record->status_text);
+- user_record->status_text = NULL;
+- }
+-
+- if (text)
+- user_record->status_text = g_strdup(text);
+-}
+-
+-gboolean
+-nm_user_record_get_auth_attr(NMUserRecord *user_record)
+-{
+- if (user_record == NULL)
+- return FALSE;
+-
+- return user_record->auth_attr;
+-}
+-
+-int
+-nm_user_record_get_property_count(NMUserRecord * user_record)
+-{
+- NMField *locate, *fields;
+-
+- int count = 0;
+-
+- if (user_record && user_record->fields) {
+- locate = nm_locate_field(NM_A_FA_INFO_DISPLAY_ARRAY,
+- (NMField *) user_record->fields);
+- if (locate && (fields = (NMField *) (locate->ptr_value))) {
+- count = (int) nm_count_fields(fields);
+- }
+- }
+- return count;
+-}
+-
+-NMProperty *
+-nm_user_record_get_property(NMUserRecord * user_record, int index)
+-{
+- NMProperty *property = NULL;
+- NMField *field = NULL, *fields, *locate;
+-
+- if (user_record && user_record->fields) {
+- locate = nm_locate_field(NM_A_FA_INFO_DISPLAY_ARRAY,
+- (NMField *) user_record->fields);
+- if (locate && (fields = (NMField *) (locate->ptr_value))) {
+- int max = nm_count_fields(fields);
+-
+- if (index < max) {
+- if (user_record) {
+- field = &fields[index];
+- if (field && field->tag && field->ptr_value) {
+- property = g_new0(NMProperty, 1);
+- property->tag = g_strdup(field->tag);
+- property->value = _get_attribute_value(field);
+- }
+- }
+- }
+- }
+- }
+-
+- return property;
+-}
+-
+-void
+-nm_release_property(NMProperty * property)
+-{
+- if (property) {
+- if (property->tag)
+- g_free(property->tag);
+-
+- if (property->value)
+- g_free(property->value);
+-
+- g_free(property);
+- }
+-}
+-
+-const char *
+-nm_property_get_tag(NMProperty * property)
+-{
+- if (property)
+- return property->tag;
+- else
+- return NULL;
+-}
+-
+-const char *
+-nm_property_get_value(NMProperty * property)
+-{
+- if (property)
+- return property->value;
+- else
+- return NULL;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.h pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.h
+--- pidgin-2.10.7/libpurple/protocols/novell/nmuserrecord.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/nmuserrecord.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,273 +0,0 @@
+-/*
+- * nmuserrecord.h
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef __NM_USER_RECORD_H__
+-#define __NM_USER_RECORD_H__
+-
+-#include <glib.h>
+-
+-typedef struct _NMUserRecord NMUserRecord;
+-typedef struct _NMProperty NMProperty;
+-
+-#include "nmfield.h"
+-#include "nmuser.h"
+-
+-/**
+- * Creates an NMUserRecord
+- *
+- * The NMUserRecord should be released by calling
+- * nm_release_user_record
+- *
+- * @return The new user record
+- *
+- */
+-NMUserRecord *nm_create_user_record(void);
+-
+-/**
+- * Creates an NMUserRecord
+- *
+- * The NMUserRecord should be released by calling
+- * nm_release_user_record
+- *
+- * @param details Should be a NM_A_FA_USER_DETAILS
+- *
+- *
+- * @return The new user record
+- *
+- */
+-NMUserRecord *nm_create_user_record_from_fields(NMField * details);
+-
+-/**
+- * Add a reference to an existing user_record
+- *
+- * The reference should be released by calling
+- * nm_release_user_record
+- *
+- * @param user_record The contact to addref
+- *
+- */
+-void nm_user_record_add_ref(NMUserRecord * user_record);
+-
+-/**
+- * Release a reference to the user record
+- *
+- * @param user_record The user record
+- *
+- */
+-void nm_release_user_record(NMUserRecord * user_record);
+-
+-/**
+- * Set the status for the user record
+- *
+- * @param user_record The user record
+- * @param status The status for the user
+- * @param text The status text for the user
+- *
+- */
+-void nm_user_record_set_status(NMUserRecord * user_record, NMSTATUS_T status,
+- const char *text);
+-
+-/**
+- * Get the status for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The status for the user record
+- */
+-NMSTATUS_T nm_user_record_get_status(NMUserRecord * user_record);
+-
+-/**
+- * Get the status text for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The status text if there is any, NULL otherwise
+- *
+- */
+-const char *nm_user_record_get_status_text(NMUserRecord * user_record);
+-
+-/**
+- * Set the DN for the user record
+- *
+- * @param user_record The user record
+- * @param dn The new DN for the user record
+- *
+- */
+-void nm_user_record_set_dn(NMUserRecord * user_record, const char *dn);
+-
+-/**
+- * Get the DN for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The DN for the user record
+- */
+-const char *nm_user_record_get_dn(NMUserRecord * user_record);
+-
+-/**
+- * Set the user id for the
+- *
+- * @param user_record The user record
+- * @param userid The userid (CN) for the user record
+- *
+- */
+-void nm_user_record_set_userid(NMUserRecord * user_record, const char *userid);
+-
+-/**
+- * Get the user id for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The user id for the user record
+- */
+-const char *nm_user_record_get_userid(NMUserRecord * user_record);
+-
+-/**
+- * Set the display id for the user record
+- *
+- * @param user_record The user record
+- * @param display_id The new display id for the user
+- *
+- */
+-void nm_user_record_set_display_id(NMUserRecord * user_record,
+- const char *display_id);
+-
+-/**
+- * Get the display id for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The display id for the user record
+- */
+-const char *nm_user_record_get_display_id(NMUserRecord * user_record);
+-
+-/**
+- * Return whether or not the display id is an auth attribute or not.
+- *
+- * @param user_record The user record
+- *
+- * @return TRUE if display_id is an auth attribute, FALSE otherwise.
+- */
+-gboolean
+-nm_user_record_get_auth_attr(NMUserRecord *user_record);
+-
+-/**
+- * Get the full name for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The full name for the user
+- */
+-const char *nm_user_record_get_full_name(NMUserRecord * user_record);
+-
+-/**
+- * Get the first name for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The first name for the user
+- */
+-const char *nm_user_record_get_first_name(NMUserRecord * user_record);
+-
+-/**
+- * Get the last name for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The last name for the user
+- */
+-const char *nm_user_record_get_last_name(NMUserRecord * user_record);
+-
+-/**
+- * Set the user defined data for the user record
+- *
+- * @param user_record The user record
+- * @param data The user defined data for the user record
+- *
+- */
+-void nm_user_record_set_data(NMUserRecord * user_record, gpointer data);
+-
+-/**
+- * Get the user defined data for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The user defined data for the user record
+- */
+-gpointer nm_user_record_get_data(NMUserRecord * user_record);
+-
+-/**
+- * Get the property count for the user record
+- *
+- * @param user_record The user record
+- *
+- * @return The number of information properties for the user record
+- *
+- */
+-int nm_user_record_get_property_count(NMUserRecord * user_record);
+-
+-/**
+- * Get an info property for the user record. The property must be released
+- * by calling nm_release_property()
+- *
+- * @param user_record The user record
+- * @param index The index of the property to get (zero based)
+- *
+- * @return The property
+- */
+-NMProperty *nm_user_record_get_property(NMUserRecord * user_record, int index);
+-
+-/**
+- * Release a property object
+- *
+- * @param property The property
+- *
+- */
+-void nm_release_property(NMProperty * property);
+-
+-/**
+- * Get the tag for the property
+- *
+- * @param property The property
+- *
+- * @return The tag of the property (i.e. "Email Address")
+- */
+-const char *nm_property_get_tag(NMProperty * property);
+-
+-/**
+- * Get the value for the property
+- *
+- * @param property The property
+- *
+- * @return The value of the property (i.e. "nobody@nowhere.com")
+- */
+-const char *nm_property_get_value(NMProperty * property);
+-
+-/**
+- * Copy a user record (deep copy). The dest user record must have already been
+- * created (nm_create_user_record)
+- *
+- * @param dest The destination of the copy
+- * @param src The source of the copy
+- *
+- */
+-void nm_user_record_copy(NMUserRecord * dest, NMUserRecord * src);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/novell/novell.c pidgin-2.10.7-nonprism/libpurple/protocols/novell/novell.c
+--- pidgin-2.10.7/libpurple/protocols/novell/novell.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/novell/novell.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,3590 +0,0 @@
+-/*
+- * novell.c
+- *
+- * Copyright (c) 2004 Novell, Inc. All Rights Reserved.
+- *
+- * 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.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-#include "accountopt.h"
+-#include "debug.h"
+-#include "prpl.h"
+-#include "server.h"
+-#include "nmuser.h"
+-#include "notify.h"
+-#include "util.h"
+-#include "sslconn.h"
+-#include "request.h"
+-#include "network.h"
+-#include "privacy.h"
+-#include "status.h"
+-#include "version.h"
+-
+-#define DEFAULT_PORT 8300
+-#define NOVELL_CONNECT_STEPS 4
+-#define NM_ROOT_FOLDER_NAME "GroupWise Messenger"
+-
+-#define NOVELL_STATUS_TYPE_AVAILABLE "available"
+-#define NOVELL_STATUS_TYPE_AWAY "away"
+-#define NOVELL_STATUS_TYPE_BUSY "busy"
+-#define NOVELL_STATUS_TYPE_OFFLINE "offline"
+-#define NOVELL_STATUS_TYPE_IDLE "idle"
+-#define NOVELL_STATUS_TYPE_APPEAR_OFFLINE "appearoffline"
+-
+-static PurplePlugin *my_protocol = NULL;
+-
+-static gboolean
+-_is_disconnect_error(NMERR_T err);
+-
+-static gboolean
+-_check_for_disconnect(NMUser * user, NMERR_T err);
+-
+-static void
+-_send_message(NMUser * user, NMMessage * message);
+-
+-static void
+-_update_buddy_status(NMUser *user, PurpleBuddy * buddy, int status, int gmt);
+-
+-static void
+-_remove_purple_buddies(NMUser * user);
+-
+-static void
+-_add_contacts_to_purple_blist(NMUser * user, NMFolder * folder);
+-
+-static void
+-_add_purple_buddies(NMUser * user);
+-
+-static void
+-_sync_contact_list(NMUser *user);
+-
+-static void
+-_sync_privacy_lists(NMUser *user);
+-
+-static void
+-_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name);
+-
+-const char *
+-_get_conference_name(int id);
+-
+-/*******************************************************************************
+- * Response callbacks
+- *******************************************************************************/
+-
+-/* Handle login response */
+-static void
+-_login_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- const char *alias;
+- NMERR_T rc;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+- if (gc == NULL)
+- return;
+-
+- if (ret_code == NM_OK) {
+-
+- /* Set alias for user if not set (use Full Name) */
+- alias = purple_account_get_alias(user->client_data);
+- if (alias == NULL || *alias == '\0') {
+- alias = nm_user_record_get_full_name(user->user_record);
+-
+- if (alias)
+- purple_account_set_alias(user->client_data, alias);
+- }
+-
+- /* Tell Purple that we are connected */
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+-
+- _sync_contact_list(user);
+-
+- rc = nm_send_set_status(user, NM_STATUS_AVAILABLE, NULL, NULL, NULL,
+- NULL);
+- _check_for_disconnect(user, rc);
+-
+- } else {
+- PurpleConnectionError reason;
+- char *err = g_strdup_printf(_("Unable to login: %s"),
+- nm_error_to_string (ret_code));
+-
+- switch (ret_code) {
+- case NMERR_AUTHENTICATION_FAILED:
+- case NMERR_CREDENTIALS_MISSING:
+- case NMERR_PASSWORD_INVALID:
+- /* Don't attempt to auto-reconnect if our
+- * password was invalid.
+- */
+- if (!purple_account_get_remember_password(gc->account))
+- purple_account_set_password(gc->account, NULL);
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+- default:
+- /* FIXME: There are other reasons login could fail */
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- }
+-
+- purple_connection_error_reason(gc, reason, err);
+- g_free(err);
+- }
+-}
+-
+-/* Handle getstatus response*/
+-static void
+-_get_status_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleBuddy *buddy;
+- GSList *buddies;
+- GSList *bnode;
+- NMUserRecord *user_record = (NMUserRecord *) resp_data;
+- int status;
+-
+- if (user == NULL || user_record == NULL)
+- return;
+-
+- if (ret_code == NM_OK) {
+-
+- /* Find all Purple buddies and update their statuses */
+- const char *name = nm_user_record_get_display_id(user_record);
+-
+- if (name) {
+- buddies = purple_find_buddies((PurpleAccount *) user->client_data, name);
+- for (bnode = buddies; bnode; bnode = bnode->next) {
+- buddy = (PurpleBuddy *) bnode->data;
+- if (buddy) {
+- status = nm_user_record_get_status(user_record);
+- _update_buddy_status(user, buddy, status, time(0));
+- }
+- }
+- g_slist_free(buddies);
+- }
+-
+- } else {
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_get_status_resp_cb(): rc = 0x%X\n", ret_code);
+-
+- }
+-}
+-
+-/* Show an error if the rename failed */
+-static void
+-_rename_contact_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- if (ret_code != NM_OK) {
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_rename_contact_resp_cb(): rc = 0x%X\n", ret_code);
+- }
+-}
+-
+-/* Handle the getdetails response and send the message */
+-static void
+-_get_details_resp_send_msg(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConversation *gconv;
+- PurpleConnection *gc;
+- NMUserRecord *user_record = NULL;
+- NMContact *cntct = NULL;
+- NMConference *conf;
+- NMMessage *msg = user_data;
+- const char *dn = NULL;
+- const char *name;
+-
+- if (user == NULL || msg == NULL)
+- return;
+-
+- if (ret_code == NM_OK) {
+- user_record = (NMUserRecord *) resp_data;
+- if (user_record) {
+-
+- /* Set the title for the conversation */
+- /* XXX - Should this be PURPLE_CONV_TYPE_IM? */
+- gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+- nm_user_record_get_display_id(user_record),
+- (PurpleAccount *) user->client_data);
+- if (gconv) {
+-
+- dn = nm_user_record_get_dn(user_record);
+- if (dn) {
+- cntct = nm_find_contact(user, dn);
+- }
+-
+- if (cntct) {
+- purple_conversation_set_title(gconv,
+- nm_contact_get_display_name(cntct));
+- } else {
+-
+- /* Not in the contact list, try to user full name */
+- name = (char *) nm_user_record_get_full_name(user_record);
+- if (name)
+- purple_conversation_set_title(gconv, name);
+- }
+- }
+-
+- /* Add the user record to particpant list */
+- conf = nm_message_get_conference(msg);
+- if (conf) {
+- nm_conference_add_participant(conf, user_record);
+- _send_message(user, msg);
+- }
+- }
+-
+- } else {
+-
+- gc = purple_account_get_connection(user->client_data);
+- if (gc != NULL) {
+- char *err = g_strdup_printf(_("Unable to send message."
+- " Could not get details for user (%s)."),
+- nm_error_to_string (ret_code));
+-
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-
+- if (msg)
+- nm_release_message(msg);
+- }
+-}
+-
+-/* Set up the new PurpleBuddy based on the response from getdetails */
+-static void
+-_get_details_resp_setup_buddy(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMUserRecord *user_record;
+- NMContact *contact;
+- PurpleBuddy *buddy;
+- const char *alias;
+- NMERR_T rc = NM_OK;
+-
+- if (user == NULL || resp_data == NULL || user_data == NULL)
+- return;
+-
+- contact = user_data;
+-
+- if (ret_code == NM_OK) {
+- user_record = resp_data;
+-
+- buddy = nm_contact_get_data(contact);
+-
+- nm_contact_set_user_record(contact, user_record);
+-
+- /* Set the display id */
+- purple_blist_rename_buddy(buddy,
+- nm_user_record_get_display_id(user_record));
+-
+- alias = purple_buddy_get_alias(buddy);
+- if (alias == NULL || *alias == '\0' || (strcmp(alias, purple_buddy_get_name(buddy)) == 0)) {
+- purple_blist_alias_buddy(buddy,
+- nm_user_record_get_full_name(user_record));
+-
+- /* Tell the server about the new display name */
+- rc = nm_send_rename_contact(user, contact,
+- nm_user_record_get_full_name(user_record),
+- NULL, NULL);
+- _check_for_disconnect(user, rc);
+-
+- }
+-
+-
+- /* Get initial status for the buddy */
+- rc = nm_send_get_status(user, resp_data, _get_status_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+-/* nm_release_contact(contact);*/
+-
+- }
+-
+- if (contact)
+- nm_release_contact(contact);
+-}
+-
+-/* Add the new contact into the PurpleBuddy list */
+-static void
+-_create_contact_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMContact *tmp_contact = (NMContact *) user_data;
+- NMContact *new_contact = NULL;
+- NMFolder *folder = NULL;
+- PurpleGroup *group;
+- PurpleBuddy *buddy;
+- const char *folder_name = NULL;
+- NMERR_T rc = NM_OK;
+-
+- if (user == NULL)
+- return;
+-
+- if (ret_code == NM_OK) {
+-
+- new_contact = (NMContact *) resp_data;
+- if (new_contact == NULL || tmp_contact == NULL)
+- return;
+-
+- /* Get the userid and folder name for the new contact */
+- folder = nm_find_folder_by_id(user,
+- nm_contact_get_parent_id(new_contact));
+- if (folder) {
+- folder_name = nm_folder_get_name(folder);
+- }
+-
+- if (folder_name == NULL || *folder_name == '\0')
+- folder_name = NM_ROOT_FOLDER_NAME;
+-
+- /* Re-add the buddy now that we got the okay from the server */
+- if (folder_name && (group = purple_find_group(folder_name))) {
+-
+- const char *alias = nm_contact_get_display_name(tmp_contact);
+- const char *display_id = nm_contact_get_display_id(new_contact);
+-
+- if (display_id == NULL)
+- display_id = nm_contact_get_dn(new_contact);
+-
+- if (alias && strcmp(alias, display_id)) {
+-
+- /* The user requested an alias, tell the server about it. */
+- rc = nm_send_rename_contact(user, new_contact, alias,
+- _rename_contact_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+- } else {
+-
+- alias = "";
+-
+- }
+-
+- /* Add it to the purple buddy list if it is not there */
+- buddy = purple_find_buddy_in_group(user->client_data, display_id, group);
+- if (buddy == NULL) {
+- buddy = purple_buddy_new(user->client_data, display_id, alias);
+- purple_blist_add_buddy(buddy, NULL, group, NULL);
+- }
+-
+- /* Save the new buddy as part of the contact object */
+- nm_contact_set_data(new_contact, (gpointer) buddy);
+-
+- /* We need details for the user before we can setup the
+- * new Purple buddy. We always call this because the
+- * 'createcontact' response fields do not always contain
+- * everything that we need.
+- */
+- nm_contact_add_ref(new_contact);
+-
+- rc = nm_send_get_details(user, nm_contact_get_dn(new_contact),
+- _get_details_resp_setup_buddy, new_contact);
+- _check_for_disconnect(user, rc);
+-
+- }
+-
+- } else {
+- PurpleConnection *gc = purple_account_get_connection(user->client_data);
+- const char *name = nm_contact_get_dn(tmp_contact);
+- char *err;
+-
+- err =
+- g_strdup_printf(_("Unable to add %s to your buddy list (%s)."),
+- name, nm_error_to_string (ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-
+- if (tmp_contact)
+- nm_release_contact(tmp_contact);
+-}
+-
+-/* Show an error if we failed to send the message */
+-static void
+-_send_message_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- char *err = NULL;
+-
+- if (user == NULL)
+- return;
+-
+- if (ret_code != NM_OK) {
+- gc = purple_account_get_connection(user->client_data);
+-
+- /* TODO: Improve this! message to who or for what conference? */
+- err = g_strdup_printf(_("Unable to send message (%s)."),
+- nm_error_to_string (ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-}
+-
+-/* Show an error if the remove failed */
+-static void
+-_remove_contact_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- if (ret_code != NM_OK) {
+- /* TODO: Display an error? */
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_remove_contact_resp_cb(): rc = 0x%x\n", ret_code);
+- }
+-}
+-
+-/* Show an error if the remove failed */
+-static void
+-_remove_folder_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- if (ret_code != NM_OK) {
+- /* TODO: Display an error? */
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_remove_folder_resp_cb(): rc = 0x%x\n", ret_code);
+- }
+-}
+-
+-/* Show an error if the move failed */
+-static void
+-_move_contact_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- if (ret_code != NM_OK) {
+- /* TODO: Display an error? */
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_move_contact_resp_cb(): rc = 0x%x\n", ret_code);
+- }
+-}
+-
+-/* Show an error if the rename failed */
+-static void
+-_rename_folder_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- if (ret_code != NM_OK) {
+- /* TODO: Display an error? */
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_rename_folder_resp_cb(): rc = 0x%x\n", ret_code);
+- }
+-}
+-
+-static void
+-_sendinvite_resp_cb(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- char *err;
+- PurpleConnection *gc;
+-
+- if (user == NULL)
+- return;
+-
+- if (ret_code != NM_OK) {
+- gc = purple_account_get_connection(user->client_data);
+- err = g_strdup_printf(_("Unable to invite user (%s)."), nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_sendinvite_resp_cb(): rc = 0x%x\n", ret_code);
+- }
+-
+-}
+-
+-/* If the createconf was successful attempt to send the message,
+- * otherwise display an error message to the user.
+- */
+-static void
+-_createconf_resp_send_msg(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMConference *conf;
+- NMMessage *msg = user_data;
+-
+- if (user == NULL || msg == NULL)
+- return;
+-
+- if (ret_code == NM_OK) {
+- _send_message(user, msg);
+- } else {
+-
+- if ((conf = nm_message_get_conference(msg))) {
+-
+- PurpleConnection *gc = purple_account_get_connection(user->client_data);
+- const char *name = NULL;
+- char *err;
+- NMUserRecord *ur;
+-
+- ur = nm_conference_get_participant(conf, 0);
+- if (ur)
+- name = nm_user_record_get_userid(ur);
+-
+- if (name)
+- err = g_strdup_printf(_("Unable to send message to %s."
+- " Could not create the conference (%s)."),
+- name,
+- nm_error_to_string (ret_code));
+- else
+- err = g_strdup_printf(_("Unable to send message."
+- " Could not create the conference (%s)."),
+- nm_error_to_string (ret_code));
+-
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-
+- if (msg)
+- nm_release_message(msg);
+- }
+-}
+-
+-/* Move contact to newly created folder */
+-static void
+-_create_folder_resp_move_contact(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMContact *contact = user_data;
+- NMFolder *new_folder;
+- char *folder_name = resp_data;
+- NMERR_T rc = NM_OK;
+-
+- if (user == NULL || folder_name == NULL || contact == NULL) {
+-
+- if (folder_name)
+- g_free(folder_name);
+-
+- return;
+- }
+-
+- if (ret_code == NM_OK || ret_code == NMERR_DUPLICATE_FOLDER) {
+- new_folder = nm_find_folder(user, folder_name);
+- if (new_folder) {
+-
+- /* Tell the server to move the contact to the new folder */
+-/* rc = nm_send_move_contact(user, contact, new_folder,
+- _move_contact_resp_cb, NULL); */
+-
+- rc = nm_send_create_contact(user, new_folder, contact,
+- NULL, NULL);
+-
+- _check_for_disconnect(user, rc);
+-
+- }
+- } else {
+- PurpleConnection *gc = purple_account_get_connection(user->client_data);
+- char *err = g_strdup_printf(_("Unable to move user %s"
+- " to folder %s in the server side list."
+- " Error while creating folder (%s)."),
+- nm_contact_get_dn(contact),
+- folder_name,
+- nm_error_to_string (ret_code));
+-
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-
+- if (folder_name)
+- g_free(folder_name);
+-}
+-
+-/* Add contact to newly create folder */
+-static void
+-_create_folder_resp_add_contact(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMContact *contact = (NMContact *) user_data;
+- NMFolder *folder;
+- char *folder_name = (char *) resp_data;
+- NMERR_T rc = NM_OK;
+-
+- if (user == NULL || folder_name == NULL || contact == NULL) {
+-
+- if (contact)
+- nm_release_contact(contact);
+-
+- if (folder_name)
+- g_free(folder_name);
+-
+- return;
+- }
+-
+- if (ret_code == NM_OK || ret_code == NMERR_DUPLICATE_FOLDER) {
+- folder = nm_find_folder(user, folder_name);
+- if (folder) {
+-
+- rc = nm_send_create_contact(user, folder, contact,
+- _create_contact_resp_cb, contact);
+- _check_for_disconnect(user, rc);
+- }
+- } else {
+- PurpleConnection *gc = purple_account_get_connection(user->client_data);
+- const char *name = nm_contact_get_dn(contact);
+- char *err =
+- g_strdup_printf(_("Unable to add %s to your buddy list."
+- " Error creating folder in server side list (%s)."),
+- name, nm_error_to_string (ret_code));
+-
+- purple_notify_error(gc, NULL, err, NULL);
+-
+- nm_release_contact(contact);
+- g_free(err);
+- }
+-
+- g_free(folder_name);
+-}
+-
+-static void
+-_join_conf_resp_cb(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConversation *chat;
+- PurpleConnection *gc;
+- NMUserRecord *ur;
+- NMConference *conference = user_data;
+- const char *name, *conf_name;
+- int i, count;
+-
+- if (user == NULL || conference == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+-
+- if (ret_code == NM_OK) {
+- conf_name = _get_conference_name(++user->conference_count);
+- chat = serv_got_joined_chat(gc, user->conference_count, conf_name);
+- if (chat) {
+-
+- nm_conference_set_data(conference, (gpointer) chat);
+-
+- count = nm_conference_get_participant_count(conference);
+- for (i = 0; i < count; i++) {
+- ur = nm_conference_get_participant(conference, i);
+- if (ur) {
+- name = nm_user_record_get_display_id(ur);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+- }
+- }
+- }
+- }
+-}
+-
+-/* Show info returned by getdetails */
+-static void
+-_get_details_resp_show_info(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record;
+- char *name;
+- char *err;
+-
+- if (user == NULL)
+- return;
+-
+- name = user_data;
+-
+- if (ret_code == NM_OK) {
+- user_record = (NMUserRecord *) resp_data;
+- if (user_record) {
+- _show_info(purple_account_get_connection(user->client_data),
+- user_record, g_strdup(name));
+- }
+- } else {
+- gc = purple_account_get_connection(user->client_data);
+- err =
+- g_strdup_printf(_("Could not get details for user %s (%s)."),
+- name, nm_error_to_string (ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-
+- if (name)
+- g_free(name);
+-}
+-
+-/* Handle get details response add to privacy list */
+-static void
+-_get_details_resp_add_privacy_item(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record = resp_data;
+- char *err;
+- gboolean allowed = GPOINTER_TO_INT(user_data);
+- const char *display_id;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+- display_id = nm_user_record_get_display_id(user_record);
+-
+- if (ret_code == NM_OK) {
+-
+- if (allowed) {
+-
+- if (!g_slist_find_custom(gc->account->permit,
+- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_permit_add(gc->account, display_id, TRUE);
+- }
+-
+- } else {
+-
+- if (!g_slist_find_custom(gc->account->permit,
+- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_deny_add(gc->account, display_id, TRUE);
+- }
+- }
+-
+- } else {
+-
+- err = g_strdup_printf(_("Unable to add user to privacy list (%s)."),
+- nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-}
+-
+-/* Handle response to create privacy item request */
+-static void
+-_create_privacy_item_deny_resp_cb(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record;
+- char *who = user_data;
+- char *err;
+- NMERR_T rc = NM_OK;
+- const char *display_id = NULL;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+-
+- if (ret_code == NM_OK) {
+-
+- user_record = nm_find_user_record(user, who);
+- if (user_record)
+- display_id = nm_user_record_get_display_id(user_record);
+-
+- if (display_id) {
+-
+- if (!g_slist_find_custom(gc->account->deny,
+- display_id, (GCompareFunc)purple_utf8_strcasecmp)) {
+-
+- purple_privacy_deny_add(gc->account, display_id, TRUE);
+- }
+-
+- } else {
+- rc = nm_send_get_details(user, who,
+- _get_details_resp_add_privacy_item,
+- (gpointer)FALSE);
+- _check_for_disconnect(user, rc);
+- }
+- } else {
+-
+- err = g_strdup_printf(_("Unable to add %s to deny list (%s)."),
+- who, nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-
+- if (who)
+- g_free(who);
+-
+-}
+-
+-/* Handle response to create privacy item request */
+-static void
+-_create_privacy_item_permit_resp_cb(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record;
+- char *who = user_data;
+- char *err;
+- NMERR_T rc = NM_OK;
+- const char *display_id = NULL;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+-
+- if (ret_code == NM_OK) {
+-
+- user_record = nm_find_user_record(user, who);
+- if (user_record)
+- display_id = nm_user_record_get_display_id(user_record);
+-
+- if (display_id) {
+-
+- if (!g_slist_find_custom(gc->account->permit,
+- display_id,
+- (GCompareFunc)purple_utf8_strcasecmp)) {
+-
+- purple_privacy_permit_add(gc->account, display_id, TRUE);
+- }
+-
+- } else {
+- rc = nm_send_get_details(user, who,
+- _get_details_resp_add_privacy_item,
+- (gpointer)TRUE);
+- _check_for_disconnect(user, rc);
+- }
+-
+- } else {
+-
+- err = g_strdup_printf(_("Unable to add %s to permit list (%s)."), who,
+- nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-
+- if (who)
+- g_free(who);
+-}
+-
+-static void
+-_get_details_send_privacy_create(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMERR_T rc = NM_OK;
+- PurpleConnection *gc;
+- NMUserRecord *user_record = resp_data;
+- char *err;
+- gboolean allowed = GPOINTER_TO_INT(user_data);
+- const char *dn, *display_id;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+- dn = nm_user_record_get_dn(user_record);
+- display_id = nm_user_record_get_display_id(user_record);
+-
+- if (ret_code == NM_OK) {
+-
+- if (allowed) {
+- rc = nm_send_create_privacy_item(user, dn, TRUE,
+- _create_privacy_item_permit_resp_cb,
+- g_strdup(display_id));
+- _check_for_disconnect(user, rc);
+-
+- } else {
+- rc = nm_send_create_privacy_item(user, dn, FALSE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(display_id));
+- _check_for_disconnect(user, rc);
+- }
+-
+- } else {
+-
+- err = g_strdup_printf(_("Unable to add user to privacy list (%s)."),
+- nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-}
+-
+-static void
+-_remove_privacy_item_resp_cb(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- char *who = user_data;
+- char *err;
+-
+- if (user == NULL)
+- return;
+-
+- if (ret_code != NM_OK) {
+-
+- gc = purple_account_get_connection(user->client_data);
+- err = g_strdup_printf(_("Unable to remove %s from privacy list (%s)."), who,
+- nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-
+- if (who)
+- g_free(who);
+-}
+-
+-static void
+-_set_privacy_default_resp_cb(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- PurpleConnection *gc;
+- char *err;
+-
+- if (user == NULL)
+- return;
+-
+- if (ret_code != NM_OK) {
+-
+- gc = purple_account_get_connection(user->client_data);
+- err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."),
+- nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-}
+-
+-/* Handle get details response add to privacy list */
+-static void
+-_get_details_resp_send_invite(NMUser *user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMERR_T rc = NM_OK;
+- PurpleConnection *gc;
+- NMUserRecord *user_record = resp_data;
+- char *err;
+- GSList *cnode;
+- NMConference *conference;
+- gpointer chat;
+- long id = (long) user_data;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+-
+- if (ret_code == NM_OK) {
+-
+- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
+- conference = cnode->data;
+- if (conference && (chat = nm_conference_get_data(conference))) {
+- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
+- rc = nm_send_conference_invite(user, conference, user_record,
+- NULL, _sendinvite_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- break;
+- }
+- }
+- }
+-
+- } else {
+-
+- err = g_strdup_printf(_("Unable to invite user (%s)."), nm_error_to_string(ret_code));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-
+- }
+-}
+-
+-static void
+-_createconf_resp_send_invite(NMUser * user, NMERR_T ret_code,
+- gpointer resp_data, gpointer user_data)
+-{
+- NMERR_T rc = NM_OK;
+- NMConference *conference = resp_data;
+- NMUserRecord *user_record = user_data;
+- PurpleConnection *gc;
+- char *err;
+-
+- if (user == NULL)
+- return;
+-
+-
+-
+- if (ret_code == NM_OK) {
+- rc = nm_send_conference_invite(user, conference, user_record,
+- NULL, _sendinvite_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- } else {
+- err = g_strdup_printf(_("Unable to create conference (%s)."), nm_error_to_string(ret_code));
+- gc = purple_account_get_connection(user->client_data);
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+- }
+-}
+-
+-/*******************************************************************************
+- * Helper functions
+- ******************************************************************************/
+-
+-static char *
+-_user_agent_string(void)
+-{
+-
+-#if !defined(_WIN32)
+-
+- const char *sysname = "";
+- const char *release = "";
+- struct utsname u;
+-
+- if (uname(&u) == 0) {
+- sysname = u.sysname;
+- release = u.release;
+- } else {
+- sysname = "Linux";
+- release = "Unknown";
+- }
+-
+- return g_strdup_printf("Purple/%s (%s; %s)", VERSION, sysname, release);
+-
+-#else
+-
+- const char *sysname = "";
+- OSVERSIONINFO os_info;
+- SYSTEM_INFO sys_info;
+-
+- os_info.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+- GetVersionEx(&os_info);
+- GetSystemInfo(&sys_info);
+-
+- if (os_info.dwPlatformId == VER_PLATFORM_WIN32_NT) {
+- switch (os_info.dwMajorVersion) {
+- case 3:
+- case 4:
+- sysname = "Windows NT";
+- break;
+- case 5:
+- switch (os_info.dwMinorVersion) {
+- case 0:
+- sysname = "Windows 2000";
+- break;
+- case 1:
+- sysname = "Windows XP";
+- break;
+- case 2:
+- sysname = "Windows Server 2003";
+- break;
+- default:
+- sysname = "Windows";
+- break;
+- }
+- break;
+- default:
+- sysname = "Windows";
+- break;
+- }
+-
+- } else if (os_info.dwPlatformId == VER_PLATFORM_WIN32_WINDOWS) {
+- switch (os_info.dwMinorVersion) {
+- case 0:
+- sysname = "Windows 95";
+- break;
+- case 10:
+- sysname = "Windows 98";
+- break;
+- case 90:
+- sysname = "Windows ME";
+- break;
+- default:
+- sysname = "Windows";
+- break;
+- }
+- } else {
+- sysname = "Windows";
+- }
+-
+- return g_strdup_printf("Purple/%s (%s; %ld.%ld)", VERSION, sysname,
+- os_info.dwMajorVersion, os_info.dwMinorVersion);
+-
+-#endif
+-
+-
+-}
+-
+-static gboolean
+-_is_disconnect_error(NMERR_T err)
+-{
+- return (err == NMERR_TCP_WRITE ||
+- err == NMERR_TCP_READ || err == NMERR_PROTOCOL);
+-}
+-
+-static gboolean
+-_check_for_disconnect(NMUser * user, NMERR_T err)
+-{
+- PurpleConnection *gc = purple_account_get_connection(user->client_data);
+-
+- if (_is_disconnect_error(err)) {
+-
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Error communicating with server. Closing connection."));
+- return TRUE;
+-
+- }
+-
+- return FALSE;
+-}
+-
+-/* Check to see if the conference is instantiated, if so send the message.
+- * If not send the create conference -- the response handler for the createconf
+- * will call this function again.
+- */
+-static void
+-_send_message(NMUser * user, NMMessage * message)
+-{
+- NMConference *conf;
+- NMERR_T rc = NM_OK;
+-
+- conf = nm_message_get_conference(message);
+- if (conf) {
+- /* We have a conference make sure that the
+- server knows about it already. */
+- if (nm_conference_is_instantiated(conf)) {
+-
+- /* We have everything that we need...finally! */
+- rc = nm_send_message(user, message, _send_message_resp_cb);
+- _check_for_disconnect(user, rc);
+-
+- nm_release_message(message);
+-
+- } else {
+- rc = nm_send_create_conference(user, conf, _createconf_resp_send_msg, message);
+- _check_for_disconnect(user, rc);
+- }
+- }
+-}
+-
+-/*
+- * Update the status of the given buddy in the Purple buddy list
+- */
+-static void
+-_update_buddy_status(NMUser *user, PurpleBuddy * buddy, int novellstatus, int gmt)
+-{
+- PurpleAccount *account;
+- const char *status_id;
+- const char *text = NULL;
+- const char *dn;
+- const char *name;
+- int idle = 0;
+- gboolean loggedin = TRUE;
+-
+- account = purple_buddy_get_account(buddy);
+- name = purple_buddy_get_name(buddy);
+-
+- switch (novellstatus) {
+- case NM_STATUS_AVAILABLE:
+- status_id = NOVELL_STATUS_TYPE_AVAILABLE;
+- break;
+- case NM_STATUS_AWAY:
+- status_id = NOVELL_STATUS_TYPE_AWAY;
+- break;
+- case NM_STATUS_BUSY:
+- status_id = NOVELL_STATUS_TYPE_BUSY;
+- break;
+- case NM_STATUS_OFFLINE:
+- status_id = NOVELL_STATUS_TYPE_OFFLINE;
+- loggedin = FALSE;
+- break;
+- case NM_STATUS_AWAY_IDLE:
+- status_id = NOVELL_STATUS_TYPE_AWAY;
+- idle = gmt;
+- break;
+- default:
+- status_id = NOVELL_STATUS_TYPE_OFFLINE;
+- loggedin = FALSE;
+- break;
+- }
+-
+- /* Get status text for the user */
+- dn = nm_lookup_dn(user, name);
+- if (dn) {
+- NMUserRecord *user_record = nm_find_user_record(user, dn);
+- if (user_record) {
+- text = nm_user_record_get_status_text(user_record);
+- }
+- }
+-
+- purple_prpl_got_user_status(account, name, status_id,
+- "message", text, NULL);
+- purple_prpl_got_user_idle(account, name,
+- (novellstatus == NM_STATUS_AWAY_IDLE), idle);
+-}
+-
+-/* Iterate through the cached Purple buddy list and remove buddies
+- * that are not in the server side list.
+- */
+-static void
+-_remove_purple_buddies(NMUser *user)
+-{
+- PurpleBlistNode *gnode;
+- PurpleBlistNode *cnode;
+- PurpleBlistNode *bnode;
+- PurpleGroup *group;
+- PurpleBuddy *buddy;
+- GSList *rem_list = NULL;
+- GSList *l;
+- NMFolder *folder = NULL;
+- const char *gname = NULL;
+-
+- for (gnode = purple_blist_get_root(); gnode;
+- gnode = purple_blist_node_get_sibling_next(gnode)) {
+- if (!PURPLE_BLIST_NODE_IS_GROUP(gnode))
+- continue;
+- group = (PurpleGroup *) gnode;
+- gname = purple_group_get_name(group);
+- for (cnode = purple_blist_node_get_first_child(gnode);
+- cnode;
+- cnode = purple_blist_node_get_sibling_next(cnode)) {
+- if (!PURPLE_BLIST_NODE_IS_CONTACT(cnode))
+- continue;
+- for (bnode = purple_blist_node_get_first_child(cnode);
+- bnode;
+- bnode = purple_blist_node_get_sibling_next(bnode)) {
+- if (!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
+- continue;
+- buddy = (PurpleBuddy *) bnode;
+- if (purple_buddy_get_account(buddy) == user->client_data) {
+- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0)
+- gname = "";
+- folder = nm_find_folder(user, gname);
+- if (folder == NULL ||
+- !nm_folder_find_contact_by_display_id(folder, purple_buddy_get_name(buddy))) {
+- rem_list = g_slist_append(rem_list, buddy);
+- }
+- }
+- }
+- }
+- }
+-
+- if (rem_list) {
+- for (l = rem_list; l; l = l->next) {
+- purple_blist_remove_buddy(l->data);
+- }
+- g_slist_free(rem_list);
+- }
+-}
+-
+-/* Add all of the contacts in the given folder to the Purple buddy list */
+-static void
+-_add_contacts_to_purple_blist(NMUser * user, NMFolder * folder)
+-{
+- NMUserRecord *user_record = NULL;
+- NMContact *contact = NULL;
+- PurpleBuddy *buddy = NULL;
+- PurpleGroup *group;
+- NMERR_T cnt = 0, i;
+- const char *text = NULL;
+- const char *name = NULL;
+- const char *fname = NULL;
+- int status = 0;
+-
+- /* If this is the root folder give it a name. Purple does not have the concept of
+- * a root folder.
+- */
+- fname = nm_folder_get_name(folder);
+- if (fname == NULL || *fname == '\0') {
+- fname = NM_ROOT_FOLDER_NAME;
+- }
+-
+- /* Does the Purple group exist already? */
+- group = purple_find_group(fname);
+- if (group == NULL) {
+- group = purple_group_new(fname);
+- purple_blist_add_group(group, NULL);
+- }
+-
+- /* Get each contact for this folder */
+- cnt = nm_folder_get_contact_count(folder);
+- for (i = 0; i < cnt; i++) {
+- contact = nm_folder_get_contact(folder, i);
+- if (contact) {
+-
+- name = nm_contact_get_display_id(contact);
+- if (name) {
+-
+- buddy = purple_find_buddy_in_group(user->client_data, name, group);
+- if (buddy == NULL) {
+- /* Add it to the purple buddy list */
+- buddy = purple_buddy_new(user->client_data,
+- name,
+- nm_contact_get_display_name(contact));
+-
+- purple_blist_add_buddy(buddy, NULL, group, NULL);
+- }
+-
+- /* Set the initial status for the buddy */
+- user_record = nm_contact_get_user_record(contact);
+- if (user_record) {
+- status = nm_user_record_get_status(user_record);
+- text = nm_user_record_get_status_text(user_record);
+- }
+- _update_buddy_status(user, buddy, status, time(0));
+-
+- /* Save the new buddy as part of the contact object */
+- nm_contact_set_data(contact, (gpointer) buddy);
+- }
+-
+- } else {
+- /* NULL contact. This should not happen, but
+- * let's break out of the loop.
+- */
+- break;
+- }
+- }
+-}
+-
+-/* Add all of the server side contacts to the Purple buddy list. */
+-static void
+-_add_purple_buddies(NMUser * user)
+-{
+- int cnt = 0, i;
+- NMFolder *root_folder = NULL;
+- NMFolder *folder = NULL;
+-
+- root_folder = nm_get_root_folder(user);
+- if (root_folder) {
+-
+- /* Add sub-folders and contacts to sub-folders...
+- * iterate throught the sub-folders in reverse order
+- * because Purple adds the folders to the front -- so we
+- * want to add the first folder last
+- */
+- cnt = nm_folder_get_subfolder_count(root_folder);
+- for (i = cnt-1; i >= 0; i--) {
+- folder = nm_folder_get_subfolder(root_folder, i);
+- if (folder) {
+- _add_contacts_to_purple_blist(user, folder);
+- }
+- }
+-
+- /* Add contacts for the root folder */
+- _add_contacts_to_purple_blist(user, root_folder);
+- }
+-}
+-
+-static void
+-_sync_contact_list(NMUser *user)
+-{
+- /* Remove all buddies from the local list that are
+- * not in the server side list and add all buddies
+- * from the server side list that are not in
+- * the local list
+- */
+- _remove_purple_buddies(user);
+- _add_purple_buddies(user);
+- user->clist_synched = TRUE;
+-}
+-
+-static void
+-_sync_privacy_lists(NMUser *user)
+-{
+- GSList *node = NULL, *rem_list = NULL;
+- PurpleConnection *gc;
+- const char *name, *dn;
+- NMUserRecord *user_record;
+-
+- if (user == NULL)
+- return;
+-
+- gc = purple_account_get_connection(user->client_data);
+- if (gc == NULL)
+- return;
+-
+- /* Set the Purple privacy setting */
+- if (user->default_deny) {
+- if (user->allow_list == NULL) {
+- gc->account->perm_deny = PURPLE_PRIVACY_DENY_ALL;
+- } else {
+- gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_USERS;
+- }
+- } else {
+- if (user->deny_list == NULL) {
+- gc->account->perm_deny = PURPLE_PRIVACY_ALLOW_ALL;
+- } else {
+- gc->account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+- }
+- }
+-
+- /* Add stuff */
+- for (node = user->allow_list; node; node = node->next) {
+- user_record = nm_find_user_record(user, (char *)node->data);
+- if (user_record)
+- name = nm_user_record_get_display_id(user_record);
+- else
+- name =(char *)node->data;
+-
+- if (!g_slist_find_custom(gc->account->permit,
+- name, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_permit_add(gc->account, name , TRUE);
+- }
+- }
+-
+- for (node = user->deny_list; node; node = node->next) {
+- user_record = nm_find_user_record(user, (char *)node->data);
+- if (user_record)
+- name = nm_user_record_get_display_id(user_record);
+- else
+- name =(char *)node->data;
+-
+- if (!g_slist_find_custom(gc->account->deny,
+- name, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_deny_add(gc->account, name, TRUE);
+- }
+- }
+-
+-
+- /* Remove stuff */
+- for (node = gc->account->permit; node; node = node->next) {
+- dn = nm_lookup_dn(user, (char *)node->data);
+- if (dn != NULL &&
+- !g_slist_find_custom(user->allow_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
+- rem_list = g_slist_append(rem_list, node->data);
+- }
+- }
+-
+- if (rem_list) {
+- for (node = rem_list; node; node = node->next) {
+- purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
+- }
+- g_slist_free(rem_list);
+- rem_list = NULL;
+- }
+-
+- for (node = gc->account->deny; node; node = node->next) {
+- dn = nm_lookup_dn(user, (char *)node->data);
+- if (dn != NULL &&
+- !g_slist_find_custom(user->deny_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
+- rem_list = g_slist_append(rem_list, node->data);
+- }
+- }
+-
+- if (rem_list) {
+- for (node = rem_list; node; node = node->next) {
+- purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
+- }
+- g_slist_free(rem_list);
+- }
+-}
+-
+- /* Map known property tags to user-friendly strings */
+-static const char *
+-_map_property_tag(const char *tag)
+-{
+- if (tag == NULL) return NULL;
+-
+- if (strcmp(tag, "telephoneNumber") == 0)
+- return _("Telephone Number");
+- else if (strcmp(tag, "L") == 0)
+- return _("Location");
+- else if (strcmp(tag, "OU") == 0)
+- return _("Department");
+- else if (strcmp(tag, "personalTitle") == 0)
+- return _("Personal Title");
+- else if (strcmp(tag, "Title") == 0)
+- return _("Job Title");
+- else if (strcmp(tag, "mailstop") == 0)
+- return _("Mailstop");
+- else if (strcmp(tag, "Internet EMail Address") == 0)
+- return _("Email Address");
+- else
+- return tag;
+-}
+-
+-/* Display a dialog box showing the properties for the given user record */
+-static void
+-_show_info(PurpleConnection * gc, NMUserRecord * user_record, char * name)
+-{
+- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
+- int count, i;
+- NMProperty *property;
+- const char *tag, *value;
+-
+- tag = _("User ID");
+- value = nm_user_record_get_userid(user_record);
+- if (value) {
+- purple_notify_user_info_add_pair(user_info, tag, value);
+- }
+-
+-/* tag = _("DN");
+- value = nm_user_record_get_dn(user_record);
+- if (value) {
+- purple_notify_user_info_add_pair(user_info, tag, value);
+- }
+-*/
+-
+- tag = _("Full name");
+- value = nm_user_record_get_full_name(user_record);
+- if (value) {
+- purple_notify_user_info_add_pair(user_info, tag, value);
+- }
+-
+- count = nm_user_record_get_property_count(user_record);
+- for (i = 0; i < count; i++) {
+- property = nm_user_record_get_property(user_record, i);
+- if (property) {
+- tag = _map_property_tag(nm_property_get_tag(property));
+- value = nm_property_get_value(property);
+- if (tag && value) {
+- purple_notify_user_info_add_pair(user_info, tag, value);
+- }
+- nm_release_property(property);
+- }
+- }
+-
+- purple_notify_userinfo(gc, name, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-
+- g_free(name);
+-}
+-
+-/* Send a join conference, the first item in the parms list is the
+- * NMUser object and the second item is the conference to join.
+- * This callback is passed to purple_request_action when we ask the
+- * user if they want to join the conference.
+- */
+-static void
+-_join_conference_cb(GSList * parms)
+-{
+- NMUser *user;
+- NMConference *conference;
+- NMERR_T rc = NM_OK;
+-
+- if (parms == NULL || g_slist_length(parms) != 2)
+- return;
+-
+- user = g_slist_nth_data(parms, 0);
+- conference = g_slist_nth_data(parms, 1);
+-
+- if (user && conference) {
+- rc = nm_send_join_conference(user, conference,
+- _join_conf_resp_cb, conference);
+- _check_for_disconnect(user, rc);
+- }
+-
+- g_slist_free(parms);
+-}
+-
+-/* Send a reject conference, the first item in the parms list is the
+- * NMUser object and the second item is the conference to reject.
+- * This callback is passed to purple_request_action when we ask the
+- * user if they want to joing the conference.
+- */
+-static void
+-_reject_conference_cb(GSList * parms)
+-{
+- NMUser *user;
+- NMConference *conference;
+- NMERR_T rc = NM_OK;
+-
+- if (parms == NULL || g_slist_length(parms) != 2)
+- return;
+-
+- user = g_slist_nth_data(parms, 0);
+- conference = g_slist_nth_data(parms, 1);
+-
+- if (user && conference) {
+- rc = nm_send_reject_conference(user, conference, NULL, NULL);
+- _check_for_disconnect(user, rc);
+- }
+-
+- g_slist_free(parms);
+-}
+-
+-static void
+-_initiate_conference_cb(PurpleBlistNode *node, gpointer ignored)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+-
+- NMUser *user;
+- const char *conf_name;
+- PurpleConversation *chat = NULL;
+- NMUserRecord *user_record;
+- NMConference *conference;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- /* We should already have a userrecord for the buddy */
+- user_record = nm_find_user_record(user, purple_buddy_get_name(buddy));
+- if (user_record == NULL)
+- return;
+-
+- conf_name = _get_conference_name(++user->conference_count);
+- chat = serv_got_joined_chat(gc, user->conference_count, conf_name);
+- if (chat) {
+-
+- conference = nm_create_conference(NULL);
+- nm_conference_set_data(conference, (gpointer) chat);
+- nm_send_create_conference(user, conference, _createconf_resp_send_invite, user_record);
+- nm_release_conference(conference);
+- }
+-}
+-
+-const char *
+-_get_conference_name(int id)
+-{
+- static char *name = NULL;
+-
+- if (name)
+- g_free(name);
+-
+- name = g_strdup_printf(_("GroupWise Conference %d"), id);
+-
+- return name;
+-}
+-
+-static void
+-_show_privacy_locked_error(PurpleConnection *gc, NMUser *user)
+-{
+- char *err;
+-
+- err = g_strdup_printf(_("Unable to change server side privacy settings (%s)."),
+- nm_error_to_string(NMERR_ADMIN_LOCKED));
+- purple_notify_error(gc, NULL, err, NULL);
+- g_free(err);
+-}
+-
+-/*******************************************************************************
+- * Connect and recv callbacks
+- ******************************************************************************/
+-
+-static void
+-novell_ssl_connect_error(PurpleSslConnection * gsc,
+- PurpleSslErrorType error, gpointer data)
+-{
+- PurpleConnection *gc;
+- NMUser *user;
+-
+- gc = data;
+- user = gc->proto_data;
+- user->conn->ssl_conn->data = NULL;
+-
+- purple_connection_ssl_error (gc, error);
+-}
+-
+-static void
+-novell_ssl_recv_cb(gpointer data, PurpleSslConnection * gsc,
+- PurpleInputCondition condition)
+-{
+- PurpleConnection *gc = data;
+- NMUser *user;
+- NMERR_T rc;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- rc = nm_process_new_data(user);
+- if (rc != NM_OK) {
+-
+- if (_is_disconnect_error(rc)) {
+-
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Error communicating with server. Closing connection."));
+- } else {
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "Error processing event or response (%d).\n", rc);
+- }
+- }
+-}
+-
+-static void
+-novell_ssl_connected_cb(gpointer data, PurpleSslConnection * gsc,
+- PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = data;
+- NMUser *user;
+- NMConn *conn;
+- NMERR_T rc = 0;
+- const char *pwd = NULL;
+- const char *my_addr = NULL;
+- char *ua = NULL;
+-
+- if (gc == NULL || gsc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if ((user == NULL) || (conn = user->conn) == NULL)
+- return;
+-
+- purple_connection_update_progress(gc, _("Authenticating..."),
+- 2, NOVELL_CONNECT_STEPS);
+-
+- my_addr = purple_network_get_my_ip(gsc->fd);
+- pwd = purple_connection_get_password(gc);
+- ua = _user_agent_string();
+-
+- rc = nm_send_login(user, pwd, my_addr, ua, _login_resp_cb, NULL);
+- if (rc == NM_OK) {
+- conn->connected = TRUE;
+- purple_ssl_input_add(gsc, novell_ssl_recv_cb, gc);
+- } else {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- }
+-
+- purple_connection_update_progress(gc, _("Waiting for response..."),
+- 3, NOVELL_CONNECT_STEPS);
+-
+- g_free(ua);
+-}
+-
+-/*******************************************************************************
+- * Event callback and event handlers
+- ******************************************************************************/
+-
+-static void
+-_evt_receive_message(NMUser * user, NMEvent * event)
+-{
+- NMUserRecord *user_record = NULL;
+- NMContact *contact = NULL;
+- PurpleConversation *gconv;
+- NMConference *conference;
+- PurpleMessageFlags flags;
+- char *text = NULL;
+-
+- text = g_markup_escape_text(nm_event_get_text(event), -1);
+-
+- conference = nm_event_get_conference(event);
+- if (conference) {
+-
+- PurpleConversation *chat = nm_conference_get_data(conference);
+-
+- /* Is this a single person 'conversation' or a conference? */
+- if (chat == NULL && nm_conference_get_participant_count(conference) == 1) {
+-
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+-
+- flags = 0;
+- if (nm_event_get_type(event) == NMEVT_RECEIVE_AUTOREPLY)
+- flags |= PURPLE_MESSAGE_AUTO_RESP;
+-
+- serv_got_im(purple_account_get_connection(user->client_data),
+- nm_user_record_get_display_id(user_record),
+- text, flags,
+- nm_event_get_gmt(event));
+-
+- gconv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- nm_user_record_get_display_id(user_record),
+- (PurpleAccount *) user->client_data);
+- if (gconv) {
+-
+- contact = nm_find_contact(user, nm_event_get_source(event));
+- if (contact) {
+-
+- purple_conversation_set_title(
+- gconv, nm_contact_get_display_name(contact));
+-
+-
+- } else {
+-
+- const char *name =
+- nm_user_record_get_full_name(user_record);
+-
+- if (name == NULL)
+- name = nm_user_record_get_userid(user_record);
+-
+- purple_conversation_set_title(gconv, name);
+- }
+-
+- }
+-
+- } else {
+- /* this should not happen, see the event code.
+- * the event code will get the contact details from
+- * the server if it does not have them before calling
+- * the event callback.
+- */
+- }
+-
+- } else if (chat) {
+-
+- /* get the contact for send if we have one */
+- NMContact *contact = nm_find_contact(user,
+- nm_event_get_source(event));
+-
+- /* get the user record for the sender */
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- const char *name = nm_contact_get_display_name(contact);
+-
+- if (name == NULL) {
+- name = nm_user_record_get_full_name(user_record);
+- if (name == NULL)
+- name = nm_user_record_get_display_id(user_record);
+- }
+-
+- serv_got_chat_in(purple_account_get_connection(user->client_data),
+- purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)),
+- name, 0, text, nm_event_get_gmt(event));
+- }
+- }
+- }
+-
+- g_free(text);
+-}
+-
+-static void
+-_evt_conference_left(NMUser * user, NMEvent * event)
+-{
+- PurpleConversation *chat;
+- NMConference *conference;
+-
+- conference = nm_event_get_conference(event);
+- if (conference) {
+- chat = nm_conference_get_data(conference);
+- if (chat) {
+- NMUserRecord *ur = nm_find_user_record(user,
+- nm_event_get_source(event));
+-
+- if (ur)
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(chat),
+- nm_user_record_get_display_id(ur),
+- NULL);
+- }
+- }
+-}
+-
+-static void
+-_evt_conference_invite_notify(NMUser * user, NMEvent * event)
+-{
+- PurpleConversation *gconv;
+- NMConference *conference;
+- NMUserRecord *user_record = NULL;
+- char *str = NULL;
+-
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- conference = nm_event_get_conference(event);
+- if (user_record && conference) {
+- gconv = nm_conference_get_data(conference);
+- str = g_strdup_printf(_("%s has been invited to this conversation."),
+- nm_user_record_get_display_id(user_record));
+- purple_conversation_write(gconv, NULL, str,
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(str);
+- }
+-}
+-
+-static void
+-_evt_conference_invite(NMUser * user, NMEvent * event)
+-{
+- NMUserRecord *ur;
+- PurpleConnection *gc;
+- GSList *parms = NULL;
+- const char *title = NULL;
+- const char *secondary = NULL;
+- const char *name = NULL;
+- char *primary = NULL;
+- time_t gmt;
+-
+- ur = nm_find_user_record(user, nm_event_get_source(event));
+- if (ur)
+- name = nm_user_record_get_full_name(ur);
+-
+- if (name == NULL)
+- name = nm_event_get_source(event);
+-
+- gmt = nm_event_get_gmt(event);
+- title = _("Invitation to Conversation");
+- primary = g_strdup_printf(_("Invitation from: %s\n\nSent: %s"),
+- name, purple_date_format_full(localtime(&gmt)));
+- secondary = _("Would you like to join the conversation?");
+-
+- /* Set up parms list for the callbacks
+- * We need to send the NMUser object and
+- * the NMConference object to the callbacks
+- */
+- parms = NULL;
+- parms = g_slist_append(parms, user);
+- parms = g_slist_append(parms, nm_event_get_conference(event));
+-
+- /* Prompt the user */
+- /* TODO: Would it be better to use serv_got_chat_invite() here? */
+- gc = purple_account_get_connection(user->client_data);
+- purple_request_action(gc, title, primary, secondary,
+- PURPLE_DEFAULT_ACTION_NONE,
+- purple_connection_get_account(gc), name, NULL,
+- parms, 2,
+- _("Yes"), G_CALLBACK(_join_conference_cb),
+- _("No"), G_CALLBACK(_reject_conference_cb));
+-
+- g_free(primary);
+-}
+-
+-
+-static void
+-_evt_conference_joined(NMUser * user, NMEvent * event)
+-{
+- PurpleConversation *chat = NULL;
+- PurpleConnection *gc;
+- NMConference *conference = NULL;
+- NMUserRecord *ur = NULL;
+- const char *name;
+- const char *conf_name;
+-
+- gc = purple_account_get_connection(user->client_data);
+- if (gc == NULL)
+- return;
+-
+- conference = nm_event_get_conference(event);
+- if (conference) {
+- chat = nm_conference_get_data(conference);
+- if (nm_conference_get_participant_count(conference) == 2 && chat == NULL) {
+- ur = nm_conference_get_participant(conference, 0);
+- if (ur) {
+- conf_name = _get_conference_name(++user->conference_count);
+- chat =
+- serv_got_joined_chat(gc, user->conference_count, conf_name);
+- if (chat) {
+-
+- nm_conference_set_data(conference, (gpointer) chat);
+-
+- name = nm_user_record_get_display_id(ur);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+-
+- }
+- }
+- }
+-
+- if (chat != NULL) {
+- ur = nm_find_user_record(user, nm_event_get_source(event));
+- if (ur) {
+- name = nm_user_record_get_display_id(ur);
+- if (!purple_conv_chat_find_user(PURPLE_CONV_CHAT(chat), name)) {
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(chat), name, NULL,
+- PURPLE_CBFLAGS_NONE, TRUE);
+- }
+- }
+- }
+- }
+-}
+-
+-static void
+-_evt_status_change(NMUser * user, NMEvent * event)
+-{
+- PurpleBuddy *buddy = NULL;
+- GSList *buddies;
+- GSList *bnode;
+- NMUserRecord *user_record;
+- const char *display_id;
+- int status;
+-
+- user_record = nm_event_get_user_record(event);
+- if (user_record) {
+-
+- /* Retrieve new status */
+- status = nm_user_record_get_status(user_record);
+-
+- /* Update status for buddy in all folders */
+- display_id = nm_user_record_get_display_id(user_record);
+- buddies = purple_find_buddies(user->client_data, display_id);
+- for (bnode = buddies; bnode; bnode = bnode->next) {
+- buddy = (PurpleBuddy *) bnode->data;
+- if (buddy) {
+- _update_buddy_status(user, buddy, status, nm_event_get_gmt(event));
+- }
+- }
+-
+- g_slist_free(buddies);
+-
+- }
+-}
+-
+-static void
+-_evt_user_disconnect(NMUser * user, NMEvent * event)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account = user->client_data;
+-
+- gc = purple_account_get_connection(account);
+- if (gc)
+- {
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NAME_IN_USE,
+- _("You have signed on from another location"));
+- }
+-}
+-
+-static void
+-_evt_user_typing(NMUser * user, NMEvent * event)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record = NULL;
+-
+- gc = purple_account_get_connection((PurpleAccount *) user->client_data);
+- if (gc) {
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- serv_got_typing(gc, nm_user_record_get_display_id(user_record),
+- 30, PURPLE_TYPING);
+- }
+- }
+-}
+-
+-static void
+-_evt_user_not_typing(NMUser * user, NMEvent * event)
+-{
+- PurpleConnection *gc;
+- NMUserRecord *user_record;
+-
+- gc = purple_account_get_connection((PurpleAccount *) user->client_data);
+- if (gc) {
+- user_record = nm_find_user_record(user, nm_event_get_source(event));
+- if (user_record) {
+- serv_got_typing_stopped(gc,
+- nm_user_record_get_display_id(user_record));
+- }
+- }
+-}
+-
+-static void
+-_evt_undeliverable_status(NMUser * user, NMEvent * event)
+-{
+- NMUserRecord *ur;
+- PurpleConversation *gconv;
+- char *str;
+-
+- ur = nm_find_user_record(user, nm_event_get_source(event));
+- if (ur) {
+- /* XXX - Should this be PURPLE_CONV_TYPE_IM? */
+- gconv =
+- purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+- nm_user_record_get_display_id(ur),
+- user->client_data);
+- if (gconv) {
+- const char *name = nm_user_record_get_full_name(ur);
+-
+- if (name == NULL) {
+- name = nm_user_record_get_display_id(ur);
+- }
+- str = g_strdup_printf(_("%s appears to be offline and did not receive"
+- " the message that you just sent."), name);
+- purple_conversation_write(gconv, NULL, str,
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(str);
+- }
+- }
+-}
+-
+-static void
+-_event_callback(NMUser * user, NMEvent * event)
+-{
+- if (user == NULL || event == NULL)
+- return;
+-
+- switch (nm_event_get_type(event)) {
+- case NMEVT_STATUS_CHANGE:
+- _evt_status_change(user, event);
+- break;
+- case NMEVT_RECEIVE_AUTOREPLY:
+- case NMEVT_RECEIVE_MESSAGE:
+- _evt_receive_message(user, event);
+- break;
+- case NMEVT_USER_DISCONNECT:
+- _evt_user_disconnect(user, event);
+- break;
+- case NMEVT_USER_TYPING:
+- _evt_user_typing(user, event);
+- break;
+- case NMEVT_USER_NOT_TYPING:
+- _evt_user_not_typing(user, event);
+- break;
+- case NMEVT_SERVER_DISCONNECT:
+- /* Nothing to do? */
+- break;
+- case NMEVT_INVALID_RECIPIENT:
+- break;
+- case NMEVT_UNDELIVERABLE_STATUS:
+- _evt_undeliverable_status(user, event);
+- break;
+- case NMEVT_CONFERENCE_INVITE_NOTIFY:
+- /* Someone else has been invited to join a
+- * conference that we are currently a part of
+- */
+- _evt_conference_invite_notify(user, event);
+- break;
+- case NMEVT_CONFERENCE_INVITE:
+- /* We have been invited to join a conference */
+- _evt_conference_invite(user, event);
+- break;
+- case NMEVT_CONFERENCE_JOINED:
+- /* Some one has joined a conference that we
+- * are a part of
+- */
+- _evt_conference_joined(user, event);
+- break;
+- case NMEVT_CONFERENCE_LEFT:
+- /* Someone else has left a conference that we
+- * are currently a part of
+- */
+- _evt_conference_left(user, event);
+- break;
+- default:
+- purple_debug(PURPLE_DEBUG_INFO, "novell",
+- "_event_callback(): unhandled event, %d\n",
+- nm_event_get_type(event));
+- break;
+- }
+-}
+-
+-/*******************************************************************************
+- * Prpl Ops
+- ******************************************************************************/
+-
+-static void
+-novell_login(PurpleAccount * account)
+-{
+- PurpleConnection *gc;
+- NMUser *user = NULL;
+- const char *server;
+- const char *name;
+- int port;
+-
+- if (account == NULL)
+- return;
+-
+- gc = purple_account_get_connection(account);
+- if (gc == NULL)
+- return;
+-
+- server = purple_account_get_string(account, "server", NULL);
+- if (server == NULL || *server == '\0') {
+-
+- /* TODO: Would be nice to prompt if not set!
+- * purple_request_fields(gc, _("Server Address"),...);
+- */
+-
+- /* ...but for now just error out with a nice message. */
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+- _("Unable to connect to server. Please enter the "
+- "address of the server to which you wish to connect."));
+- return;
+- }
+-
+- port = purple_account_get_int(account, "port", DEFAULT_PORT);
+- name = purple_account_get_username(account);
+-
+- user = nm_initialize_user(name, server, port, account, _event_callback);
+- if (user && user->conn) {
+- /* save user */
+- gc->proto_data = user;
+-
+- /* connect to the server */
+- purple_connection_update_progress(gc, _("Connecting"),
+- 1, NOVELL_CONNECT_STEPS);
+-
+- user->conn->use_ssl = TRUE;
+-
+- user->conn->ssl_conn = g_new0(NMSSLConn, 1);
+- user->conn->ssl_conn->read = (nm_ssl_read_cb) purple_ssl_read;
+- user->conn->ssl_conn->write = (nm_ssl_write_cb) purple_ssl_write;
+-
+- user->conn->ssl_conn->data = purple_ssl_connect(user->client_data,
+- user->conn->addr, user->conn->port,
+- novell_ssl_connected_cb, novell_ssl_connect_error, gc);
+- if (user->conn->ssl_conn->data == NULL) {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+- _("SSL support unavailable"));
+- }
+- }
+-}
+-
+-static void
+-novell_close(PurpleConnection * gc)
+-{
+- NMUser *user;
+- NMConn *conn;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user) {
+- conn = user->conn;
+- if (conn && conn->ssl_conn) {
+- purple_ssl_close(user->conn->ssl_conn->data);
+- }
+- nm_deinitialize_user(user);
+- }
+- gc->proto_data = NULL;
+-}
+-
+-static int
+-novell_send_im(PurpleConnection * gc, const char *name,
+- const char *message_body, PurpleMessageFlags flags)
+-{
+- NMUserRecord *user_record = NULL;
+- NMConference *conf = NULL;
+- NMMessage *message;
+- NMUser *user;
+- const char *dn = NULL;
+- char *plain;
+- gboolean done = TRUE, created_conf = FALSE;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || name == NULL ||
+- message_body == NULL || *message_body == '\0')
+- return 0;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return 0;
+-
+- /* Create a new message */
+- plain = purple_unescape_html(message_body);
+- message = nm_create_message(plain);
+- g_free(plain);
+-
+- /* Need to get the DN for the buddy so we can look up the convo */
+- dn = nm_lookup_dn(user, name);
+-
+- /* Do we already know about the sender? */
+- user_record = nm_find_user_record(user, dn);
+- if (user_record) {
+-
+- /* Do we already have an instantiated conference? */
+- conf = nm_find_conversation(user, dn);
+- if (conf == NULL) {
+-
+- /* If not, create a blank conference */
+- conf = nm_create_conference(NULL);
+- created_conf = TRUE;
+-
+- nm_conference_add_participant(conf, user_record);
+- }
+-
+- nm_message_set_conference(message, conf);
+-
+- /* Make sure conference is instantiated */
+- if (!nm_conference_is_instantiated(conf)) {
+-
+- /* It is not, so send the createconf. We will
+- * have to finish sending the message when we
+- * get the response with the new conference guid.
+- */
+- rc = nm_send_create_conference(user, conf, _createconf_resp_send_msg, message);
+- _check_for_disconnect(user, rc);
+-
+- done = FALSE;
+- }
+-
+- } else {
+-
+- /* If we don't have details for the user, then we don't have
+- * a conference yet. So create one and send the getdetails
+- * to the server. We will have to finish sending the message
+- * when we get the response from the server.
+- */
+- conf = nm_create_conference(NULL);
+- created_conf = TRUE;
+-
+- nm_message_set_conference(message, conf);
+-
+- rc = nm_send_get_details(user, name, _get_details_resp_send_msg, message);
+- _check_for_disconnect(user, rc);
+-
+- done = FALSE;
+- }
+-
+- if (done) {
+-
+- /* Did we find everything we needed? */
+- rc = nm_send_message(user, message, _send_message_resp_cb);
+- _check_for_disconnect(user, rc);
+-
+- nm_release_message(message);
+- }
+-
+- if (created_conf && conf)
+- nm_release_conference(conf);
+-
+- return 1;
+-}
+-
+-static unsigned int
+-novell_send_typing(PurpleConnection * gc, const char *name, PurpleTypingState state)
+-{
+- NMConference *conf = NULL;
+- NMUser *user;
+- const char *dn = NULL;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || name == NULL)
+- return 0;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return 0;
+-
+- /* Need to get the DN for the buddy so we can look up the convo */
+- dn = nm_lookup_dn(user, name);
+- if (dn) {
+-
+- /* Now find the conference in our list */
+- conf = nm_find_conversation(user, dn);
+- if (conf) {
+-
+- rc = nm_send_typing(user, conf,
+- ((state == PURPLE_TYPING) ? TRUE : FALSE), NULL);
+- _check_for_disconnect(user, rc);
+-
+- }
+-
+- }
+-
+- return 0;
+-}
+-
+-static void
+-novell_convo_closed(PurpleConnection * gc, const char *who)
+-{
+- NMUser *user;
+- NMConference *conf;
+- const char *dn;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || who == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user && (dn = nm_lookup_dn(user, who))) {
+- conf = nm_find_conversation(user, dn);
+- if (conf) {
+- rc = nm_send_leave_conference(user, conf, NULL, NULL);
+- _check_for_disconnect(user, rc);
+- }
+- }
+-}
+-
+-static void
+-novell_chat_leave(PurpleConnection * gc, int id)
+-{
+- NMConference *conference;
+- NMUser *user;
+- PurpleConversation *chat;
+- GSList *cnode;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
+- conference = cnode->data;
+- if (conference && (chat = nm_conference_get_data(conference))) {
+- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
+- rc = nm_send_leave_conference(user, conference, NULL, NULL);
+- _check_for_disconnect(user, rc);
+- break;
+- }
+- }
+- }
+-
+- serv_got_chat_left(gc, id);
+-}
+-
+-static void
+-novell_chat_invite(PurpleConnection *gc, int id,
+- const char *message, const char *who)
+-{
+- NMConference *conference;
+- NMUser *user;
+- PurpleConversation *chat;
+- GSList *cnode;
+- NMERR_T rc = NM_OK;
+- NMUserRecord *user_record = NULL;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- user_record = nm_find_user_record(user, who);
+- if (user_record == NULL) {
+- rc = nm_send_get_details(user, who, _get_details_resp_send_invite, GINT_TO_POINTER(id));
+- _check_for_disconnect(user, rc);
+- return;
+- }
+-
+- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
+- conference = cnode->data;
+- if (conference && (chat = nm_conference_get_data(conference))) {
+- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
+- rc = nm_send_conference_invite(user, conference, user_record,
+- message, _sendinvite_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- break;
+- }
+- }
+- }
+-}
+-
+-static int
+-novell_chat_send(PurpleConnection * gc, int id, const char *text, PurpleMessageFlags flags)
+-{
+- NMConference *conference;
+- PurpleConversation *chat;
+- GSList *cnode;
+- NMMessage *message;
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *name;
+- char *str, *plain;
+-
+- if (gc == NULL || text == NULL)
+- return -1;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return -1;
+-
+- plain = purple_unescape_html(text);
+- message = nm_create_message(plain);
+- g_free(plain);
+-
+- for (cnode = user->conferences; cnode != NULL; cnode = cnode->next) {
+- conference = cnode->data;
+- if (conference && (chat = nm_conference_get_data(conference))) {
+- if (purple_conv_chat_get_id(PURPLE_CONV_CHAT(chat)) == id) {
+-
+- nm_message_set_conference(message, conference);
+-
+- /* check to see if the conference is instatiated yet */
+- if (!nm_conference_is_instantiated(conference)) {
+- nm_message_add_ref(message);
+- nm_send_create_conference(user, conference, _createconf_resp_send_msg, message);
+- } else {
+- rc = nm_send_message(user, message, _send_message_resp_cb);
+- }
+-
+- nm_release_message(message);
+-
+- if (!_check_for_disconnect(user, rc)) {
+-
+- /* Use the account alias if it is set */
+- name = purple_account_get_alias(user->client_data);
+- if (name == NULL || *name == '\0') {
+-
+- /* If there is no account alias, try full name */
+- name = nm_user_record_get_full_name(user->user_record);
+- if (name == NULL || *name == '\0') {
+-
+- /* Fall back to the username that we are signed in with */
+- name = purple_account_get_username(user->client_data);
+- }
+- }
+-
+- serv_got_chat_in(gc, id, name, flags, text, time(NULL));
+- return 0;
+- } else
+- return -1;
+-
+- }
+- }
+- }
+-
+-
+- /* The conference was not found, must be closed */
+- chat = purple_find_chat(gc, id);
+- if (chat) {
+- str = g_strdup(_("This conference has been closed."
+- " No more messages can be sent."));
+- purple_conversation_write(chat, NULL, str, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(str);
+- }
+-
+- if (message)
+- nm_release_message(message);
+-
+- return -1;
+-}
+-
+-static void
+-novell_add_buddy(PurpleConnection * gc, PurpleBuddy *buddy, PurpleGroup * group)
+-{
+- NMFolder *folder = NULL;
+- NMContact *contact;
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *alias, *gname, *bname;
+-
+- if (gc == NULL || buddy == NULL || group == NULL)
+- return;
+-
+- user = (NMUser *) purple_connection_get_protocol_data(gc);
+- if (user == NULL)
+- return;
+-
+- /* If we haven't synched the contact list yet, ignore
+- * the add_buddy calls. Server side list is the master.
+- */
+- if (!user->clist_synched)
+- return;
+-
+- /* Don't re-add a buddy that is already on our contact list */
+- if (nm_find_user_record(user, purple_buddy_get_name(buddy)) != NULL)
+- return;
+-
+- contact = nm_create_contact();
+- nm_contact_set_dn(contact, purple_buddy_get_name(buddy));
+-
+- /* Remove the PurpleBuddy (we will add it back after adding it
+- * to the server side list). Save the alias if there is one.
+- */
+- alias = purple_buddy_get_alias(buddy);
+- bname = purple_buddy_get_name(buddy);
+- if (alias && strcmp(alias, bname))
+- nm_contact_set_display_name(contact, alias);
+-
+- purple_blist_remove_buddy(buddy);
+- buddy = NULL;
+-
+- gname = purple_group_get_name(group);
+- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) {
+- gname = "";
+- }
+-
+- folder = nm_find_folder(user, gname);
+- if (folder) {
+-
+- /* We have everything that we need, so send the createcontact */
+- rc = nm_send_create_contact(user, folder, contact,
+- _create_contact_resp_cb, contact);
+-
+- } else {
+-
+- /* Need to create the folder before we can add the contact */
+- rc = nm_send_create_folder(user, gname,
+- _create_folder_resp_add_contact, contact);
+- }
+-
+- _check_for_disconnect(user, rc);
+-
+-}
+-
+-static void
+-novell_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- NMContact *contact;
+- NMFolder *folder;
+- NMUser *user;
+- const char *dn, *gname;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || buddy == NULL || group == NULL)
+- return;
+-
+- user = (NMUser *) gc->proto_data;
+- if (user && (dn = nm_lookup_dn(user, purple_buddy_get_name(buddy)))) {
+- gname = purple_group_get_name(group);
+- if (strcmp(gname, NM_ROOT_FOLDER_NAME) == 0) {
+- gname = "";
+- }
+- folder = nm_find_folder(user, gname);
+- if (folder) {
+- contact = nm_folder_find_contact(folder, dn);
+- if (contact) {
+-
+- /* Remove the buddy from the contact */
+- nm_contact_set_data(contact, NULL);
+-
+- /* Tell the server to remove the contact */
+- rc = nm_send_remove_contact(user, folder, contact,
+- _remove_contact_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- }
+- }
+- }
+-}
+-
+-static void
+-novell_remove_group(PurpleConnection * gc, PurpleGroup *group)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || group == NULL)
+- return;
+-
+- user = (NMUser *) gc->proto_data;
+- if (user) {
+- NMFolder *folder = nm_find_folder(user, purple_group_get_name(group));
+-
+- if (folder) {
+- rc = nm_send_remove_folder(user, folder,
+- _remove_folder_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- }
+- }
+-}
+-
+-static void
+-novell_alias_buddy(PurpleConnection * gc, const char *name, const char *alias)
+-{
+- NMContact *contact;
+- NMUser *user;
+- GList *contacts = NULL;
+- GList *cnode = NULL;
+- const char *dn = NULL, *fname = NULL;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || name == NULL || alias == NULL)
+- return;
+-
+- user = (NMUser *) gc->proto_data;
+- if (user && (dn = nm_lookup_dn(user, name))) {
+-
+- /* Alias all of instances of the contact */
+- contacts = nm_find_contacts(user, dn);
+- for (cnode = contacts; cnode != NULL; cnode = cnode->next) {
+- contact = (NMContact *) cnode->data;
+- if (contact) {
+- PurpleGroup *group = NULL;
+- PurpleBuddy *buddy;
+- NMFolder *folder;
+-
+- /* Alias the Purple buddy? */
+- folder = nm_find_folder_by_id(user,
+- nm_contact_get_parent_id(contact));
+- if (folder) {
+- fname = nm_folder_get_name(folder);
+- if (*fname == '\0') {
+- fname = NM_ROOT_FOLDER_NAME;
+- }
+- group = purple_find_group(fname);
+- }
+-
+- if (group) {
+- const char *balias;
+- buddy = purple_find_buddy_in_group(user->client_data,
+- name, group);
+- balias = buddy ? purple_buddy_get_local_buddy_alias(buddy) : NULL;
+- if (balias && strcmp(balias, alias))
+- purple_blist_alias_buddy(buddy, alias);
+- }
+-
+- /* Tell the server to alias the contact */
+- rc = nm_send_rename_contact(user, contact, alias,
+- _rename_contact_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- }
+- }
+- if (contacts)
+- g_list_free(contacts);
+- }
+-}
+-
+-static void
+-novell_group_buddy(PurpleConnection * gc,
+- const char *name, const char *old_group_name,
+- const char *new_group_name)
+-{
+- NMFolder *old_folder;
+- NMFolder *new_folder;
+- NMContact *contact;
+- NMUser *user;
+- const char *dn;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL || name == NULL ||
+- old_group_name == NULL || new_group_name == NULL)
+- return;
+-
+- user = (NMUser *) gc->proto_data;
+- if (user && (dn = nm_lookup_dn(user, name))) {
+-
+- /* Find the old folder */
+- if (strcmp(old_group_name, NM_ROOT_FOLDER_NAME) == 0) {
+- old_folder = nm_get_root_folder(user);
+- if (nm_folder_find_contact(old_folder, dn) == NULL)
+- old_folder = nm_find_folder(user, old_group_name);
+- } else {
+- old_folder = nm_find_folder(user, old_group_name);
+- }
+-
+- if (old_folder && (contact = nm_folder_find_contact(old_folder, dn))) {
+-
+- /* Find the new folder */
+- new_folder = nm_find_folder(user, new_group_name);
+- if (new_folder == NULL) {
+- if (strcmp(new_group_name, NM_ROOT_FOLDER_NAME) == 0)
+- new_folder = nm_get_root_folder(user);
+- }
+-
+- if (new_folder) {
+-
+- /* Tell the server to move the contact to the new folder */
+- rc = nm_send_move_contact(user, contact, new_folder,
+- _move_contact_resp_cb, NULL);
+-
+- } else {
+-
+- nm_contact_add_ref(contact);
+-
+- /* Remove the old contact first */
+- nm_send_remove_contact(user, old_folder, contact,
+- _remove_contact_resp_cb, NULL);
+-
+- /* New folder does not exist yet, so create it */
+- rc = nm_send_create_folder(user, new_group_name,
+- _create_folder_resp_move_contact,
+- contact);
+- }
+-
+- _check_for_disconnect(user, rc);
+- }
+- }
+-}
+-
+-static void
+-novell_rename_group(PurpleConnection * gc, const char *old_name,
+- PurpleGroup *group, GList *moved_buddies)
+-{
+- NMERR_T rc = NM_OK;
+- NMFolder *folder;
+- NMUser *user;
+-
+- if (gc == NULL || old_name == NULL || group == NULL || moved_buddies == NULL) {
+- return;
+- }
+-
+- user = gc->proto_data;
+- if (user) {
+- const char *gname = purple_group_get_name(group);
+- /* Does new folder exist already? */
+- if (nm_find_folder(user, gname)) {
+- /* purple_blist_rename_group() adds the buddies
+- * to the new group and removes the old group...
+- * so there is nothing more to do here.
+- */
+- return;
+- }
+-
+- if (strcmp(old_name, NM_ROOT_FOLDER_NAME) == 0) {
+- /* Can't rename the root folder ... need to revisit this */
+- return;
+- }
+-
+- folder = nm_find_folder(user, old_name);
+- if (folder) {
+- rc = nm_send_rename_folder(user, folder, gname,
+- _rename_folder_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+- }
+- }
+-}
+-
+-static const char *
+-novell_list_icon(PurpleAccount * account, PurpleBuddy * buddy)
+-{
+- return "novell";
+-}
+-
+-static void
+-novell_tooltip_text(PurpleBuddy * buddy, PurpleNotifyUserInfo * user_info, gboolean full)
+-{
+- NMUserRecord *user_record = NULL;
+- PurpleConnection *gc;
+- NMUser *user;
+- int status = 0;
+- const char *status_str = NULL;
+- const char *text = NULL;
+-
+- if (buddy == NULL)
+- return;
+-
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- if (gc == NULL || (user = gc->proto_data) == NULL)
+- return;
+-
+- if (PURPLE_BUDDY_IS_ONLINE(buddy)) {
+- user_record = nm_find_user_record(user, purple_buddy_get_name(buddy));
+- if (user_record) {
+- status = nm_user_record_get_status(user_record);
+- text = nm_user_record_get_status_text(user_record);
+- /* No custom text, so default it ... */
+- switch (status) {
+- case NM_STATUS_AVAILABLE:
+- status_str = _("Available");
+- break;
+- case NM_STATUS_AWAY:
+- status_str = _("Away");
+- break;
+- case NM_STATUS_BUSY:
+- status_str = _("Busy");
+- break;
+- case NM_STATUS_AWAY_IDLE:
+- status_str = _("Idle");
+- break;
+- case NM_STATUS_OFFLINE:
+- status_str = _("Offline");
+- break;
+- default:
+- status_str = _("Unknown");
+- break;
+- }
+-
+- purple_notify_user_info_add_pair(user_info, _("Status"), status_str);
+-
+- if (text)
+- purple_notify_user_info_add_pair(user_info, _("Message"), text);
+- }
+- }
+-}
+-
+-static void
+-novell_set_idle(PurpleConnection * gc, int time)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *id = NULL;
+- PurpleStatus *status = NULL;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- status = purple_account_get_active_status(purple_connection_get_account(gc));
+- id = purple_status_get_id(status);
+-
+- /* Only go idle if active status is available */
+- if (!strcmp(id, NOVELL_STATUS_TYPE_AVAILABLE)) {
+- if (time > 0) {
+- rc = nm_send_set_status(user, NM_STATUS_AWAY_IDLE, NULL, NULL, NULL, NULL);
+- } else {
+- rc = nm_send_set_status(user, NM_STATUS_AVAILABLE, NULL, NULL, NULL, NULL);
+- }
+- }
+-
+- _check_for_disconnect(user, rc);
+-}
+-
+-static void
+-novell_get_info(PurpleConnection * gc, const char *name)
+-{
+- NMUserRecord *user_record;
+- NMUser *user;
+- NMERR_T rc;
+-
+- if (gc == NULL || name == NULL)
+- return;
+-
+- user = (NMUser *) gc->proto_data;
+- if (user) {
+-
+- user_record = nm_find_user_record(user, name);
+- if (user_record) {
+- _show_info(gc, user_record, g_strdup(name));
+-
+- } else {
+- rc = nm_send_get_details(user, name,
+- _get_details_resp_show_info, g_strdup(name));
+-
+- _check_for_disconnect(user, rc);
+-
+- }
+-
+- }
+-}
+-
+-static char *
+-novell_status_text(PurpleBuddy * buddy)
+-{
+- const char *text = NULL;
+- const char *dn = NULL;
+- PurpleAccount *account;
+-
+- account = buddy ? purple_buddy_get_account(buddy) : NULL;
+- if (buddy && account) {
+- PurpleConnection *gc = purple_account_get_connection(account);
+-
+- if (gc && gc->proto_data) {
+- NMUser *user = gc->proto_data;
+-
+- dn = nm_lookup_dn(user, purple_buddy_get_name(buddy));
+- if (dn) {
+- NMUserRecord *user_record = nm_find_user_record(user, dn);
+-
+- if (user_record) {
+- text = nm_user_record_get_status_text(user_record);
+- if (text)
+- return g_strdup(text);
+- }
+- }
+- }
+- }
+-
+- return NULL;
+-}
+-
+-static GList *
+-novell_status_types(PurpleAccount *account)
+-{
+- GList *status_types = NULL;
+- PurpleStatusType *type;
+-
+- g_return_val_if_fail(account != NULL, NULL);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, NOVELL_STATUS_TYPE_AVAILABLE,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- status_types = g_list_append(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, NOVELL_STATUS_TYPE_AWAY,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- status_types = g_list_append(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, NOVELL_STATUS_TYPE_BUSY,
+- _("Busy"), TRUE, TRUE, FALSE,
+- "message", _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- status_types = g_list_append(status_types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_INVISIBLE, NOVELL_STATUS_TYPE_APPEAR_OFFLINE,
+- NULL, TRUE, TRUE, FALSE);
+- status_types = g_list_append(status_types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE, NULL, NULL, TRUE, TRUE, FALSE);
+- status_types = g_list_append(status_types, type);
+-
+- return status_types;
+-}
+-
+-static void
+-novell_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleConnection *gc;
+- gboolean connected;
+- PurplePresence *presence;
+- PurpleStatusType *type;
+- PurpleStatusPrimitive primitive;
+- NMUser *user;
+- NMSTATUS_T novellstatus = NM_STATUS_AVAILABLE;
+- NMERR_T rc = NM_OK;
+- const char *msg = NULL;
+- char *text = NULL;
+-
+- connected = purple_account_is_connected(account);
+- presence = purple_status_get_presence(status);
+- type = purple_status_get_type(status);
+- primitive = purple_status_type_get_primitive(type);
+-
+- /*
+- * We don't have any independent statuses, so we don't need to
+- * do anything when a status is deactivated (because another
+- * status is about to be activated).
+- */
+- if (!purple_status_is_active(status))
+- return;
+-
+- if (!connected)
+- return;
+-
+- gc = purple_account_get_connection(account);
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- if (primitive == PURPLE_STATUS_AVAILABLE) {
+- novellstatus = NM_STATUS_AVAILABLE;
+- } else if (primitive == PURPLE_STATUS_AWAY) {
+- novellstatus = NM_STATUS_AWAY;
+- } else if (primitive == PURPLE_STATUS_UNAVAILABLE) {
+- novellstatus = NM_STATUS_BUSY;
+- } else if (primitive == PURPLE_STATUS_INVISIBLE) {
+- novellstatus = NM_STATUS_OFFLINE;
+- } else if (purple_presence_is_idle(presence)) {
+- novellstatus = NM_STATUS_AWAY_IDLE;
+- } else {
+- novellstatus = NM_STATUS_AVAILABLE;
+- }
+-
+- if (primitive == PURPLE_STATUS_AWAY || primitive == PURPLE_STATUS_AVAILABLE ||
+- primitive == PURPLE_STATUS_UNAVAILABLE) {
+- msg = purple_status_get_attr_string(status, "message");
+- text = g_strdup(msg);
+-
+- if (primitive == PURPLE_STATUS_AVAILABLE)
+- msg = NULL; /* no auto replies for online status */
+-
+- /* Don't want newlines in status text */
+- purple_util_chrreplace(text, '\n', ' ');
+- }
+-
+- rc = nm_send_set_status(user, novellstatus, text, msg, NULL, NULL);
+- _check_for_disconnect(user, rc);
+-
+- if (text)
+- g_free(text);
+-}
+-
+-static void
+-novell_add_permit(PurpleConnection *gc, const char *who)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *name = who;
+-
+- if (gc == NULL || who == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- /* Remove first -- we will add it back in when we get
+- * the okay from the server
+- */
+- purple_privacy_permit_remove(gc->account, who, TRUE);
+-
+- if (nm_user_is_privacy_locked(user)) {
+- _show_privacy_locked_error(gc, user);
+- _sync_privacy_lists(user);
+- return;
+- }
+-
+- /* Work around for problem with un-typed, dotted contexts */
+- if (strchr(who, '.')) {
+- const char *dn = nm_lookup_dn(user, who);
+- if (dn == NULL) {
+- rc = nm_send_get_details(user, who, _get_details_send_privacy_create,
+- (gpointer)TRUE);
+- _check_for_disconnect(user, rc);
+- return;
+- } else {
+- name = dn;
+- }
+- }
+-
+- rc = nm_send_create_privacy_item(user, name, TRUE,
+- _create_privacy_item_permit_resp_cb,
+- g_strdup(who));
+- _check_for_disconnect(user, rc);
+-}
+-
+-static void
+-novell_add_deny(PurpleConnection *gc, const char *who)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *name = who;
+-
+- if (gc == NULL || who == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- /* Remove first -- we will add it back in when we get
+- * the okay from the server
+- */
+- purple_privacy_deny_remove(gc->account, who, TRUE);
+-
+- if (nm_user_is_privacy_locked(user)) {
+- _show_privacy_locked_error(gc, user);
+- _sync_privacy_lists(user);
+- return;
+- }
+-
+- /* Work around for problem with un-typed, dotted contexts */
+- if (strchr(who, '.')) {
+- const char *dn = nm_lookup_dn(user, who);
+- if (dn == NULL) {
+- rc = nm_send_get_details(user, who, _get_details_send_privacy_create,
+- (gpointer)FALSE);
+- _check_for_disconnect(user, rc);
+- return;
+- } else {
+- name = dn;
+- }
+- }
+-
+- rc = nm_send_create_privacy_item(user, name, FALSE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(who));
+- _check_for_disconnect(user, rc);
+-}
+-
+-static void
+-novell_rem_permit(PurpleConnection *gc, const char *who)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *dn = NULL;
+-
+- if (gc == NULL || who == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- if (nm_user_is_privacy_locked(user)) {
+- _show_privacy_locked_error(gc, user);
+- _sync_privacy_lists(user);
+- return;
+- }
+-
+- dn = nm_lookup_dn(user, who);
+- if (dn == NULL)
+- dn = who;
+-
+- rc = nm_send_remove_privacy_item(user, dn, TRUE,
+- _remove_privacy_item_resp_cb,
+- g_strdup(who));
+- _check_for_disconnect(user, rc);
+-}
+-
+-static void
+-novell_rem_deny(PurpleConnection *gc, const char *who)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+- const char *dn = NULL;
+-
+- if (gc == NULL || who == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- if (nm_user_is_privacy_locked(user)) {
+- _show_privacy_locked_error(gc, user);
+- _sync_privacy_lists(user);
+- return;
+- }
+-
+- dn = nm_lookup_dn(user, who);
+- if (dn == NULL)
+- dn = who;
+-
+- rc = nm_send_remove_privacy_item(user, dn, FALSE,
+- _remove_privacy_item_resp_cb,
+- g_strdup(who));
+- _check_for_disconnect(user, rc);
+-}
+-
+-static void
+-novell_set_permit_deny(PurpleConnection *gc)
+-{
+- NMERR_T rc = NM_OK;
+- const char *dn, *name = NULL;
+- NMUserRecord *user_record = NULL;
+- GSList *node = NULL, *copy = NULL;
+- NMUser *user;
+- int i, j, num_contacts, num_folders;
+- NMContact *contact;
+- NMFolder *folder = NULL;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- if (user->privacy_synched == FALSE) {
+- _sync_privacy_lists(user);
+- user->privacy_synched = TRUE;
+- return;
+- }
+-
+- if (nm_user_is_privacy_locked(user)) {
+- _show_privacy_locked_error(gc, user);
+- _sync_privacy_lists(user);
+- return;
+- }
+-
+- switch (gc->account->perm_deny) {
+-
+- case PURPLE_PRIVACY_ALLOW_ALL:
+- rc = nm_send_set_privacy_default(user, FALSE,
+- _set_privacy_default_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+- /* clear server side deny list */
+- if (rc == NM_OK) {
+- copy = g_slist_copy(user->deny_list);
+- for (node = copy; node && node->data; node = node->next) {
+- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
+- FALSE, NULL, NULL);
+- if (_check_for_disconnect(user, rc))
+- break;
+- }
+- g_slist_free(copy);
+- g_slist_free(user->deny_list);
+- user->deny_list = NULL;
+- }
+- break;
+-
+- case PURPLE_PRIVACY_DENY_ALL:
+- rc = nm_send_set_privacy_default(user, TRUE,
+- _set_privacy_default_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+- /* clear server side allow list */
+- if (rc == NM_OK) {
+- copy = g_slist_copy(user->allow_list);
+- for (node = copy; node && node->data; node = node->next) {
+- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
+- TRUE, NULL, NULL);
+- if (_check_for_disconnect(user, rc))
+- break;
+- }
+- g_slist_free(copy);
+- g_slist_free(user->allow_list);
+- user->allow_list = NULL;
+- }
+- break;
+-
+- case PURPLE_PRIVACY_ALLOW_USERS:
+-
+- rc = nm_send_set_privacy_default(user, TRUE,
+- _set_privacy_default_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+- /* sync allow lists */
+- if (rc == NM_OK) {
+-
+- for (node = user->allow_list; node; node = node->next) {
+- user_record = nm_find_user_record(user, (char *)node->data);
+- if (user_record) {
+- name = nm_user_record_get_display_id(user_record);
+-
+- if (!g_slist_find_custom(gc->account->permit,
+- name, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_permit_add(gc->account, name , TRUE);
+- }
+- }
+- }
+-
+- for (node = gc->account->permit; node; node = node->next) {
+- name = NULL;
+- dn = nm_lookup_dn(user, (char *)node->data);
+- if (dn) {
+- user_record = nm_find_user_record(user, dn);
+- name = nm_user_record_get_display_id(user_record);
+-
+- if (!g_slist_find_custom(user->allow_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
+- rc = nm_send_create_privacy_item(user, dn, TRUE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(dn));
+- }
+- } else {
+- purple_privacy_permit_remove(gc->account, (char *)node->data, TRUE);
+- }
+- }
+- }
+- break;
+-
+- case PURPLE_PRIVACY_DENY_USERS:
+-
+- /* set to default allow */
+- rc = nm_send_set_privacy_default(user, FALSE,
+- _set_privacy_default_resp_cb, NULL);
+- _check_for_disconnect(user, rc);
+-
+- /* sync deny lists */
+- if (rc == NM_OK) {
+-
+- for (node = user->deny_list; node; node = node->next) {
+- user_record = nm_find_user_record(user, (char *)node->data);
+- if (user_record) {
+- name = nm_user_record_get_display_id(user_record);
+-
+- if (!g_slist_find_custom(gc->account->deny,
+- name, (GCompareFunc)purple_utf8_strcasecmp)) {
+- purple_privacy_deny_add(gc->account, name , TRUE);
+- }
+- }
+- }
+-
+- for (node = gc->account->deny; node; node = node->next) {
+-
+- name = NULL;
+- dn = nm_lookup_dn(user, (char *)node->data);
+- if (dn) {
+- user_record = nm_find_user_record(user, dn);
+- name = nm_user_record_get_display_id(user_record);
+-
+- if (!g_slist_find_custom(user->deny_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp)) {
+- rc = nm_send_create_privacy_item(user, dn, FALSE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(name));
+- }
+- } else {
+- purple_privacy_deny_remove(gc->account, (char *)node->data, TRUE);
+- }
+- }
+-
+- }
+- break;
+-
+- case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
+-
+- /* remove users from allow list that are not in buddy list */
+- copy = g_slist_copy(user->allow_list);
+- for (node = copy; node && node->data; node = node->next) {
+- if (!nm_find_contacts(user, node->data)) {
+- rc = nm_send_remove_privacy_item(user, (const char *)node->data,
+- TRUE, NULL, NULL);
+- if (_check_for_disconnect(user, rc))
+- return;
+- }
+- }
+- g_slist_free(copy);
+-
+- /* add all buddies to allow list */
+- num_contacts = nm_folder_get_contact_count(user->root_folder);
+- for (i = 0; i < num_contacts; i++) {
+- contact = nm_folder_get_contact(user->root_folder, i);
+- dn = nm_contact_get_dn(contact);
+- if (dn && !g_slist_find_custom(user->allow_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp))
+- {
+- rc = nm_send_create_privacy_item(user, dn, TRUE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(dn));
+- if (_check_for_disconnect(user, rc))
+- return;
+- }
+-
+- }
+-
+- num_folders = nm_folder_get_subfolder_count(user->root_folder);
+- for (i = 0; i < num_folders; i++) {
+- folder = nm_folder_get_subfolder(user->root_folder, i);
+- num_contacts = nm_folder_get_contact_count(folder);
+- for (j = 0; j < num_contacts; j++) {
+- contact = nm_folder_get_contact(folder, j);
+- dn = nm_contact_get_dn(contact);
+- if (dn && !g_slist_find_custom(user->allow_list,
+- dn, (GCompareFunc)purple_utf8_strcasecmp))
+- {
+- rc = nm_send_create_privacy_item(user, dn, TRUE,
+- _create_privacy_item_deny_resp_cb,
+- g_strdup(dn));
+- if (_check_for_disconnect(user, rc))
+- return;
+- }
+- }
+- }
+-
+- /* set to default deny */
+- rc = nm_send_set_privacy_default(user, TRUE,
+- _set_privacy_default_resp_cb, NULL);
+- if (_check_for_disconnect(user, rc))
+- break;
+-
+- break;
+- }
+-}
+-
+-static GList *
+-novell_blist_node_menu(PurpleBlistNode *node)
+-{
+- GList *list = NULL;
+- PurpleMenuAction *act;
+-
+- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+- act = purple_menu_action_new(_("Initiate _Chat"),
+- PURPLE_CALLBACK(_initiate_conference_cb),
+- NULL, NULL);
+- list = g_list_append(list, act);
+- }
+-
+- return list;
+-}
+-
+-static void
+-novell_keepalive(PurpleConnection *gc)
+-{
+- NMUser *user;
+- NMERR_T rc = NM_OK;
+-
+- if (gc == NULL)
+- return;
+-
+- user = gc->proto_data;
+- if (user == NULL)
+- return;
+-
+- rc = nm_send_keepalive(user, NULL, NULL);
+- _check_for_disconnect(user, rc);
+-}
+-
+-static PurplePluginProtocolInfo prpl_info = {
+- 0,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- NO_BUDDY_ICONS, /* icon_spec */
+- novell_list_icon, /* list_icon */
+- NULL, /* list_emblems */
+- novell_status_text, /* status_text */
+- novell_tooltip_text, /* tooltip_text */
+- novell_status_types, /* status_types */
+- novell_blist_node_menu, /* blist_node_menu */
+- NULL, /* chat_info */
+- NULL, /* chat_info_defaults */
+- novell_login, /* login */
+- novell_close, /* close */
+- novell_send_im, /* send_im */
+- NULL, /* set_info */
+- novell_send_typing, /* send_typing */
+- novell_get_info, /* get_info */
+- novell_set_status, /* set_status */
+- novell_set_idle, /* set_idle */
+- NULL, /* change_passwd */
+- novell_add_buddy, /* add_buddy */
+- NULL, /* add_buddies */
+- novell_remove_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- novell_add_permit, /* add_permit */
+- novell_add_deny, /* add_deny */
+- novell_rem_permit, /* rem_permit */
+- novell_rem_deny, /* rem_deny */
+- novell_set_permit_deny, /* set_permit_deny */
+- NULL, /* join_chat */
+- NULL, /* reject_chat */
+- NULL, /* get_chat_name */
+- novell_chat_invite, /* chat_invite */
+- novell_chat_leave, /* chat_leave */
+- NULL, /* chat_whisper */
+- novell_chat_send, /* chat_send */
+- novell_keepalive, /* keepalive */
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- novell_alias_buddy, /* alias_buddy */
+- novell_group_buddy, /* group_buddy */
+- novell_rename_group, /* rename_group */
+- NULL, /* buddy_free */
+- novell_convo_closed, /* convo_closed */
+- purple_normalize_nocase, /* normalize */
+- NULL, /* set_buddy_icon */
+- novell_remove_group, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- NULL, /* can_receive_file */
+- NULL, /* send_file */
+- NULL, /* new_xfer */
+- NULL, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- NULL, /* send_attention */
+- NULL, /* get_attention_types */
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- NULL, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- NULL, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-novell", /**< id */
+- "GroupWise", /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("Novell GroupWise Messenger Protocol Plugin"),
+- /** description */
+- N_("Novell GroupWise Messenger Protocol Plugin"),
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+-
+- NULL, /**< load */
+- NULL, /**< unload */
+- NULL, /**< destroy */
+-
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL,
+- NULL,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin * plugin)
+-{
+- PurpleAccountOption *option;
+-
+- option = purple_account_option_string_new(_("Server address"), "server", NULL);
+- prpl_info.protocol_options =
+- g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_int_new(_("Server port"), "port", DEFAULT_PORT);
+- prpl_info.protocol_options =
+- g_list_append(prpl_info.protocol_options, option);
+-
+- my_protocol = plugin;
+-}
+-
+-PURPLE_INIT_PLUGIN(novell, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/null/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/null/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.in 2013-08-16 23:51:32.453142958 -0300
+@@ -184,8 +184,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -247,8 +245,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/null/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/null/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/null/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,79 +0,0 @@
+-#
+-# 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 install_real clean
+-
+-all: $(TARGET).dll
+-
+-install_real: all $(DLL_INSTALL_DIR) $(PURPLE_INSTALL_DIR)
+- cp $(TARGET).dll $(DLL_INSTALL_DIR)
+-
+-install: all
+-
+-$(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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/authorization.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/authorization.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/authorization.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/authorization.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,131 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Everything related to OSCAR authorization requests.
+- */
+-
+-#include "oscar.h"
+-#include "request.h"
+-
+-/* When you ask other people for authorization */
+-void
+-oscar_auth_sendrequest(PurpleConnection *gc, const char *bname, const char *msg)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- PurpleGroup *group;
+- const char *gname;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+- buddy = purple_find_buddy(account, bname);
+- if (buddy != NULL)
+- group = purple_buddy_get_group(buddy);
+- else
+- group = NULL;
+-
+- if (group != NULL)
+- {
+- gname = purple_group_get_name(group);
+- purple_debug_info("oscar", "ssi: adding buddy %s to group %s\n",
+- bname, gname);
+- aim_ssi_sendauthrequest(od, bname, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
+- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY))
+- {
+- aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
+-
+- /* Mobile users should always be online */
+- if (bname[0] == '+') {
+- purple_prpl_got_user_status(account,
+- purple_buddy_get_name(buddy),
+- OSCAR_STATUS_ID_AVAILABLE, NULL);
+- purple_prpl_got_user_status(account,
+- purple_buddy_get_name(buddy),
+- OSCAR_STATUS_ID_MOBILE, NULL);
+- }
+- }
+- }
+-}
+-
+-static void
+-oscar_auth_grant(gpointer cbdata)
+-{
+- struct name_data *data = cbdata;
+- PurpleConnection *gc = data->gc;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- aim_ssi_sendauthreply(od, data->name, 0x01, NULL);
+-
+- oscar_free_name_data(data);
+-}
+-
+-static void
+-oscar_auth_dontgrant(struct name_data *data, char *msg)
+-{
+- PurpleConnection *gc = data->gc;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- aim_ssi_sendauthreply(od, data->name, 0x00, msg ? msg : _("No reason given."));
+-
+- oscar_free_name_data(data);
+-}
+-
+-static void
+-oscar_auth_dontgrant_msgprompt(gpointer cbdata)
+-{
+- struct name_data *data = cbdata;
+- purple_request_input(data->gc, NULL, _("Authorization Denied Message:"),
+- NULL, _("No reason given."), TRUE, FALSE, NULL,
+- _("_OK"), G_CALLBACK(oscar_auth_dontgrant),
+- _("_Cancel"), G_CALLBACK(oscar_free_name_data),
+- purple_connection_get_account(data->gc), data->name, NULL,
+- data);
+-}
+-
+-void
+-oscar_auth_sendrequest_menu(PurpleBlistNode *node, gpointer ignored)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- oscar_auth_sendrequest(gc, purple_buddy_get_name(buddy), NULL);
+-}
+-
+-/* When other people ask you for authorization */
+-void
+-oscar_auth_recvrequest(PurpleConnection *gc, gchar *name, gchar *nick, gchar *reason)
+-{
+- PurpleAccount* account = purple_connection_get_account(gc);
+- struct name_data *data = g_new(struct name_data, 1);
+-
+- data->gc = gc;
+- data->name = name;
+- data->nick = nick;
+-
+- purple_account_request_authorization(account, data->name, NULL, data->nick,
+- reason, purple_find_buddy(account, data->name) != NULL,
+- oscar_auth_grant, oscar_auth_dontgrant_msgprompt, data);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/AUTHORS pidgin-2.10.7-nonprism/libpurple/protocols/oscar/AUTHORS
+--- pidgin-2.10.7/libpurple/protocols/oscar/AUTHORS 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/AUTHORS 1969-12-31 21:00:00.000000000 -0300
+@@ -1,49 +0,0 @@
+-
+-N: ComBOTS Product GmbH (htfv)
+-T: 2007
+-E: foss@combots.com
+-
+-N: Jonathan Clark
+-T: 2005-2006
+-E: ardentlygnarley a.t users d.o.t sourceforge d.o.t net
+-
+-N: Mark Doliner
+-T: 2001-2006
+-H: markdoliner
+-E: thekingant a.t users d.o.t sourceforge d.o.t net
+-W: http://kingant.net/
+-
+-N: Adam Fritzler
+-T: 1998-2001
+-H: mid
+-E: mid a.t auk d.o.t cx
+-W: http://www.auk.cx/~mid,http://www.auk.cx/faim
+-D: Wrote most of the wap of crap that you see before you.
+-
+-N: Josh Myer
+-T: 1998-2001
+-E: josh a.t joshisanerd d.o.t com
+-D: OFT/ODC (not quite finished yet..), random little things, Munger-At-Large, compile-time warnings.
+-
+-N: Daniel M. Pomerantz
+-H: dmprantz
+-D: Made initial versions cross platform
+-
+-N: Daniel Reed
+-T: 1998-2001
+-H: n, linuxkitty
+-E: n a.t ml d.o.t org
+-W: http://users.n.ml.org/n/
+-D: Fixed aim_snac.c
+-
+-N: Eric Warmenhoven
+-T: 1998-2001
+-E: warmenhoven a.t linux d.o.t com
+-D: Some OFT info, initial author of the libpurple-side of the oscar protocol plugin
+-
+-N: Brock Wilcox
+-T: 1998-2001
+-H: awwaiid
+-E: awwaiid a.t auk d.o.t cx
+-D: Figured out original password roasting
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/bstream.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/bstream.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/bstream.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/bstream.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,288 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * This file contains all functions needed to use bstreams.
+- */
+-
+-#include "oscar.h"
+-
+-int byte_stream_new(ByteStream *bs, size_t len)
+-{
+- if (bs == NULL)
+- return -1;
+-
+- return byte_stream_init(bs, g_malloc(len), len);
+-}
+-
+-int byte_stream_init(ByteStream *bs, guint8 *data, size_t len)
+-{
+- if (bs == NULL)
+- return -1;
+-
+- bs->data = data;
+- bs->len = len;
+- bs->offset = 0;
+-
+- return 0;
+-}
+-
+-void byte_stream_destroy(ByteStream *bs)
+-{
+- g_free(bs->data);
+-}
+-
+-int byte_stream_bytes_left(ByteStream *bs)
+-{
+- return bs->len - bs->offset;
+-}
+-
+-int byte_stream_curpos(ByteStream *bs)
+-{
+- return bs->offset;
+-}
+-
+-int byte_stream_setpos(ByteStream *bs, size_t off)
+-{
+- g_return_val_if_fail(off <= bs->len, -1);
+-
+- bs->offset = off;
+- return off;
+-}
+-
+-void byte_stream_rewind(ByteStream *bs)
+-{
+- byte_stream_setpos(bs, 0);
+-}
+-
+-/*
+- * N can be negative, which can be used for going backwards
+- * in a bstream.
+- */
+-int byte_stream_advance(ByteStream *bs, int n)
+-{
+- g_return_val_if_fail(byte_stream_curpos(bs) + n >= 0, 0);
+- g_return_val_if_fail(n <= byte_stream_bytes_left(bs), 0);
+-
+- bs->offset += n;
+- return n;
+-}
+-
+-guint8 byte_stream_get8(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
+-
+- bs->offset++;
+- return aimutil_get8(bs->data + bs->offset - 1);
+-}
+-
+-guint16 byte_stream_get16(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
+-
+- bs->offset += 2;
+- return aimutil_get16(bs->data + bs->offset - 2);
+-}
+-
+-guint32 byte_stream_get32(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
+-
+- bs->offset += 4;
+- return aimutil_get32(bs->data + bs->offset - 4);
+-}
+-
+-guint8 byte_stream_getle8(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
+-
+- bs->offset++;
+- return aimutil_getle8(bs->data + bs->offset - 1);
+-}
+-
+-guint16 byte_stream_getle16(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
+-
+- bs->offset += 2;
+- return aimutil_getle16(bs->data + bs->offset - 2);
+-}
+-
+-guint32 byte_stream_getle32(ByteStream *bs)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
+-
+- bs->offset += 4;
+- return aimutil_getle32(bs->data + bs->offset - 4);
+-}
+-
+-static void byte_stream_getrawbuf_nocheck(ByteStream *bs, guint8 *buf, size_t len)
+-{
+- memcpy(buf, bs->data + bs->offset, len);
+- bs->offset += len;
+-}
+-
+-int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, size_t len)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
+-
+- byte_stream_getrawbuf_nocheck(bs, buf, len);
+- return len;
+-}
+-
+-guint8 *byte_stream_getraw(ByteStream *bs, size_t len)
+-{
+- guint8 *ob;
+-
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL);
+-
+- ob = g_malloc(len);
+- byte_stream_getrawbuf_nocheck(bs, ob, len);
+- return ob;
+-}
+-
+-char *byte_stream_getstr(ByteStream *bs, size_t len)
+-{
+- char *ob;
+-
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, NULL);
+-
+- ob = g_malloc(len + 1);
+- byte_stream_getrawbuf_nocheck(bs, (guint8 *)ob, len);
+- ob[len] = '\0';
+- return ob;
+-}
+-
+-int byte_stream_put8(ByteStream *bs, guint8 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
+-
+- bs->offset += aimutil_put8(bs->data + bs->offset, v);
+- return 1;
+-}
+-
+-int byte_stream_put16(ByteStream *bs, guint16 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
+-
+- bs->offset += aimutil_put16(bs->data + bs->offset, v);
+- return 2;
+-}
+-
+-int byte_stream_put32(ByteStream *bs, guint32 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
+-
+- bs->offset += aimutil_put32(bs->data + bs->offset, v);
+- return 1;
+-}
+-
+-int byte_stream_putle8(ByteStream *bs, guint8 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 1, 0);
+-
+- bs->offset += aimutil_putle8(bs->data + bs->offset, v);
+- return 1;
+-}
+-
+-int byte_stream_putle16(ByteStream *bs, guint16 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 2, 0);
+-
+- bs->offset += aimutil_putle16(bs->data + bs->offset, v);
+- return 2;
+-}
+-
+-int byte_stream_putle32(ByteStream *bs, guint32 v)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= 4, 0);
+-
+- bs->offset += aimutil_putle32(bs->data + bs->offset, v);
+- return 1;
+-}
+-
+-
+-int byte_stream_putraw(ByteStream *bs, const guint8 *v, size_t len)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
+-
+- memcpy(bs->data + bs->offset, v, len);
+- bs->offset += len;
+- return len;
+-}
+-
+-int byte_stream_putstr(ByteStream *bs, const char *str)
+-{
+- return byte_stream_putraw(bs, (guint8 *)str, strlen(str));
+-}
+-
+-int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, size_t len)
+-{
+- g_return_val_if_fail(byte_stream_bytes_left(srcbs) >= len, 0);
+- g_return_val_if_fail(byte_stream_bytes_left(bs) >= len, 0);
+-
+- memcpy(bs->data + bs->offset, srcbs->data + srcbs->offset, len);
+- bs->offset += len;
+- srcbs->offset += len;
+- return len;
+-}
+-
+-int byte_stream_putuid(ByteStream *bs, OscarData *od)
+-{
+- PurpleAccount *account;
+-
+- account = purple_connection_get_account(od->gc);
+-
+- return byte_stream_putle32(bs, atoi(purple_account_get_username(account)));
+-}
+-
+-void byte_stream_put_bart_asset(ByteStream *bs, guint16 type, ByteStream *data)
+-{
+- byte_stream_put16(bs, type);
+-
+- if (data != NULL && data->len > 0) {
+- /* Flags. 0x04 means "this asset has data attached to it" */
+- byte_stream_put8(bs, 0x04); /* Flags */
+- byte_stream_put8(bs, data->len); /* Length */
+- byte_stream_rewind(data);
+- byte_stream_putbs(bs, data, data->len); /* Data */
+- } else {
+- byte_stream_put8(bs, 0x00); /* No flags */
+- byte_stream_put8(bs, 0x00); /* Length */
+- /* No data */
+- }
+-}
+-
+-void byte_stream_put_bart_asset_str(ByteStream *bs, guint16 type, const char *datastr)
+-{
+- ByteStream data;
+- size_t len = datastr != NULL ? strlen(datastr) : 0;
+-
+- if (len > 0) {
+- byte_stream_new(&data, 2 + len + 2);
+- byte_stream_put16(&data, len); /* Length */
+- byte_stream_putstr(&data, datastr); /* String */
+- byte_stream_put16(&data, 0x0000); /* Unknown */
+- byte_stream_put_bart_asset(bs, type, &data);
+- byte_stream_destroy(&data);
+- } else {
+- byte_stream_put_bart_asset(bs, type, NULL);
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/clientlogin.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/clientlogin.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/clientlogin.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/clientlogin.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,654 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/**
+- * This file implements AIM's clientLogin procedure for authenticating
+- * users. This replaces the older MD5-based and XOR-based
+- * authentication methods that use SNAC family 0x0017.
+- *
+- * This doesn't use SNACs or FLAPs at all. It makes http and https
+- * POSTs to AOL to validate the user based on the password they
+- * provided to us. Upon successful authentication we request a
+- * connection to the BOS server by calling startOSCARsession. The
+- * AOL server gives us the hostname and port number to use, as well
+- * as the cookie to use to authenticate to the BOS server. And then
+- * everything else is the same as with BUCP.
+- *
+- * For details, see:
+- * http://dev.aol.com/aim/oscar/#AUTH
+- * http://dev.aol.com/authentication_for_clients
+- */
+-
+-#include "oscar.h"
+-#include "oscarcommon.h"
+-
+-#include "cipher.h"
+-#include "core.h"
+-
+-#define AIM_LOGIN_HOST "api.screenname.aol.com"
+-#define ICQ_LOGIN_HOST "api.login.icq.net"
+-
+-#define AIM_API_HOST "api.oscar.aol.com"
+-#define ICQ_API_HOST "api.icq.net"
+-
+-#define CLIENT_LOGIN_PAGE "/auth/clientLogin"
+-#define START_OSCAR_SESSION_PAGE "/aim/startOSCARSession"
+-
+-#define HTTPS_FORMAT_URL(host, page) "https://" host page
+-
+-static const gchar *client_login_urls[] = {
+- HTTPS_FORMAT_URL(AIM_LOGIN_HOST, CLIENT_LOGIN_PAGE),
+- HTTPS_FORMAT_URL(ICQ_LOGIN_HOST, CLIENT_LOGIN_PAGE),
+-};
+-
+-static const gchar *start_oscar_session_urls[] = {
+- HTTPS_FORMAT_URL(AIM_API_HOST, START_OSCAR_SESSION_PAGE),
+- HTTPS_FORMAT_URL(ICQ_API_HOST, START_OSCAR_SESSION_PAGE),
+-};
+-
+-static const gchar *get_client_login_url(OscarData *od)
+-{
+- return client_login_urls[od->icq ? 1 : 0];
+-}
+-
+-static const gchar *get_start_oscar_session_url(OscarData *od)
+-{
+- return start_oscar_session_urls[od->icq ? 1 : 0];
+-}
+-
+-/*
+- * Using clientLogin requires a developer ID. This key is for libpurple.
+- * It is the default key for all libpurple-based clients. AOL encourages
+- * UIs (especially ones with lots of users) to override this with their
+- * own key. This key is owned by the AIM account "markdoliner"
+- *
+- * Keys can be managed at http://developer.aim.com/manageKeys.jsp
+- */
+-#define DEFAULT_CLIENT_KEY "ma15d7JTxbmVG-RP"
+-
+-static const char *get_client_key(OscarData *od)
+-{
+- return oscar_get_ui_info_string(
+- od->icq ? "prpl-icq-clientkey" : "prpl-aim-clientkey",
+- DEFAULT_CLIENT_KEY);
+-}
+-
+-static gchar *generate_error_message(xmlnode *resp, const char *url)
+-{
+- xmlnode *text;
+- xmlnode *status_code_node;
+- gchar *status_code;
+- gboolean have_error_code = TRUE;
+- gchar *err = NULL;
+- gchar *details = NULL;
+-
+- status_code_node = xmlnode_get_child(resp, "statusCode");
+- if (status_code_node) {
+- /* We can get 200 OK here if the server omitted something we think it shouldn't have (see #12783).
+- * No point in showing the "Ok" string to the user.
+- */
+- if ((status_code = xmlnode_get_data_unescaped(status_code_node)) && strcmp(status_code, "200") == 0) {
+- have_error_code = FALSE;
+- }
+- }
+- if (have_error_code && resp && (text = xmlnode_get_child(resp, "statusText"))) {
+- details = xmlnode_get_data(text);
+- }
+-
+- if (details && *details) {
+- err = g_strdup_printf(_("Received unexpected response from %s: %s"), url, details);
+- } else {
+- err = g_strdup_printf(_("Received unexpected response from %s"), url);
+- }
+-
+- g_free(details);
+- return err;
+-}
+-
+-/**
+- * @return A null-terminated base64 encoded version of the HMAC
+- * calculated using the given key and data.
+- */
+-static gchar *hmac_sha256(const char *key, const char *message)
+-{
+- PurpleCipherContext *context;
+- guchar digest[32];
+-
+- context = purple_cipher_context_new_by_name("hmac", NULL);
+- purple_cipher_context_set_option(context, "hash", "sha256");
+- purple_cipher_context_set_key(context, (guchar *)key);
+- purple_cipher_context_append(context, (guchar *)message, strlen(message));
+- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- return purple_base64_encode(digest, sizeof(digest));
+-}
+-
+-/**
+- * @return A base-64 encoded HMAC-SHA256 signature created using the
+- * technique documented at
+- * http://dev.aol.com/authentication_for_clients#signing
+- */
+-static gchar *generate_signature(const char *method, const char *url, const char *parameters, const char *session_key)
+-{
+- char *encoded_url, *signature_base_string, *signature;
+- const char *encoded_parameters;
+-
+- encoded_url = g_strdup(purple_url_encode(url));
+- encoded_parameters = purple_url_encode(parameters);
+- signature_base_string = g_strdup_printf("%s&%s&%s",
+- method, encoded_url, encoded_parameters);
+- g_free(encoded_url);
+-
+- signature = hmac_sha256(session_key, signature_base_string);
+- g_free(signature_base_string);
+-
+- return signature;
+-}
+-
+-static gboolean parse_start_oscar_session_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **host, unsigned short *port, char **cookie, char **tls_certname)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- xmlnode *response_node, *tmp_node, *data_node;
+- xmlnode *host_node = NULL, *port_node = NULL, *cookie_node = NULL, *tls_node = NULL;
+- char *tmp;
+- guint code;
+- const gchar *encryption_type = purple_account_get_string(purple_connection_get_account(gc), "encryption", OSCAR_DEFAULT_ENCRYPTION);
+-
+- /* Parse the response as XML */
+- response_node = xmlnode_from_str(response, response_len);
+- if (response_node == NULL)
+- {
+- char *msg;
+- purple_debug_error("oscar", "startOSCARSession could not parse "
+- "response as XML: %s\n", response);
+- /* Note to translators: %s in this string is a URL */
+- msg = generate_error_message(response_node,
+- get_start_oscar_session_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- return FALSE;
+- }
+-
+- /* Grab the necessary XML nodes */
+- tmp_node = xmlnode_get_child(response_node, "statusCode");
+- data_node = xmlnode_get_child(response_node, "data");
+- if (data_node != NULL) {
+- host_node = xmlnode_get_child(data_node, "host");
+- port_node = xmlnode_get_child(data_node, "port");
+- cookie_node = xmlnode_get_child(data_node, "cookie");
+- }
+-
+- /* Make sure we have a status code */
+- if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
+- char *msg;
+- purple_debug_error("oscar", "startOSCARSession response was "
+- "missing statusCode: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_start_oscar_session_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- /* Make sure the status code was 200 */
+- code = atoi(tmp);
+- if (code != 200)
+- {
+- xmlnode *status_detail_node;
+- guint status_detail = 0;
+-
+- status_detail_node = xmlnode_get_child(response_node,
+- "statusDetailCode");
+- if (status_detail_node) {
+- gchar *data = xmlnode_get_data(status_detail_node);
+- if (data) {
+- status_detail = atoi(data);
+- g_free(data);
+- }
+- }
+-
+- purple_debug_error("oscar", "startOSCARSession response statusCode "
+- "was %s: %s\n", tmp, response);
+-
+- if ((code == 401 && status_detail != 1014) || code == 607)
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+- _("You have been connecting and disconnecting too "
+- "frequently. Wait ten minutes and try again. If "
+- "you continue to try, you will need to wait even "
+- "longer."));
+- else {
+- char *msg;
+- msg = generate_error_message(response_node,
+- get_start_oscar_session_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
+- g_free(msg);
+- }
+-
+- g_free(tmp);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+- g_free(tmp);
+-
+- /* Make sure we have everything else */
+- if (data_node == NULL || host_node == NULL || port_node == NULL || cookie_node == NULL)
+- {
+- char *msg;
+- purple_debug_error("oscar", "startOSCARSession response was missing "
+- "something: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_start_oscar_session_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- if (strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0) {
+- tls_node = xmlnode_get_child(data_node, "tlsCertName");
+- if (tls_node != NULL) {
+- *tls_certname = xmlnode_get_data_unescaped(tls_node);
+- } else {
+- if (strcmp(encryption_type, OSCAR_OPPORTUNISTIC_ENCRYPTION) == 0) {
+- purple_debug_warning("oscar", "We haven't received a tlsCertName to use. We will not do SSL to BOS.\n");
+- } else {
+- purple_debug_error("oscar", "startOSCARSession was missing tlsCertName: %s\n", response);
+- purple_connection_error_reason(
+- gc,
+- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+- _("You required encryption in your account settings, but one of the servers doesn't support it."));
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+- }
+- }
+-
+- /* Extract data from the XML */
+- *host = xmlnode_get_data_unescaped(host_node);
+- tmp = xmlnode_get_data_unescaped(port_node);
+- *cookie = xmlnode_get_data_unescaped(cookie_node);
+-
+- if (*host == NULL || **host == '\0' || tmp == NULL || *tmp == '\0' || *cookie == NULL || **cookie == '\0')
+- {
+- char *msg;
+- purple_debug_error("oscar", "startOSCARSession response was missing "
+- "something: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_start_oscar_session_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- g_free(*host);
+- g_free(tmp);
+- g_free(*cookie);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- *port = atoi(tmp);
+- g_free(tmp);
+-
+- return TRUE;
+-}
+-
+-static void start_oscar_session_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
+-{
+- OscarData *od;
+- PurpleConnection *gc;
+- char *host, *cookie;
+- char *tls_certname = NULL;
+- unsigned short port;
+- guint8 *cookiedata;
+- gsize cookiedata_len = 0;
+-
+- od = user_data;
+- gc = od->gc;
+-
+- od->url_data = NULL;
+-
+- if (error_message != NULL || len == 0) {
+- gchar *tmp;
+- /* Note to translators: The first %s is a URL, the second is an
+- error message. */
+- tmp = g_strdup_printf(_("Error requesting %s: %s"),
+- get_start_oscar_session_url(od), error_message ?
+- error_message : _("The server returned an empty response"));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- if (!parse_start_oscar_session_response(gc, url_text, len, &host, &port, &cookie, &tls_certname))
+- return;
+-
+- cookiedata = purple_base64_decode(cookie, &cookiedata_len);
+- oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len, tls_certname);
+- g_free(cookiedata);
+-
+- g_free(host);
+- g_free(cookie);
+- g_free(tls_certname);
+-}
+-
+-static void send_start_oscar_session(OscarData *od, const char *token, const char *session_key, time_t hosttime)
+-{
+- char *query_string, *signature, *url;
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- const gchar *encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
+-
+- /*
+- * Construct the GET parameters. 0x00000611 is the distid given to
+- * us by AOL for use as the default libpurple distid.
+- */
+- query_string = g_strdup_printf("a=%s"
+- "&distId=%d"
+- "&f=xml"
+- "&k=%s"
+- "&ts=%" PURPLE_TIME_T_MODIFIER
+- "&useTLS=%d",
+- purple_url_encode(token),
+- oscar_get_ui_info_int(od->icq ? "prpl-icq-distid" : "prpl-aim-distid", 0x00000611),
+- get_client_key(od),
+- hosttime,
+- strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0 ? 1 : 0);
+- signature = generate_signature("GET", get_start_oscar_session_url(od),
+- query_string, session_key);
+- url = g_strdup_printf("%s?%s&sig_sha256=%s", get_start_oscar_session_url(od),
+- query_string, signature);
+- g_free(query_string);
+- g_free(signature);
+-
+- /* Make the request */
+- od->url_data = purple_util_fetch_url_request_len_with_account(account,
+- url, TRUE, NULL, FALSE, NULL, FALSE, -1,
+- start_oscar_session_cb, od);
+- g_free(url);
+-}
+-
+-/**
+- * This function parses the given response from a clientLogin request
+- * and extracts the useful information.
+- *
+- * @param gc The PurpleConnection. If the response data does
+- * not indicate then purple_connection_error_reason()
+- * will be called to close this connection.
+- * @param response The response data from the clientLogin request.
+- * @param response_len The length of the above response, or -1 if
+- * @response is NUL terminated.
+- * @param token If parsing was successful then this will be set to
+- * a newly allocated string containing the token. The
+- * caller should g_free this string when it is finished
+- * with it. On failure this value will be untouched.
+- * @param secret If parsing was successful then this will be set to
+- * a newly allocated string containing the secret. The
+- * caller should g_free this string when it is finished
+- * with it. On failure this value will be untouched.
+- * @param hosttime If parsing was successful then this will be set to
+- * the time on the OpenAuth Server in seconds since the
+- * Unix epoch. On failure this value will be untouched.
+- *
+- * @return TRUE if the request was successful and we were able to
+- * extract all info we need. Otherwise FALSE.
+- */
+-static gboolean parse_client_login_response(PurpleConnection *gc, const gchar *response, gsize response_len, char **token, char **secret, time_t *hosttime)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- xmlnode *response_node, *tmp_node, *data_node;
+- xmlnode *secret_node = NULL, *hosttime_node = NULL, *token_node = NULL, *tokena_node = NULL;
+- char *tmp;
+-
+- /* Parse the response as XML */
+- response_node = xmlnode_from_str(response, response_len);
+- if (response_node == NULL)
+- {
+- char *msg;
+- purple_debug_error("oscar", "clientLogin could not parse "
+- "response as XML: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_client_login_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- return FALSE;
+- }
+-
+- /* Grab the necessary XML nodes */
+- tmp_node = xmlnode_get_child(response_node, "statusCode");
+- data_node = xmlnode_get_child(response_node, "data");
+- if (data_node != NULL) {
+- secret_node = xmlnode_get_child(data_node, "sessionSecret");
+- hosttime_node = xmlnode_get_child(data_node, "hostTime");
+- token_node = xmlnode_get_child(data_node, "token");
+- if (token_node != NULL)
+- tokena_node = xmlnode_get_child(token_node, "a");
+- }
+-
+- /* Make sure we have a status code */
+- if (tmp_node == NULL || (tmp = xmlnode_get_data_unescaped(tmp_node)) == NULL) {
+- char *msg;
+- purple_debug_error("oscar", "clientLogin response was "
+- "missing statusCode: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_client_login_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- /* Make sure the status code was 200 */
+- if (strcmp(tmp, "200") != 0)
+- {
+- int status_code, status_detail_code = 0;
+-
+- status_code = atoi(tmp);
+- g_free(tmp);
+- tmp_node = xmlnode_get_child(response_node, "statusDetailCode");
+- if (tmp_node != NULL && (tmp = xmlnode_get_data_unescaped(tmp_node)) != NULL) {
+- status_detail_code = atoi(tmp);
+- g_free(tmp);
+- }
+-
+- purple_debug_error("oscar", "clientLogin response statusCode "
+- "was %d (%d): %s\n", status_code, status_detail_code, response);
+-
+- if (status_code == 330 && status_detail_code == 3011) {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+- _("Incorrect password"));
+- } else if (status_code == 330 && status_detail_code == 3015) {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+- _("Server requested that you fill out a CAPTCHA in order to "
+- "sign in, but this client does not currently support CAPTCHAs."));
+- } else if (status_code == 401 && status_detail_code == 3019) {
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR,
+- _("AOL does not allow your screen name to authenticate here"));
+- } else {
+- char *msg;
+- msg = generate_error_message(response_node,
+- get_client_login_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_OTHER_ERROR, msg);
+- g_free(msg);
+- }
+-
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+- g_free(tmp);
+-
+- /* Make sure we have everything else */
+- if (data_node == NULL || secret_node == NULL ||
+- token_node == NULL || tokena_node == NULL)
+- {
+- char *msg;
+- purple_debug_error("oscar", "clientLogin response was missing "
+- "something: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_client_login_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- /* Extract data from the XML */
+- *token = xmlnode_get_data_unescaped(tokena_node);
+- *secret = xmlnode_get_data_unescaped(secret_node);
+- tmp = xmlnode_get_data_unescaped(hosttime_node);
+- if (*token == NULL || **token == '\0' || *secret == NULL || **secret == '\0' || tmp == NULL || *tmp == '\0')
+- {
+- char *msg;
+- purple_debug_error("oscar", "clientLogin response was missing "
+- "something: %s\n", response);
+- msg = generate_error_message(response_node,
+- get_client_login_url(od));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- g_free(*token);
+- g_free(*secret);
+- g_free(tmp);
+- xmlnode_free(response_node);
+- return FALSE;
+- }
+-
+- *hosttime = strtol(tmp, NULL, 10);
+- g_free(tmp);
+-
+- xmlnode_free(response_node);
+-
+- return TRUE;
+-}
+-
+-static void client_login_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
+-{
+- OscarData *od;
+- PurpleConnection *gc;
+- char *token, *secret, *session_key;
+- time_t hosttime;
+- int password_len;
+- char *password;
+-
+- od = user_data;
+- gc = od->gc;
+-
+- od->url_data = NULL;
+-
+- if (error_message != NULL || len == 0) {
+- gchar *tmp;
+- tmp = g_strdup_printf(_("Error requesting %s: %s"),
+- get_client_login_url(od), error_message ?
+- error_message : _("The server returned an empty response"));
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- if (!parse_client_login_response(gc, url_text, len, &token, &secret, &hosttime))
+- return;
+-
+- password_len = strlen(purple_connection_get_password(gc));
+- password = g_strdup_printf("%.*s",
+- od->icq ? MIN(password_len, MAXICQPASSLEN) : password_len,
+- purple_connection_get_password(gc));
+- session_key = hmac_sha256(password, secret);
+- g_free(password);
+- g_free(secret);
+-
+- send_start_oscar_session(od, token, session_key, hosttime);
+-
+- g_free(token);
+- g_free(session_key);
+-}
+-
+-/**
+- * This function sends a request to
+- * https://api.screenname.aol.com/auth/clientLogin with the user's
+- * username and password and receives the user's session key, which is
+- * used to request a connection to the BOSS server.
+- */
+-void send_client_login(OscarData *od, const char *username)
+-{
+- PurpleConnection *gc;
+- GString *request, *body;
+- const char *tmp;
+- char *password;
+- int password_len;
+-
+- gc = od->gc;
+-
+- /*
+- * We truncate ICQ passwords to 8 characters. There is probably a
+- * limit for AIM passwords, too, but we really only need to do
+- * this for ICQ because older ICQ clients let you enter a password
+- * as long as you wanted and then they truncated it silently.
+- *
+- * And we can truncate based on the number of bytes and not the
+- * number of characters because passwords for AIM and ICQ are
+- * supposed to be plain ASCII (I don't know if this has always been
+- * the case, though).
+- */
+- tmp = purple_connection_get_password(gc);
+- password_len = strlen(tmp);
+- password = g_strndup(tmp, od->icq ? MIN(password_len, MAXICQPASSLEN) : password_len);
+-
+- /* Construct the body of the HTTP POST request */
+- body = g_string_new("");
+- g_string_append_printf(body, "devId=%s", get_client_key(od));
+- g_string_append_printf(body, "&f=xml");
+- g_string_append_printf(body, "&pwd=%s", purple_url_encode(password));
+- g_string_append_printf(body, "&s=%s", purple_url_encode(username));
+- g_free(password);
+-
+- /* Construct an HTTP POST request */
+- request = g_string_new("POST /auth/clientLogin HTTP/1.0\r\n"
+- "Connection: close\r\n"
+- "Accept: */*\r\n");
+-
+- /* Tack on the body */
+- g_string_append_printf(request, "Content-Type: application/x-www-form-urlencoded; charset=UTF-8\r\n");
+- g_string_append_printf(request, "Content-Length: %" G_GSIZE_FORMAT "\r\n\r\n", body->len);
+- g_string_append_len(request, body->str, body->len);
+- g_string_free(body, TRUE);
+-
+- /* Send the POST request */
+- od->url_data = purple_util_fetch_url_request_len_with_account(
+- purple_connection_get_account(gc), get_client_login_url(od),
+- TRUE, NULL, FALSE, request->str, FALSE, -1,
+- client_login_cb, od);
+- g_string_free(request, TRUE);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/COPYING pidgin-2.10.7-nonprism/libpurple/protocols/oscar/COPYING
+--- pidgin-2.10.7/libpurple/protocols/oscar/COPYING 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/COPYING 1969-12-31 21:00:00.000000000 -0300
+@@ -1,504 +0,0 @@
+- GNU LESSER GENERAL PUBLIC LICENSE
+- Version 2.1, February 1999
+-
+- Copyright (C) 1991, 1999 Free Software Foundation, Inc.
+- 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- Everyone is permitted to copy and distribute verbatim copies
+- of this license document, but changing it is not allowed.
+-
+-[This is the first released version of the Lesser GPL. It also counts
+- as the successor of the GNU Library Public License, version 2, hence
+- the version number 2.1.]
+-
+- Preamble
+-
+- The licenses for most software are designed to take away your
+-freedom to share and change it. By contrast, the GNU General Public
+-Licenses are intended to guarantee your freedom to share and change
+-free software--to make sure the software is free for all its users.
+-
+- This license, the Lesser General Public License, applies to some
+-specially designated software packages--typically libraries--of the
+-Free Software Foundation and other authors who decide to use it. You
+-can use it too, but we suggest you first think carefully about whether
+-this license or the ordinary General Public License is the better
+-strategy to use in any particular case, based on the explanations below.
+-
+- When we speak of free software, we are referring to freedom of use,
+-not price. Our General Public Licenses are designed to make sure that
+-you have the freedom to distribute copies of free software (and charge
+-for this service if you wish); that you receive source code or can get
+-it if you want it; that you can change the software and use pieces of
+-it in new free programs; and that you are informed that you can do
+-these things.
+-
+- To protect your rights, we need to make restrictions that forbid
+-distributors to deny you these rights or to ask you to surrender these
+-rights. These restrictions translate to certain responsibilities for
+-you if you distribute copies of the library or if you modify it.
+-
+- For example, if you distribute copies of the library, whether gratis
+-or for a fee, you must give the recipients all the rights that we gave
+-you. You must make sure that they, too, receive or can get the source
+-code. If you link other code with the library, you must provide
+-complete object files to the recipients, so that they can relink them
+-with the library after making changes to the library and recompiling
+-it. And you must show them these terms so they know their rights.
+-
+- We protect your rights with a two-step method: (1) we copyright the
+-library, and (2) we offer you this license, which gives you legal
+-permission to copy, distribute and/or modify the library.
+-
+- To protect each distributor, we want to make it very clear that
+-there is no warranty for the free library. Also, if the library is
+-modified by someone else and passed on, the recipients should know
+-that what they have is not the original version, so that the original
+-author's reputation will not be affected by problems that might be
+-introduced by others.
+-
+- Finally, software patents pose a constant threat to the existence of
+-any free program. We wish to make sure that a company cannot
+-effectively restrict the users of a free program by obtaining a
+-restrictive license from a patent holder. Therefore, we insist that
+-any patent license obtained for a version of the library must be
+-consistent with the full freedom of use specified in this license.
+-
+- Most GNU software, including some libraries, is covered by the
+-ordinary GNU General Public License. This license, the GNU Lesser
+-General Public License, applies to certain designated libraries, and
+-is quite different from the ordinary General Public License. We use
+-this license for certain libraries in order to permit linking those
+-libraries into non-free programs.
+-
+- When a program is linked with a library, whether statically or using
+-a shared library, the combination of the two is legally speaking a
+-combined work, a derivative of the original library. The ordinary
+-General Public License therefore permits such linking only if the
+-entire combination fits its criteria of freedom. The Lesser General
+-Public License permits more lax criteria for linking other code with
+-the library.
+-
+- We call this license the "Lesser" General Public License because it
+-does Less to protect the user's freedom than the ordinary General
+-Public License. It also provides other free software developers Less
+-of an advantage over competing non-free programs. These disadvantages
+-are the reason we use the ordinary General Public License for many
+-libraries. However, the Lesser license provides advantages in certain
+-special circumstances.
+-
+- For example, on rare occasions, there may be a special need to
+-encourage the widest possible use of a certain library, so that it becomes
+-a de-facto standard. To achieve this, non-free programs must be
+-allowed to use the library. A more frequent case is that a free
+-library does the same job as widely used non-free libraries. In this
+-case, there is little to gain by limiting the free library to free
+-software only, so we use the Lesser General Public License.
+-
+- In other cases, permission to use a particular library in non-free
+-programs enables a greater number of people to use a large body of
+-free software. For example, permission to use the GNU C Library in
+-non-free programs enables many more people to use the whole GNU
+-operating system, as well as its variant, the GNU/Linux operating
+-system.
+-
+- Although the Lesser General Public License is Less protective of the
+-users' freedom, it does ensure that the user of a program that is
+-linked with the Library has the freedom and the wherewithal to run
+-that program using a modified version of the Library.
+-
+- The precise terms and conditions for copying, distribution and
+-modification follow. Pay close attention to the difference between a
+-"work based on the library" and a "work that uses the library". The
+-former contains code derived from the library, whereas the latter must
+-be combined with the library in order to run.
+-
+- GNU LESSER GENERAL PUBLIC LICENSE
+- TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
+-
+- 0. This License Agreement applies to any software library or other
+-program which contains a notice placed by the copyright holder or
+-other authorized party saying it may be distributed under the terms of
+-this Lesser General Public License (also called "this License").
+-Each licensee is addressed as "you".
+-
+- A "library" means a collection of software functions and/or data
+-prepared so as to be conveniently linked with application programs
+-(which use some of those functions and data) to form executables.
+-
+- The "Library", below, refers to any such software library or work
+-which has been distributed under these terms. A "work based on the
+-Library" means either the Library or any derivative work under
+-copyright law: that is to say, a work containing the Library or a
+-portion of it, either verbatim or with modifications and/or translated
+-straightforwardly into another language. (Hereinafter, translation is
+-included without limitation in the term "modification".)
+-
+- "Source code" for a work means the preferred form of the work for
+-making modifications to it. For a library, complete source code means
+-all the source code for all modules it contains, plus any associated
+-interface definition files, plus the scripts used to control compilation
+-and installation of the library.
+-
+- Activities other than copying, distribution and modification are not
+-covered by this License; they are outside its scope. The act of
+-running a program using the Library is not restricted, and output from
+-such a program is covered only if its contents constitute a work based
+-on the Library (independent of the use of the Library in a tool for
+-writing it). Whether that is true depends on what the Library does
+-and what the program that uses the Library does.
+-
+- 1. You may copy and distribute verbatim copies of the Library's
+-complete source code as you receive it, in any medium, provided that
+-you conspicuously and appropriately publish on each copy an
+-appropriate copyright notice and disclaimer of warranty; keep intact
+-all the notices that refer to this License and to the absence of any
+-warranty; and distribute a copy of this License along with the
+-Library.
+-
+- You may charge a fee for the physical act of transferring a copy,
+-and you may at your option offer warranty protection in exchange for a
+-fee.
+-
+- 2. You may modify your copy or copies of the Library or any portion
+-of it, thus forming a work based on the Library, and copy and
+-distribute such modifications or work under the terms of Section 1
+-above, provided that you also meet all of these conditions:
+-
+- a) The modified work must itself be a software library.
+-
+- b) You must cause the files modified to carry prominent notices
+- stating that you changed the files and the date of any change.
+-
+- c) You must cause the whole of the work to be licensed at no
+- charge to all third parties under the terms of this License.
+-
+- d) If a facility in the modified Library refers to a function or a
+- table of data to be supplied by an application program that uses
+- the facility, other than as an argument passed when the facility
+- is invoked, then you must make a good faith effort to ensure that,
+- in the event an application does not supply such function or
+- table, the facility still operates, and performs whatever part of
+- its purpose remains meaningful.
+-
+- (For example, a function in a library to compute square roots has
+- a purpose that is entirely well-defined independent of the
+- application. Therefore, Subsection 2d requires that any
+- application-supplied function or table used by this function must
+- be optional: if the application does not supply it, the square
+- root function must still compute square roots.)
+-
+-These requirements apply to the modified work as a whole. If
+-identifiable sections of that work are not derived from the Library,
+-and can be reasonably considered independent and separate works in
+-themselves, then this License, and its terms, do not apply to those
+-sections when you distribute them as separate works. But when you
+-distribute the same sections as part of a whole which is a work based
+-on the Library, the distribution of the whole must be on the terms of
+-this License, whose permissions for other licensees extend to the
+-entire whole, and thus to each and every part regardless of who wrote
+-it.
+-
+-Thus, it is not the intent of this section to claim rights or contest
+-your rights to work written entirely by you; rather, the intent is to
+-exercise the right to control the distribution of derivative or
+-collective works based on the Library.
+-
+-In addition, mere aggregation of another work not based on the Library
+-with the Library (or with a work based on the Library) on a volume of
+-a storage or distribution medium does not bring the other work under
+-the scope of this License.
+-
+- 3. You may opt to apply the terms of the ordinary GNU General Public
+-License instead of this License to a given copy of the Library. To do
+-this, you must alter all the notices that refer to this License, so
+-that they refer to the ordinary GNU General Public License, version 2,
+-instead of to this License. (If a newer version than version 2 of the
+-ordinary GNU General Public License has appeared, then you can specify
+-that version instead if you wish.) Do not make any other change in
+-these notices.
+-
+- Once this change is made in a given copy, it is irreversible for
+-that copy, so the ordinary GNU General Public License applies to all
+-subsequent copies and derivative works made from that copy.
+-
+- This option is useful when you wish to copy part of the code of
+-the Library into a program that is not a library.
+-
+- 4. You may copy and distribute the Library (or a portion or
+-derivative of it, under Section 2) in object code or executable form
+-under the terms of Sections 1 and 2 above provided that you accompany
+-it with the complete corresponding machine-readable source code, which
+-must be distributed under the terms of Sections 1 and 2 above on a
+-medium customarily used for software interchange.
+-
+- If distribution of object code is made by offering access to copy
+-from a designated place, then offering equivalent access to copy the
+-source code from the same place satisfies the requirement to
+-distribute the source code, even though third parties are not
+-compelled to copy the source along with the object code.
+-
+- 5. A program that contains no derivative of any portion of the
+-Library, but is designed to work with the Library by being compiled or
+-linked with it, is called a "work that uses the Library". Such a
+-work, in isolation, is not a derivative work of the Library, and
+-therefore falls outside the scope of this License.
+-
+- However, linking a "work that uses the Library" with the Library
+-creates an executable that is a derivative of the Library (because it
+-contains portions of the Library), rather than a "work that uses the
+-library". The executable is therefore covered by this License.
+-Section 6 states terms for distribution of such executables.
+-
+- When a "work that uses the Library" uses material from a header file
+-that is part of the Library, the object code for the work may be a
+-derivative work of the Library even though the source code is not.
+-Whether this is true is especially significant if the work can be
+-linked without the Library, or if the work is itself a library. The
+-threshold for this to be true is not precisely defined by law.
+-
+- If such an object file uses only numerical parameters, data
+-structure layouts and accessors, and small macros and small inline
+-functions (ten lines or less in length), then the use of the object
+-file is unrestricted, regardless of whether it is legally a derivative
+-work. (Executables containing this object code plus portions of the
+-Library will still fall under Section 6.)
+-
+- Otherwise, if the work is a derivative of the Library, you may
+-distribute the object code for the work under the terms of Section 6.
+-Any executables containing that work also fall under Section 6,
+-whether or not they are linked directly with the Library itself.
+-
+- 6. As an exception to the Sections above, you may also combine or
+-link a "work that uses the Library" with the Library to produce a
+-work containing portions of the Library, and distribute that work
+-under terms of your choice, provided that the terms permit
+-modification of the work for the customer's own use and reverse
+-engineering for debugging such modifications.
+-
+- You must give prominent notice with each copy of the work that the
+-Library is used in it and that the Library and its use are covered by
+-this License. You must supply a copy of this License. If the work
+-during execution displays copyright notices, you must include the
+-copyright notice for the Library among them, as well as a reference
+-directing the user to the copy of this License. Also, you must do one
+-of these things:
+-
+- a) Accompany the work with the complete corresponding
+- machine-readable source code for the Library including whatever
+- changes were used in the work (which must be distributed under
+- Sections 1 and 2 above); and, if the work is an executable linked
+- with the Library, with the complete machine-readable "work that
+- uses the Library", as object code and/or source code, so that the
+- user can modify the Library and then relink to produce a modified
+- executable containing the modified Library. (It is understood
+- that the user who changes the contents of definitions files in the
+- Library will not necessarily be able to recompile the application
+- to use the modified definitions.)
+-
+- b) Use a suitable shared library mechanism for linking with the
+- Library. A suitable mechanism is one that (1) uses at run time a
+- copy of the library already present on the user's computer system,
+- rather than copying library functions into the executable, and (2)
+- will operate properly with a modified version of the library, if
+- the user installs one, as long as the modified version is
+- interface-compatible with the version that the work was made with.
+-
+- c) Accompany the work with a written offer, valid for at
+- least three years, to give the same user the materials
+- specified in Subsection 6a, above, for a charge no more
+- than the cost of performing this distribution.
+-
+- d) If distribution of the work is made by offering access to copy
+- from a designated place, offer equivalent access to copy the above
+- specified materials from the same place.
+-
+- e) Verify that the user has already received a copy of these
+- materials or that you have already sent this user a copy.
+-
+- For an executable, the required form of the "work that uses the
+-Library" must include any data and utility programs needed for
+-reproducing the executable from it. However, as a special exception,
+-the materials to be distributed need not include anything that is
+-normally distributed (in either source or binary form) with the major
+-components (compiler, kernel, and so on) of the operating system on
+-which the executable runs, unless that component itself accompanies
+-the executable.
+-
+- It may happen that this requirement contradicts the license
+-restrictions of other proprietary libraries that do not normally
+-accompany the operating system. Such a contradiction means you cannot
+-use both them and the Library together in an executable that you
+-distribute.
+-
+- 7. You may place library facilities that are a work based on the
+-Library side-by-side in a single library together with other library
+-facilities not covered by this License, and distribute such a combined
+-library, provided that the separate distribution of the work based on
+-the Library and of the other library facilities is otherwise
+-permitted, and provided that you do these two things:
+-
+- a) Accompany the combined library with a copy of the same work
+- based on the Library, uncombined with any other library
+- facilities. This must be distributed under the terms of the
+- Sections above.
+-
+- b) Give prominent notice with the combined library of the fact
+- that part of it is a work based on the Library, and explaining
+- where to find the accompanying uncombined form of the same work.
+-
+- 8. You may not copy, modify, sublicense, link with, or distribute
+-the Library except as expressly provided under this License. Any
+-attempt otherwise to copy, modify, sublicense, link with, or
+-distribute the Library is void, and will automatically terminate your
+-rights under this License. However, parties who have received copies,
+-or rights, from you under this License will not have their licenses
+-terminated so long as such parties remain in full compliance.
+-
+- 9. You are not required to accept this License, since you have not
+-signed it. However, nothing else grants you permission to modify or
+-distribute the Library or its derivative works. These actions are
+-prohibited by law if you do not accept this License. Therefore, by
+-modifying or distributing the Library (or any work based on the
+-Library), you indicate your acceptance of this License to do so, and
+-all its terms and conditions for copying, distributing or modifying
+-the Library or works based on it.
+-
+- 10. Each time you redistribute the Library (or any work based on the
+-Library), the recipient automatically receives a license from the
+-original licensor to copy, distribute, link with or modify the Library
+-subject to these terms and conditions. You may not impose any further
+-restrictions on the recipients' exercise of the rights granted herein.
+-You are not responsible for enforcing compliance by third parties with
+-this License.
+-
+- 11. If, as a consequence of a court judgment or allegation of patent
+-infringement or for any other reason (not limited to patent issues),
+-conditions are imposed on you (whether by court order, agreement or
+-otherwise) that contradict the conditions of this License, they do not
+-excuse you from the conditions of this License. If you cannot
+-distribute so as to satisfy simultaneously your obligations under this
+-License and any other pertinent obligations, then as a consequence you
+-may not distribute the Library at all. For example, if a patent
+-license would not permit royalty-free redistribution of the Library by
+-all those who receive copies directly or indirectly through you, then
+-the only way you could satisfy both it and this License would be to
+-refrain entirely from distribution of the Library.
+-
+-If any portion of this section is held invalid or unenforceable under any
+-particular circumstance, the balance of the section is intended to apply,
+-and the section as a whole is intended to apply in other circumstances.
+-
+-It is not the purpose of this section to induce you to infringe any
+-patents or other property right claims or to contest validity of any
+-such claims; this section has the sole purpose of protecting the
+-integrity of the free software distribution system which is
+-implemented by public license practices. Many people have made
+-generous contributions to the wide range of software distributed
+-through that system in reliance on consistent application of that
+-system; it is up to the author/donor to decide if he or she is willing
+-to distribute software through any other system and a licensee cannot
+-impose that choice.
+-
+-This section is intended to make thoroughly clear what is believed to
+-be a consequence of the rest of this License.
+-
+- 12. If the distribution and/or use of the Library is restricted in
+-certain countries either by patents or by copyrighted interfaces, the
+-original copyright holder who places the Library under this License may add
+-an explicit geographical distribution limitation excluding those countries,
+-so that distribution is permitted only in or among countries not thus
+-excluded. In such case, this License incorporates the limitation as if
+-written in the body of this License.
+-
+- 13. The Free Software Foundation may publish revised and/or new
+-versions of the Lesser General Public License from time to time.
+-Such new versions will be similar in spirit to the present version,
+-but may differ in detail to address new problems or concerns.
+-
+-Each version is given a distinguishing version number. If the Library
+-specifies a version number of this License which applies to it and
+-"any later version", you have the option of following the terms and
+-conditions either of that version or of any later version published by
+-the Free Software Foundation. If the Library does not specify a
+-license version number, you may choose any version ever published by
+-the Free Software Foundation.
+-
+- 14. If you wish to incorporate parts of the Library into other free
+-programs whose distribution conditions are incompatible with these,
+-write to the author to ask for permission. For software which is
+-copyrighted by the Free Software Foundation, write to the Free
+-Software Foundation; we sometimes make exceptions for this. Our
+-decision will be guided by the two goals of preserving the free status
+-of all derivatives of our free software and of promoting the sharing
+-and reuse of software generally.
+-
+- NO WARRANTY
+-
+- 15. BECAUSE THE LIBRARY IS LICENSED FREE OF CHARGE, THERE IS NO
+-WARRANTY FOR THE LIBRARY, TO THE EXTENT PERMITTED BY APPLICABLE LAW.
+-EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR
+-OTHER PARTIES PROVIDE THE LIBRARY "AS IS" WITHOUT WARRANTY OF ANY
+-KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE
+-IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+-PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE
+-LIBRARY IS WITH YOU. SHOULD THE LIBRARY PROVE DEFECTIVE, YOU ASSUME
+-THE COST OF ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
+-
+- 16. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN
+-WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY
+-AND/OR REDISTRIBUTE THE LIBRARY AS PERMITTED ABOVE, BE LIABLE TO YOU
+-FOR DAMAGES, INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR
+-CONSEQUENTIAL DAMAGES ARISING OUT OF THE USE OR INABILITY TO USE THE
+-LIBRARY (INCLUDING BUT NOT LIMITED TO LOSS OF DATA OR DATA BEING
+-RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD PARTIES OR A
+-FAILURE OF THE LIBRARY TO OPERATE WITH ANY OTHER SOFTWARE), EVEN IF
+-SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
+-DAMAGES.
+-
+- END OF TERMS AND CONDITIONS
+-
+- How to Apply These Terms to Your New Libraries
+-
+- If you develop a new library, and you want it to be of the greatest
+-possible use to the public, we recommend making it free software that
+-everyone can redistribute and change. You can do so by permitting
+-redistribution under these terms (or, alternatively, under the terms of the
+-ordinary General Public License).
+-
+- To apply these terms, attach the following notices to the library. It is
+-safest to attach them to the start of each source file to most effectively
+-convey the exclusion of warranty; and each file should have at least the
+-"copyright" line and a pointer to where the full notice is found.
+-
+- <one line to give the library's name and a brief idea of what it does.>
+- Copyright (C) <year> <name of author>
+-
+- This library is free software; you can redistribute it and/or
+- modify it under the terms of the GNU Lesser General Public
+- License as published by the Free Software Foundation; either
+- version 2 of the License, or (at your option) any later version.
+-
+- This library is distributed in the hope that it will be useful,
+- but WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- Lesser General Public License for more details.
+-
+- You should have received a copy of the GNU Lesser General Public
+- License along with this library; if not, write to the Free Software
+- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-
+-Also add information on how to contact you by electronic and paper mail.
+-
+-You should also get your employer (if you work as a programmer) or your
+-school, if any, to sign a "copyright disclaimer" for the library, if
+-necessary. Here is a sample; alter the names:
+-
+- Yoyodyne, Inc., hereby disclaims all copyright interest in the
+- library `Frob' (a library for tweaking knobs) written by James Random Hacker.
+-
+- <signature of Ty Coon>, 1 April 1990
+- Ty Coon, President of Vice
+-
+-That's all there is to it!
+-
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/encoding.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/encoding.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,285 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "encoding.h"
+-
+-static gchar *
+-encoding_multi_convert_to_utf8(const gchar *text, gssize textlen, const gchar *encodings, GError **error, gboolean fallback)
+-{
+- gchar *utf8 = NULL;
+- const gchar *begin = encodings;
+- const gchar *end = NULL;
+- gchar *curr_encoding = NULL; /* allocated buffer for encoding name */
+- const gchar *curr_encoding_ro = NULL; /* read-only encoding name */
+-
+- if (!encodings) {
+- purple_debug_error("oscar", "encodings is NULL");
+- return NULL;
+- }
+-
+- for (;;)
+- {
+- /* extract next encoding */
+- end = strchr(begin, ',');
+- if (!end) {
+- curr_encoding_ro = begin;
+- } else { /* allocate buffer for encoding */
+- curr_encoding = g_strndup(begin, end - begin);
+- if (!curr_encoding) {
+- purple_debug_error("oscar", "Error allocating memory for encoding");
+- break;
+- }
+- curr_encoding_ro = curr_encoding;
+- }
+-
+- if (!g_ascii_strcasecmp(curr_encoding_ro, "utf-8") && g_utf8_validate(text, textlen, NULL)) {
+- break;
+- }
+-
+- utf8 = g_convert(text, textlen, "UTF-8", curr_encoding_ro, NULL, NULL, NULL);
+-
+- if (!end) /* last occurence. do not free curr_encoding: buffer was'nt allocated */
+- break;
+-
+- g_free(curr_encoding); /* free allocated buffer for encoding here */
+-
+- if (utf8) /* text was successfully converted */
+- break;
+-
+- begin = end + 1;
+- }
+-
+- if (!utf8 && fallback)
+- { /* "begin" points to last encoding */
+- utf8 = g_convert_with_fallback(text, textlen, "UTF-8", begin, "?", NULL, NULL, error);
+- }
+-
+- return utf8;
+-}
+-
+-static gchar *
+-encoding_extract(const char *encoding)
+-{
+- char *begin, *end;
+-
+- if (encoding == NULL) {
+- return NULL;
+- }
+-
+- if (!g_str_has_prefix(encoding, "text/aolrtf; charset=") &&
+- !g_str_has_prefix(encoding, "text/x-aolrtf; charset=") &&
+- !g_str_has_prefix(encoding, "text/plain; charset=")) {
+- return g_strdup(encoding);
+- }
+-
+- begin = strchr(encoding, '"');
+- end = strrchr(encoding, '"');
+-
+- if ((begin == NULL) || (end == NULL) || (begin >= end)) {
+- return g_strdup(encoding);
+- }
+-
+- return g_strndup(begin+1, (end-1) - begin);
+-}
+-
+-gchar *
+-oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen)
+-{
+- gchar *utf8 = NULL;
+- const gchar *glib_encoding = NULL;
+- gchar *extracted_encoding = encoding_extract(encoding);
+-
+- if (extracted_encoding == NULL || *extracted_encoding == '\0') {
+- purple_debug_info("oscar", "Empty encoding, assuming UTF-8\n");
+- } else if (!g_ascii_strcasecmp(extracted_encoding, "iso-8859-1")) {
+- glib_encoding = "iso-8859-1";
+- } else if (!g_ascii_strcasecmp(extracted_encoding, "ISO-8859-1-Windows-3.1-Latin-1") || !g_ascii_strcasecmp(extracted_encoding, "us-ascii")) {
+- glib_encoding = "Windows-1252";
+- } else if (!g_ascii_strcasecmp(extracted_encoding, "unicode-2-0")) {
+- glib_encoding = "UTF-16BE";
+- } else if (g_ascii_strcasecmp(extracted_encoding, "utf-8")) {
+- glib_encoding = extracted_encoding;
+- }
+-
+- if (glib_encoding != NULL) {
+- utf8 = encoding_multi_convert_to_utf8(text, textlen, glib_encoding, NULL, FALSE);
+- }
+-
+- /*
+- * If utf8 is still NULL then either the encoding is utf-8 or
+- * we have been unable to convert the text to utf-8 from the encoding
+- * that was specified. So we check if the text is valid utf-8 then
+- * just copy it.
+- */
+- if (utf8 == NULL) {
+- if (textlen != 0 && *text != '\0' && !g_utf8_validate(text, textlen, NULL))
+- utf8 = g_strdup(_("(There was an error receiving this message. The buddy you are speaking with is probably using a different encoding than expected. If you know what encoding he is using, you can specify it in the advanced account options for your AIM/ICQ account.)"));
+- else
+- utf8 = g_strndup(text, textlen);
+- }
+-
+- g_free(extracted_encoding);
+- return utf8;
+-}
+-
+-gchar *
+-oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg)
+-{
+- const char *charset = NULL;
+- char *ret = NULL;
+-
+- if (msg == NULL)
+- return NULL;
+-
+- if (g_utf8_validate(msg, -1, NULL))
+- return g_strdup(msg);
+-
+- if (od->icq)
+- charset = purple_account_get_string(account, "encoding", NULL);
+-
+- if(charset && *charset)
+- ret = encoding_multi_convert_to_utf8(msg, -1, charset, NULL, FALSE);
+-
+- if(!ret)
+- ret = purple_utf8_try_convert(msg);
+-
+- return ret;
+-}
+-
+-static gchar *
+-oscar_convert_to_utf8(const gchar *data, gsize datalen, const char *charsetstr, gboolean fallback)
+-{
+- gchar *ret = NULL;
+- GError *err = NULL;
+-
+- if ((charsetstr == NULL) || (*charsetstr == '\0'))
+- return NULL;
+-
+- if (g_ascii_strcasecmp("UTF-8", charsetstr)) {
+- ret = encoding_multi_convert_to_utf8(data, datalen, charsetstr, &err, fallback);
+- if (err != NULL) {
+- purple_debug_warning("oscar", "Conversion from %s failed: %s.\n",
+- charsetstr, err->message);
+- g_error_free(err);
+- }
+- } else {
+- if (g_utf8_validate(data, datalen, NULL))
+- ret = g_strndup(data, datalen);
+- else
+- purple_debug_warning("oscar", "String is not valid UTF-8.\n");
+- }
+-
+- return ret;
+-}
+-
+-gchar *
+-oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen)
+-{
+- gchar *ret = NULL;
+- /* charsetstr1 is always set to what the correct encoding should be. */
+- const gchar *charsetstr1, *charsetstr2, *charsetstr3 = NULL;
+-
+- if ((datalen == 0) || (data == NULL))
+- return NULL;
+-
+- if (charset == AIM_CHARSET_UNICODE) {
+- charsetstr1 = "UTF-16BE";
+- charsetstr2 = "UTF-8";
+- } else if (charset == AIM_CHARSET_LATIN_1) {
+- if ((sourcebn != NULL) && oscar_util_valid_name_icq(sourcebn))
+- charsetstr1 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- else
+- charsetstr1 = "ISO-8859-1";
+- charsetstr2 = "UTF-8";
+- } else if (charset == AIM_CHARSET_ASCII) {
+- /* Should just be "ASCII" */
+- charsetstr1 = "ASCII";
+- charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- } else if (charset == 0x000d) {
+- /* iChat sending unicode over a Direct IM connection = UTF-8 */
+- /* Mobile AIM client on multiple devices (including Blackberry Tour, Nokia 3100, and LG VX6000) = ISO-8859-1 */
+- charsetstr1 = "UTF-8";
+- charsetstr2 = "ISO-8859-1";
+- charsetstr3 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- } else {
+- /* Unknown, hope for valid UTF-8... */
+- charsetstr1 = "UTF-8";
+- charsetstr2 = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- }
+-
+- purple_debug_info("oscar", "Parsing IM, charset=0x%04hx, datalen=%" G_GSIZE_FORMAT ", choice1=%s, choice2=%s, choice3=%s\n",
+- charset, datalen, charsetstr1, charsetstr2, (charsetstr3 ? charsetstr3 : ""));
+-
+- ret = oscar_convert_to_utf8(data, datalen, charsetstr1, FALSE);
+- if (ret == NULL) {
+- if (charsetstr3 != NULL) {
+- /* Try charsetstr2 without allowing substitutions, then fall through to charsetstr3 if needed */
+- ret = oscar_convert_to_utf8(data, datalen, charsetstr2, FALSE);
+- if (ret == NULL)
+- ret = oscar_convert_to_utf8(data, datalen, charsetstr3, TRUE);
+- } else {
+- /* Try charsetstr2, allowing substitutions */
+- ret = oscar_convert_to_utf8(data, datalen, charsetstr2, TRUE);
+- }
+- }
+- if (ret == NULL) {
+- char *str, *salvage, *tmp;
+-
+- str = g_malloc(datalen + 1);
+- strncpy(str, data, datalen);
+- str[datalen] = '\0';
+- salvage = purple_utf8_salvage(str);
+- tmp = g_strdup_printf(_("(There was an error receiving this message. Either you and %s have different encodings selected, or %s has a buggy client.)"),
+- sourcebn, sourcebn);
+- ret = g_strdup_printf("%s %s", salvage, tmp);
+- g_free(tmp);
+- g_free(str);
+- g_free(salvage);
+- }
+-
+- return ret;
+-}
+-
+-static guint16
+-get_simplest_charset(const char *utf8)
+-{
+- while (*utf8)
+- {
+- if ((unsigned char)(*utf8) > 0x7f) {
+- /* not ASCII! */
+- return AIM_CHARSET_UNICODE;
+- }
+- utf8++;
+- }
+- return AIM_CHARSET_ASCII;
+-}
+-
+-gchar *
+-oscar_encode_im(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr)
+-{
+- guint16 msg_charset = get_simplest_charset(msg);
+- if (charset != NULL) {
+- *charset = msg_charset;
+- }
+- if (charsetstr != NULL) {
+- *charsetstr = msg_charset == AIM_CHARSET_ASCII ? "us-ascii" : "unicode-2-0";
+- }
+- return g_convert(msg, -1, msg_charset == AIM_CHARSET_ASCII ? "ASCII" : "UTF-16BE", "UTF-8", NULL, result_len, NULL);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/encoding.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/encoding.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/encoding.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,46 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#ifndef _ENCODING_H_
+-#define _ENCODING_H_
+-
+-#include "oscar.h"
+-#include "oscarcommon.h"
+-
+-gchar * oscar_encoding_to_utf8(const char *encoding, const char *text, int textlen);
+-gchar * oscar_utf8_try_convert(PurpleAccount *account, OscarData *od, const gchar *msg);
+-
+-/**
+- * This attemps to decode an incoming IM into a UTF8 string.
+- *
+- * We try decoding using two different character sets. The charset
+- * specified in the IM determines the order in which we attempt to
+- * decode. We do this because there are lots of broken ICQ clients
+- * that don't correctly send non-ASCII messages. And if Purple isn't
+- * able to deal with that crap, then people complain like banshees.
+- */
+-gchar * oscar_decode_im(PurpleAccount *account, const char *sourcebn, guint16 charset, const gchar *data, gsize datalen);
+-
+-/**
+- * Figure out what encoding to use when sending a given outgoing message.
+- */
+-gchar * oscar_encode_im(const gchar *msg, gsize *result_len, guint16 *charset, gchar **charsetstr);
+-
+-#endif
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_admin.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_admin.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_admin.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_admin.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,246 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0007 - Account Administration.
+- *
+- * Used for stuff like changing the formating of your username, changing your
+- * email address, requesting an account confirmation email, getting account info,
+- */
+-
+-#include "oscar.h"
+-
+-/**
+- * Subtype 0x0002 - Request a bit of account info.
+- *
+- * Info should be one of the following:
+- * 0x0001 - Username formatting
+- * 0x0011 - Email address
+- * 0x0013 - Unknown
+- */
+-void
+-aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- byte_stream_new(&bs, 4);
+-
+- byte_stream_put16(&bs, info);
+- byte_stream_put16(&bs, 0x0000);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0002, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtypes 0x0003 and 0x0005 - Parse account info.
+- *
+- * Called in reply to both an information request (subtype 0x0002) and
+- * an information change (subtype 0x0004).
+- */
+-static void
+-infochange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- char *url=NULL, *sn=NULL, *email=NULL;
+- guint16 perms, tlvcount, err=0;
+-
+- perms = byte_stream_get16(bs);
+- tlvcount = byte_stream_get16(bs);
+-
+- while (tlvcount && byte_stream_bytes_left(bs)) {
+- guint16 type, length;
+-
+- type = byte_stream_get16(bs);
+- length = byte_stream_get16(bs);
+-
+- switch (type) {
+- case 0x0001: {
+- g_free(sn);
+- sn = byte_stream_getstr(bs, length);
+- } break;
+-
+- case 0x0004: {
+- g_free(url);
+- url = byte_stream_getstr(bs, length);
+- } break;
+-
+- case 0x0008: {
+- err = byte_stream_get16(bs);
+- } break;
+-
+- case 0x0011: {
+- g_free(email);
+- if (length == 0)
+- email = g_strdup("*suppressed");
+- else
+- email = byte_stream_getstr(bs, length);
+- } break;
+- }
+-
+- tlvcount--;
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- userfunc(od, conn, frame, (snac->subtype == 0x0005) ? 1 : 0, perms, err, url, sn, email);
+-
+- g_free(sn);
+- g_free(url);
+- g_free(email);
+-}
+-
+-/**
+- * Subtype 0x0004 - Set the formatting of username (change spaces and capitalization).
+- */
+-void
+-aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- byte_stream_new(&bs, 2+2+strlen(newnick));
+-
+- aim_tlvlist_add_str(&tlvlist, 0x0001, newnick);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0004 - Change password.
+- */
+-void
+-aim_admin_changepasswd(OscarData *od, FlapConnection *conn, const char *newpw, const char *curpw)
+-{
+- ByteStream bs;
+- GSList *tlvlist = NULL;
+- aim_snacid_t snacid;
+-
+- byte_stream_new(&bs, 4+strlen(curpw)+4+strlen(newpw));
+-
+- /* new password TLV t(0002) */
+- aim_tlvlist_add_str(&tlvlist, 0x0002, newpw);
+-
+- /* current password TLV t(0012) */
+- aim_tlvlist_add_str(&tlvlist, 0x0012, curpw);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0004 - Change email address.
+- */
+-void
+-aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- byte_stream_new(&bs, 2+2+strlen(newemail));
+-
+- aim_tlvlist_add_str(&tlvlist, 0x0011, newemail);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ADMIN, 0x0004, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ADMIN, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/*
+- * Subtype 0x0006 - Request account confirmation.
+- *
+- * This will cause an email to be sent to the address associated with
+- * the account. By following the instructions in the mail, you can
+- * get the TRIAL flag removed from your account.
+- *
+- */
+-void
+-aim_admin_reqconfirm(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n(od, conn, SNAC_FAMILY_ADMIN, 0x0006);
+-}
+-
+-/**
+- * Subtype SNAC_FAMILY_ADMIN - Account confirmation request acknowledgement.
+- */
+-static int
+-accountconfirm(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 status;
+- /* GSList *tlvlist; */
+-
+- status = byte_stream_get16(bs);
+- /* Status is 0x0013 if unable to confirm at this time */
+-
+- /* tlvlist = aim_tlvlist_read(bs); */
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, status);
+-
+- /* aim_tlvlist_free(tlvlist); */
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if ((snac->subtype == 0x0003) || (snac->subtype == 0x0005)) {
+- infochange(od, conn, mod, frame, snac, bs);
+- return 1;
+- } else if (snac->subtype == SNAC_FAMILY_ADMIN)
+- return accountconfirm(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int admin_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_ADMIN;
+- mod->version = 0x0001;
+- mod->toolid = 0x0010;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "admin", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_alert.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_alert.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_alert.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_alert.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,238 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0018 - Email notification
+- *
+- * Used for being alerted when the email address(es) associated with
+- * your username get new electronic-m. For normal AIM accounts, you
+- * get the email address username@netscape.net. AOL accounts have
+- * username@aol.com, and can also activate a netscape.net account.
+- * Note: This information might be out of date.
+- */
+-
+-#include "oscar.h"
+-
+-/**
+- * Subtype 0x0006 - Request information about your email account
+- *
+- * @param od The oscar session.
+- * @param conn The email connection for this session.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int
+-aim_email_sendcookies(OscarData *od)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT)))
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 2+16+16);
+-
+- /* Number of cookies to follow */
+- byte_stream_put16(&bs, 0x0002);
+-
+- /* Cookie */
+- byte_stream_put16(&bs, 0x5d5e);
+- byte_stream_put16(&bs, 0x1708);
+- byte_stream_put16(&bs, 0x55aa);
+- byte_stream_put16(&bs, 0x11d3);
+- byte_stream_put16(&bs, 0xb143);
+- byte_stream_put16(&bs, 0x0060);
+- byte_stream_put16(&bs, 0xb0fb);
+- byte_stream_put16(&bs, 0x1ecb);
+-
+- /* Cookie */
+- byte_stream_put16(&bs, 0xb380);
+- byte_stream_put16(&bs, 0x9ad8);
+- byte_stream_put16(&bs, 0x0dba);
+- byte_stream_put16(&bs, 0x11d5);
+- byte_stream_put16(&bs, 0x9f8a);
+- byte_stream_put16(&bs, 0x0060);
+- byte_stream_put16(&bs, 0xb0ee);
+- byte_stream_put16(&bs, 0x0631);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0006, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-
+-/**
+- * Subtype 0x0007 - Receive information about your email account
+- *
+- * So I don't even know if you can have multiple 16 byte keys,
+- * but this is coded so it will handle that, and handle it well.
+- * This tells you if you have unread mail or not, the URL you
+- * should use to access that mail, and the domain name for the
+- * email account (username@domainname.com). If this is the
+- * first 0x0007 SNAC you've received since you signed on, or if
+- * this is just a periodic status update, this will also contain
+- * the number of unread emails that you have.
+- */
+-static int
+-parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- struct aim_emailinfo *new;
+- GSList *tlvlist;
+- guint8 *cookie8, *cookie16;
+- int tmp, havenewmail = 0; /* Used to tell the client we have _new_ mail */
+-
+- char *alertitle = NULL, *alerturl = NULL;
+-
+- cookie8 = byte_stream_getraw(bs, 8); /* Possibly the code used to log you in to mail? */
+- cookie16 = byte_stream_getraw(bs, 16); /* Mail cookie sent above */
+-
+- /* See if we already have some info associated with this cookie */
+- for (new = od->emailinfo; (new && memcmp(cookie16, new->cookie16, 16)); new = new->next);
+- if (new) {
+- /* Free some of the old info, if it exists */
+- g_free(new->cookie8);
+- g_free(new->cookie16);
+- g_free(new->url);
+- g_free(new->domain);
+- } else {
+- /* We don't already have info, so create a new struct for it */
+- new = g_new0(struct aim_emailinfo, 1);
+- new->next = od->emailinfo;
+- od->emailinfo = new;
+- }
+-
+- new->cookie8 = cookie8;
+- new->cookie16 = cookie16;
+-
+- tlvlist = aim_tlvlist_readnum(bs, byte_stream_get16(bs));
+-
+- tmp = aim_tlv_get16(tlvlist, 0x0080, 1);
+- if (tmp) {
+- if (new->nummsgs < tmp)
+- havenewmail = 1;
+- new->nummsgs = tmp;
+- } else {
+- /* If they don't send a 0x0080 TLV, it means we definitely have new mail */
+- /* (ie. this is not just another status update) */
+- havenewmail = 1;
+- new->nummsgs++; /* We know we have at least 1 new email */
+- }
+- new->url = aim_tlv_getstr(tlvlist, 0x0007, 1);
+- if (!(new->unread = aim_tlv_get8(tlvlist, 0x0081, 1))) {
+- havenewmail = 0;
+- new->nummsgs = 0;
+- }
+- new->domain = aim_tlv_getstr(tlvlist, 0x0082, 1);
+- new->flag = aim_tlv_get16(tlvlist, 0x0084, 1);
+-
+- alertitle = aim_tlv_getstr(tlvlist, 0x0005, 1);
+- alerturl = aim_tlv_getstr(tlvlist, 0x000d, 1);
+-
+- 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);
+-
+- g_free(alertitle);
+- g_free(alerturl);
+-
+- return ret;
+-}
+-
+-/**
+- * Subtype 0x0016 - Send something or other
+- *
+- * @param od The oscar session.
+- * @param conn The email connection for this session.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int
+-aim_email_activate(OscarData *od)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ALERT)))
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 1+16);
+-
+- /* I would guess this tells AIM that you want updates for your mail accounts */
+- /* ...but I really have no idea */
+- byte_stream_put8(&bs, 0x02);
+- byte_stream_put32(&bs, 0x04000000);
+- byte_stream_put32(&bs, 0x04000000);
+- byte_stream_put32(&bs, 0x04000000);
+- byte_stream_put32(&bs, 0x00000000);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ALERT, 0x0016, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ALERT, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0007)
+- return parseinfo(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-static void
+-email_shutdown(OscarData *od, aim_module_t *mod)
+-{
+- while (od->emailinfo)
+- {
+- struct aim_emailinfo *tmp = od->emailinfo;
+- od->emailinfo = od->emailinfo->next;
+- g_free(tmp->cookie16);
+- g_free(tmp->cookie8);
+- g_free(tmp->url);
+- g_free(tmp->domain);
+- g_free(tmp);
+- }
+-
+- return;
+-}
+-
+-int
+-email_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_ALERT;
+- mod->version = 0x0001;
+- mod->toolid = 0x0010;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "alert", sizeof(mod->name));
+- mod->snachandler = snachandler;
+- mod->shutdown = email_shutdown;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_auth.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_auth.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_auth.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_auth.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,631 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0017 - Authentication.
+- *
+- * Deals with the authorizer for SNAC-based login, and also old-style
+- * non-SNAC login.
+- *
+- */
+-
+-#include "oscar.h"
+-
+-#include <ctype.h>
+-
+-#include "cipher.h"
+-
+-/* #define USE_XOR_FOR_ICQ */
+-
+-#ifdef USE_XOR_FOR_ICQ
+-/**
+- * Encode a password using old XOR method
+- *
+- * This takes a const pointer to a (null terminated) string
+- * containing the unencoded password. It also gets passed
+- * an already allocated buffer to store the encoded password.
+- * This buffer should be the exact length of the password without
+- * the null. The encoded password buffer /is not %NULL terminated/.
+- *
+- * The encoding_table seems to be a fixed set of values. We'll
+- * hope it doesn't change over time!
+- *
+- * This is only used for the XOR method, not the better MD5 method.
+- *
+- * @param password Incoming password.
+- * @param encoded Buffer to put encoded password.
+- */
+-static int
+-aim_encode_password(const char *password, guint8 *encoded)
+-{
+- guint8 encoding_table[] = {
+- 0xf3, 0x26, 0x81, 0xc4,
+- 0x39, 0x86, 0xdb, 0x92,
+- 0x71, 0xa3, 0xb9, 0xe6,
+- 0x53, 0x7a, 0x95, 0x7c
+- };
+- unsigned int i;
+-
+- for (i = 0; i < strlen(password); i++)
+- encoded[i] = (password[i] ^ encoding_table[i]);
+-
+- return 0;
+-}
+-#endif
+-
+-#ifdef USE_OLD_MD5
+-static int
+-aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
+-{
+- PurpleCipherContext *context;
+-
+- context = purple_cipher_context_new_by_name("md5", NULL);
+- purple_cipher_context_append(context, (const guchar *)key, strlen(key));
+- purple_cipher_context_append(context, (const guchar *)password, password_len);
+- purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
+- purple_cipher_context_digest(context, 16, digest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- return 0;
+-}
+-#else
+-static int
+-aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
+-{
+- PurpleCipher *cipher;
+- PurpleCipherContext *context;
+- guchar passdigest[16];
+-
+- cipher = purple_ciphers_find_cipher("md5");
+-
+- context = purple_cipher_context_new(cipher, NULL);
+- purple_cipher_context_append(context, (const guchar *)password, password_len);
+- purple_cipher_context_digest(context, 16, passdigest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- context = purple_cipher_context_new(cipher, NULL);
+- purple_cipher_context_append(context, (const guchar *)key, strlen(key));
+- purple_cipher_context_append(context, passdigest, 16);
+- purple_cipher_context_append(context, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING));
+- purple_cipher_context_digest(context, 16, digest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- return 0;
+-}
+-#endif
+-
+-#ifdef USE_XOR_FOR_ICQ
+-/*
+- * Part two of the ICQ hack. Note the ignoring of the key.
+- */
+-static int
+-goddamnicq2(OscarData *od, FlapConnection *conn, const char *sn, const char *password, ClientInfo *ci)
+-{
+- FlapFrame *frame;
+- GSList *tlvlist = NULL;
+- int passwdlen;
+- guint8 *password_encoded;
+- guint32 distrib;
+-
+- passwdlen = strlen(password);
+- password_encoded = (guint8 *)g_malloc(passwdlen+1);
+- if (passwdlen > MAXICQPASSLEN)
+- passwdlen = MAXICQPASSLEN;
+-
+- frame = flap_frame_new(od, 0x01, 1152);
+-
+- aim_encode_password(password, password_encoded);
+-
+- distrib = oscar_get_ui_info_int(
+- od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
+- ci->distrib);
+-
+- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
+- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
+- aim_tlvlist_add_raw(&tlvlist, 0x0002, passwdlen, password_encoded);
+-
+- if (ci->clientstring != NULL)
+- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
+- else {
+- gchar *clientstring = oscar_get_clientstring();
+- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
+- g_free(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, distrib); /* distribution chan */
+- aim_tlvlist_add_str(&tlvlist, 0x000f, ci->lang);
+- aim_tlvlist_add_str(&tlvlist, 0x000e, ci->country);
+-
+- aim_tlvlist_write(&frame->data, &tlvlist);
+-
+- g_free(password_encoded);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send(conn, frame);
+-
+- return 0;
+-}
+-#endif
+-
+-/*
+- * Subtype 0x0002
+- *
+- * This is the initial login request packet.
+- *
+- * NOTE!! If you want/need to make use of the aim_sendmemblock() function,
+- * then the client information you send here must exactly match the
+- * executable that you're pulling the data from.
+- *
+- * Java AIM 1.1.19:
+- * clientstring = "AOL Instant Messenger (TM) version 1.1.19 for Java built 03/24/98, freeMem 215871 totalMem 1048567, i686, Linus, #2 SMP Sun Feb 11 03:41:17 UTC 2001 2.4.1-ac9, IBM Corporation, 1.1.8, 45.3, Tue Mar 27 12:09:17 PST 2001"
+- * clientid = 0x0001
+- * major = 0x0001
+- * minor = 0x0001
+- * point = (not sent)
+- * build = 0x0013
+- * unknown= (not sent)
+- *
+- * AIM for Linux 1.1.112:
+- * clientstring = "AOL Instant Messenger (SM)"
+- * clientid = 0x1d09
+- * major = 0x0001
+- * minor = 0x0001
+- * point = 0x0001
+- * build = 0x0070
+- * unknown= 0x0000008b
+- * serverstore = 0x01
+- *
+- * @param truncate_pass Truncate the password to 8 characters. This
+- * usually happens for AOL accounts. We are told that we
+- * should truncate it if the 0x0017/0x0007 SNAC contains
+- * a TLV of type 0x0026 with data 0x0000.
+- * @param allow_multiple_logins Allow multiple logins? If TRUE, the AIM
+- * server will prompt the user when multiple logins occur. If
+- * FALSE, existing connections (on other clients) will be
+- * disconnected automatically as we connect.
+- */
+-int
+-aim_send_login(OscarData *od, FlapConnection *conn, const char *sn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins)
+-{
+- FlapFrame *frame;
+- GSList *tlvlist = NULL;
+- guint8 digest[16];
+- aim_snacid_t snacid;
+- size_t password_len;
+- guint32 distrib;
+-
+- if (!ci || !sn || !password)
+- return -EINVAL;
+-
+-#ifdef USE_XOR_FOR_ICQ
+- /* If we're signing on an ICQ account then use the older, XOR login method */
+- if (aim_snvalid_icq(sn))
+- return goddamnicq2(od, conn, sn, password, ci);
+-#endif
+-
+- frame = flap_frame_new(od, 0x02, 1152);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0002, 0x0000, NULL, 0);
+- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0002, snacid);
+-
+- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
+-
+- /* Truncate ICQ and AOL passwords, if necessary */
+- password_len = strlen(password);
+- if (oscar_util_valid_name_icq(sn) && (password_len > MAXICQPASSLEN))
+- password_len = MAXICQPASSLEN;
+- else if (truncate_pass && password_len > 8)
+- password_len = 8;
+-
+- aim_encode_password_md5(password, password_len, key, digest);
+-
+- distrib = oscar_get_ui_info_int(
+- od->icq ? "prpl-icq-distid" : "prpl-aim-distid",
+- ci->distrib);
+-
+- aim_tlvlist_add_raw(&tlvlist, 0x0025, 16, digest);
+-
+-#ifndef USE_OLD_MD5
+- aim_tlvlist_add_noval(&tlvlist, 0x004c);
+-#endif
+-
+- if (ci->clientstring != NULL)
+- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
+- else {
+- gchar *clientstring = oscar_get_clientstring();
+- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
+- g_free(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, 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(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));
+-
+- aim_tlvlist_write(&frame->data, &tlvlist);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send(conn, frame);
+-
+- return 0;
+-}
+-
+-/*
+- * This is sent back as a general response to the login command.
+- * It can be either an error or a success, depending on the
+- * presence of certain TLVs.
+- *
+- * The client should check the value passed as errorcode. If
+- * its nonzero, there was an error.
+- */
+-static int
+-parse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- GSList *tlvlist;
+- aim_rxcallback_t userfunc;
+- struct aim_authresp_info *info;
+- int ret = 0;
+-
+- info = g_new0(struct aim_authresp_info, 1);
+-
+- /*
+- * Read block of TLVs. All further data is derived
+- * from what is parsed here.
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * No matter what, we should have a username.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0001, 1)) {
+- info->bn = aim_tlv_getstr(tlvlist, 0x0001, 1);
+- purple_connection_set_display_name(od->gc, info->bn);
+- }
+-
+- /*
+- * Check for an error code. If so, we should also
+- * have an error url.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
+- info->errorcode = aim_tlv_get16(tlvlist, 0x0008, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0004, 1))
+- info->errorurl = aim_tlv_getstr(tlvlist, 0x0004, 1);
+-
+- /*
+- * BOS server address.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
+- info->bosip = aim_tlv_getstr(tlvlist, 0x0005, 1);
+-
+- /*
+- * Authorization cookie.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
+- aim_tlv_t *tmptlv;
+-
+- tmptlv = aim_tlv_gettlv(tlvlist, 0x0006, 1);
+- if (tmptlv != NULL)
+- {
+- info->cookielen = tmptlv->length;
+- info->cookie = tmptlv->value;
+- }
+- }
+-
+- /*
+- * The email address attached to this account
+- * Not available for ICQ or @mac.com logins.
+- * If you receive this TLV, then you are allowed to use
+- * family 0x0018 to check the status of your email.
+- * XXX - Not really true!
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0011, 1))
+- info->email = aim_tlv_getstr(tlvlist, 0x0011, 1);
+-
+- /*
+- * The registration status. (Not real sure what it means.)
+- * Not available for ICQ or @mac.com logins.
+- *
+- * 1 = No disclosure
+- * 2 = Limited disclosure
+- * 3 = Full disclosure
+- *
+- * This has to do with whether your email address is available
+- * to other users or not. AFAIK, this feature is no longer used.
+- *
+- * Means you can use the admin family? (0x0007)
+- *
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0013, 1))
+- info->regstatus = aim_tlv_get16(tlvlist, 0x0013, 1);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x0040, 1))
+- info->latestbeta.build = aim_tlv_get32(tlvlist, 0x0040, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0041, 1))
+- info->latestbeta.url = aim_tlv_getstr(tlvlist, 0x0041, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0042, 1))
+- info->latestbeta.info = aim_tlv_getstr(tlvlist, 0x0042, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0043, 1))
+- info->latestbeta.name = aim_tlv_getstr(tlvlist, 0x0043, 1);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x0044, 1))
+- info->latestrelease.build = aim_tlv_get32(tlvlist, 0x0044, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0045, 1))
+- info->latestrelease.url = aim_tlv_getstr(tlvlist, 0x0045, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0046, 1))
+- info->latestrelease.info = aim_tlv_getstr(tlvlist, 0x0046, 1);
+- if (aim_tlv_gettlv(tlvlist, 0x0047, 1))
+- info->latestrelease.name = aim_tlv_getstr(tlvlist, 0x0047, 1);
+-
+- /*
+- * URL to change password.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0054, 1))
+- info->chpassurl = aim_tlv_getstr(tlvlist, 0x0054, 1);
+-
+- od->authinfo = info;
+-
+- if ((userfunc = aim_callhandler(od, snac ? snac->family : SNAC_FAMILY_AUTH, snac ? snac->subtype : 0x0003)))
+- ret = userfunc(od, conn, frame, info);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-#ifdef USE_XOR_FOR_ICQ
+-/*
+- * Subtype 0x0007 (kind of) - Send a fake type 0x0007 SNAC to the client
+- *
+- * This is a bit confusing.
+- *
+- * Normal SNAC login goes like this:
+- * - connect
+- * - server sends flap version
+- * - client sends flap version
+- * - client sends username (17/6)
+- * - server sends hash key (17/7)
+- * - client sends auth request (17/2 -- aim_send_login)
+- * - server yells
+- *
+- * XOR login (for ICQ) goes like this:
+- * - connect
+- * - server sends flap version
+- * - client sends auth request which contains flap version (aim_send_login)
+- * - server yells
+- *
+- * For the client API, we make them implement the most complicated version,
+- * and for the simpler version, we fake it and make it look like the more
+- * complicated process.
+- *
+- * This is done by giving the client a faked key, just so we can convince
+- * them to call aim_send_login right away, which will detect the session
+- * flag that says this is XOR login and ignore the key, sending an ICQ
+- * login request instead of the normal SNAC one.
+- *
+- * As soon as AOL makes ICQ log in the same way as AIM, this is /gone/.
+- */
+-static int
+-goddamnicq(OscarData *od, FlapConnection *conn, const char *sn)
+-{
+- FlapFrame frame;
+- aim_rxcallback_t userfunc;
+-
+- if ((userfunc = aim_callhandler(od, SNAC_FAMILY_AUTH, 0x0007)))
+- userfunc(od, conn, &frame, "");
+-
+- return 0;
+-}
+-#endif
+-
+-/*
+- * Subtype 0x0006
+- *
+- * In AIM 3.5 protocol, the first stage of login is to request login from the
+- * Authorizer, passing it the username for verification. If the name is
+- * invalid, a 0017/0003 is spit back, with the standard error contents. If
+- * valid, a 0017/0007 comes back, which is the signal to send it the main
+- * login command (0017/0002).
+- *
+- */
+-int
+-aim_request_login(OscarData *od, FlapConnection *conn, const char *sn)
+-{
+- FlapFrame *frame;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- if (!od || !conn || !sn)
+- return -EINVAL;
+-
+-#ifdef USE_XOR_FOR_ICQ
+- if (aim_snvalid_icq(sn))
+- return goddamnicq(od, conn, sn);
+-#endif
+-
+- frame = flap_frame_new(od, 0x02, 10+2+2+strlen(sn)+8);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, 0x0006, 0x0000, NULL, 0);
+- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, 0x0006, snacid);
+-
+- aim_tlvlist_add_str(&tlvlist, 0x0001, sn);
+-
+- /* Tell the server we support SecurID logins. */
+- aim_tlvlist_add_noval(&tlvlist, 0x004b);
+-
+- /* Unknown. Sent in recent WinAIM clients.*/
+- aim_tlvlist_add_noval(&tlvlist, 0x005a);
+-
+- aim_tlvlist_write(&frame->data, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send(conn, frame);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0007
+- *
+- * Middle handler for 0017/0007 SNACs. Contains the auth key prefixed
+- * by only its length in a two byte word.
+- *
+- * Calls the client, which should then use the value to call aim_send_login.
+- *
+- */
+-static int
+-keyparse(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int keylen, ret = 1;
+- aim_rxcallback_t userfunc;
+- char *keystr;
+- GSList *tlvlist;
+- gboolean truncate_pass;
+-
+- keylen = byte_stream_get16(bs);
+- keystr = byte_stream_getstr(bs, keylen);
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * If the truncate_pass TLV exists then we should truncate the
+- * user's password to 8 characters. This flag is sent to us
+- * when logging in with an AOL user's username.
+- */
+- truncate_pass = aim_tlv_gettlv(tlvlist, 0x0026, 1) != NULL;
+-
+- /* XXX - When GiantGrayPanda signed on AIM I got a thing asking me to register
+- * for the netscape network. This SNAC had a type 0x0058 TLV with length 10.
+- * Data is 0x0007 0004 3e19 ae1e 0006 0004 0000 0005 */
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, keystr, (int)truncate_pass);
+-
+- g_free(keystr);
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/**
+- * Subtype 0x000a
+- *
+- * Receive SecurID request.
+- */
+-static int
+-got_securid_request(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+-
+- return ret;
+-}
+-
+-/**
+- * Subtype 0x000b
+- *
+- * Send SecurID response.
+- */
+-int
+-aim_auth_securid_send(OscarData *od, const char *securid)
+-{
+- FlapConnection *conn;
+- FlapFrame *frame;
+- aim_snacid_t snacid;
+- int len;
+-
+- if (!od || !(conn = flap_connection_getbytype_all(od, SNAC_FAMILY_AUTH)) || !securid)
+- return -EINVAL;
+-
+- len = strlen(securid);
+-
+- frame = flap_frame_new(od, 0x02, 10+2+len);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0x0000, NULL, 0);
+- aim_putsnac(&frame->data, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_RESPONSE, 0);
+-
+- byte_stream_put16(&frame->data, len);
+- byte_stream_putstr(&frame->data, securid);
+-
+- flap_connection_send(conn, frame);
+-
+- return 0;
+-}
+-
+-static void
+-auth_shutdown(OscarData *od, aim_module_t *mod)
+-{
+- if (od->authinfo != NULL)
+- {
+- g_free(od->authinfo->bn);
+- g_free(od->authinfo->bosip);
+- g_free(od->authinfo->errorurl);
+- g_free(od->authinfo->email);
+- g_free(od->authinfo->chpassurl);
+- g_free(od->authinfo->latestrelease.name);
+- g_free(od->authinfo->latestrelease.url);
+- g_free(od->authinfo->latestrelease.info);
+- g_free(od->authinfo->latestbeta.name);
+- g_free(od->authinfo->latestbeta.url);
+- g_free(od->authinfo->latestbeta.info);
+- g_free(od->authinfo);
+- }
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0003)
+- return parse(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0007)
+- return keyparse(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000a)
+- return got_securid_request(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-auth_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_AUTH;
+- mod->version = 0x0000;
+- mod->flags = 0;
+- strncpy(mod->name, "auth", sizeof(mod->name));
+- mod->snachandler = snachandler;
+- mod->shutdown = auth_shutdown;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_bart.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bart.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_bart.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bart.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,186 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0010 - Server stored buddy art
+- *
+- * Used for storing and retrieving your cute little buddy icon
+- * from the AIM servers.
+- *
+- */
+-
+-#include "oscar.h"
+-
+-/**
+- * Subtype 0x0002 - Upload your icon.
+- *
+- * @param od The oscar session.
+- * @param icon The raw data of the icon image file.
+- * @param iconlen Length of the raw data of the icon image file.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int
+-aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !icon || !iconlen)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 2 + 2 + iconlen);
+-
+- /* The reference number for the icon */
+- byte_stream_put16(&bs, 1);
+-
+- /* The icon */
+- byte_stream_put16(&bs, iconlen);
+- byte_stream_putraw(&bs, icon, iconlen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0002, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0003 - Acknowledgement for uploading a buddy icon.
+- *
+- * You get this honky after you upload a buddy icon.
+- */
+-static int
+-uploadack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 something, somethingelse;
+- guint8 onemorething;
+-
+- something = byte_stream_get16(bs);
+- somethingelse = byte_stream_get16(bs);
+- onemorething = byte_stream_get8(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+-
+- return ret;
+-}
+-
+-/**
+- * Subtype 0x0004 - Request someone's icon.
+- *
+- * @param od The oscar session.
+- * @param bn The name of the buddy whose icon you are requesting.
+- * @param iconcsum The MD5 checksum of the icon you are requesting.
+- * @param iconcsumlen Length of the MD5 checksum given above. Should be 10 bytes.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int
+-aim_bart_request(OscarData *od, const char *bn, guint8 iconcsumtype, const guint8 *iconcsum, guint16 iconcsumlen)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_BART)) || !bn || !strlen(bn) || !iconcsum || !iconcsumlen)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 1+strlen(bn) + 4 + 1+iconcsumlen);
+-
+- /* Buddy name */
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- /* Some numbers. You like numbers, right? */
+- byte_stream_put8(&bs, 0x01);
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put8(&bs, iconcsumtype);
+-
+- /* Icon string */
+- byte_stream_put8(&bs, iconcsumlen);
+- byte_stream_putraw(&bs, iconcsum, iconcsumlen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_BART, 0x0004, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_BART, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0005 - Receive a buddy icon.
+- *
+- * This is sent in response to a buddy icon request.
+- */
+-static int
+-parseicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- char *bn;
+- guint16 flags, iconlen;
+- guint8 iconcsumtype, iconcsumlen, *iconcsum, *icon;
+-
+- bn = byte_stream_getstr(bs, byte_stream_get8(bs));
+- flags = byte_stream_get16(bs);
+- iconcsumtype = byte_stream_get8(bs);
+- iconcsumlen = byte_stream_get8(bs);
+- iconcsum = byte_stream_getraw(bs, iconcsumlen);
+- iconlen = byte_stream_get16(bs);
+- icon = byte_stream_getraw(bs, iconlen);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, bn, iconcsumtype, iconcsum, iconcsumlen, icon, iconlen);
+-
+- g_free(bn);
+- g_free(iconcsum);
+- g_free(icon);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0003)
+- return uploadack(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0005)
+- return parseicon(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-bart_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_BART;
+- mod->version = 0x0001;
+- mod->toolid = 0x0010;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "bart", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_bos.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bos.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_bos.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_bos.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,92 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0009 - Basic Oscar Service.
+- *
+- * The functionality of this family has been replaced by SSI.
+- */
+-
+-#include "oscar.h"
+-
+-#include <string.h>
+-
+-/* Subtype 0x0002 - Request BOS rights. */
+-void
+-aim_bos_reqrights(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_BOS, 0x0002);
+-}
+-
+-/* Subtype 0x0003 - BOS Rights. */
+-static int rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- GSList *tlvlist;
+- guint16 maxpermits = 0, maxdenies = 0;
+- int ret = 0;
+-
+- /*
+- * TLVs follow
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * TLV type 0x0001: Maximum number of buddies on permit list.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
+- maxpermits = aim_tlv_get16(tlvlist, 0x0001, 1);
+-
+- /*
+- * TLV type 0x0002: Maximum number of buddies on deny list.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
+- maxdenies = aim_tlv_get16(tlvlist, 0x0002, 1);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, maxpermits, maxdenies);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0003)
+- return rights(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-bos_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_BOS;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "bos", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_buddy.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_buddy.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_buddy.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_buddy.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,153 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0003 (SNAC_FAMILY_BUDDY) - Old-style Buddylist Management (non-SSI).
+- *
+- */
+-
+-#include "oscar.h"
+-
+-#include <string.h>
+-
+-/*
+- * Subtype 0x0002 - Request rights.
+- *
+- * Request Buddy List rights.
+- *
+- */
+-void
+-aim_buddylist_reqrights(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_REQRIGHTS);
+-}
+-
+-/*
+- * Subtype 0x0003 - Rights.
+- *
+- */
+-static int
+-rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- GSList *tlvlist;
+- guint16 maxbuddies = 0, maxwatchers = 0;
+- int ret = 0;
+-
+- /*
+- * TLVs follow
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * TLV type 0x0001: Maximum number of buddies.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
+- maxbuddies = aim_tlv_get16(tlvlist, 0x0001, 1);
+-
+- /*
+- * TLV type 0x0002: Maximum number of watchers.
+- *
+- * Watchers are other users who have you on their buddy
+- * list. (This is called the "reverse list" by a certain
+- * other IM protocol.)
+- *
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
+- maxwatchers = aim_tlv_get16(tlvlist, 0x0002, 1);
+-
+- /*
+- * TLV type 0x0003: Unknown.
+- *
+- * ICQ only?
+- */
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, maxbuddies, maxwatchers);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtypes 0x000b (SNAC_SUBTYPE_BUDDY_ONCOMING) and 0x000c (SNAC_SUBTYPE_BUDDY_OFFGOING) - Change in buddy status
+- *
+- * Oncoming Buddy notifications contain a subset of the
+- * user information structure. It's close enough to run
+- * through aim_info_extract() however.
+- *
+- * Although the offgoing notification contains no information,
+- * it is still in a format parsable by aim_info_extract().
+- *
+- */
+-static int
+-buddychange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_userinfo_t userinfo;
+- aim_rxcallback_t userfunc;
+-
+- aim_info_extract(od, bs, &userinfo);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, &userinfo);
+-
+- if (snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING &&
+- userinfo.capabilities & OSCAR_CAPABILITY_XTRAZ) {
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- PurpleBuddy *buddy = purple_find_buddy(account, userinfo.bn);
+-
+- if (buddy) {
+- PurplePresence *presence = purple_buddy_get_presence(buddy);
+-
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+- icq_im_xstatus_request(od, userinfo.bn);
+- }
+- }
+- aim_info_free(&userinfo);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == SNAC_SUBTYPE_BUDDY_RIGHTSINFO)
+- return rights(od, conn, mod, frame, snac, bs);
+- else if ((snac->subtype == SNAC_SUBTYPE_BUDDY_ONCOMING) || (snac->subtype == SNAC_SUBTYPE_BUDDY_OFFGOING))
+- return buddychange(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-buddylist_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_BUDDY;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "buddy", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_chat.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chat.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_chat.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chat.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,398 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x000e - Routines for the Chat service.
+- *
+- */
+-
+-#include "oscar.h"
+-
+-#include <string.h>
+-
+-/* Stored in the ->internal of chat connections */
+-struct chatconnpriv
+-{
+- guint16 exchange;
+- char *name;
+- guint16 instance;
+-};
+-
+-void
+-flap_connection_destroy_chat(OscarData *od, FlapConnection *conn)
+-{
+- struct chatconnpriv *ccp = (struct chatconnpriv *)conn->internal;
+-
+- if (ccp)
+- g_free(ccp->name);
+- g_free(ccp);
+-
+- return;
+-}
+-
+-int
+-aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo)
+-{
+- if (!bs || !outinfo)
+- return 0;
+-
+- outinfo->exchange = byte_stream_get16(bs);
+- outinfo->namelen = byte_stream_get8(bs);
+- outinfo->name = (char *)byte_stream_getraw(bs, outinfo->namelen);
+- outinfo->instance = byte_stream_get16(bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0002 - General room information. Lots of stuff.
+- *
+- * Values I know are in here but I haven't attached
+- * them to any of the 'Unknown's:
+- * - Language (English)
+- *
+- */
+-static int
+-infoupdate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- int ret = 0;
+- guint8 detaillevel = 0;
+- struct aim_chat_roominfo roominfo;
+- GSList *tlvlist;
+- guint16 maxmsglen, maxvisiblemsglen;
+-
+- aim_chat_readroominfo(bs, &roominfo);
+-
+- detaillevel = byte_stream_get8(bs);
+-
+- if (detaillevel != 0x02) {
+- purple_debug_misc("oscar", "faim: chat_roomupdateinfo: detail level %d not supported\n", detaillevel);
+- return 1;
+- }
+-
+- byte_stream_get16(bs); /* skip the TLV count */
+-
+- /*
+- * Everything else are TLVs.
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * Type 0x00d1: Maximum Message Length
+- */
+- maxmsglen = aim_tlv_get16(tlvlist, 0x00d1, 1);
+-
+- /*
+- * Type 0x00da: Maximum visible message length
+- */
+- maxvisiblemsglen = aim_tlv_get16(tlvlist, 0x00da, 1);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
+- ret = userfunc(od, conn, frame, maxmsglen, maxvisiblemsglen);
+- }
+-
+- g_free(roominfo.name);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/* Subtypes 0x0003 and 0x0004 */
+-static int
+-userlistchange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_userinfo_t *userinfo = NULL;
+- aim_rxcallback_t userfunc;
+- int curcount = 0, ret = 0;
+-
+- while (byte_stream_bytes_left(bs)) {
+- curcount++;
+- userinfo = g_realloc(userinfo, curcount * sizeof(aim_userinfo_t));
+- aim_info_extract(od, bs, &userinfo[curcount-1]);
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, curcount, userinfo);
+-
+- aim_info_free(userinfo);
+- g_free(userinfo);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0005 - Send a Chat Message.
+- *
+- * Possible flags:
+- * AIM_CHATFLAGS_NOREFLECT -- Unset the flag that requests messages
+- * should be sent to their sender.
+- * AIM_CHATFLAGS_AWAY -- Mark the message as an autoresponse
+- * (Note that WinAIM does not honor this,
+- * and displays the message as normal.)
+- *
+- * XXX convert this to use tlvchains
+- */
+-int
+-aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language)
+-{
+- int i;
+- ByteStream bs;
+- IcbmCookie *cookie;
+- aim_snacid_t snacid;
+- guint8 ckstr[8];
+- GSList *tlvlist = NULL, *inner_tlvlist = NULL;
+-
+- if (!od || !conn || !msg || (msglen <= 0))
+- return 0;
+-
+- byte_stream_new(&bs, 1142);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_CHAT, 0x0005, 0x0000, NULL, 0);
+-
+- /*
+- * Cookie
+- *
+- * XXX mkcookie should generate the cookie and cache it in one
+- * operation to preserve uniqueness.
+- */
+- for (i = 0; i < 8; i++)
+- ckstr[i] = (guint8)rand();
+-
+- cookie = aim_mkcookie(ckstr, AIM_COOKIETYPE_CHAT, NULL);
+- cookie->data = NULL; /* XXX store something useful here */
+-
+- aim_cachecookie(od, cookie);
+-
+- /* ICBM Header */
+- byte_stream_putraw(&bs, ckstr, 8); /* Cookie */
+- byte_stream_put16(&bs, 0x0003); /* Channel */
+-
+- /*
+- * Type 1: Flag meaning this message is destined to the room.
+- */
+- aim_tlvlist_add_noval(&tlvlist, 0x0001);
+-
+- /*
+- * Type 6: Reflect
+- */
+- if (!(flags & AIM_CHATFLAGS_NOREFLECT))
+- aim_tlvlist_add_noval(&tlvlist, 0x0006);
+-
+- /*
+- * Type 7: Autoresponse
+- */
+- if (flags & AIM_CHATFLAGS_AWAY)
+- aim_tlvlist_add_noval(&tlvlist, 0x0007);
+-
+- /*
+- * SubTLV: Type 1: Message
+- */
+- aim_tlvlist_add_raw(&inner_tlvlist, 0x0001, msglen, (guchar *)msg);
+-
+- /*
+- * SubTLV: Type 2: Encoding
+- */
+- if (encoding != NULL)
+- aim_tlvlist_add_str(&inner_tlvlist, 0x0002, encoding);
+-
+- /*
+- * SubTLV: Type 3: Language
+- */
+- if (language != NULL)
+- aim_tlvlist_add_str(&inner_tlvlist, 0x0003, language);
+-
+- /*
+- * Type 5: Message block. Contains more TLVs.
+- *
+- * This could include other information... We just
+- * put in a message TLV however.
+- *
+- */
+- aim_tlvlist_add_frozentlvlist(&tlvlist, 0x0005, &inner_tlvlist);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_CHAT, 0x0005, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0006
+- *
+- * We could probably include this in the normal ICBM parsing
+- * code as channel 0x0003, however, since only the start
+- * would be the same, we might as well do it here.
+- *
+- * General outline of this SNAC:
+- * snac
+- * cookie
+- * channel id
+- * tlvlist
+- * unknown
+- * source user info
+- * name
+- * evility
+- * userinfo tlvs
+- * online time
+- * etc
+- * message metatlv
+- * message tlv
+- * message string
+- * possibly others
+- *
+- */
+-static int
+-incomingim_ch3(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0, i;
+- aim_rxcallback_t userfunc;
+- aim_userinfo_t userinfo;
+- guint8 cookie[8];
+- guint16 channel;
+- GSList *tlvlist;
+- char *msg = NULL;
+- int len = 0;
+- char *encoding = NULL, *language = NULL;
+- IcbmCookie *ck;
+- aim_tlv_t *tlv;
+- ByteStream tbs;
+-
+- memset(&userinfo, 0, sizeof(aim_userinfo_t));
+-
+- /*
+- * Read ICBM Cookie.
+- */
+- for (i = 0; i < 8; i++)
+- cookie[i] = byte_stream_get8(bs);
+-
+- if ((ck = aim_uncachecookie(od, cookie, AIM_COOKIETYPE_CHAT))) {
+- g_free(ck->data);
+- g_free(ck);
+- }
+-
+- /*
+- * Channel ID
+- *
+- * Channel 0x0003 is used for chat messages.
+- *
+- */
+- channel = byte_stream_get16(bs);
+-
+- if (channel != 0x0003) {
+- purple_debug_misc("oscar", "faim: chat_incoming: unknown channel! (0x%04x)\n", channel);
+- return 0;
+- }
+-
+- /*
+- * Start parsing TLVs right away.
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * Type 0x0003: Source User Information
+- */
+- tlv = aim_tlv_gettlv(tlvlist, 0x0003, 1);
+- if (tlv != NULL)
+- {
+- byte_stream_init(&tbs, tlv->value, tlv->length);
+- aim_info_extract(od, &tbs, &userinfo);
+- }
+-
+- /*
+- * Type 0x0005: Message Block. Conains more TLVs.
+- */
+- tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1);
+- if (tlv != NULL)
+- {
+- GSList *inner_tlvlist;
+- aim_tlv_t *inner_tlv;
+-
+- byte_stream_init(&tbs, tlv->value, tlv->length);
+- inner_tlvlist = aim_tlvlist_read(&tbs);
+-
+- /*
+- * Type 0x0001: Message.
+- */
+- inner_tlv = aim_tlv_gettlv(inner_tlvlist, 0x0001, 1);
+- if (inner_tlv != NULL)
+- {
+- len = inner_tlv->length;
+- msg = aim_tlv_getvalue_as_string(inner_tlv);
+- }
+-
+- /*
+- * Type 0x0002: Encoding.
+- */
+- encoding = aim_tlv_getstr(inner_tlvlist, 0x0002, 1);
+-
+- /*
+- * Type 0x0003: Language.
+- */
+- language = aim_tlv_getstr(inner_tlvlist, 0x0003, 1);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, &userinfo, len, msg, encoding, language);
+-
+- aim_info_free(&userinfo);
+- g_free(msg);
+- g_free(encoding);
+- g_free(language);
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0002)
+- return infoupdate(od, conn, mod, frame, snac, bs);
+- else if ((snac->subtype == 0x0003) || (snac->subtype == 0x0004))
+- return userlistchange(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0006)
+- return incomingim_ch3(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-chat_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_CHAT;
+- mod->version = 0x0001;
+- mod->toolid = 0x0010;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "chat", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_chatnav.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chatnav.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_chatnav.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_chatnav.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,448 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x000d - Handle ChatNav.
+- *
+- * The ChatNav(igation) service does various things to keep chat
+- * alive. It provides room information, room searching and creating,
+- * as well as giving users the right ("permission") to use chat.
+- *
+- */
+-
+-#include "oscar.h"
+-
+-static int
+-error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_snac_t *snac2;
+- guint16 error, chatnav_error;
+- GSList *tlvlist;
+-
+- snac2 = aim_remsnac(od, snac->id);
+- if (!snac2) {
+- purple_debug_warning("oscar", "chatnav error: received response to unknown request (%08x)\n", snac->id);
+- return 0;
+- }
+-
+- if (snac2->family != SNAC_FAMILY_CHATNAV) {
+- purple_debug_warning("oscar", "chatnav error: received response that maps to corrupt request (fam=%04x)\n", snac2->family);
+- g_free(snac2->data);
+- g_free(snac2);
+- return 0;
+- }
+-
+- /*
+- * We now know what the original SNAC subtype was.
+- */
+- if (snac2->type == 0x0008) /* create room */
+- {
+- error = byte_stream_get16(bs);
+- tlvlist = aim_tlvlist_read(bs);
+- chatnav_error = aim_tlv_get16(tlvlist, 0x0008, 1);
+-
+- purple_debug_warning("oscar",
+- "Could not join room, error=0x%04hx, chatnav_error=0x%04hx\n",
+- error, chatnav_error);
+- purple_notify_error(od->gc, NULL, _("Could not join chat room"),
+- chatnav_error == 0x0033 ? _("Invalid chat room name") : _("Unknown error"));
+-
+- ret = 1;
+- }
+-
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0002
+- *
+- * conn must be a chatnav connection!
+- *
+- */
+-void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_CHATNAV, 0x0002);
+-}
+-
+-/*
+- * Subtype 0x0008
+- */
+-int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange)
+-{
+- static const char ck[] = {"create"};
+- static const char lang[] = {"en"};
+- static const char charset[] = {"us-ascii"};
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- byte_stream_new(&bs, 1142);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_CHATNAV, 0x0008, 0x0000, NULL, 0);
+-
+- /* exchange */
+- byte_stream_put16(&bs, exchange);
+-
+- /*
+- * This looks to be a big hack. You'll note that this entire
+- * SNAC is just a room info structure, but the hard room name,
+- * here, is set to "create".
+- *
+- * Either this goes on the "list of questions concerning
+- * why-the-hell-did-you-do-that", or this value is completely
+- * ignored. Without experimental evidence, but a good knowledge of
+- * AOL style, I'm going to guess that it is the latter, and that
+- * the value of the room name in create requests is ignored.
+- */
+- byte_stream_put8(&bs, strlen(ck));
+- byte_stream_putstr(&bs, ck);
+-
+- /*
+- * instance
+- *
+- * Setting this to 0xffff apparently assigns the last instance.
+- *
+- */
+- byte_stream_put16(&bs, 0xffff);
+-
+- /* detail level */
+- byte_stream_put8(&bs, 0x01);
+-
+- 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(&bs, aim_tlvlist_count(tlvlist));
+- aim_tlvlist_write(&bs, &tlvlist);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_CHATNAV, 0x0008, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-static int
+-parseinfo_perms(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs, aim_snac_t *snac2)
+-{
+- aim_rxcallback_t userfunc;
+- int ret = 0;
+- struct aim_chat_exchangeinfo *exchanges = NULL;
+- int curexchange;
+- aim_tlv_t *exchangetlv;
+- guint8 maxrooms = 0;
+- GSList *tlvlist, *innerlist;
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /*
+- * Type 0x0002: Maximum concurrent rooms.
+- */
+- if (aim_tlv_gettlv(tlvlist, 0x0002, 1))
+- maxrooms = aim_tlv_get8(tlvlist, 0x0002, 1);
+-
+- /*
+- * Type 0x0003: Exchange information
+- *
+- * There can be any number of these, each one
+- * representing another exchange.
+- *
+- */
+- for (curexchange = 0; ((exchangetlv = aim_tlv_gettlv(tlvlist, 0x0003, curexchange+1))); ) {
+- ByteStream tbs;
+-
+- byte_stream_init(&tbs, exchangetlv->value, exchangetlv->length);
+-
+- curexchange++;
+-
+- exchanges = g_realloc(exchanges, curexchange * sizeof(struct aim_chat_exchangeinfo));
+-
+- /* exchange number */
+- exchanges[curexchange-1].number = byte_stream_get16(&tbs);
+- innerlist = aim_tlvlist_read(&tbs);
+-
+- /*
+- * Type 0x0002: Unknown
+- */
+- if (aim_tlv_gettlv(innerlist, 0x0002, 1)) {
+- guint16 classperms;
+-
+- classperms = aim_tlv_get16(innerlist, 0x0002, 1);
+-
+- purple_debug_misc("oscar", "faim: class permissions %x\n", classperms);
+- }
+-
+- /*
+- * Type 0x00c9: Flags
+- *
+- * 1 Evilable
+- * 2 Nav Only
+- * 4 Instancing Allowed
+- * 8 Occupant Peek Allowed
+- *
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
+- exchanges[curexchange-1].flags = aim_tlv_get16(innerlist, 0x00c9, 1);
+-
+- /*
+- * Type 0x00d3: Exchange Description
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
+- exchanges[curexchange-1].name = aim_tlv_getstr(innerlist, 0x00d3, 1);
+- else
+- exchanges[curexchange-1].name = NULL;
+-
+- /*
+- * Type 0x00d5: Creation Permissions
+- *
+- * 0 Creation not allowed
+- * 1 Room creation allowed
+- * 2 Exchange creation allowed
+- *
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d5, 1)) {
+- guint8 createperms;
+-
+- createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
+- }
+-
+- /*
+- * Type 0x00d6: Character Set (First Time)
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d6, 1))
+- exchanges[curexchange-1].charset1 = aim_tlv_getstr(innerlist, 0x00d6, 1);
+- else
+- exchanges[curexchange-1].charset1 = NULL;
+-
+- /*
+- * Type 0x00d7: Language (First Time)
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d7, 1))
+- exchanges[curexchange-1].lang1 = aim_tlv_getstr(innerlist, 0x00d7, 1);
+- else
+- exchanges[curexchange-1].lang1 = NULL;
+-
+- /*
+- * Type 0x00d8: Character Set (Second Time)
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d8, 1))
+- exchanges[curexchange-1].charset2 = aim_tlv_getstr(innerlist, 0x00d8, 1);
+- else
+- exchanges[curexchange-1].charset2 = NULL;
+-
+- /*
+- * Type 0x00d9: Language (Second Time)
+- */
+- if (aim_tlv_gettlv(innerlist, 0x00d9, 1))
+- exchanges[curexchange-1].lang2 = aim_tlv_getstr(innerlist, 0x00d9, 1);
+- else
+- exchanges[curexchange-1].lang2 = NULL;
+-
+- aim_tlvlist_free(innerlist);
+- }
+-
+- /*
+- * Call client.
+- */
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, snac2->type, maxrooms, curexchange, exchanges);
+-
+- for (curexchange--; curexchange >= 0; curexchange--) {
+- g_free(exchanges[curexchange].name);
+- g_free(exchanges[curexchange].charset1);
+- g_free(exchanges[curexchange].lang1);
+- g_free(exchanges[curexchange].charset2);
+- g_free(exchanges[curexchange].lang2);
+- }
+- g_free(exchanges);
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-static int
+-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;
+- 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;
+- guint8 createperms = 0, detaillevel;
+- int cklen;
+- aim_tlv_t *bigblock;
+- int ret = 0;
+- ByteStream bbbs;
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- 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);
+- return 0;
+- }
+-
+- byte_stream_init(&bbbs, bigblock->value, bigblock->length);
+-
+- exchange = byte_stream_get16(&bbbs);
+- cklen = byte_stream_get8(&bbbs);
+- ck = byte_stream_getstr(&bbbs, cklen);
+- instance = byte_stream_get16(&bbbs);
+- detaillevel = byte_stream_get8(&bbbs);
+-
+- if (detaillevel != 0x02) {
+- purple_debug_misc("oscar", "unknown detaillevel in create room response (0x%02x)\n", detaillevel);
+- aim_tlvlist_free(tlvlist);
+- g_free(ck);
+- return 0;
+- }
+-
+- unknown = byte_stream_get16(&bbbs);
+-
+- innerlist = aim_tlvlist_read(&bbbs);
+-
+- if (aim_tlv_gettlv(innerlist, 0x006a, 1))
+- fqcn = aim_tlv_getstr(innerlist, 0x006a, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00c9, 1))
+- flags = aim_tlv_get16(innerlist, 0x00c9, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00ca, 1))
+- createtime = aim_tlv_get32(innerlist, 0x00ca, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00d1, 1))
+- maxmsglen = aim_tlv_get16(innerlist, 0x00d1, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00d2, 1))
+- maxoccupancy = aim_tlv_get16(innerlist, 0x00d2, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00d3, 1))
+- name = aim_tlv_getstr(innerlist, 0x00d3, 1);
+-
+- if (aim_tlv_gettlv(innerlist, 0x00d5, 1))
+- createperms = aim_tlv_get8(innerlist, 0x00d5, 1);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype))) {
+- ret = userfunc(od, conn, frame, snac2->type, fqcn, instance, exchange, flags, createtime, maxmsglen, maxoccupancy, createperms, unknown, name, ck);
+- }
+-
+- g_free(ck);
+- g_free(name);
+- g_free(fqcn);
+- aim_tlvlist_free(innerlist);
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0009
+- *
+- * Since multiple things can trigger this callback, we must lookup the
+- * snacid to determine the original snac subtype that was called.
+- *
+- * XXX This isn't really how this works. But this is: Every d/9 response
+- * has a 16bit value at the beginning. That matches to:
+- * Short Desc = 1
+- * Full Desc = 2
+- * Instance Info = 4
+- * Nav Short Desc = 8
+- * Nav Instance Info = 16
+- * And then everything is really asynchronous. There is no specific
+- * attachment of a response to a create room request, for example. Creating
+- * the room yields no different a response than requesting the room's info.
+- *
+- */
+-static int
+-parseinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_snac_t *snac2;
+- int ret = 0;
+-
+- if (!(snac2 = aim_remsnac(od, snac->id))) {
+- purple_debug_misc("oscar", "faim: chatnav_parse_info: received response to unknown request! (%08x)\n", snac->id);
+- return 0;
+- }
+-
+- if (snac2->family != SNAC_FAMILY_CHATNAV) {
+- purple_debug_misc("oscar", "faim: chatnav_parse_info: received response that maps to corrupt request! (fam=%04x)\n", snac2->family);
+- g_free(snac2->data);
+- g_free(snac2);
+- return 0;
+- }
+-
+- /*
+- * We now know what the original SNAC subtype was.
+- */
+- if (snac2->type == 0x0002) /* request chat rights */
+- ret = parseinfo_perms(od, conn, mod, frame, snac, bs, snac2);
+- else if (snac2->type == 0x0003) /* request exchange info */
+- purple_debug_misc("oscar", "chatnav_parse_info: response to exchange info\n");
+- else if (snac2->type == 0x0004) /* request room info */
+- purple_debug_misc("oscar", "chatnav_parse_info: response to room info\n");
+- else if (snac2->type == 0x0005) /* request more room info */
+- purple_debug_misc("oscar", "chatnav_parse_info: response to more room info\n");
+- else if (snac2->type == 0x0006) /* request occupant list */
+- purple_debug_misc("oscar", "chatnav_parse_info: response to occupant info\n");
+- else if (snac2->type == 0x0007) /* search for a room */
+- purple_debug_misc("oscar", "chatnav_parse_info: search results\n");
+- else if (snac2->type == 0x0008) /* create room */
+- ret = parseinfo_create(od, conn, mod, frame, snac, bs, snac2);
+- else
+- purple_debug_misc("oscar", "chatnav_parse_info: unknown request subtype (%04x)\n", snac2->type);
+-
+- if (snac2)
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return error(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0009)
+- return parseinfo(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-chatnav_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_CHATNAV;
+- mod->version = 0x0001;
+- mod->toolid = 0x0010;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "chatnav", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_feedbag.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_feedbag.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_feedbag.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_feedbag.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1981 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0013 - Server-Side/Stored Information.
+- *
+- * Relatively new facility that allows certain types of information, such as
+- * a user's buddy list, permit/deny list, and permit/deny preferences, to be
+- * stored on the server, so that they can be accessed from any client.
+- *
+- * We keep 2 copies of SSI data:
+- * 1) An exact copy of what is stored on the AIM servers.
+- * 2) A local copy that we make changes to, and then send diffs
+- * between this and the exact copy to keep them in sync.
+- *
+- * All the "aim_ssi_itemlist_bleh" functions near the top just modify the list
+- * that is given to them (i.e. they don't send SNACs).
+- *
+- * The SNAC sending and receiving functions are lower down in the file, and
+- * they're simpler. They are in the order of the subtypes they deal with,
+- * starting with the request rights function (subtype 0x0002), then parse
+- * rights (subtype 0x0003), then--well, you get the idea.
+- *
+- * This is entirely too complicated.
+- * You don't know the half of it.
+- *
+- */
+-
+-#include "oscar.h"
+-#include "debug.h"
+-
+-static int aim_ssi_addmoddel(OscarData *od);
+-
+-/**
+- * List types based on http://dev.aol.com/aim/oscar/#FEEDBAG (archive.org)
+- * and http://iserverd.khstu.ru/oscar/ssi_item.html
+- *
+- * @param type The type of a list item as integer number, as provided by an aim_ssi_item struct.
+- * @return Returns the name of the item type as a character string.
+- */
+-static const gchar*
+-aim_ssi_type_to_string(guint16 type)
+-{
+- struct TypeStringPair
+- {
+- guint16 type;
+- const gchar *string;
+- };
+- static const struct TypeStringPair type_strings[] = {
+- { 0x0000, "Buddy" },
+- { 0x0001, "Group" },
+- { 0x0002, "Permit/Visible" },
+- { 0x0003, "Deny/Invisible" },
+- { 0x0004, "PDInfo" },
+- { 0x0005, "PresencePrefs" },
+- { 0x0006, "Non-Buddy Info" },
+- { 0x0009, "ClientPrefs" },
+- { 0x000e, "ICQDeny/Ignore" },
+- { 0x0014, "Buddy Icon" },
+- { 0x0015, "Recent Buddies" },
+- { 0x0019, "Non-Buddy" },
+- { 0x001d, "Vanity Info" },
+- { 0x0020, "ICQ-MDir" },
+- { 0x0029, "Facebook" },
+- };
+- int i;
+- for (i = 0; i < G_N_ELEMENTS(type_strings); i++) {
+- if (type_strings[i].type == type) {
+- return type_strings[i].string;
+- }
+- }
+- return "unknown";
+-}
+-
+-/** For debug log output: Appends a line containing information about a given list item to a string.
+- *
+- * @param str String to which the line will be appended.
+- * @param prefix A string which will be prepended to the line.
+- * @param item List item from which information is extracted.
+- */
+-static void
+-aim_ssi_item_debug_append(GString *str, char *prefix, struct aim_ssi_item *item)
+-{
+- g_string_append_printf(str,
+- "%s gid=0x%04hx, bid=0x%04hx, list_type=0x%04hx [%s], name=%s.\n",
+- prefix, item->gid, item->bid, item->type, aim_ssi_type_to_string(item->type),
+- item->name ? item->name : "(null)");
+-}
+-
+-/**
+- * Locally rebuild the 0x00c8 TLV in the additional data of the given group.
+- *
+- * @param list A pointer to a pointer to the current list of items.
+- * @param name A null terminated string containing the group name, or NULL
+- * if you want to modify the master group.
+- * @return Return a pointer to the modified item.
+- */
+-static void
+-aim_ssi_itemlist_rebuildgroup(struct aim_ssi_item *list, const char *name)
+-{
+- int newlen;
+- struct aim_ssi_item *cur, *group;
+-
+- /* Find the group */
+- if (!(group = aim_ssi_itemlist_finditem(list, name, NULL, AIM_SSI_TYPE_GROUP)))
+- return;
+-
+- /* Find the length for the new additional data */
+- newlen = 0;
+- if (group->gid == 0x0000) {
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
+- newlen += 2;
+- } else {
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
+- newlen += 2;
+- }
+-
+- /* Build the new TLV list */
+- if (newlen > 0) {
+- guint8 *newdata;
+-
+- newdata = (guint8 *)g_malloc((newlen)*sizeof(guint8));
+- newlen = 0;
+- if (group->gid == 0x0000) {
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid != 0x0000))
+- newlen += aimutil_put16(newdata+newlen, cur->gid);
+- } else {
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->gid == group->gid) && (cur->type == AIM_SSI_TYPE_BUDDY))
+- newlen += aimutil_put16(newdata+newlen, cur->bid);
+- }
+- aim_tlvlist_replace_raw(&group->data, 0x00c8, newlen, newdata);
+-
+- g_free(newdata);
+- }
+-}
+-
+-/**
+- * Locally add a new item to the given item list.
+- *
+- * @param list A pointer to a pointer to the current list of items.
+- * @param name A null terminated string of the name of the new item, or NULL if the
+- * item should have no name.
+- * @param gid The group ID# you want the new item to have, or 0xFFFF if we should pick something.
+- * @param bid The buddy ID# you want the new item to have, or 0xFFFF if we should pick something.
+- * @param type The type of the item, 0x0000 for a contact, 0x0001 for a group, etc.
+- * @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, GSList *data)
+-{
+- gboolean exists;
+- struct aim_ssi_item *cur, *new;
+-
+- new = g_new(struct aim_ssi_item, 1);
+-
+- /* Set the name */
+- new->name = g_strdup(name);
+-
+- /* Set the group ID# and buddy ID# */
+- new->gid = gid;
+- new->bid = bid;
+- if (type == AIM_SSI_TYPE_GROUP) {
+- if ((new->gid == 0xFFFF) && name) {
+- do {
+- new->gid += 0x0001;
+- exists = FALSE;
+- for (cur = *list; cur != NULL; cur = cur->next)
+- if ((cur->type == AIM_SSI_TYPE_GROUP) && (cur->gid == new->gid)) {
+- exists = TRUE;
+- break;
+- }
+- } while (exists);
+- }
+- } else if (new->gid == 0x0000) {
+- /*
+- * This is weird, but apparently items in the root group can't
+- * have a buddy ID equal to any group ID. You'll get error
+- * 0x0003 when trying to add, which is "item already exists"
+- */
+- if (new->bid == 0xFFFF) {
+- do {
+- new->bid += 0x0001;
+- exists = FALSE;
+- for (cur = *list; cur != NULL; cur = cur->next)
+- if (cur->bid == new->bid || cur->gid == new->bid) {
+- exists = TRUE;
+- break;
+- }
+- } while (exists);
+- }
+- } else {
+- if (new->bid == 0xFFFF) {
+- do {
+- new->bid += 0x0001;
+- exists = FALSE;
+- for (cur = *list; cur != NULL; cur = cur->next)
+- if (cur->bid == new->bid && cur->gid == new->gid) {
+- exists = TRUE;
+- break;
+- }
+- } while (exists);
+- }
+- }
+-
+- /* Set the type */
+- new->type = type;
+-
+- /* Set the TLV list */
+- new->data = aim_tlvlist_copy(data);
+-
+- /* Add the item to the list in the correct numerical position. Fancy, eh? */
+- if (*list) {
+- if ((new->gid < (*list)->gid) || ((new->gid == (*list)->gid) && (new->bid < (*list)->bid))) {
+- new->next = *list;
+- *list = new;
+- } else {
+- struct aim_ssi_item *prev;
+- for ((prev=*list, cur=(*list)->next); (cur && ((new->gid > cur->gid) || ((new->gid == cur->gid) && (new->bid > cur->bid)))); prev=cur, cur=cur->next);
+- new->next = prev->next;
+- prev->next = new;
+- }
+- } else {
+- new->next = *list;
+- *list = new;
+- }
+-
+- return new;
+-}
+-
+-/**
+- * Locally delete an item from the given item list.
+- *
+- * @param list A pointer to a pointer to the current list of items.
+- * @param del A pointer to the item you want to remove from the list.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-static int aim_ssi_itemlist_del(struct aim_ssi_item **list, struct aim_ssi_item *del)
+-{
+- if (!(*list) || !del)
+- return -EINVAL;
+-
+- /* Remove the item from the list */
+- if (*list == del) {
+- *list = (*list)->next;
+- } else {
+- struct aim_ssi_item *cur;
+- for (cur=*list; (cur->next && (cur->next!=del)); cur=cur->next);
+- if (cur->next)
+- cur->next = del->next;
+- }
+-
+- /* Free the removed item */
+- g_free(del->name);
+- aim_tlvlist_free(del->data);
+- g_free(del);
+-
+- return 0;
+-}
+-
+-/**
+- * Compare two items to see if they have the same data.
+- *
+- * @param cur1 A pointer to a pointer to the first item.
+- * @param cur2 A pointer to a pointer to the second item.
+- * @return Return 0 if no differences, or a number if there are differences.
+- */
+-static int aim_ssi_itemlist_cmp(struct aim_ssi_item *cur1, struct aim_ssi_item *cur2)
+-{
+- if (!cur1 || !cur2)
+- return 1;
+-
+- if (cur1->data && !cur2->data)
+- return 2;
+-
+- if (!cur1->data && cur2->data)
+- return 3;
+-
+- if ((cur1->data && cur2->data) && (aim_tlvlist_cmp(cur1->data, cur2->data)))
+- return 4;
+-
+- if (cur1->name && !cur2->name)
+- return 5;
+-
+- if (!cur1->name && cur2->name)
+- return 6;
+-
+- if (cur1->name && cur2->name && oscar_util_name_compare(cur1->name, cur2->name))
+- return 7;
+-
+- if (cur1->gid != cur2->gid)
+- return 8;
+-
+- if (cur1->bid != cur2->bid)
+- return 9;
+-
+- if (cur1->type != cur2->type)
+- return 10;
+-
+- return 0;
+-}
+-
+-static gboolean aim_ssi_itemlist_valid(struct aim_ssi_item *list, struct aim_ssi_item *item)
+-{
+- struct aim_ssi_item *cur;
+- for (cur=list; cur; cur=cur->next)
+- if (cur == item)
+- return TRUE;
+- return FALSE;
+-}
+-
+-/**
+- * Locally find an item given a group ID# and a buddy ID#.
+- *
+- * @param list A pointer to the current list of items.
+- * @param gid The group ID# of the desired item.
+- * @param bid The buddy ID# of the desired item.
+- * @return Return a pointer to the item if found, else return NULL;
+- */
+-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid)
+-{
+- struct aim_ssi_item *cur;
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->gid == gid) && (cur->bid == bid))
+- return cur;
+- return NULL;
+-}
+-
+-/**
+- * Locally find an item given a group name, buddy name, and type. If group name
+- * and buddy name are null, then just return the first item of the given type.
+- *
+- * @param list A pointer to the current list of items.
+- * @param gn The group name of the desired item.
+- * @param bn The buddy name of the desired item.
+- * @param type The type of the desired item.
+- * @return Return a pointer to the item if found, else return NULL.
+- */
+-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type)
+-{
+- struct aim_ssi_item *cur;
+- if (!list)
+- return NULL;
+-
+- if (gn && bn) { /* For finding buddies in groups */
+- for (cur=list; cur; cur=cur->next)
+- if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
+- struct aim_ssi_item *curg;
+- for (curg=list; curg; curg=curg->next)
+- if ((curg->type == AIM_SSI_TYPE_GROUP) && (curg->gid == cur->gid) && (curg->name) && !(oscar_util_name_compare(curg->name, gn)))
+- return cur;
+- }
+-
+- } else if (gn) { /* For finding groups */
+- for (cur=list; cur; cur=cur->next) {
+- if ((cur->type == type) && (cur->bid == 0x0000) && (cur->name) && !(oscar_util_name_compare(cur->name, gn))) {
+- return cur;
+- }
+- }
+-
+- } else if (bn) { /* For finding permits, denies, and ignores */
+- for (cur=list; cur; cur=cur->next) {
+- if ((cur->type == type) && (cur->name) && !(oscar_util_name_compare(cur->name, bn))) {
+- return cur;
+- }
+- }
+-
+- /* For stuff without names--permit deny setting, visibility mask, etc. */
+- } else for (cur=list; cur; cur=cur->next) {
+- if ((cur->type == type) && (!cur->name))
+- return cur;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Check if the given buddy exists in any group in the buddy list.
+- *
+- * @param list A pointer to the current list of items.
+- * @param bn The group name of the desired item.
+- * @return Return a pointer to the name of the item if found, else return NULL;
+- */
+-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn)
+-{
+- if (!bn)
+- return NULL;
+- return aim_ssi_itemlist_finditem(list, NULL, bn, AIM_SSI_TYPE_BUDDY);
+-}
+-
+-/**
+- * Locally find the parent item of the given buddy name.
+- *
+- * @param list A pointer to the current list of items.
+- * @param bn The buddy name of the desired item.
+- * @return Return a pointer to the name of the item if found, else return NULL;
+- */
+-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn)
+-{
+- struct aim_ssi_item *cur, *curg;
+- if (!list || !bn)
+- return NULL;
+- if (!(cur = aim_ssi_itemlist_exists(list, bn)))
+- return NULL;
+- if (!(curg = aim_ssi_itemlist_find(list, cur->gid, 0x0000)))
+- return NULL;
+- return curg->name;
+-}
+-
+-/**
+- * Locally find the permit/deny setting item, and return the setting.
+- *
+- * @param list A pointer to the current list of items.
+- * @return Return the current SSI permit deny setting, or 0 if no setting was found.
+- */
+-int aim_ssi_getpermdeny(struct aim_ssi_item *list)
+-{
+- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PDINFO);
+- if (cur) {
+- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00ca, 1);
+- if (tlv && tlv->value)
+- return aimutil_get8(tlv->value);
+- }
+- return 0;
+-}
+-
+-/**
+- * Locally find the presence flag item, and return the setting. The returned setting is a
+- * bitmask of the preferences. See the AIM_SSI_PRESENCE_FLAG_* #defines in oscar.h.
+- *
+- * @param list A pointer to the current list of items.
+- * @return Return the current set of preferences.
+- */
+-guint32 aim_ssi_getpresence(struct aim_ssi_item *list)
+-{
+- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS);
+- if (cur) {
+- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x00c9, 1);
+- if (tlv && tlv->length)
+- return aimutil_get32(tlv->value);
+- }
+- return 0xFFFFFFFF;
+-}
+-
+-/**
+- * Locally find the alias of the given buddy.
+- *
+- * @param list A pointer to the current list of items.
+- * @param gn The group of the buddy.
+- * @param bn The name of the buddy.
+- * @return A pointer to a NULL terminated string that is the buddy's
+- * alias, or NULL if the buddy has no alias. You should free
+- * this returned value!
+- */
+-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn)
+-{
+- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
+- if (cur) {
+- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x0131, 1);
+- if (tlv && tlv->length)
+- return g_strndup((const gchar *)tlv->value, tlv->length);
+- }
+- return NULL;
+-}
+-
+-/**
+- * Locally find the comment of the given buddy.
+- *
+- * @param list A pointer to the current list of items.
+- * @param gn The group of the buddy.
+- * @param bn The name of the buddy.
+- * @return A pointer to a NULL terminated string that is the buddy's
+- * comment, or NULL if the buddy has no comment. You should free
+- * this returned value!
+- */
+-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn)
+-{
+- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
+- if (cur) {
+- aim_tlv_t *tlv = aim_tlv_gettlv(cur->data, 0x013c, 1);
+- if (tlv && tlv->length) {
+- return g_strndup((const gchar *)tlv->value, tlv->length);
+- }
+- }
+- return NULL;
+-}
+-
+-/**
+- * Locally find if you are waiting for authorization for a buddy.
+- *
+- * @param list A pointer to the current list of items.
+- * @param gn The group of the buddy.
+- * @param bn The name of the buddy.
+- * @return 1 if you are waiting for authorization; 0 if you are not
+- */
+-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn)
+-{
+- struct aim_ssi_item *cur = aim_ssi_itemlist_finditem(list, gn, bn, AIM_SSI_TYPE_BUDDY);
+- if (cur) {
+- if (aim_tlv_gettlv(cur->data, 0x0066, 1))
+- return TRUE;
+- }
+- return FALSE;
+-}
+-
+-/**
+- * If there are changes, then create temporary items and
+- * call addmoddel.
+- *
+- * @param od The oscar session.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-static int aim_ssi_sync(OscarData *od)
+-{
+- struct aim_ssi_item *cur1, *cur2;
+- struct aim_ssi_tmp *cur, *new;
+- int n = 0;
+- GString *debugstr = g_string_new("");
+-
+- /*
+- * The variable "n" is used to limit the number of addmoddel's that
+- * are performed in a single SNAC. It will hopefully keep the size
+- * of the SNAC below the maximum SNAC size.
+- */
+-
+- if (!od)
+- return -EINVAL;
+-
+- /* If we're waiting for an ack, we shouldn't do anything else */
+- if (od->ssi.waiting_for_ack)
+- return 0;
+-
+- /*
+- * Compare the 2 lists and create an aim_ssi_tmp for each difference.
+- * We should only send either additions, modifications, or deletions
+- * before waiting for an acknowledgement. So first do deletions, then
+- * additions, then modifications. Also, both the official and the local
+- * list should be in ascending numerical order for the group ID#s and the
+- * buddy ID#s, which makes things more efficient. I think.
+- */
+-
+- /* Deletions */
+- if (!od->ssi.pending) {
+- for (cur1=od->ssi.official; cur1 && (n < 15); cur1=cur1->next) {
+- if (!aim_ssi_itemlist_find(od->ssi.local, cur1->gid, cur1->bid)) {
+- n++;
+- new = g_new(struct aim_ssi_tmp, 1);
+- new->action = SNAC_SUBTYPE_FEEDBAG_DEL;
+- new->ack = 0xffff;
+- new->name = NULL;
+- new->item = cur1;
+- new->next = NULL;
+- if (od->ssi.pending) {
+- for (cur=od->ssi.pending; cur->next; cur=cur->next);
+- cur->next = new;
+- } else
+- od->ssi.pending = new;
+- aim_ssi_item_debug_append(debugstr, "Deleting item ", cur1);
+- }
+- }
+- }
+-
+- /* Additions */
+- if (!od->ssi.pending) {
+- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
+- if (!aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid)) {
+- n++;
+- new = g_new(struct aim_ssi_tmp, 1);
+- new->action = SNAC_SUBTYPE_FEEDBAG_ADD;
+- new->ack = 0xffff;
+- new->name = NULL;
+- new->item = cur1;
+- new->next = NULL;
+- if (od->ssi.pending) {
+- for (cur=od->ssi.pending; cur->next; cur=cur->next);
+- cur->next = new;
+- } else
+- od->ssi.pending = new;
+- aim_ssi_item_debug_append(debugstr, "Adding item ", cur1);
+- }
+- }
+- }
+-
+- /* Modifications */
+- if (!od->ssi.pending) {
+- for (cur1=od->ssi.local; cur1 && (n < 15); cur1=cur1->next) {
+- cur2 = aim_ssi_itemlist_find(od->ssi.official, cur1->gid, cur1->bid);
+- if (cur2 && (aim_ssi_itemlist_cmp(cur1, cur2))) {
+- n++;
+- new = g_new(struct aim_ssi_tmp, 1);
+- new->action = SNAC_SUBTYPE_FEEDBAG_MOD;
+- new->ack = 0xffff;
+- new->name = NULL;
+- new->item = cur1;
+- new->next = NULL;
+- if (od->ssi.pending) {
+- for (cur=od->ssi.pending; cur->next; cur=cur->next);
+- cur->next = new;
+- } else
+- od->ssi.pending = new;
+- aim_ssi_item_debug_append(debugstr, "Modifying item ", cur1);
+- }
+- }
+- }
+- if (debugstr->len > 0) {
+- purple_debug_info("oscar", "%s", debugstr->str);
+- if (purple_debug_is_verbose()) {
+- g_string_truncate(debugstr, 0);
+- for (cur1 = od->ssi.local; cur1; cur1 = cur1->next)
+- aim_ssi_item_debug_append(debugstr, "\t", cur1);
+- purple_debug_misc("oscar", "Dumping item list of account %s:\n%s",
+- purple_connection_get_account(od->gc)->username, debugstr->str);
+- }
+- }
+- g_string_free(debugstr, TRUE);
+-
+- /* We're out of stuff to do, so tell the AIM servers we're done and exit */
+- if (!od->ssi.pending) {
+- if (od->ssi.in_transaction) {
+- aim_ssi_modend(od);
+- od->ssi.in_transaction = FALSE;
+- }
+- return 0;
+- }
+-
+- /* If this is the first in a series of add/mod/del
+- * requests then send the "begin transaction" message. */
+- if (!od->ssi.in_transaction)
+- {
+- aim_ssi_modbegin(od);
+- od->ssi.in_transaction = TRUE;
+- }
+-
+- /* Make sure we don't send anything else between now
+- * and when we receive the ack for the following operation */
+- od->ssi.waiting_for_ack = TRUE;
+-
+- /* Now go mail off our data and wait 4 to 6 weeks */
+- return aim_ssi_addmoddel(od);;
+-}
+-
+-/**
+- * Free all SSI data.
+- *
+- * This doesn't remove it from the server, that's different.
+- *
+- * @param od The oscar odion.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-static void
+-aim_ssi_freelist(OscarData *od)
+-{
+- struct aim_ssi_item *cur, *del;
+- struct aim_ssi_tmp *curtmp, *deltmp;
+-
+- cur = od->ssi.official;
+- while (cur) {
+- del = cur;
+- cur = cur->next;
+- g_free(del->name);
+- aim_tlvlist_free(del->data);
+- g_free(del);
+- }
+-
+- cur = od->ssi.local;
+- while (cur) {
+- del = cur;
+- cur = cur->next;
+- g_free(del->name);
+- aim_tlvlist_free(del->data);
+- g_free(del);
+- }
+-
+- curtmp = od->ssi.pending;
+- while (curtmp) {
+- deltmp = curtmp;
+- curtmp = curtmp->next;
+- g_free(deltmp);
+- }
+-
+- od->ssi.numitems = 0;
+- od->ssi.official = NULL;
+- od->ssi.local = NULL;
+- od->ssi.pending = NULL;
+- od->ssi.timestamp = (time_t)0;
+-}
+-
+-/**
+- * This "cleans" the ssi list. It does the following:
+- * 1) Makes sure all buddies, permits, and denies have names.
+- * 2) Makes sure that all buddies are in a group that exist.
+- * 3) Deletes any empty groups
+- *
+- * @param od The oscar odion.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_cleanlist(OscarData *od)
+-{
+- struct aim_ssi_item *cur, *next;
+-
+- if (!od)
+- return -EINVAL;
+-
+- /* Delete any buddies, permits, or denies with empty names. */
+- /* If there are any buddies directly in the master group, add them to a real group. */
+- /* DESTROY any buddies that are directly in the master group. */
+- /* Do the same for buddies that are in a non-existant group. */
+- /* This will kind of mess up if you hit the item limit, but this function isn't too critical */
+- cur = od->ssi.local;
+- while (cur) {
+- next = cur->next;
+- if (!cur->name) {
+- if (cur->type == AIM_SSI_TYPE_BUDDY)
+- aim_ssi_delbuddy(od, NULL, NULL);
+- else if (cur->type == AIM_SSI_TYPE_PERMIT || cur->type == AIM_SSI_TYPE_DENY || cur->type == AIM_SSI_TYPE_ICQDENY)
+- aim_ssi_del_from_private_list(od, NULL, cur->type);
+- } 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", NULL, alias, NULL, NULL, FALSE);
+- aim_ssi_delbuddy(od, cur->name, NULL);
+- g_free(alias);
+- }
+- cur = next;
+- }
+-
+- /* Make sure there aren't any duplicate buddies in a group, or duplicate permits or denies */
+- cur = od->ssi.local;
+- while (cur) {
+- if ((cur->type == AIM_SSI_TYPE_BUDDY) || (cur->type == AIM_SSI_TYPE_PERMIT) || (cur->type == AIM_SSI_TYPE_DENY))
+- {
+- struct aim_ssi_item *cur2, *next2;
+- cur2 = cur->next;
+- while (cur2) {
+- next2 = cur2->next;
+- if ((cur->type == cur2->type) && (cur->gid == cur2->gid) && (cur->name != NULL) && (cur2->name != NULL) && (!oscar_util_name_compare(cur->name, cur2->name))) {
+- aim_ssi_itemlist_del(&od->ssi.local, cur2);
+- }
+- cur2 = next2;
+- }
+- }
+- cur = cur->next;
+- }
+-
+- /* If we've made any changes then sync our list with the server's */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Add a buddy to the list.
+- *
+- * @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, GSList *data, const char *alias, const char *comment, const char *smsnum, gboolean needauth)
+-{
+- struct aim_ssi_item *parent;
+-
+- if (!od || !name || !group)
+- return -EINVAL;
+-
+- /* Find the parent */
+- if (!(parent = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP))) {
+- /* Find the parent's parent (the master group) */
+- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- /* Add the parent */
+- parent = aim_ssi_itemlist_add(&od->ssi.local, group, 0xFFFF, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- /* Modify the parent's parent (the master group) */
+- aim_ssi_itemlist_rebuildgroup(od->ssi.local, NULL);
+- }
+-
+- /* Create a TLV list for the new buddy */
+- if (needauth)
+- aim_tlvlist_add_noval(&data, 0x0066);
+- if (alias != NULL)
+- aim_tlvlist_add_str(&data, 0x0131, alias);
+- if (smsnum != NULL)
+- aim_tlvlist_add_str(&data, 0x013a, smsnum);
+- 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);
+-
+- /* Modify the parent group */
+- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-int
+-aim_ssi_add_to_private_list(OscarData *od, const char* name, guint16 list_type)
+-{
+- if (!od || !name || !od->ssi.received_data)
+- return -EINVAL;
+-
+- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- aim_ssi_itemlist_add(&od->ssi.local, name, 0x0000, 0xFFFF, list_type, NULL);
+- return aim_ssi_sync(od);
+-}
+-
+-int
+-aim_ssi_del_from_private_list(OscarData* od, const char* name, guint16 list_type)
+-{
+- struct aim_ssi_item *del;
+-
+- if (!od)
+- return -EINVAL;
+-
+- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, NULL, name, list_type)))
+- return -EINVAL;
+-
+- aim_ssi_itemlist_del(&od->ssi.local, del);
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Deletes a buddy from the list.
+- *
+- * @param od The oscar odion.
+- * @param name The name of the item, or NULL.
+- * @param group The group of the item, or NULL.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_delbuddy(OscarData *od, const char *name, const char *group)
+-{
+- struct aim_ssi_item *del;
+-
+- if (!od)
+- return -EINVAL;
+-
+- /* Find the buddy */
+- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, name, AIM_SSI_TYPE_BUDDY)))
+- return -EINVAL;
+-
+- /* Remove the item from the list */
+- aim_ssi_itemlist_del(&od->ssi.local, del);
+-
+- /* Modify the parent group */
+- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Deletes a group from the list.
+- *
+- * @param od The oscar odion.
+- * @param group The name of the group.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_delgroup(OscarData *od, const char *group)
+-{
+- struct aim_ssi_item *del;
+- aim_tlv_t *tlv;
+-
+- if (!od)
+- return -EINVAL;
+-
+- /* Find the group */
+- if (!(del = aim_ssi_itemlist_finditem(od->ssi.local, group, NULL, AIM_SSI_TYPE_GROUP)))
+- return -EINVAL;
+-
+- /* Don't delete the group if it's not empty */
+- tlv = aim_tlv_gettlv(del->data, 0x00c8, 1);
+- if (tlv && tlv->length > 0)
+- return -EINVAL;
+-
+- /* Remove the item from the list */
+- aim_ssi_itemlist_del(&od->ssi.local, del);
+-
+- /* Modify the parent group */
+- aim_ssi_itemlist_rebuildgroup(od->ssi.local, group);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Move a buddy from one group to another group. This basically just deletes the
+- * buddy and re-adds it.
+- *
+- * @param od The oscar odion.
+- * @param oldgn The group that the buddy is currently in.
+- * @param newgn The group that the buddy should be moved in to.
+- * @param bn The name of the buddy to be moved.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *bn)
+-{
+- struct aim_ssi_item *buddy;
+- GSList *data;
+-
+- /* Find the buddy */
+- buddy = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, bn, AIM_SSI_TYPE_BUDDY);
+- if (buddy == NULL)
+- return -EINVAL;
+-
+- /* Make a copy of the buddy's TLV list */
+- data = aim_tlvlist_copy(buddy->data);
+-
+- /* Delete the old item */
+- aim_ssi_delbuddy(od, bn, oldgn);
+-
+- /* Add the new item using the EXACT SAME TLV list */
+- aim_ssi_addbuddy(od, bn, newgn, data, NULL, NULL, NULL, FALSE);
+-
+- return 0;
+-}
+-
+-/**
+- * Change the alias stored on the server for a given buddy.
+- *
+- * @param od The oscar odion.
+- * @param gn The group that the buddy is currently in.
+- * @param bn The name of the buddy.
+- * @param alias The new alias for the buddy, or NULL if you want to remove
+- * a buddy's comment.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias)
+-{
+- struct aim_ssi_item *tmp;
+-
+- if (!od || !gn || !bn)
+- return -EINVAL;
+-
+- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+- return -EINVAL;
+-
+- /* Either add or remove the 0x0131 TLV from the TLV chain */
+- if ((alias != NULL) && (strlen(alias) > 0))
+- aim_tlvlist_replace_str(&tmp->data, 0x0131, alias);
+- else
+- aim_tlvlist_remove(&tmp->data, 0x0131);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Change the comment stored on the server for a given buddy.
+- *
+- * @param od The oscar odion.
+- * @param gn The group that the buddy is currently in.
+- * @param bn The name of the buddy.
+- * @param alias The new comment for the buddy, or NULL if you want to remove
+- * a buddy's comment.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *comment)
+-{
+- struct aim_ssi_item *tmp;
+-
+- if (!od || !gn || !bn)
+- return -EINVAL;
+-
+- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, gn, bn, AIM_SSI_TYPE_BUDDY)))
+- return -EINVAL;
+-
+- /* Either add or remove the 0x0131 TLV from the TLV chain */
+- if ((comment != NULL) && (strlen(comment) > 0))
+- aim_tlvlist_replace_str(&tmp->data, 0x013c, comment);
+- else
+- aim_tlvlist_remove(&tmp->data, 0x013c);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Rename a group.
+- *
+- * @param od The oscar odion.
+- * @param oldgn The old group name.
+- * @param newgn The new group name.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn)
+-{
+- struct aim_ssi_item *group;
+-
+- if (!od || !oldgn || !newgn)
+- return -EINVAL;
+-
+- if (!(group = aim_ssi_itemlist_finditem(od->ssi.local, oldgn, NULL, AIM_SSI_TYPE_GROUP)))
+- return -EINVAL;
+-
+- g_free(group->name);
+- group->name = g_strdup(newgn);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Stores your permit/deny setting on the server, and starts using it.
+- *
+- * @param od The oscar odion.
+- * @param permdeny Your permit/deny setting. For ICQ accounts, it actually affects your visibility
+- * and has nothing to do with blocking. Can be one of the following:
+- * 1 - Allow all users
+- * 2 - Block all users
+- * 3 - Allow only the users below
+- * 4 - Block only the users below
+- * 5 - Allow only users on my buddy list
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny)
+-{
+- struct aim_ssi_item *tmp;
+-
+- if (!od || !od->ssi.received_data)
+- return -EINVAL;
+-
+- /* Find the PDINFO item, or add it if it does not exist */
+- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PDINFO))) {
+- /* Make sure the master group exists */
+- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PDINFO, NULL);
+- }
+-
+- /* Need to add the 0x00ca TLV to the TLV chain */
+- aim_tlvlist_replace_8(&tmp->data, 0x00ca, permdeny);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/**
+- * Set buddy icon information
+- *
+- * @param od The oscar odion.
+- * @param iconcsum The MD5 checksum of the icon you are using.
+- * @param iconcsumlen Length of the MD5 checksum given above. Should be 0x10 bytes.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen)
+-{
+- struct aim_ssi_item *tmp;
+- guint8 *csumdata;
+-
+- if (!od || !iconsum || !iconsumlen || !od->ssi.received_data)
+- return -EINVAL;
+-
+- /* Find the ICONINFO item, or add it if it does not exist */
+- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, "1", AIM_SSI_TYPE_ICONINFO))) {
+- /* Make sure the master group exists */
+- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- tmp = aim_ssi_itemlist_add(&od->ssi.local, "1", 0x0000, 0xFFFF, AIM_SSI_TYPE_ICONINFO, NULL);
+- }
+-
+- /* Need to add the 0x00d5 TLV to the TLV chain */
+- csumdata = (guint8 *)g_malloc((iconsumlen+2)*sizeof(guint8));
+- aimutil_put8(&csumdata[0], 0x00);
+- aimutil_put8(&csumdata[1], iconsumlen);
+- memcpy(&csumdata[2], iconsum, iconsumlen);
+- aim_tlvlist_replace_raw(&tmp->data, 0x00d5, (iconsumlen+2) * sizeof(guint8), csumdata);
+- g_free(csumdata);
+-
+- /* Need to add the 0x0131 TLV to the TLV chain, used to cache the icon */
+- aim_tlvlist_replace_noval(&tmp->data, 0x0131);
+-
+- /* Sync our local list with the server list */
+- aim_ssi_sync(od);
+- return 0;
+-}
+-
+-/**
+- * Remove a reference to a server stored buddy icon. This will make your
+- * icon stop showing up to other people.
+- *
+- * Really this function just sets the icon to a dummy value. It's weird...
+- * but I think the dummy value basically means "I don't have an icon!"
+- *
+- * @param od The oscar session.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_delicon(OscarData *od)
+-{
+- const guint8 csumdata[] = {0x02, 0x01, 0xd2, 0x04, 0x72};
+-
+- return aim_ssi_seticon(od, csumdata, 5);
+-}
+-
+-/**
+- * Stores your setting for various SSI settings. Whether you
+- * should show up as idle or not, etc.
+- *
+- * @param od The oscar odion.
+- * @param presence A bitmask of the first 32 entries [0-31] from
+- * http://dev.aol.com/aim/oscar/#FEEDBAG__BUDDY_PREFS
+- * 0x00000002 - Hide "eBuddy group" (whatever that is)
+- * 0x00000400 - Allow others to see your idle time
+- * 0x00020000 - Don't show Recent Buddies
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_ssi_setpresence(OscarData *od, guint32 presence) {
+- struct aim_ssi_item *tmp;
+-
+- if (!od || !od->ssi.received_data)
+- return -EINVAL;
+-
+- /* Find the PRESENCEPREFS item, or add it if it does not exist */
+- if (!(tmp = aim_ssi_itemlist_finditem(od->ssi.local, NULL, NULL, AIM_SSI_TYPE_PRESENCEPREFS))) {
+- /* Make sure the master group exists */
+- if (aim_ssi_itemlist_find(od->ssi.local, 0x0000, 0x0000) == NULL)
+- aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0x0000, AIM_SSI_TYPE_GROUP, NULL);
+-
+- tmp = aim_ssi_itemlist_add(&od->ssi.local, NULL, 0x0000, 0xFFFF, AIM_SSI_TYPE_PRESENCEPREFS, NULL);
+- }
+-
+- /* Need to add the x00c9 TLV to the TLV chain */
+- aim_tlvlist_replace_32(&tmp->data, 0x00c9, presence);
+-
+- /* Sync our local list with the server list */
+- return aim_ssi_sync(od);
+-}
+-
+-/*
+- * Subtype 0x0002 - Request SSI Rights.
+- */
+-int aim_ssi_reqrights(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
+- return -EINVAL;
+-
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQRIGHTS);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0003 - SSI Rights Information.
+- */
+-static int parserights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0, i;
+- aim_rxcallback_t userfunc;
+- GSList *tlvlist;
+- aim_tlv_t *tlv;
+- ByteStream bstream;
+- guint16 *maxitems;
+-
+- /* This SNAC is made up of a bunch of TLVs */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /* TLV 0x0004 contains the maximum number of each item */
+- if (!(tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
+- aim_tlvlist_free(tlvlist);
+- return 0;
+- }
+-
+- byte_stream_init(&bstream, tlv->value, tlv->length);
+-
+- maxitems = (guint16 *)g_malloc((tlv->length/2)*sizeof(guint16));
+-
+- for (i=0; i<(tlv->length/2); i++)
+- maxitems[i] = byte_stream_get16(&bstream);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, tlv->length/2, maxitems);
+-
+- aim_tlvlist_free(tlvlist);
+- g_free(maxitems);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0004 - Request SSI Data when you don't have a timestamp and
+- * revision number.
+- *
+- */
+-int aim_ssi_reqdata(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
+- return -EINVAL;
+-
+- /* Free any current data, just in case */
+- aim_ssi_freelist(od);
+-
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_REQDATA);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0006 - SSI Data.
+- */
+-static int parsedata(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint8 fmtver; /* guess */
+- guint16 namelen, gid, bid, type;
+- char *name;
+- GSList *data;
+- GString *debugstr = g_string_new("");
+-
+- 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 */
+-
+- /* Read in the list */
+- while (byte_stream_bytes_left(bs) > 4) { /* last four bytes are timestamp */
+- if ((namelen = byte_stream_get16(bs)))
+- name = byte_stream_getstr(bs, namelen);
+- else
+- name = NULL;
+- gid = byte_stream_get16(bs);
+- bid = byte_stream_get16(bs);
+- type = byte_stream_get16(bs);
+- data = aim_tlvlist_readlen(bs, byte_stream_get16(bs));
+- aim_ssi_item_debug_append(debugstr, "\t", aim_ssi_itemlist_add(&od->ssi.official, name, gid, bid, type, data));
+- g_free(name);
+- aim_tlvlist_free(data);
+- }
+- purple_debug_misc("oscar", "Reading items from tlvlist for account %s:\n%s",
+- purple_connection_get_account(od->gc)->username, debugstr->str);
+- g_string_free(debugstr, TRUE);
+-
+- /* Read in the timestamp */
+- od->ssi.timestamp = byte_stream_get32(bs);
+-
+- if (!(snac->flags & 0x0001)) {
+- /* Make a copy of the list */
+- struct aim_ssi_item *cur;
+- for (cur=od->ssi.official; cur; cur=cur->next)
+- aim_ssi_itemlist_add(&od->ssi.local, cur->name, cur->gid, cur->bid, cur->type, cur->data);
+-
+- od->ssi.received_data = TRUE;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, fmtver, od->ssi.numitems, od->ssi.timestamp);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0007 - SSI Activate Data.
+- *
+- * Should be sent after receiving 13/6 or 13/f to tell the server you
+- * are ready to begin using the list. It will promptly give you the
+- * presence information for everyone in your list and put your permit/deny
+- * settings into effect.
+- *
+- */
+-int aim_ssi_enable(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
+- return -EINVAL;
+-
+- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, 0x0007);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0008/0x0009/0x000a - SSI Add/Mod/Del Item(s).
+- *
+- * Sends the SNAC to add, modify, or delete items from the server-stored
+- * information. These 3 SNACs all have an identical structure. The only
+- * difference is the subtype that is set for the SNAC.
+- *
+- */
+-static int aim_ssi_addmoddel(OscarData *od)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen;
+- struct aim_ssi_tmp *cur;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !od->ssi.pending || !od->ssi.pending->item)
+- return -EINVAL;
+-
+- /* Calculate total SNAC size */
+- bslen = 0;
+- for (cur=od->ssi.pending; cur; cur=cur->next) {
+- bslen += 10; /* For length, GID, BID, type, and length */
+- if (cur->item->name)
+- bslen += strlen(cur->item->name);
+- if (cur->item->data)
+- bslen += aim_tlvlist_size(cur->item->data);
+- }
+-
+- byte_stream_new(&bs, bslen);
+-
+- for (cur=od->ssi.pending; cur; cur=cur->next) {
+- byte_stream_put16(&bs, cur->item->name ? strlen(cur->item->name) : 0);
+- if (cur->item->name)
+- byte_stream_putstr(&bs, cur->item->name);
+- byte_stream_put16(&bs, cur->item->gid);
+- byte_stream_put16(&bs, cur->item->bid);
+- byte_stream_put16(&bs, cur->item->type);
+- byte_stream_put16(&bs, cur->item->data ? aim_tlvlist_size(cur->item->data) : 0);
+- if (cur->item->data)
+- aim_tlvlist_write(&bs, &cur->item->data);
+- }
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, od->ssi.pending->action, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0008 - Incoming SSI add.
+- *
+- * Sent by the server, for example, when someone is added to
+- * your "Recent Buddies" group.
+- */
+-static int parseadd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- char *name;
+- guint16 len, gid, bid, type;
+- GSList *data;
+-
+- while (byte_stream_bytes_left(bs)) {
+- if ((len = byte_stream_get16(bs)))
+- name = byte_stream_getstr(bs, len);
+- else
+- name = NULL;
+- gid = byte_stream_get16(bs);
+- bid = byte_stream_get16(bs);
+- type = byte_stream_get16(bs);
+- if ((len = byte_stream_get16(bs)))
+- data = aim_tlvlist_readlen(bs, len);
+- else
+- data = NULL;
+-
+- 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);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, snac->subtype, type, name);
+-
+- g_free(name);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0009 - Incoming SSI mod.
+- */
+-static int parsemod(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- char *name;
+- guint16 len, gid, bid, type;
+- GSList *data;
+- struct aim_ssi_item *item;
+-
+- while (byte_stream_bytes_left(bs)) {
+- if ((len = byte_stream_get16(bs)))
+- name = byte_stream_getstr(bs, len);
+- else
+- name = NULL;
+- gid = byte_stream_get16(bs);
+- bid = byte_stream_get16(bs);
+- type = byte_stream_get16(bs);
+- if ((len = byte_stream_get16(bs)))
+- data = aim_tlvlist_readlen(bs, len);
+- else
+- data = NULL;
+-
+- /* Replace the 2 local items with the given one */
+- if ((item = aim_ssi_itemlist_find(od->ssi.local, gid, bid))) {
+- item->type = type;
+- g_free(item->name);
+- item->name = g_strdup(name);
+- aim_tlvlist_free(item->data);
+- item->data = aim_tlvlist_copy(data);
+- }
+-
+- if ((item = aim_ssi_itemlist_find(od->ssi.official, gid, bid))) {
+- item->type = type;
+- g_free(item->name);
+- item->name = g_strdup(name);
+- aim_tlvlist_free(item->data);
+- item->data = aim_tlvlist_copy(data);
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, snac->subtype, type, name);
+-
+- g_free(name);
+- aim_tlvlist_free(data);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x000a - Incoming SSI del.
+- *
+- * XXX - It would probably be good for the client to actually do something when it gets this.
+- */
+-static int parsedel(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 gid, bid;
+- struct aim_ssi_item *del;
+-
+- while (byte_stream_bytes_left(bs)) {
+- byte_stream_advance(bs, byte_stream_get16(bs));
+- gid = byte_stream_get16(bs);
+- bid = byte_stream_get16(bs);
+- byte_stream_get16(bs);
+- byte_stream_advance(bs, byte_stream_get16(bs));
+-
+- if ((del = aim_ssi_itemlist_find(od->ssi.local, gid, bid)))
+- aim_ssi_itemlist_del(&od->ssi.local, del);
+- if ((del = aim_ssi_itemlist_find(od->ssi.official, gid, bid)))
+- aim_ssi_itemlist_del(&od->ssi.official, del);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x000e - SSI Add/Mod/Del Ack.
+- *
+- * Response to add, modify, or delete SNAC (sent with aim_ssi_addmoddel).
+- *
+- */
+-static int parseack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- struct aim_ssi_tmp *cur, *del;
+-
+- /* Read in the success/failure flags from the ack SNAC */
+- cur = od->ssi.pending;
+- while (cur && (byte_stream_bytes_left(bs)>0)) {
+- cur->ack = byte_stream_get16(bs);
+- cur = cur->next;
+- }
+-
+- /*
+- * If outcome is 0, then add the item to the item list, or replace the other item,
+- * or remove the old item. If outcome is non-zero, then remove the item from the
+- * local list, or unmodify it, or add it.
+- */
+- for (cur=od->ssi.pending; (cur && (cur->ack != 0xffff)); cur=cur->next) {
+- if (cur->item) {
+- if (cur->ack) {
+- /* Our action was unsuccessful, so change the local list back to how it was */
+- if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
+- /* Remove the item from the local list */
+- /* Make sure cur->item is still valid memory */
+- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+- cur->name = g_strdup(cur->item->name);
+- aim_ssi_itemlist_del(&od->ssi.local, cur->item);
+- }
+- cur->item = NULL;
+-
+- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
+- /* Replace the local item with the item from the official list */
+- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+- struct aim_ssi_item *cur1;
+- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
+- g_free(cur->item->name);
+- cur->item->name = g_strdup(cur1->name);
+- aim_tlvlist_free(cur->item->data);
+- cur->item->data = aim_tlvlist_copy(cur1->data);
+- }
+- } else
+- cur->item = NULL;
+-
+- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
+- /* Add the item back into the local list */
+- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item)) {
+- aim_ssi_itemlist_add(&od->ssi.local, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
+- } else
+- cur->item = NULL;
+- }
+-
+- } else {
+- /* Do the exact opposite */
+- if (cur->action == SNAC_SUBTYPE_FEEDBAG_ADD) {
+- /* Add the local item to the official list */
+- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+- aim_ssi_itemlist_add(&od->ssi.official, cur->item->name, cur->item->gid, cur->item->bid, cur->item->type, cur->item->data);
+- } else
+- cur->item = NULL;
+-
+- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_MOD) {
+- /* Replace the official item with the item from the local list */
+- if (aim_ssi_itemlist_valid(od->ssi.local, cur->item)) {
+- struct aim_ssi_item *cur1;
+- if ((cur1 = aim_ssi_itemlist_find(od->ssi.official, cur->item->gid, cur->item->bid))) {
+- g_free(cur1->name);
+- cur1->name = g_strdup(cur->item->name);
+- aim_tlvlist_free(cur1->data);
+- cur1->data = aim_tlvlist_copy(cur->item->data);
+- }
+- } else
+- cur->item = NULL;
+-
+- } else if (cur->action == SNAC_SUBTYPE_FEEDBAG_DEL) {
+- /* Remove the item from the official list */
+- if (aim_ssi_itemlist_valid(od->ssi.official, cur->item))
+- aim_ssi_itemlist_del(&od->ssi.official, cur->item);
+- cur->item = NULL;
+- }
+-
+- }
+- } /* End if (cur->item) */
+- } /* End for loop */
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, od->ssi.pending);
+-
+- /* Free all aim_ssi_tmp's with an outcome */
+- cur = od->ssi.pending;
+- while (cur && (cur->ack != 0xffff)) {
+- del = cur;
+- cur = cur->next;
+- g_free(del->name);
+- g_free(del);
+- }
+- od->ssi.pending = cur;
+-
+- /* If we're not waiting for any more acks, then send more SNACs */
+- if (!od->ssi.pending) {
+- od->ssi.waiting_for_ack = FALSE;
+- aim_ssi_sync(od);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x000f - SSI Data Unchanged.
+- *
+- * Response to aim_ssi_reqifchanged() if the server-side data is not newer than
+- * posted local stamp/revision.
+- *
+- */
+-static int parsedataunchanged(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+-
+- od->ssi.received_data = TRUE;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0011 - SSI Begin Data Modification.
+- *
+- * Tell the server you're going to start modifying data. This marks
+- * the beginning of a transaction.
+- */
+-int aim_ssi_modbegin(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
+- return -EINVAL;
+-
+- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTART);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0012 - SSI End Data Modification.
+- *
+- * Tell the server you're finished modifying data. The marks the end
+- * of a transaction.
+- */
+-int aim_ssi_modend(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)))
+- return -EINVAL;
+-
+- aim_genericreq_n(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_EDITSTOP);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0015 - Receive an authorization grant
+- */
+-static int receiveauthgrant(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 tmp;
+- char *bn, *msg, *tmpstr;
+-
+- /* Read buddy name */
+- tmp = byte_stream_get8(bs);
+- if (!tmp) {
+- purple_debug_warning("oscar", "Dropping auth grant SNAC "
+- "because username was empty\n");
+- return 0;
+- }
+- bn = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(bn, -1, NULL)) {
+- purple_debug_warning("oscar", "Dropping auth grant SNAC "
+- "because the username was not valid UTF-8\n");
+- g_free(bn);
+- }
+-
+- /* Read message */
+- tmp = byte_stream_get16(bs);
+- if (tmp) {
+- msg = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(msg, -1, NULL)) {
+- /* Ugh, msg isn't UTF8. Let's salvage. */
+- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+- "grant from %s\n", bn);
+- tmpstr = purple_utf8_salvage(msg);
+- g_free(msg);
+- msg = tmpstr;
+- }
+- } else
+- msg = NULL;
+-
+- /* Unknown */
+- tmp = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, bn, msg);
+-
+- g_free(bn);
+- g_free(msg);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0018 - Send authorization request
+- *
+- * Sends a request for authorization to the given contact. The request will either be
+- * granted, denied, or dropped.
+- *
+- */
+-int aim_ssi_sendauthrequest(OscarData *od, const char *bn, const char *msg)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !bn)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 1+strlen(bn) + 2+(msg ? strlen(msg)+1 : 0) + 2);
+-
+- /* Username */
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- /* Message (null terminated) */
+- byte_stream_put16(&bs, msg ? strlen(msg) : 0);
+- if (msg) {
+- byte_stream_putstr(&bs, msg);
+- byte_stream_put8(&bs, 0x00);
+- }
+-
+- /* Unknown */
+- byte_stream_put16(&bs, 0x0000);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0019 - Receive an authorization request
+- */
+-static int receiveauthrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 tmp;
+- char *bn, *msg, *tmpstr;
+-
+- /* Read buddy name */
+- tmp = byte_stream_get8(bs);
+- if (!tmp) {
+- purple_debug_warning("oscar", "Dropping auth request SNAC "
+- "because username was empty\n");
+- return 0;
+- }
+- bn = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(bn, -1, NULL)) {
+- purple_debug_warning("oscar", "Dropping auth request SNAC "
+- "because the username was not valid UTF-8\n");
+- g_free(bn);
+- }
+-
+- /* Read message */
+- tmp = byte_stream_get16(bs);
+- if (tmp) {
+- msg = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(msg, -1, NULL)) {
+- /* Ugh, msg isn't UTF8. Let's salvage. */
+- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+- "request from %s\n", bn);
+- tmpstr = purple_utf8_salvage(msg);
+- g_free(msg);
+- msg = tmpstr;
+- }
+- } else
+- msg = NULL;
+-
+- /* Unknown */
+- tmp = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, bn, msg);
+-
+- g_free(bn);
+- g_free(msg);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x001a - Send authorization reply
+- *
+- * Sends a reply to a request for authorization. The reply can either
+- * grant authorization or deny authorization.
+- *
+- * if reply=0x00 then deny
+- * if reply=0x01 then grant
+- *
+- */
+-int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_FEEDBAG)) || !bn)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 1+strlen(bn) + 1 + 2+(msg ? (strlen(msg)+1) : 0) + 2);
+-
+- /* Username */
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- /* Grant or deny */
+- byte_stream_put8(&bs, reply);
+-
+- /* Message (null terminated) */
+- byte_stream_put16(&bs, msg ? (strlen(msg)+1) : 0);
+- if (msg) {
+- byte_stream_putstr(&bs, msg);
+- byte_stream_put8(&bs, 0x00);
+- }
+-
+- /* Unknown */
+- byte_stream_put16(&bs, 0x0000);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x001b - Receive an authorization reply
+- *
+- * You get this bad boy when other people respond to the authorization
+- * request that you have previously sent them.
+- */
+-static int receiveauthreply(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 tmp;
+- guint8 reply;
+- char *bn, *msg, *tmpstr;
+-
+- /* Read buddy name */
+- tmp = byte_stream_get8(bs);
+- if (!tmp) {
+- purple_debug_warning("oscar", "Dropping auth reply SNAC "
+- "because username was empty\n");
+- return 0;
+- }
+- bn = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(bn, -1, NULL)) {
+- purple_debug_warning("oscar", "Dropping auth reply SNAC "
+- "because the username was not valid UTF-8\n");
+- g_free(bn);
+- }
+-
+- /* Read reply */
+- reply = byte_stream_get8(bs);
+-
+- /* Read message */
+- tmp = byte_stream_get16(bs);
+- if (tmp) {
+- msg = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(msg, -1, NULL)) {
+- /* Ugh, msg isn't UTF8. Let's salvage. */
+- purple_debug_warning("oscar", "Got non-UTF8 message in auth "
+- "reply from %s\n", bn);
+- tmpstr = purple_utf8_salvage(msg);
+- g_free(msg);
+- msg = tmpstr;
+- }
+- } else
+- msg = NULL;
+-
+- /* Unknown */
+- tmp = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, bn, reply, msg);
+-
+- g_free(bn);
+- g_free(msg);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x001c - Receive a message telling you someone added you to their list.
+- */
+-static int receiveadded(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 tmp;
+- char *bn;
+-
+- /* Read buddy name */
+- tmp = byte_stream_get8(bs);
+- if (!tmp) {
+- purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+- "because username was empty\n");
+- return 0;
+- }
+- bn = byte_stream_getstr(bs, tmp);
+- if (!g_utf8_validate(bn, -1, NULL)) {
+- purple_debug_warning("oscar", "Dropping 'you were added' SNAC "
+- "because the username was not valid UTF-8\n");
+- g_free(bn);
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, bn);
+-
+- g_free(bn);
+-
+- return ret;
+-}
+-
+-/*
+- * If we're on ICQ, then AIM_SSI_TYPE_DENY is used for the "permanently invisible" list.
+- * AIM_SSI_TYPE_ICQDENY is used for blocking users instead.
+- */
+-guint16
+-aim_ssi_getdenyentrytype(OscarData* od)
+-{
+- return od->icq ? AIM_SSI_TYPE_ICQDENY : AIM_SSI_TYPE_DENY;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO)
+- return parserights(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_LIST)
+- return parsedata(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADD)
+- return parseadd(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_MOD)
+- return parsemod(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_DEL)
+- return parsedel(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_SRVACK)
+- return parseack(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_NOLIST)
+- return parsedataunchanged(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTH)
+- return receiveauthgrant(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ)
+- return receiveauthrequest(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP)
+- return receiveauthreply(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == SNAC_SUBTYPE_FEEDBAG_ADDED)
+- return receiveadded(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-static void
+-ssi_shutdown(OscarData *od, aim_module_t *mod)
+-{
+- aim_ssi_freelist(od);
+-}
+-
+-int
+-ssi_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_FEEDBAG;
+- mod->version = 0x0004;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "feedbag", sizeof(mod->name));
+- mod->snachandler = snachandler;
+- mod->shutdown = ssi_shutdown;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_icbm.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icbm.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_icbm.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icbm.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,2138 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0004 - Routines for sending/receiving Instant Messages.
+- *
+- * Note the term ICBM (Inter-Client Basic Message) which blankets
+- * all types of generically routed through-server messages. Within
+- * the ICBM types (family 4), a channel is defined. Each channel
+- * represents a different type of message. Channel 1 is used for
+- * what would commonly be called an "instant message". Channel 2
+- * is used for negotiating "rendezvous". These transactions end in
+- * something more complex happening, such as a chat invitation, or
+- * a file transfer. Channel 3 is used for chat messages (not in
+- * the same family as these channels). Channel 4 is used for
+- * various ICQ messages. Examples are normal messages, URLs, and
+- * old-style authorization.
+- *
+- * In addition to the channel, every ICBM contains a cookie. For
+- * standard IMs, these are only used for error messages. However,
+- * the more complex rendezvous messages make suitably more complex
+- * use of this field.
+- *
+- * TODO: Split this up into an im.c file an an icbm.c file. It
+- * will be beautiful, you'll see.
+- *
+- * Make sure flap_connection_findbygroup is used by all functions.
+- */
+-
+-#include "encoding.h"
+-#include "oscar.h"
+-#include "peer.h"
+-
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#endif
+-
+-#include "util.h"
+-
+-static const char * const errcodereason[] = {
+- N_("Invalid error"),
+- N_("Not logged in"),
+- N_("Cannot receive IM due to parental controls"),
+- N_("Cannot send SMS without accepting terms"),
+- N_("Cannot send SMS"), /* SMS_WITHOUT_DISCLAIMER is weird */
+- N_("Cannot send SMS to this country"),
+- N_("Unknown error"), /* Undocumented */
+- N_("Unknown error"), /* Undocumented */
+- N_("Cannot send SMS to unknown country"),
+- N_("Bot accounts cannot initiate IMs"),
+- N_("Bot account cannot IM this user"),
+- N_("Bot account reached IM limit"),
+- N_("Bot account reached daily IM limit"),
+- N_("Bot account reached monthly IM limit"),
+- N_("Unable to receive offline messages"),
+- N_("Offline message store full")
+-};
+-static const int errcodereasonlen = G_N_ELEMENTS(errcodereason);
+-
+-/**
+- * Add a standard ICBM header to the given bstream with the given
+- * information.
+- *
+- * @param bs The bstream to write the ICBM header to.
+- * @param c c is for cookie, and cookie is for me.
+- * @param channel The ICBM channel (1 through 4).
+- * @param bn Null-terminated scrizeen nizame.
+- * @return The number of bytes written. It's really not useful.
+- */
+-static int aim_im_puticbm(ByteStream *bs, const guchar *c, guint16 channel, const char *bn)
+-{
+- byte_stream_putraw(bs, c, 8);
+- byte_stream_put16(bs, channel);
+- byte_stream_put8(bs, strlen(bn));
+- byte_stream_putstr(bs, bn);
+- return 8+2+1+strlen(bn);
+-}
+-
+-/**
+- * Generates a random ICBM cookie in a character array of length 8
+- * and copies it into the variable passed as cookie
+- * TODO: Maybe we should stop limiting our characters to the visible range?
+- */
+-void aim_icbm_makecookie(guchar *cookie)
+-{
+- int i;
+-
+- /* Should be like "21CBF95" and null terminated */
+- for (i = 0; i < 7; i++)
+- cookie[i] = 0x30 + ((guchar)rand() % 10);
+- cookie[7] = '\0';
+-}
+-
+-/*
+- * Subtype 0x0001 - Error
+- */
+-static int
+-error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_snac_t *snac2;
+- guint16 reason, errcode = 0;
+- const char *bn;
+- GSList *tlvlist;
+- PurpleConnection *gc = od->gc;
+-#ifdef TODOFT
+- PurpleXfer *xfer;
+-#endif
+- const char *reason_str;
+- char *buf;
+-
+- snac2 = aim_remsnac(od, snac->id);
+- if (!snac2) {
+- purple_debug_misc("oscar", "icbm error: received response from unknown request!\n");
+- return 1;
+- }
+-
+- if (snac2->family != SNAC_FAMILY_ICBM) {
+- purple_debug_misc("oscar", "icbm error: received response from invalid request! %d\n", snac2->family);
+- g_free(snac2->data);
+- g_free(snac2);
+- return 1;
+- }
+-
+- /* Data is assumed to be the destination bn */
+- bn = snac2->data;
+- if (!bn || bn[0] == '\0') {
+- purple_debug_misc("oscar", "icbm error: received response from request without a buddy name!\n");
+- g_free(snac2->data);
+- g_free(snac2);
+- return 1;
+- }
+-
+- reason = byte_stream_get16(bs);
+-
+- tlvlist = aim_tlvlist_read(bs);
+- if (aim_tlv_gettlv(tlvlist, 0x0008, 1))
+- errcode = aim_tlv_get16(tlvlist, 0x0008, 1);
+- aim_tlvlist_free(tlvlist);
+-
+- purple_debug_error("oscar",
+- "Message error with bn %s and reason %hu and errcode %hu\n",
+- (bn != NULL ? bn : ""), reason, errcode);
+-
+-#ifdef TODOFT
+- /* If this was a file transfer request, bn is a cookie */
+- if ((xfer = oscar_find_xfer_by_cookie(od->file_transfers, bn))) {
+- purple_xfer_cancel_remote(xfer);
+- return 1;
+- }
+-#endif
+-
+- /* Notify the user that the message wasn't delivered */
+- reason_str = oscar_get_msgerr_reason(reason);
+- if (errcode != 0 && errcode < errcodereasonlen)
+- buf = g_strdup_printf(_("Unable to send message: %s (%s)"), reason_str,
+- _(errcodereason[errcode]));
+- else
+- buf = g_strdup_printf(_("Unable to send message: %s"), reason_str);
+-
+- if (!purple_conv_present_error(bn, purple_connection_get_account(gc), buf)) {
+- g_free(buf);
+- if (errcode != 0 && errcode < errcodereasonlen)
+- buf = g_strdup_printf(_("Unable to send message to %s: %s (%s)"),
+- bn ? bn : "(unknown)", reason_str,
+- _(errcodereason[errcode]));
+- else
+- buf = g_strdup_printf(_("Unable to send message to %s: %s"),
+- bn ? bn : "(unknown)", reason_str);
+- purple_notify_error(od->gc, NULL, buf, reason_str);
+- }
+- g_free(buf);
+-
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- return 1;
+-}
+-
+-/**
+- * Subtype 0x0002 - Set ICBM parameters.
+- *
+- * I definitely recommend sending this. If you don't, you'll be stuck
+- * with the rather unreasonable defaults.
+- *
+- */
+-int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- if (!params)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 16);
+-
+- /* This is read-only (see Parameter Reply). Must be set to zero here. */
+- byte_stream_put16(&bs, 0x0000);
+-
+- /* These are all read-write */
+- byte_stream_put32(&bs, params->flags);
+- byte_stream_put16(&bs, params->maxmsglen);
+- byte_stream_put16(&bs, params->maxsenderwarn);
+- byte_stream_put16(&bs, params->maxrecverwarn);
+- byte_stream_put32(&bs, params->minmsginterval);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0002, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0004 - Request ICBM parameter information.
+- *
+- */
+-int aim_im_reqparams(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_ICBM, 0x0004);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0005 - Receive parameter information.
+- *
+- */
+-static int aim_im_paraminfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- struct aim_icbmparameters params;
+-
+- params.maxchan = byte_stream_get16(bs);
+- params.flags = byte_stream_get32(bs);
+- params.maxmsglen = byte_stream_get16(bs);
+- params.maxsenderwarn = byte_stream_get16(bs);
+- params.maxrecverwarn = byte_stream_get16(bs);
+- params.minmsginterval = byte_stream_get32(bs);
+-
+- params.flags = AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED
+- | AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED
+- | AIM_IMPARAM_FLAG_EVENTS_ALLOWED
+- | AIM_IMPARAM_FLAG_SMS_SUPPORTED
+- | AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED
+- | AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ;
+- params.maxmsglen = 8000;
+- params.minmsginterval = 0;
+-
+- aim_im_setparams(od, &params);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0006 - Send an ICBM (instant message).
+- *
+- *
+- * Possible flags:
+- * AIM_IMFLAGS_AWAY -- Marks the message as an autoresponse
+- * AIM_IMFLAGS_OFFLINE--If destination is offline, store it until they are
+- * online (probably ICQ only).
+- *
+- * Implementation note: Since this is one of the most-used functions
+- * in all of libfaim, it is written with performance in mind. As such,
+- * it is not as clear as it could be in respect to how this message is
+- * supposed to be layed out. Most obviously, tlvlists should be used
+- * instead of writing out the bytes manually.
+- */
+-int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args)
+-{
+- FlapConnection *conn;
+- aim_snacid_t snacid;
+- ByteStream data;
+- guchar cookie[8];
+- int msgtlvlen;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- if (!args)
+- return -EINVAL;
+-
+- if (!args->msg || (args->msglen <= 0))
+- return -EINVAL;
+-
+- if (args->msglen > MAXMSGLEN)
+- return -E2BIG;
+-
+- /* Painfully calculate the size of the message TLV */
+- msgtlvlen = 1 + 1; /* 0501 */
+- msgtlvlen += 2 + args->featureslen;
+- msgtlvlen += 2 /* 0101 */ + 2 /* block len */;
+- msgtlvlen += 4 /* charset */ + args->msglen;
+-
+- byte_stream_new(&data, msgtlvlen + 128);
+-
+- /* Generate an ICBM cookie */
+- aim_icbm_makecookie(cookie);
+-
+- /* ICBM header */
+- aim_im_puticbm(&data, cookie, 0x0001, args->destbn);
+-
+- /* Message TLV (type 0x0002) */
+- byte_stream_put16(&data, 0x0002);
+- byte_stream_put16(&data, msgtlvlen);
+-
+- /* Features TLV (type 0x0501) */
+- byte_stream_put16(&data, 0x0501);
+- byte_stream_put16(&data, args->featureslen);
+- byte_stream_putraw(&data, args->features, args->featureslen);
+-
+- /* Insert message text in a TLV (type 0x0101) */
+- byte_stream_put16(&data, 0x0101);
+-
+- /* Message block length */
+- byte_stream_put16(&data, args->msglen + 0x04);
+-
+- /* Character set */
+- byte_stream_put16(&data, args->charset);
+- /* Character subset -- we always use 0 here */
+- byte_stream_put16(&data, 0x0);
+-
+- /* Message. Not terminated */
+- byte_stream_putraw(&data, (guchar *)args->msg, args->msglen);
+-
+- /* Set the Autoresponse flag */
+- if (args->flags & AIM_IMFLAGS_AWAY) {
+- byte_stream_put16(&data, 0x0004);
+- byte_stream_put16(&data, 0x0000);
+- } else {
+- /* Set the Request Acknowledge flag */
+- byte_stream_put16(&data, 0x0003);
+- byte_stream_put16(&data, 0x0000);
+-
+- if (args->flags & AIM_IMFLAGS_OFFLINE) {
+- /* Allow this message to be queued as an offline message */
+- byte_stream_put16(&data, 0x0006);
+- byte_stream_put16(&data, 0x0000);
+- }
+- }
+-
+- /*
+- * Set the I HAVE A REALLY PURTY ICON flag.
+- * XXX - This should really only be sent on initial
+- * IMs and when you change your icon.
+- */
+- if (args->flags & AIM_IMFLAGS_HASICON) {
+- byte_stream_put16(&data, 0x0008);
+- byte_stream_put16(&data, 0x000c);
+- byte_stream_put32(&data, args->iconlen);
+- byte_stream_put16(&data, 0x0001);
+- byte_stream_put16(&data, args->iconsum);
+- byte_stream_put32(&data, args->iconstamp);
+- }
+-
+- /*
+- * Set the Buddy Icon Requested flag.
+- * XXX - Every time? Surely not...
+- */
+- if (args->flags & AIM_IMFLAGS_BUDDYREQ) {
+- byte_stream_put16(&data, 0x0009);
+- byte_stream_put16(&data, 0x0000);
+- }
+-
+- /* XXX - should be optional */
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, args->destbn, strlen(args->destbn)+1);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &data);
+- byte_stream_destroy(&data);
+-
+- /* clean out SNACs over 60sec old */
+- aim_cleansnacs(od, 60);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0006 - Send a chat invitation.
+- */
+-int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- IcbmCookie *msgcookie;
+- struct aim_invite_priv *priv;
+- guchar cookie[8];
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- if (!bn || !msg || !roomname)
+- return -EINVAL;
+-
+- aim_icbm_makecookie(cookie);
+-
+- byte_stream_new(&bs, 1142+strlen(bn)+strlen(roomname)+strlen(msg));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, bn, strlen(bn)+1);
+-
+- /* XXX should be uncached by an unwritten 'invite accept' handler */
+- priv = g_malloc(sizeof(struct aim_invite_priv));
+- priv->bn = g_strdup(bn);
+- priv->roomname = g_strdup(roomname);
+- priv->exchange = exchange;
+- priv->instance = instance;
+-
+- if ((msgcookie = aim_mkcookie(cookie, AIM_COOKIETYPE_INVITE, priv)))
+- aim_cachecookie(od, msgcookie);
+- else
+- g_free(priv);
+-
+- /* ICBM Header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- /*
+- * TLV t(0005)
+- *
+- * Everything else is inside this TLV.
+- *
+- * Sigh. AOL was rather inconsistent right here. So we have
+- * to play some minor tricks. Right inside the type 5 is some
+- * raw data, followed by a series of TLVs.
+- *
+- */
+- byte_stream_new(&hdrbs, 2+8+16+6+4+4+strlen(msg)+4+2+1+strlen(roomname)+2);
+-
+- byte_stream_put16(&hdrbs, 0x0000); /* Unknown! */
+- byte_stream_putraw(&hdrbs, cookie, sizeof(cookie)); /* I think... */
+- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_CHAT);
+-
+- 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);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Subtype 0x0006 - Send your icon to a given user.
+- *
+- * This is also performance sensitive. (If you can believe it...)
+- *
+- */
+-int aim_im_sendch2_icon(OscarData *od, const char *bn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- guchar cookie[8];
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- if (!bn || !icon || (iconlen <= 0) || (iconlen >= MAXICONLEN))
+- return -EINVAL;
+-
+- aim_icbm_makecookie(cookie);
+-
+- byte_stream_new(&bs, 8+2+1+strlen(bn)+2+2+2+8+16+2+2+2+2+2+2+2+4+4+4+iconlen+strlen(AIM_ICONIDENT)+2+2);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- /*
+- * TLV t(0005)
+- *
+- * Encompasses everything below.
+- */
+- byte_stream_put16(&bs, 0x0005);
+- byte_stream_put16(&bs, 2+8+16+6+4+4+iconlen+4+4+4+strlen(AIM_ICONIDENT));
+-
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_putraw(&bs, cookie, 8);
+- byte_stream_putcaps(&bs, OSCAR_CAPABILITY_BUDDYICON);
+-
+- /* TLV t(000a) */
+- byte_stream_put16(&bs, 0x000a);
+- byte_stream_put16(&bs, 0x0002);
+- byte_stream_put16(&bs, 0x0001);
+-
+- /* TLV t(000f) */
+- byte_stream_put16(&bs, 0x000f);
+- byte_stream_put16(&bs, 0x0000);
+-
+- /* TLV t(2711) */
+- byte_stream_put16(&bs, 0x2711);
+- byte_stream_put16(&bs, 4+4+4+iconlen+strlen(AIM_ICONIDENT));
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, iconsum);
+- byte_stream_put32(&bs, iconlen);
+- byte_stream_put32(&bs, stamp);
+- byte_stream_putraw(&bs, icon, iconlen);
+- byte_stream_putstr(&bs, AIM_ICONIDENT);
+-
+- /* TLV t(0003) */
+- byte_stream_put16(&bs, 0x0003);
+- byte_stream_put16(&bs, 0x0000);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Cancel a rendezvous invitation. It could be an invitation to
+- * establish a direct connection, or a file-send, or a chat invite.
+- */
+-void
+-aim_im_sendch2_cancel(PeerConnection *peer_conn)
+-{
+- OscarData *od;
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+-
+- od = peer_conn->od;
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 118+strlen(peer_conn->bn));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->bn);
+-
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
+-
+- byte_stream_new(&hdrbs, 64);
+-
+- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_CANCEL);
+- byte_stream_putraw(&hdrbs, peer_conn->cookie, 8);
+- byte_stream_putcaps(&hdrbs, peer_conn->type);
+-
+- /* This TLV means "cancel!" */
+- 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);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0006 - Send an "I accept and I've connected to
+- * you" message.
+- */
+-void
+-aim_im_sendch2_connected(PeerConnection *peer_conn)
+-{
+- OscarData *od;
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- od = peer_conn->od;
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 11+strlen(peer_conn->bn) + 4+2+8+16);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, peer_conn->cookie, 0x0002, peer_conn->bn);
+-
+- byte_stream_put16(&bs, 0x0005);
+- byte_stream_put16(&bs, 0x001a);
+- byte_stream_put16(&bs, AIM_RENDEZVOUS_CONNECTED);
+- byte_stream_putraw(&bs, peer_conn->cookie, 8);
+- byte_stream_putcaps(&bs, peer_conn->type);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0006 - Send a direct connect rendezvous ICBM. This
+- * could have a number of meanings, depending on the content:
+- * "I want you to connect to me"
+- * "I want to connect to you"
+- * "I want to connect through a proxy server"
+- */
+-void
+-aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 246+strlen(bn));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
+-
+- byte_stream_new(&hdrbs, 128);
+-
+- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
+- byte_stream_putraw(&hdrbs, cookie, 8);
+- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
+-
+- 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);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0006 - Send a direct connect rendezvous ICBM asking the
+- * remote user to connect to us via a proxy server.
+- */
+-void
+-aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+- guint8 ip_comp[4];
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 246+strlen(bn));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
+-
+- byte_stream_new(&hdrbs, 128);
+-
+- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
+- byte_stream_putraw(&hdrbs, cookie, 8);
+- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_DIRECTIM);
+-
+- 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(&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);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0006 - Send an "I want to send you this file" message
+- *
+- */
+-void
+-aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+-
+- g_return_if_fail(bn != NULL);
+- g_return_if_fail(ip != NULL);
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 1014);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
+-
+- byte_stream_new(&hdrbs, 512);
+-
+- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
+- byte_stream_putraw(&hdrbs, cookie, 8);
+- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
+-
+- 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 (filename != NULL)
+- {
+- ByteStream inner_bs;
+-
+- /* Begin TLV t(2711) */
+- byte_stream_new(&inner_bs, 2+2+4+strlen(filename)+1);
+- byte_stream_put16(&inner_bs, (numfiles > 1) ? 0x0002 : 0x0001);
+- byte_stream_put16(&inner_bs, numfiles);
+- byte_stream_put32(&inner_bs, size);
+-
+- /* Filename - NULL terminated, for some odd reason */
+- byte_stream_putstr(&inner_bs, filename);
+- byte_stream_put8(&inner_bs, 0x00);
+-
+- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, inner_bs.len, inner_bs.data);
+- byte_stream_destroy(&inner_bs);
+- /* End TLV t(2711) */
+- }
+-
+- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Subtype 0x0006 - Send a sendfile connect rendezvous ICBM asking the
+- * remote user to connect to us via a proxy server.
+- */
+-void
+-aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream hdrbs;
+- guint8 ip_comp[4];
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (conn == NULL)
+- return;
+-
+- byte_stream_new(&bs, 1014);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0006, 0x0000, NULL, 0);
+-
+- /* ICBM header */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+-
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003);
+-
+- byte_stream_new(&hdrbs, 512);
+-
+- byte_stream_put16(&hdrbs, AIM_RENDEZVOUS_PROPOSE);
+- byte_stream_putraw(&hdrbs, cookie, 8);
+- byte_stream_putcaps(&hdrbs, OSCAR_CAPABILITY_SENDFILE);
+-
+- 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(&inner_tlvlist, 0x0016, 4, ip_comp);
+- aim_tlvlist_add_16(&inner_tlvlist, 0x0017, ~pin);
+-
+- if (filename != NULL)
+- {
+- ByteStream filename_bs;
+-
+- /* Begin TLV t(2711) */
+- byte_stream_new(&filename_bs, 2+2+4+strlen(filename)+1);
+- byte_stream_put16(&filename_bs, (numfiles > 1) ? 0x0002 : 0x0001);
+- byte_stream_put16(&filename_bs, numfiles);
+- byte_stream_put32(&filename_bs, size);
+-
+- /* Filename - NULL terminated, for some odd reason */
+- byte_stream_putstr(&filename_bs, filename);
+- byte_stream_put8(&filename_bs, 0x00);
+-
+- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, filename_bs.len, filename_bs.data);
+- byte_stream_destroy(&filename_bs);
+- /* End TLV t(2711) */
+- }
+-
+- aim_tlvlist_write(&hdrbs, &inner_tlvlist);
+-
+- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&hdrbs), hdrbs.data);
+- byte_stream_destroy(&hdrbs);
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- aim_tlvlist_free(inner_tlvlist);
+- aim_tlvlist_free(outer_tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0006, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-static void
+-incomingim_ch1_parsemsg(OscarData *od, aim_userinfo_t *userinfo, ByteStream *message, struct aim_incomingim_ch1_args *args)
+-{
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- /*
+- * We're interested in the inner TLV 0x101, which contains precious, precious message.
+- */
+- while (byte_stream_bytes_left(message) >= 4) {
+- guint16 type = byte_stream_get16(message);
+- guint16 length = byte_stream_get16(message);
+- if (type == 0x101) {
+- gchar *msg;
+- guint16 msglen = length - 4; /* charset + charsubset */
+- guint16 charset = byte_stream_get16(message);
+- byte_stream_advance(message, 2); /* charsubset */
+-
+- msg = byte_stream_getstr(message, msglen);
+- args->msg = oscar_decode_im(account, userinfo->bn, charset, msg, msglen);
+- g_free(msg);
+- } else {
+- byte_stream_advance(message, length);
+- }
+- }
+-}
+-
+-static int
+-incomingim_ch1(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, guint16 channel, aim_userinfo_t *userinfo, ByteStream *bs, guint8 *cookie)
+-{
+- guint16 type, length;
+- aim_rxcallback_t userfunc;
+- int ret = 0;
+- struct aim_incomingim_ch1_args args;
+- unsigned int endpos;
+-
+- memset(&args, 0, sizeof(args));
+-
+- /*
+- * This used to be done using tlvchains. For performance reasons,
+- * I've changed it to process the TLVs in-place. This avoids lots
+- * of per-IM memory allocations.
+- */
+- while (byte_stream_bytes_left(bs) >= 4)
+- {
+- type = byte_stream_get16(bs);
+- length = byte_stream_get16(bs);
+-
+- if (length > byte_stream_bytes_left(bs))
+- {
+- purple_debug_misc("oscar", "Received an IM containing an invalid message part from %s. They are probably trying to do something malicious.\n", userinfo->bn);
+- break;
+- }
+-
+- endpos = byte_stream_curpos(bs) + length;
+-
+- if (type == 0x0002) { /* Message Block */
+- ByteStream tlv02;
+- byte_stream_init(&tlv02, bs->data + bs->offset, length);
+- incomingim_ch1_parsemsg(od, userinfo, &tlv02, &args);
+- } else if (type == 0x0003) { /* Server Ack Requested */
+- args.icbmflags |= AIM_IMFLAGS_ACK;
+- } else if (type == 0x0004) { /* Message is Auto Response */
+- args.icbmflags |= AIM_IMFLAGS_AWAY;
+- } else if (type == 0x0006) { /* Message was received offline. */
+- /*
+- * This flag is set on incoming offline messages for both
+- * AIM and ICQ accounts.
+- */
+- args.icbmflags |= AIM_IMFLAGS_OFFLINE;
+- } else if (type == 0x0008) { /* I-HAVE-A-REALLY-PURTY-ICON Flag */
+- args.iconlen = byte_stream_get32(bs);
+- byte_stream_get16(bs); /* 0x0001 */
+- args.iconsum = byte_stream_get16(bs);
+- args.iconstamp = byte_stream_get32(bs);
+-
+- /*
+- * This looks to be a client bug. MacAIM 4.3 will
+- * send this tag, but with all zero values, in the
+- * first message of a conversation. This makes no
+- * sense whatsoever, so I'm going to say its a bug.
+- *
+- * You really shouldn't advertise a zero-length icon
+- * anyway.
+- *
+- */
+- if (args.iconlen)
+- args.icbmflags |= AIM_IMFLAGS_HASICON;
+- } else if (type == 0x0009) {
+- args.icbmflags |= AIM_IMFLAGS_BUDDYREQ;
+- } else if (type == 0x000b) { /* Non-direct connect typing notification */
+- args.icbmflags |= AIM_IMFLAGS_TYPINGNOT;
+- } else if (type == 0x0016) {
+- /*
+- * UTC timestamp for when the message was sent. Only
+- * provided for offline messages.
+- */
+- args.timestamp = byte_stream_get32(bs);
+- }
+-
+- /*
+- * This is here to protect ourselves from ourselves. That
+- * is, if something above doesn't completely parse its value
+- * section, or, worse, overparses it, this will set the
+- * stream where it needs to be in order to land on the next
+- * TLV when the loop continues.
+- *
+- */
+- byte_stream_setpos(bs, endpos);
+- }
+-
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, userinfo, &args);
+-
+- g_free(args.msg);
+- return ret;
+-}
+-
+-static void
+-incomingim_ch2_buddylist(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
+-{
+- /*
+- * This goes like this...
+- *
+- * group name length
+- * group name
+- * num of buddies in group
+- * buddy name length
+- * buddy name
+- * buddy name length
+- * buddy name
+- * ...
+- * group name length
+- * group name
+- * num of buddies in group
+- * buddy name length
+- * buddy name
+- * ...
+- * ...
+- */
+- while (byte_stream_bytes_left(servdata))
+- {
+- guint16 gnlen, numb;
+- int i;
+- char *gn;
+-
+- gnlen = byte_stream_get16(servdata);
+- gn = byte_stream_getstr(servdata, gnlen);
+- numb = byte_stream_get16(servdata);
+-
+- for (i = 0; i < numb; i++) {
+- guint16 bnlen;
+- char *bn;
+-
+- bnlen = byte_stream_get16(servdata);
+- bn = byte_stream_getstr(servdata, bnlen);
+-
+- purple_debug_misc("oscar", "got a buddy list from %s: group %s, buddy %s\n", userinfo->bn, gn, bn);
+-
+- g_free(bn);
+- }
+-
+- g_free(gn);
+- }
+-
+- return;
+-}
+-
+-static void
+-incomingim_ch2_buddyicon_free(OscarData *od, IcbmArgsCh2 *args)
+-{
+- g_free(args->info.icon.icon);
+-
+- return;
+-}
+-
+-static void
+-incomingim_ch2_buddyicon(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
+-{
+- args->info.icon.checksum = byte_stream_get32(servdata);
+- args->info.icon.length = byte_stream_get32(servdata);
+- args->info.icon.timestamp = byte_stream_get32(servdata);
+- args->info.icon.icon = byte_stream_getraw(servdata, args->info.icon.length);
+-
+- args->destructor = (void *)incomingim_ch2_buddyicon_free;
+-
+- return;
+-}
+-
+-static void
+-incomingim_ch2_chat_free(OscarData *od, IcbmArgsCh2 *args)
+-{
+- /* XXX - aim_chat_roominfo_free() */
+- g_free(args->info.chat.roominfo.name);
+-
+- return;
+-}
+-
+-static void
+-incomingim_ch2_chat(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
+-{
+- /*
+- * Chat room info.
+- */
+- aim_chat_readroominfo(servdata, &args->info.chat.roominfo);
+-
+- args->destructor = (void *)incomingim_ch2_chat_free;
+-}
+-
+-static void
+-incomingim_ch2_icqserverrelay_free(OscarData *od, IcbmArgsCh2 *args)
+-{
+- g_free((char *)args->info.rtfmsg.msg);
+-}
+-
+-/*
+- * The relationship between OSCAR_CAPABILITY_ICQSERVERRELAY and OSCAR_CAPABILITY_ICQRTF is
+- * kind of odd. This sends the client ICQRTF since that is all that I've seen
+- * SERVERRELAY used for.
+- *
+- * Note that this is all little-endian. Cringe.
+- *
+- */
+-static void
+-incomingim_ch2_icqserverrelay(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
+-{
+- guint16 hdrlen, msglen;
+-
+- args->destructor = (void *)incomingim_ch2_icqserverrelay_free;
+-
+-#define SKIP_HEADER(expected_hdrlen) \
+- hdrlen = byte_stream_getle16(servdata); \
+- if (hdrlen != expected_hdrlen) { \
+- purple_debug_warning("oscar", "Expected to find a header with length " #expected_hdrlen "; ignoring message"); \
+- return; \
+- } \
+- byte_stream_advance(servdata, hdrlen);
+-
+- SKIP_HEADER(0x001b);
+- SKIP_HEADER(0x000e);
+-
+- args->info.rtfmsg.msgtype = byte_stream_get8(servdata);
+- /*
+- * Copied from http://iserverd.khstu.ru/oscar/message.html:
+- * xx byte message flags
+- * xx xx word (LE) status code
+- * xx xx word (LE) priority code
+- *
+- * We don't need any of these, so just skip them.
+- */
+- byte_stream_advance(servdata, 1 + 2 + 2);
+-
+- msglen = byte_stream_getle16(servdata);
+- args->info.rtfmsg.msg = byte_stream_getstr(servdata, msglen);
+-}
+-
+-static void
+-incomingim_ch2_sendfile_free(OscarData *od, IcbmArgsCh2 *args)
+-{
+- g_free(args->info.sendfile.filename);
+-}
+-
+-/* Someone is sending us a file */
+-static void
+-incomingim_ch2_sendfile(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, aim_userinfo_t *userinfo, IcbmArgsCh2 *args, ByteStream *servdata)
+-{
+- int flen;
+-
+- args->destructor = (void *)incomingim_ch2_sendfile_free;
+-
+- /* Maybe there is a better way to tell what kind of sendfile
+- * this is? Maybe TLV t(000a)? */
+-
+- /* subtype is one of AIM_OFT_SUBTYPE_* */
+- args->info.sendfile.subtype = byte_stream_get16(servdata);
+- args->info.sendfile.totfiles = byte_stream_get16(servdata);
+- args->info.sendfile.totsize = byte_stream_get32(servdata);
+-
+- /*
+- * I hope to God I'm right when I guess that there is a
+- * 32 char max filename length for single files. I think
+- * OFT tends to do that. Gotta love inconsistency. I saw
+- * a 26 byte filename?
+- */
+- /* AAA - create an byte_stream_getnullstr function (don't anymore)(maybe) */
+- /* Use an inelegant way of getting the null-terminated filename,
+- * since there's no easy bstream routine. */
+- for (flen = 0; byte_stream_get8(servdata); flen++);
+- byte_stream_advance(servdata, -flen -1);
+- args->info.sendfile.filename = byte_stream_getstr(servdata, flen);
+-
+- /* There is sometimes more after the null-terminated filename,
+- * but I'm unsure of its format. */
+- /* I don't believe him. */
+- /* There is sometimes a null byte inside a unicode filename,
+- * but as far as I can tell the filename is the last
+- * piece of data that will be in this message. --Jonathan */
+-}
+-
+-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, GSList *tlvlist, guint8 *cookie)
+-{
+- aim_rxcallback_t userfunc;
+- aim_tlv_t *block1, *servdatatlv;
+- GSList *list2;
+- aim_tlv_t *tlv;
+- IcbmArgsCh2 args;
+- ByteStream bbs, sdbs, *sdbsptr = NULL;
+- guint8 *cookie2;
+- int ret = 0;
+-
+- char proxyip[30] = {""};
+- char clientip[30] = {""};
+- char verifiedip[30] = {""};
+-
+- memset(&args, 0, sizeof(args));
+-
+- /*
+- * There's another block of TLVs embedded in the type 5 here.
+- */
+- block1 = aim_tlv_gettlv(tlvlist, 0x0005, 1);
+- if (block1 == NULL)
+- {
+- /* The server sent us ch2 ICBM without ch2 info? Weird. */
+- return 1;
+- }
+- byte_stream_init(&bbs, block1->value, block1->length);
+-
+- /*
+- * First two bytes represent the status of the connection.
+- * One of the AIM_RENDEZVOUS_ defines.
+- *
+- * 0 is a request, 1 is a cancel, 2 is an accept
+- */
+- args.status = byte_stream_get16(&bbs);
+-
+- /*
+- * Next comes the cookie. Should match the ICBM cookie.
+- */
+- cookie2 = byte_stream_getraw(&bbs, 8);
+- if (memcmp(cookie, cookie2, 8) != 0)
+- {
+- purple_debug_warning("oscar",
+- "Cookies don't match in rendezvous ICBM, bailing out.\n");
+- g_free(cookie2);
+- return 1;
+- }
+- memcpy(args.cookie, cookie2, 8);
+- g_free(cookie2);
+-
+- /*
+- * The next 16bytes are a capability block so we can
+- * identify what type of rendezvous this is.
+- */
+- args.type = aim_locate_getcaps(od, &bbs, 0x10);
+-
+- /*
+- * What follows may be TLVs or nothing, depending on the
+- * purpose of the message.
+- *
+- * Ack packets for instance have nothing more to them.
+- */
+- list2 = aim_tlvlist_read(&bbs);
+-
+- /*
+- * IP address to proxy the file transfer through.
+- *
+- * TODO: I don't like this. Maybe just read in an int? Or inet_ntoa...
+- */
+- tlv = aim_tlv_gettlv(list2, 0x0002, 1);
+- if ((tlv != NULL) && (tlv->length == 4))
+- snprintf(proxyip, sizeof(proxyip), "%hhu.%hhu.%hhu.%hhu",
+- tlv->value[0], tlv->value[1],
+- tlv->value[2], tlv->value[3]);
+-
+- /*
+- * IP address from the perspective of the client.
+- */
+- tlv = aim_tlv_gettlv(list2, 0x0003, 1);
+- if ((tlv != NULL) && (tlv->length == 4))
+- snprintf(clientip, sizeof(clientip), "%hhu.%hhu.%hhu.%hhu",
+- tlv->value[0], tlv->value[1],
+- tlv->value[2], tlv->value[3]);
+-
+- /*
+- * Verified IP address (from the perspective of Oscar).
+- *
+- * This is added by the server.
+- */
+- tlv = aim_tlv_gettlv(list2, 0x0004, 1);
+- if ((tlv != NULL) && (tlv->length == 4))
+- snprintf(verifiedip, sizeof(verifiedip), "%hhu.%hhu.%hhu.%hhu",
+- tlv->value[0], tlv->value[1],
+- tlv->value[2], tlv->value[3]);
+-
+- /*
+- * Port number for something.
+- */
+- if (aim_tlv_gettlv(list2, 0x0005, 1))
+- args.port = aim_tlv_get16(list2, 0x0005, 1);
+-
+- /*
+- * File transfer "request number":
+- * 0x0001 - Initial file transfer request for no proxy or stage 1 proxy
+- * 0x0002 - "Reply request" for a stage 2 proxy (receiver wants to use proxy)
+- * 0x0003 - A third request has been sent; applies only to stage 3 proxied transfers
+- */
+- if (aim_tlv_gettlv(list2, 0x000a, 1))
+- args.requestnumber = aim_tlv_get16(list2, 0x000a, 1);
+-
+- /*
+- * Terminate connection/error code. 0x0001 means the other user
+- * cancelled the connection.
+- */
+- if (aim_tlv_gettlv(list2, 0x000b, 1))
+- args.errorcode = aim_tlv_get16(list2, 0x000b, 1);
+-
+- /*
+- * Invitation message / chat description.
+- */
+- if (aim_tlv_gettlv(list2, 0x000c, 1)) {
+- args.msg = aim_tlv_getstr(list2, 0x000c, 1);
+- args.msglen = aim_tlv_getlength(list2, 0x000c, 1);
+- }
+-
+- /*
+- * Character set.
+- */
+- if (aim_tlv_gettlv(list2, 0x000d, 1))
+- args.encoding = aim_tlv_getstr(list2, 0x000d, 1);
+-
+- /*
+- * Language.
+- */
+- if (aim_tlv_gettlv(list2, 0x000e, 1))
+- args.language = aim_tlv_getstr(list2, 0x000e, 1);
+-
+- /*
+- * Flag meaning we should proxy the file transfer through an AIM server
+- */
+- if (aim_tlv_gettlv(list2, 0x0010, 1))
+- args.use_proxy = TRUE;
+-
+- if (strlen(proxyip))
+- args.proxyip = (char *)proxyip;
+- if (strlen(clientip))
+- args.clientip = (char *)clientip;
+- if (strlen(verifiedip))
+- args.verifiedip = (char *)verifiedip;
+-
+- /*
+- * This must be present in PROPOSALs, but will probably not
+- * exist in CANCELs and ACCEPTs. Also exists in ICQ Lite
+- * Beta 4.0 URLs (OSCAR_CAPABILITY_ICQSERVERRELAY).
+- *
+- * Service Data blocks are module-specific in format.
+- */
+- if ((servdatatlv = aim_tlv_gettlv(list2, 0x2711 /* 10001 */, 1))) {
+-
+- byte_stream_init(&sdbs, servdatatlv->value, servdatatlv->length);
+- sdbsptr = &sdbs;
+-
+- /*
+- * The rest of the handling depends on what type it is.
+- *
+- * Not all of them have special handling (yet).
+- */
+- if (args.type & OSCAR_CAPABILITY_BUDDYICON)
+- incomingim_ch2_buddyicon(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
+- else if (args.type & OSCAR_CAPABILITY_SENDBUDDYLIST)
+- incomingim_ch2_buddylist(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
+- else if (args.type & OSCAR_CAPABILITY_CHAT)
+- incomingim_ch2_chat(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
+- else if (args.type & OSCAR_CAPABILITY_ICQSERVERRELAY)
+- incomingim_ch2_icqserverrelay(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
+- else if (args.type & OSCAR_CAPABILITY_SENDFILE)
+- incomingim_ch2_sendfile(od, conn, mod, frame, snac, userinfo, &args, sdbsptr);
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, userinfo, &args);
+-
+-
+- if (args.destructor)
+- ((ch2_args_destructor_t)args.destructor)(od, &args);
+-
+- g_free((char *)args.msg);
+- g_free((char *)args.encoding);
+- g_free((char *)args.language);
+-
+- 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, GSList *tlvlist, guint8 *cookie)
+-{
+- ByteStream meat;
+- aim_rxcallback_t userfunc;
+- aim_tlv_t *block;
+- struct aim_incomingim_ch4_args args;
+- int ret = 0;
+-
+- /*
+- * Make a bstream for the meaty part. Yum. Meat.
+- */
+- if (!(block = aim_tlv_gettlv(tlvlist, 0x0005, 1)))
+- return -1;
+- byte_stream_init(&meat, block->value, block->length);
+-
+- args.uin = byte_stream_getle32(&meat);
+- args.type = byte_stream_getle8(&meat);
+- args.flags = byte_stream_getle8(&meat);
+- if (args.type == 0x1a)
+- /* There seems to be a problem with the length in SMS msgs from server, this fixed it */
+- args.msglen = block->length - 6;
+- else
+- args.msglen = byte_stream_getle16(&meat);
+- args.msg = (gchar *)byte_stream_getraw(&meat, args.msglen);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, userinfo, &args);
+-
+- g_free(args.msg);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0007
+- *
+- * It can easily be said that parsing ICBMs is THE single
+- * most difficult thing to do in the in AIM protocol. In
+- * fact, I think I just did say that.
+- *
+- * Below is the best damned solution I've come up with
+- * over the past sixteen months of battling with it. This
+- * can parse both away and normal messages from every client
+- * I have access to. Its not fast, its not clean. But it works.
+- *
+- */
+-static int incomingim(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- guchar *cookie;
+- guint16 channel;
+- aim_userinfo_t userinfo;
+-
+- memset(&userinfo, 0x00, sizeof(aim_userinfo_t));
+-
+- /*
+- * Read ICBM Cookie.
+- */
+- cookie = byte_stream_getraw(bs, 8);
+-
+- /*
+- * Channel ID.
+- *
+- * Channel 0x0001 is the message channel. It is
+- * used to send basic ICBMs.
+- *
+- * Channel 0x0002 is the Rendezvous channel, which
+- * is where Chat Invitiations and various client-client
+- * connection negotiations come from.
+- *
+- * Channel 0x0003 is used for chat messages.
+- *
+- * Channel 0x0004 is used for ICQ authorization, or
+- * possibly any system notice.
+- *
+- */
+- channel = byte_stream_get16(bs);
+-
+- /*
+- * Extract the standard user info block.
+- *
+- * Note that although this contains TLVs that appear contiguous
+- * with the TLVs read below, they are two different pieces. The
+- * userinfo block contains the number of TLVs that contain user
+- * information, the rest are not even though there is no separation.
+- * You can start reading the message TLVs after aim_info_extract()
+- * parses out the standard userinfo block.
+- *
+- * That also means that TLV types can be duplicated between the
+- * userinfo block and the rest of the message, however there should
+- * never be two TLVs of the same type in one block.
+- *
+- */
+- aim_info_extract(od, bs, &userinfo);
+-
+- /*
+- * From here on, its depends on what channel we're on.
+- *
+- * Technically all channels have a TLV list have this, however,
+- * for the common channel 1 case, in-place parsing is used for
+- * performance reasons (less memory allocation).
+- */
+- if (channel == 1) {
+-
+- ret = incomingim_ch1(od, conn, mod, frame, snac, channel, &userinfo, bs, cookie);
+-
+- } else if (channel == 2) {
+- GSList *tlvlist;
+-
+- /*
+- * Read block of TLVs (not including the userinfo data). All
+- * further data is derived from what is parsed here.
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- ret = incomingim_ch2(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- } else if (channel == 4) {
+- GSList *tlvlist;
+-
+- tlvlist = aim_tlvlist_read(bs);
+- ret = incomingim_ch4(od, conn, mod, frame, snac, channel, &userinfo, tlvlist, cookie);
+- aim_tlvlist_free(tlvlist);
+-
+- } else {
+- purple_debug_misc("oscar", "icbm: ICBM received on an unsupported channel. Ignoring. (chan = %04x)\n", channel);
+- }
+-
+- aim_info_free(&userinfo);
+- g_free(cookie);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x000a */
+-static int missedcall(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 channel, nummissed, reason;
+- aim_userinfo_t userinfo;
+-
+- while (byte_stream_bytes_left(bs)) {
+-
+- channel = byte_stream_get16(bs);
+- aim_info_extract(od, bs, &userinfo);
+- nummissed = byte_stream_get16(bs);
+- reason = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, &userinfo, nummissed, reason);
+-
+- aim_info_free(&userinfo);
+- }
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x000b
+- *
+- * Possible codes:
+- * AIM_TRANSFER_DENY_DECLINE -- "client has declined transfer"
+- *
+- */
+-int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 8+2+1+strlen(bn)+6);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x000b, 0x0000, NULL, 0);
+-
+- byte_stream_putraw(&bs, cookie, 8);
+-
+- byte_stream_put16(&bs, 0x0002); /* channel */
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- aim_tlvlist_add_16(&tlvlist, 0x0003, code);
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x000b, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x000b.
+- * Send confirmation for a channel 2 message (Miranda wants it by default).
+- */
+-void
+-aim_im_send_icq_confirmation(OscarData *od, const char *bn, const guchar *cookie)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- guint32 header_size, data_size;
+- guint16 cookie2 = (guint16)g_random_int();
+-
+- purple_debug_misc("oscar", "Sending message ack to %s\n", bn);
+-
+- header_size = 8 + 2 + 1 + strlen(bn) + 2;
+- data_size = 2 + 1 + 16 + 4*2 + 2*3 + 4*3 + 1*2 + 2*3 + 1;
+- byte_stream_new(&bs, header_size + data_size);
+-
+- /* The message header. */
+- aim_im_puticbm(&bs, cookie, 0x0002, bn);
+- byte_stream_put16(&bs, 0x0003); /* reason */
+-
+- /* The actual message. */
+- byte_stream_putle16(&bs, 0x1b); /* subheader #1 length */
+- byte_stream_put8(&bs, 0x08); /* protocol version */
+- byte_stream_putcaps(&bs, OSCAR_CAPABILITY_EMPTY);
+- byte_stream_put32(&bs, 0x3); /* client features */
+- byte_stream_put32(&bs, 0x0004); /* DC type */
+- byte_stream_put16(&bs, cookie2); /* a cookie, chosen by fair dice roll */
+- byte_stream_putle16(&bs, 0x0e); /* header #2 len? */
+- byte_stream_put16(&bs, cookie2); /* the same cookie again */
+- byte_stream_put32(&bs, 0); /* unknown */
+- byte_stream_put32(&bs, 0); /* unknown */
+- byte_stream_put32(&bs, 0); /* unknown */
+- byte_stream_put8(&bs, 0x01); /* plain text message */
+- byte_stream_put8(&bs, 0x00); /* no message flags */
+- byte_stream_put16(&bs, 0x0000); /* no icq status */
+- byte_stream_put16(&bs, 0x0100); /* priority */
+- byte_stream_putle16(&bs, 1); /* query message len */
+- byte_stream_put8(&bs, 0x00); /* empty query message */
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x000b, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, flap_connection_findbygroup(od, SNAC_FAMILY_ICBM), SNAC_FAMILY_ICBM, 0x000b, snacid, &bs);
+- byte_stream_destroy(&bs);
+-}
+-
+-/*
+- * Subtype 0x000b - Receive the response from an ICQ status message
+- * request (in which case this contains the ICQ status message) or
+- * a file transfer or direct IM request was declined.
+- */
+-static int clientautoresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 channel, reason;
+- char *bn;
+- guchar *cookie;
+- guint8 bnlen;
+- char *xml = NULL;
+- guint16 hdrlen;
+- int curpos;
+- guint16 num1, num2;
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- PurplePresence *presence;
+- PurpleStatus *status;
+-
+- cookie = byte_stream_getraw(bs, 8);
+- channel = byte_stream_get16(bs);
+- bnlen = byte_stream_get8(bs);
+- bn = byte_stream_getstr(bs, bnlen);
+- reason = byte_stream_get16(bs);
+-
+- if (channel == 0x0002)
+- {
+- hdrlen = byte_stream_getle16(bs);
+- if (hdrlen == 27 && bs->len > (27 + 51)) {
+- byte_stream_advance(bs, 51);
+- num1 = byte_stream_getle16(bs);
+- num2 = byte_stream_getle16(bs);
+- purple_debug_misc("oscar", "X-Status: num1 %hu, num2 %hu\n", num1, num2);
+-
+- if (num1 == 0x4f00 && num2 == 0x3b00) {
+- byte_stream_advance(bs, 86);
+- curpos = byte_stream_curpos(bs);
+- xml = byte_stream_getstr(bs, bs->len - curpos);
+- purple_debug_misc("oscar", "X-Status: Received XML reply\n");
+- if (xml) {
+- GString *xstatus;
+- char *tmp1, *tmp2, *unescaped_xstatus;
+-
+- /* purple_debug_misc("oscar", "X-Status: XML reply: %s\n", xml); */
+-
+- xstatus = g_string_new(NULL);
+-
+- tmp1 = strstr(xml, "&lt;title&gt;");
+- if (tmp1 != NULL) {
+- tmp1 += 13;
+- tmp2 = strstr(tmp1, "&lt;/title&gt;");
+- if (tmp2 != NULL)
+- g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
+- }
+- tmp1 = strstr(xml, "&lt;desc&gt;");
+- if (tmp1 != NULL) {
+- tmp1 += 12;
+- tmp2 = strstr(tmp1, "&lt;/desc&gt;");
+- if (tmp2 != NULL) {
+- if (xstatus->len > 0 && tmp2 > tmp1)
+- g_string_append(xstatus, " - ");
+- g_string_append_len(xstatus, tmp1, tmp2 - tmp1);
+- }
+- }
+- unescaped_xstatus = purple_unescape_text(xstatus->str);
+- g_string_free(xstatus, TRUE);
+- if (*unescaped_xstatus) {
+- purple_debug_misc("oscar", "X-Status reply: %s\n", unescaped_xstatus);
+- account = purple_connection_get_account(od->gc);
+- buddy = purple_find_buddy(account, bn);
+- presence = purple_buddy_get_presence(buddy);
+- status = purple_presence_get_status(presence, "mood");
+- if (status) {
+- purple_prpl_got_user_status(account, bn,
+- "mood",
+- PURPLE_MOOD_NAME, purple_status_get_attr_string(status, PURPLE_MOOD_NAME),
+- PURPLE_MOOD_COMMENT, unescaped_xstatus, NULL);
+- }
+- }
+- g_free(unescaped_xstatus);
+- } else {
+- purple_debug_misc("oscar", "X-Status: Can't get XML reply string\n");
+- }
+- } else {
+- purple_debug_misc("oscar", "X-Status: 0x0004, 0x000b not an xstatus reply\n");
+- }
+-
+- }
+-
+- } else if (channel == 0x0004) { /* ICQ message */
+- switch (reason) {
+- case 0x0003: { /* ICQ status message. Maybe other stuff too, you never know with these people. */
+- guint8 statusmsgtype, *msg;
+- guint16 len;
+- guint32 state;
+-
+- len = byte_stream_getle16(bs); /* Should be 0x001b */
+- byte_stream_advance(bs, len); /* Unknown */
+-
+- len = byte_stream_getle16(bs); /* Should be 0x000e */
+- byte_stream_advance(bs, len); /* Unknown */
+-
+- statusmsgtype = byte_stream_getle8(bs);
+- switch (statusmsgtype) {
+- case 0xe8:
+- state = AIM_ICQ_STATE_AWAY;
+- break;
+- case 0xe9:
+- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
+- break;
+- case 0xea:
+- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_OUT;
+- break;
+- case 0xeb:
+- state = AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
+- break;
+- case 0xec:
+- state = AIM_ICQ_STATE_CHAT;
+- break;
+- default:
+- state = 0;
+- break;
+- }
+-
+- byte_stream_getle8(bs); /* Unknown - 0x03 Maybe this means this is an auto-reply */
+- byte_stream_getle16(bs); /* Unknown - 0x0000 */
+- byte_stream_getle16(bs); /* Unknown - 0x0000 */
+-
+- len = byte_stream_getle16(bs);
+- msg = byte_stream_getraw(bs, len);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, bn, reason, state, msg);
+-
+- g_free(msg);
+- } break;
+-
+- default: {
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, bn, reason);
+- } break;
+- } /* end switch */
+- }
+-
+- g_free(cookie);
+- g_free(bn);
+- g_free(xml);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x000c - Receive an ack after sending an ICBM. The ack contains the ICBM header of the message you sent.
+- */
+-static int msgack(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- guint16 ch;
+- guchar *cookie;
+- char *bn;
+- int ret = 0;
+-
+- cookie = byte_stream_getraw(bs, 8);
+- ch = byte_stream_get16(bs);
+- bn = byte_stream_getstr(bs, byte_stream_get8(bs));
+-
+- purple_debug_info("oscar", "Sent message to %s.\n", bn);
+-
+- g_free(bn);
+- g_free(cookie);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0010 - Request any offline messages that are waiting for
+- * us. This is the "new" way of handling offline messages which is
+- * used for both AIM and ICQ. The old way is to use the ugly
+- * aim_icq_reqofflinemsgs() function, but that is no longer necessary.
+- *
+- * We set the 0x00000100 flag on the ICBM message parameters, which
+- * tells the oscar servers that we support offline messages. When we
+- * set that flag the servers do not automatically send us offline
+- * messages. Instead we must request them using this function. This
+- * should happen after sending the 0x0001/0x0002 "client online" SNAC.
+- */
+-int aim_im_reqofflinemsgs(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
+- return -EINVAL;
+-
+- aim_genericreq_n(od, conn, SNAC_FAMILY_ICBM, 0x0010);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0014 - Send a mini typing notification (mtn) packet.
+- *
+- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
+- * and Purple 0.60 and newer.
+- *
+- */
+-int aim_im_sendmtn(OscarData *od, guint16 channel, const char *bn, guint16 event)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
+- return -EINVAL;
+-
+- if (!bn)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 11 + strlen(bn) + 2);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICBM, 0x0014, 0x0000, NULL, 0);
+-
+- /* ICBM cookie */
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+-
+- /*
+- * Channel (should be 0x0001 for mtn)
+- */
+- byte_stream_put16(&bs, channel);
+-
+- /*
+- * Dest buddy name
+- */
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- /*
+- * Event (should be 0x0000, 0x0001, or 0x0002 for mtn)
+- */
+- byte_stream_put16(&bs, event);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICBM, 0x0014, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0006 - Send eXtra Status request
+- */
+-int icq_im_xstatus_request(OscarData *od, const char *sn)
+-{
+- FlapConnection *conn;
+- aim_snacid_t snacid;
+- guchar cookie[8];
+- GSList *outer_tlvlist = NULL, *inner_tlvlist = NULL;
+- ByteStream bs, header, plugindata;
+- PurpleAccount *account;
+- const char *fmt;
+- char *statxml;
+- int xmllen;
+-
+- static const guint8 pluginid[] = {
+- 0x09, 0x46, 0x13, 0x49, 0x4C, 0x7F, 0x11, 0xD1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00
+- };
+-
+- static const guint8 c_plugindata[] = {
+- 0x1B, 0x00, 0x0A,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x1A, 0x00, 0x00, 0x00, 0x01, 0x00,
+- 0x01, 0x00, 0x00, 0x4F, 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0, 0x9C,
+- 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00, 0x00, 0x53, 0x63, 0x72, 0x69, 0x70,
+- 0x74, 0x20, 0x50, 0x6C, 0x75, 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
+- 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74, 0x69, 0x6F, 0x6E, 0x20, 0x41,
+- 0x72, 0x72, 0x69, 0x76, 0x65, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x14, 0x01, 0x00, 0x00, 0x10, 0x01, 0x00, 0x00
+- };
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, 0x0004)))
+- return -EINVAL;
+-
+- if (!sn)
+- return -EINVAL;
+-
+- fmt = "<N><QUERY>&lt;Q&gt;&lt;PluginID&gt;srvMng&lt;/PluginID&gt;&lt;/Q&gt;</QUERY><NOTIFY>&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;req&gt;&lt;id&gt;AwayStat&lt;/id&gt;&lt;trans&gt;2&lt;/trans&gt;&lt;senderId&gt;%s&lt;/senderId&gt;&lt;/req&gt;&lt;/srv&gt;</NOTIFY></N>\r\n";
+-
+- account = purple_connection_get_account(od->gc);
+-
+- statxml = g_strdup_printf(fmt, account->username);
+- xmllen = strlen(statxml);
+-
+- aim_icbm_makecookie(cookie);
+-
+- byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2
+- + 2 + 2 + 8 + 16 + 2 + 2 + 2 + 2 + 2
+- + 2 + 2 + sizeof(c_plugindata) + xmllen
+- + 2 + 2);
+-
+- snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+- aim_im_puticbm(&bs, cookie, 0x0002, sn);
+-
+- byte_stream_new(&header, (7*2) + 16 + 8 + 2 + sizeof(c_plugindata) + xmllen); /* TLV 0x0005 Stream + Size */
+- byte_stream_put16(&header, 0x0000); /* Message Type: Request */
+- byte_stream_putraw(&header, cookie, sizeof(cookie)); /* Message ID */
+- byte_stream_putraw(&header, pluginid, sizeof(pluginid)); /* Plugin ID */
+-
+- aim_tlvlist_add_16(&inner_tlvlist, 0x000a, 0x0001);
+- aim_tlvlist_add_noval(&inner_tlvlist, 0x000f);
+-
+- /* Add Plugin Specific Data */
+- byte_stream_new(&plugindata, (sizeof(c_plugindata) + xmllen));
+- byte_stream_putraw(&plugindata, c_plugindata, sizeof(c_plugindata)); /* Content of TLV 0x2711 */
+- byte_stream_putraw(&plugindata, (const guint8*)statxml, xmllen);
+-
+- aim_tlvlist_add_raw(&inner_tlvlist, 0x2711, (sizeof(c_plugindata) + xmllen), plugindata.data);
+-
+- aim_tlvlist_write(&header, &inner_tlvlist);
+- aim_tlvlist_free(inner_tlvlist);
+-
+- aim_tlvlist_add_raw(&outer_tlvlist, 0x0005, byte_stream_curpos(&header), header.data);
+- aim_tlvlist_add_noval(&outer_tlvlist, 0x0003); /* Empty TLV 0x0003 */
+-
+- aim_tlvlist_write(&bs, &outer_tlvlist);
+-
+- purple_debug_misc("oscar", "X-Status Request\n");
+- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, snacid, &bs, TRUE);
+-
+- aim_tlvlist_free(outer_tlvlist);
+- byte_stream_destroy(&header);
+- byte_stream_destroy(&plugindata);
+- byte_stream_destroy(&bs);
+- g_free(statxml);
+-
+- return 0;
+-}
+-
+-int icq_relay_xstatus(OscarData *od, const char *sn, const guchar *cookie)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- PurpleAccount *account;
+- PurpleStatus *status;
+- const char *fmt;
+- const char *formatted_msg;
+- char *msg;
+- char *statxml;
+- const char *title;
+- int len;
+-
+- static const guint8 plugindata[] = {
+- 0x1B, 0x00,
+- 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x01, 0x00, 0x00, 0x00, 0x00, 0xF9, 0xD1, 0x0E, 0x00, 0xF9, 0xD1,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x1A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x4F,
+- 0x00, 0x3B, 0x60, 0xB3, 0xEF, 0xD8, 0x2A, 0x6C, 0x45, 0xA4, 0xE0,
+- 0x9C, 0x5A, 0x5E, 0x67, 0xE8, 0x65, 0x08, 0x00, 0x2A, 0x00, 0x00,
+- 0x00, 0x53, 0x63, 0x72, 0x69, 0x70, 0x74, 0x20, 0x50, 0x6C, 0x75,
+- 0x67, 0x2D, 0x69, 0x6E, 0x3A, 0x20, 0x52, 0x65, 0x6D, 0x6F, 0x74,
+- 0x65, 0x20, 0x4E, 0x6F, 0x74, 0x69, 0x66, 0x69, 0x63, 0x61, 0x74,
+- 0x69, 0x6F, 0x6E, 0x20, 0x41, 0x72, 0x72, 0x69, 0x76, 0x65, 0x00,
+- 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0xF3, 0x01, 0x00, 0x00, 0xEF, 0x01, 0x00, 0x00
+- };
+-
+- fmt = "<NR><RES>&lt;ret event='OnRemoteNotification'&gt;&lt;srv&gt;&lt;id&gt;cAwaySrv&lt;/id&gt;&lt;val srv_id='cAwaySrv'&gt;&lt;Root&gt;&lt;CASXtraSetAwayMessage&gt;&lt;/CASXtraSetAwayMessage&gt;&l t;uin&gt;%s&lt;/uin&gt;&lt;index&gt;1&lt;/index&gt;&lt;title&gt;%s&lt;/title&gt;&lt;desc&gt;%s&lt;/desc&gt;&lt;/Root&gt;&lt;/val&gt;&lt;/srv&gt;&lt;srv&gt;&lt;id&gt;cRandomizerSrv&lt;/id&gt;&lt;val srv_id='cRandomizerSrv'&gt;undefined&lt;/val&gt;&lt;/srv&gt;&lt;/ret&gt;</RES></NR>\r\n";
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, 0x0002)))
+- return -EINVAL;
+-
+- if (!sn)
+- return -EINVAL;
+-
+- account = purple_connection_get_account(od->gc);
+- if (!account)
+- return -EINVAL;
+-
+- /* if (!strcmp(account->username, sn))
+- icq_im_xstatus_request(od, sn); */
+-
+- status = purple_presence_get_active_status(account->presence);
+- if (!status)
+- return -EINVAL;
+-
+- title = purple_status_get_name(status);
+- if (!title)
+- return -EINVAL;
+-
+- formatted_msg = purple_status_get_attr_string(status, "message");
+- if (!formatted_msg)
+- return -EINVAL;
+-
+- msg = purple_markup_strip_html(formatted_msg);
+- if (!msg)
+- return -EINVAL;
+-
+- statxml = g_strdup_printf(fmt, account->username, title, msg);
+- len = strlen(statxml);
+-
+- purple_debug_misc("oscar", "X-Status AutoReply: %s, %s\n", formatted_msg, msg);
+-
+- byte_stream_new(&bs, 10 + 8 + 2 + 1 + strlen(sn) + 2 + sizeof(plugindata) + len); /* 16 extra */
+-
+- snacid = aim_cachesnac(od, 0x0004, 0x000b, 0x0000, NULL, 0);
+- aim_im_puticbm(&bs, cookie, 0x0002, sn);
+- byte_stream_put16(&bs, 0x0003);
+- byte_stream_putraw(&bs, plugindata, sizeof(plugindata));
+- byte_stream_putraw(&bs, (const guint8*)statxml, len);
+-
+- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x000b, snacid, &bs, TRUE);
+-
+- g_free(statxml);
+- g_free(msg);
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0014 - Receive a mini typing notification (mtn) packet.
+- *
+- * This is supported by winaim5 and newer, MacAIM bleh and newer, iChat bleh and newer,
+- * and Purple 0.60 and newer.
+- *
+- */
+-static int mtn_receive(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- char *bn;
+- guint8 bnlen;
+- guint16 channel, event;
+-
+- byte_stream_advance(bs, 8); /* ICBM cookie */
+- channel = byte_stream_get16(bs);
+- bnlen = byte_stream_get8(bs);
+- bn = byte_stream_getstr(bs, bnlen);
+- event = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, channel, bn, event);
+-
+- g_free(bn);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return error(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0005)
+- return aim_im_paraminfo(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0007)
+- return incomingim(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000a)
+- return missedcall(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000b)
+- return clientautoresp(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000c)
+- return msgack(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0014)
+- return mtn_receive(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-msg_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_ICBM;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "messaging", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_icq.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icq.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_icq.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_icq.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,793 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0015 - Encapsulated ICQ.
+- *
+- */
+-
+-#include "encoding.h"
+-#include "oscar.h"
+-
+-#define AIM_ICQ_INFO_REQUEST 0x04b2
+-#define AIM_ICQ_ALIAS_REQUEST 0x04ba
+-
+-static
+-int compare_icq_infos(gconstpointer a, gconstpointer b)
+-{
+- const struct aim_icq_info* aa = a;
+- const guint16* bb = b;
+- return aa->reqid - *bb;
+-}
+-
+-static void aim_icq_freeinfo(struct aim_icq_info *info) {
+- int i;
+-
+- if (!info)
+- return;
+- g_free(info->nick);
+- g_free(info->first);
+- g_free(info->last);
+- g_free(info->email);
+- g_free(info->homecity);
+- g_free(info->homestate);
+- g_free(info->homephone);
+- g_free(info->homefax);
+- g_free(info->homeaddr);
+- g_free(info->mobile);
+- g_free(info->homezip);
+- g_free(info->personalwebpage);
+- if (info->email2)
+- for (i = 0; i < info->numaddresses; i++)
+- g_free(info->email2[i]);
+- g_free(info->email2);
+- g_free(info->workcity);
+- g_free(info->workstate);
+- g_free(info->workphone);
+- g_free(info->workfax);
+- g_free(info->workaddr);
+- g_free(info->workzip);
+- g_free(info->workcompany);
+- g_free(info->workdivision);
+- g_free(info->workposition);
+- g_free(info->workwebpage);
+- g_free(info->info);
+- g_free(info->status_note_title);
+- g_free(info->auth_request_reason);
+-}
+-
+-static
+-int error(OscarData *od, aim_modsnac_t *error_snac, ByteStream *bs)
+-{
+- aim_snac_t *original_snac = aim_remsnac(od, error_snac->id);
+- guint16 *request_type;
+- GSList *original_info_ptr;
+- struct aim_icq_info *original_info;
+- guint16 reason;
+- gchar *uin;
+-
+- if (!original_snac || (original_snac->family != SNAC_FAMILY_ICQ) || !original_snac->data) {
+- purple_debug_misc("oscar", "icq: the original snac for the error packet was not found");
+- g_free(original_snac);
+- return 0;
+- }
+-
+- request_type = original_snac->data;
+- original_info_ptr = g_slist_find_custom(od->icq_info, &original_snac->id, compare_icq_infos);
+-
+- if (!original_info_ptr) {
+- purple_debug_misc("oscar", "icq: the request info for the error packet was not found");
+- g_free(original_snac);
+- return 0;
+- }
+-
+- original_info = original_info_ptr->data;
+-
+- reason = byte_stream_get16(bs);
+- uin = g_strdup_printf("%u", original_info->uin);
+- switch (*request_type) {
+- case AIM_ICQ_INFO_REQUEST:
+- oscar_user_info_display_error(od, reason, uin);
+- break;
+- case AIM_ICQ_ALIAS_REQUEST:
+- /* Couldn't retrieve an alias for the buddy requesting authorization; have to make do with UIN only. */
+- if (original_info->for_auth_request)
+- oscar_auth_recvrequest(od->gc, uin, NULL, original_info->auth_request_reason);
+- break;
+- default:
+- purple_debug_misc("oscar", "icq: got an error packet with unknown request type %u", *request_type);
+- break;
+- }
+-
+- aim_icq_freeinfo(original_info);
+- od->icq_info = g_slist_remove(od->icq_info, original_info_ptr);
+- g_free(original_snac->data);
+- g_free(original_snac);
+- return 1;
+-}
+-
+-int
+-aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
+- return -EINVAL;
+-
+- bslen = 2+4+2+2+2+2+2+1+1+1+1+1+1;
+-
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
+-
+- /* For simplicity, don't bother using a tlvlist */
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, bslen);
+-
+- byte_stream_putle16(&bs, bslen - 2);
+- byte_stream_putuid(&bs, od);
+- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
+- byte_stream_putle16(&bs, snacid); /* eh. */
+- byte_stream_putle16(&bs, 0x0c3a); /* shrug. */
+- byte_stream_putle16(&bs, 0x030c);
+- byte_stream_putle16(&bs, 0x0001);
+- byte_stream_putle8(&bs, webaware);
+- byte_stream_putle8(&bs, 0xf8);
+- byte_stream_putle8(&bs, 0x02);
+- byte_stream_putle8(&bs, 0x01);
+- byte_stream_putle8(&bs, 0x00);
+- byte_stream_putle8(&bs, !auth_required);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/**
+- * Change your ICQ password.
+- *
+- * @param od The oscar session
+- * @param passwd The new password. If this is longer than 8 characters it
+- * will be truncated.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int aim_icq_changepasswd(OscarData *od, const char *passwd)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen, passwdlen;
+-
+- if (!passwd)
+- return -EINVAL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
+- return -EINVAL;
+-
+- passwdlen = strlen(passwd);
+- if (passwdlen > MAXICQPASSLEN)
+- passwdlen = MAXICQPASSLEN;
+- bslen = 2+4+2+2+2+2+passwdlen+1;
+-
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
+-
+- /* For simplicity, don't bother using a tlvlist */
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, bslen);
+-
+- byte_stream_putle16(&bs, bslen - 2);
+- byte_stream_putuid(&bs, od);
+- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
+- byte_stream_putle16(&bs, snacid); /* eh. */
+- byte_stream_putle16(&bs, 0x042e); /* shrug. */
+- byte_stream_putle16(&bs, passwdlen+1);
+- byte_stream_putraw(&bs, (const guint8 *)passwd, passwdlen);
+- byte_stream_putle8(&bs, '\0');
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-int aim_icq_getallinfo(OscarData *od, const char *uin)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen;
+- struct aim_icq_info *info;
+- guint16 request_type = AIM_ICQ_INFO_REQUEST;
+-
+- if (!uin || uin[0] < '0' || uin[0] > '9')
+- return -EINVAL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
+- return -EINVAL;
+-
+- bslen = 2 + 4 + 2 + 2 + 2 + 4;
+-
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
+-
+- /* For simplicity, don't bother using a tlvlist */
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, bslen);
+-
+- byte_stream_putle16(&bs, bslen - 2);
+- byte_stream_putuid(&bs, od);
+- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
+- byte_stream_putle16(&bs, snacid); /* eh. */
+- byte_stream_putle16(&bs, request_type); /* shrug. */
+- byte_stream_putle32(&bs, atoi(uin));
+-
+- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
+-
+- byte_stream_destroy(&bs);
+-
+- /* Keep track of this request and the ICQ number and request ID */
+- info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
+- info->reqid = snacid;
+- info->uin = atoi(uin);
+- od->icq_info = g_slist_prepend(od->icq_info, info);
+-
+- return 0;
+-}
+-
+-int aim_icq_getalias(OscarData *od, const char *uin, gboolean for_auth_request, char *auth_request_reason)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen;
+- struct aim_icq_info *info;
+- guint16 request_type = AIM_ICQ_ALIAS_REQUEST;
+-
+- if (!uin || uin[0] < '0' || uin[0] > '9')
+- return -EINVAL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
+- return -EINVAL;
+-
+- purple_debug_info("oscar", "Requesting ICQ alias for %s\n", uin);
+-
+- bslen = 2 + 4 + 2 + 2 + 2 + 4;
+-
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, &request_type, sizeof(request_type));
+-
+- /* For simplicity, don't bother using a tlvlist */
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, bslen);
+-
+- byte_stream_putle16(&bs, bslen - 2);
+- byte_stream_putuid(&bs, od);
+- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
+- byte_stream_putle16(&bs, snacid); /* eh. */
+- byte_stream_putle16(&bs, request_type); /* shrug. */
+- byte_stream_putle32(&bs, atoi(uin));
+-
+- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs, FALSE);
+-
+- byte_stream_destroy(&bs);
+-
+- /* Keep track of this request and the ICQ number and request ID */
+- info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
+- info->reqid = snacid;
+- info->uin = atoi(uin);
+- info->for_auth_request = for_auth_request;
+- info->auth_request_reason = g_strdup(auth_request_reason);
+- od->icq_info = g_slist_prepend(od->icq_info, info);
+-
+- return 0;
+-}
+-
+-/*
+- * Send an SMS message. This is the non-US way. The US-way is to IM
+- * their cell phone number (+19195551234).
+- *
+- * We basically construct and send an XML message. The format is:
+- * <icq_sms_message>
+- * <destination>full_phone_without_leading_+</destination>
+- * <text>message</text>
+- * <codepage>1252</codepage>
+- * <senders_UIN>self_uin</senders_UIN>
+- * <senders_name>self_name</senders_name>
+- * <delivery_receipt>Yes|No</delivery_receipt>
+- * <time>Wkd, DD Mmm YYYY HH:MM:SS TMZ</time>
+- * </icq_sms_message>
+- *
+- * Yeah hi Peter, whaaaat's happening. If there's any way to use
+- * a codepage other than 1252 that would be great. Thaaaanks.
+- */
+-int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias)
+-{
+- FlapConnection *conn;
+- PurpleAccount *account;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- int bslen, xmllen;
+- char *xml;
+- const char *timestr, *username;
+- time_t t;
+- struct tm *tm;
+- gchar *stripped;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICQ)))
+- return -EINVAL;
+-
+- if (!name || !msg || !alias)
+- return -EINVAL;
+-
+- account = purple_connection_get_account(od->gc);
+- username = purple_account_get_username(account);
+-
+- time(&t);
+- tm = gmtime(&t);
+- timestr = purple_utf8_strftime("%a, %d %b %Y %T %Z", tm);
+-
+- stripped = purple_markup_strip_html(msg);
+-
+- /* The length of xml included the null terminating character */
+- xmllen = 209 + strlen(name) + strlen(stripped) + strlen(username) + strlen(alias) + strlen(timestr) + 1;
+-
+- xml = g_new(char, xmllen);
+- snprintf(xml, xmllen, "<icq_sms_message>"
+- "<destination>%s</destination>"
+- "<text>%s</text>"
+- "<codepage>1252</codepage>"
+- "<senders_UIN>%s</senders_UIN>"
+- "<senders_name>%s</senders_name>"
+- "<delivery_receipt>Yes</delivery_receipt>"
+- "<time>%s</time>"
+- "</icq_sms_message>",
+- name, stripped, username, alias, timestr);
+-
+- bslen = 36 + xmllen;
+-
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_ICQ, 0x0002, 0x0000, NULL, 0);
+-
+- /* For simplicity, don't bother using a tlvlist */
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, bslen);
+-
+- byte_stream_putle16(&bs, bslen - 2);
+- byte_stream_putuid(&bs, od);
+- byte_stream_putle16(&bs, 0x07d0); /* I command thee. */
+- byte_stream_putle16(&bs, snacid); /* eh. */
+-
+- /* From libicq200-0.3.2/src/SNAC-SRV.cpp */
+- byte_stream_putle16(&bs, 0x1482);
+- byte_stream_put16(&bs, 0x0001);
+- byte_stream_put16(&bs, 0x0016);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+-
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, xmllen);
+- byte_stream_putstr(&bs, xml);
+- byte_stream_put8(&bs, 0x00);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_ICQ, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- g_free(xml);
+- g_free(stripped);
+-
+- return 0;
+-}
+-
+-static void
+-gotalias(OscarData *od, struct aim_icq_info *info)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleBuddy *b;
+- gchar *utf8 = oscar_utf8_try_convert(account, od, info->nick);
+-
+- if (info->for_auth_request) {
+- oscar_auth_recvrequest(gc, g_strdup_printf("%u", info->uin), utf8, info->auth_request_reason);
+- } else {
+- if (utf8 && *utf8) {
+- gchar who[16];
+- g_snprintf(who, sizeof(who), "%u", info->uin);
+- serv_got_alias(gc, who, utf8);
+- if ((b = purple_find_buddy(account, who))) {
+- purple_blist_node_set_string((PurpleBlistNode*)b, "servernick", utf8);
+- }
+- }
+- g_free(utf8);
+- }
+-}
+-
+-/**
+- * Subtype 0x0003 - Response to SNAC_FAMILY_ICQ/0x002, contains an ICQesque packet.
+- */
+-static int
+-icqresponse(OscarData *od, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- GSList *tlvlist;
+- aim_tlv_t *datatlv;
+- ByteStream qbs;
+- guint32 ouruin;
+- guint16 cmdlen, cmd, reqid;
+-
+- 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;
+- }
+-
+- byte_stream_init(&qbs, datatlv->value, datatlv->length);
+-
+- cmdlen = byte_stream_getle16(&qbs);
+- ouruin = byte_stream_getle32(&qbs);
+- cmd = byte_stream_getle16(&qbs);
+- reqid = byte_stream_getle16(&qbs);
+-
+- purple_debug_misc("oscar", "icq response: %d bytes, %u, 0x%04x, 0x%04x\n", cmdlen, ouruin, cmd, reqid);
+-
+- if (cmd == 0x07da) { /* information */
+- guint16 subtype;
+- GSList *info_ptr;
+- struct aim_icq_info *info;
+-
+- subtype = byte_stream_getle16(&qbs);
+- byte_stream_advance(&qbs, 1); /* 0x0a */
+-
+- /* find other data from the same request */
+- info_ptr = g_slist_find_custom(od->icq_info, &reqid, compare_icq_infos);
+- if (!info_ptr) {
+- struct aim_icq_info *new_info = (struct aim_icq_info *)g_new0(struct aim_icq_info, 1);
+- new_info->reqid = reqid;
+- info_ptr = od->icq_info = g_slist_prepend(od->icq_info, new_info);
+- }
+-
+- info = info_ptr->data;
+- switch (subtype) {
+- case 0x00a0: { /* hide ip status */
+- /* nothing */
+- } break;
+-
+- case 0x00aa: { /* password change status */
+- /* nothing */
+- } break;
+-
+- case 0x00c8: { /* general and "home" information */
+- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homecity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homestate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homephone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homefax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homeaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->mobile = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homezip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->homecountry = byte_stream_getle16(&qbs);
+- /* 0x0a 00 02 00 */
+- /* 1 byte timezone? */
+- /* 1 byte hide email flag? */
+- } break;
+-
+- case 0x00dc: { /* personal information */
+- info->age = byte_stream_getle8(&qbs);
+- info->unknown = byte_stream_getle8(&qbs);
+- info->gender = byte_stream_getle8(&qbs); /* Not specified=0x00, Female=0x01, Male=0x02 */
+- info->personalwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->birthyear = byte_stream_getle16(&qbs);
+- info->birthmonth = byte_stream_getle8(&qbs);
+- info->birthday = byte_stream_getle8(&qbs);
+- info->language1 = byte_stream_getle8(&qbs);
+- info->language2 = byte_stream_getle8(&qbs);
+- info->language3 = byte_stream_getle8(&qbs);
+- /* 0x00 00 01 00 00 01 00 00 00 00 00 */
+- } break;
+-
+- case 0x00d2: { /* work information */
+- info->workcity = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workstate = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workphone = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workfax = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workaddr = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workzip = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workcountry = byte_stream_getle16(&qbs);
+- info->workcompany = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workdivision = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->workposition = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- byte_stream_advance(&qbs, 2); /* 0x01 00 */
+- info->workwebpage = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- } break;
+-
+- case 0x00e6: { /* additional personal information */
+- info->info = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs)-1);
+- } break;
+-
+- case 0x00eb: { /* email address(es) */
+- int i;
+- info->numaddresses = byte_stream_getle16(&qbs);
+- info->email2 = (char **)g_new0(char *, info->numaddresses);
+- for (i = 0; i < info->numaddresses; i++) {
+- info->email2[i] = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- if (i+1 != info->numaddresses)
+- byte_stream_advance(&qbs, 1); /* 0x00 */
+- }
+- } break;
+-
+- case 0x00f0: { /* personal interests */
+- } break;
+-
+- case 0x00fa: { /* past background and current organizations */
+- } break;
+-
+- case 0x0104: { /* alias info */
+- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- byte_stream_advance(&qbs, byte_stream_getle16(&qbs)); /* email address? */
+- /* Then 0x00 02 00 */
+- } break;
+-
+- case 0x010e: { /* unknown */
+- /* 0x00 00 */
+- } break;
+-
+- case 0x019a: { /* simple info */
+- byte_stream_advance(&qbs, 2);
+- info->uin = byte_stream_getle32(&qbs);
+- info->nick = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->first = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->last = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- info->email = byte_stream_getstr(&qbs, byte_stream_getle16(&qbs));
+- /* Then 0x00 02 00 00 00 00 00 */
+- } break;
+-
+- /* status note title and send request for status note text */
+- case 0x0fb4: {
+- GSList *tlvlist;
+- aim_tlv_t *tlv;
+- FlapConnection *conn;
+- char *uin = NULL;
+- char *status_note_title = NULL;
+-
+- conn = flap_connection_findbygroup(od, 0x0004);
+- if (conn == NULL)
+- {
+- purple_debug_misc("oscar", "icq/0x0fb4: flap connection was not found.\n");
+- break;
+- }
+-
+- byte_stream_advance(&qbs, 0x02); /* length */
+- byte_stream_advance(&qbs, 0x2f); /* unknown stuff */
+-
+- tlvlist = aim_tlvlist_read(&qbs);
+-
+- tlv = aim_tlv_gettlv(tlvlist, 0x0032, 1);
+- if (tlv != NULL)
+- /* Get user number */
+- uin = aim_tlv_getvalue_as_string(tlv);
+-
+- tlv = aim_tlv_gettlv(tlvlist, 0x0226, 1);
+- if (tlv != NULL)
+- /* Get status note title */
+- status_note_title = aim_tlv_getvalue_as_string(tlv);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- if (uin == NULL || status_note_title == NULL)
+- {
+- purple_debug_misc("oscar", "icq/0x0fb4: uin or "
+- "status_note_title was not found\n");
+- g_free(uin);
+- g_free(status_note_title);
+- break;
+- }
+-
+- if (status_note_title[0] == '\0')
+- {
+- PurpleAccount *account;
+- PurpleBuddy *buddy;
+- PurplePresence *presence;
+- PurpleStatus *status;
+-
+- account = purple_connection_get_account(od->gc);
+- buddy = purple_find_buddy(account, uin);
+- presence = purple_buddy_get_presence(buddy);
+- status = purple_presence_get_active_status(presence);
+-
+- purple_prpl_got_user_status(account, uin,
+- purple_status_get_id(status),
+- "message", NULL, NULL);
+-
+- g_free(status_note_title);
+- }
+- else
+- {
+- struct aim_icq_info *info;
+- ByteStream bs;
+- guint32 bslen;
+- aim_snacid_t snacid;
+- guchar cookie[8];
+-
+- info = g_new0(struct aim_icq_info, 1);
+-
+- bslen = 13 + strlen(uin) + 30 + 6 + 4 + 55 + 85 + 4;
+- byte_stream_new(&bs, 4 + bslen);
+-
+- snacid = aim_cachesnac(od, 0x0004, 0x0006, 0x0000, NULL, 0);
+-
+- aim_icbm_makecookie(cookie);
+-
+- byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
+- byte_stream_put16(&bs, 0x0002); /* message channel */
+- byte_stream_put8(&bs, strlen(uin)); /* uin */
+- byte_stream_putstr(&bs, uin);
+-
+- byte_stream_put16(&bs, 0x0005); /* rendez vous data */
+- byte_stream_put16(&bs, 0x00b2);
+- byte_stream_put16(&bs, 0x0000); /* request */
+- byte_stream_putraw(&bs, cookie, 8); /* ICBM cookie */
+- byte_stream_put32(&bs, 0x09461349); /* ICQ server relaying */
+- byte_stream_put16(&bs, 0x4c7f);
+- byte_stream_put16(&bs, 0x11d1);
+- byte_stream_put32(&bs, 0x82224445);
+- byte_stream_put32(&bs, 0x53540000);
+-
+- byte_stream_put16(&bs, 0x000a); /* unknown TLV */
+- byte_stream_put16(&bs, 0x0002);
+- byte_stream_put16(&bs, 0x0001);
+-
+- byte_stream_put16(&bs, 0x000f); /* unknown TLV */
+- byte_stream_put16(&bs, 0x0000);
+-
+- byte_stream_put16(&bs, 0x2711); /* extended data */
+- byte_stream_put16(&bs, 0x008a);
+- byte_stream_putle16(&bs, 0x001b); /* length */
+- byte_stream_putle16(&bs, 0x0009); /* version */
+- byte_stream_putle32(&bs, 0x00000000); /* plugin: none */
+- byte_stream_putle32(&bs, 0x00000000);
+- byte_stream_putle32(&bs, 0x00000000);
+- byte_stream_putle32(&bs, 0x00000000);
+- byte_stream_putle16(&bs, 0x0000); /* unknown */
+- byte_stream_putle32(&bs, 0x00000000); /* client capabilities flags */
+- byte_stream_put8(&bs, 0x00); /* unknown */
+- byte_stream_putle16(&bs, 0x0064); /* downcounter? */
+- byte_stream_putle16(&bs, 0x000e); /* length */
+- byte_stream_putle16(&bs, 0x0064); /* downcounter? */
+- byte_stream_putle32(&bs, 0x00000000); /* unknown */
+- byte_stream_putle32(&bs, 0x00000000);
+- byte_stream_putle32(&bs, 0x00000000);
+- byte_stream_put8(&bs, 0x1a); /* message type: plugin message descibed by text string */
+- byte_stream_put8(&bs, 0x00); /* message flags */
+- byte_stream_putle16(&bs, 0x0000); /* status code */
+- byte_stream_putle16(&bs, 0x0001); /* priority code */
+- byte_stream_putle16(&bs, 0x0000); /* text length */
+-
+- byte_stream_put8(&bs, 0x3a); /* message dump */
+- byte_stream_put32(&bs, 0x00811a18);
+- byte_stream_put32(&bs, 0xbc0e6c18);
+- byte_stream_put32(&bs, 0x47a5916f);
+- byte_stream_put32(&bs, 0x18dcc76f);
+- byte_stream_put32(&bs, 0x1a010013);
+- byte_stream_put32(&bs, 0x00000041);
+- byte_stream_put32(&bs, 0x77617920);
+- byte_stream_put32(&bs, 0x53746174);
+- byte_stream_put32(&bs, 0x7573204d);
+- byte_stream_put32(&bs, 0x65737361);
+- byte_stream_put32(&bs, 0x67650100);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x00000015);
+- byte_stream_put32(&bs, 0x00000000);
+- byte_stream_put32(&bs, 0x0000000d);
+- byte_stream_put32(&bs, 0x00000074);
+- byte_stream_put32(&bs, 0x6578742f);
+- byte_stream_put32(&bs, 0x782d616f);
+- byte_stream_put32(&bs, 0x6c727466);
+-
+- byte_stream_put16(&bs, 0x0003); /* server ACK requested */
+- byte_stream_put16(&bs, 0x0000);
+-
+- info->uin = atoi(uin);
+- info->status_note_title = status_note_title;
+-
+- memcpy(&info->icbm_cookie, cookie, 8);
+-
+- od->icq_info = g_slist_prepend(od->icq_info, info);
+-
+- flap_connection_send_snac_with_priority(od, conn, 0x0004, 0x0006, snacid, &bs, FALSE);
+-
+- byte_stream_destroy(&bs);
+- }
+-
+- g_free(uin);
+-
+- } break;
+-
+- } /* End switch statement */
+-
+- if (!(snac->flags & 0x0001)) {
+- if (subtype != 0x0104)
+- oscar_user_info_display_icq(od, info);
+-
+- if (info->uin && info->nick)
+- gotalias(od, info);
+-
+- aim_icq_freeinfo(info);
+- od->icq_info = g_slist_remove(od->icq_info, info);
+- }
+- }
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return 1;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return error(od, snac, bs);
+- else if (snac->subtype == 0x0003)
+- return icqresponse(od, snac, bs);
+-
+- return 0;
+-}
+-
+-static void
+-icq_shutdown(OscarData *od, aim_module_t *mod)
+-{
+- GSList *cur;
+- for (cur = od->icq_info; cur; cur = cur->next)
+- aim_icq_freeinfo(cur->data);
+- g_slist_free(od->icq_info);
+-}
+-
+-int
+-icq_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_ICQ;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x047c;
+- mod->flags = 0;
+- strncpy(mod->name, "icq", sizeof(mod->name));
+- mod->snachandler = snachandler;
+- mod->shutdown = icq_shutdown;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_locate.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_locate.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_locate.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_locate.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1557 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0002 - Locate.
+- *
+- * The functions here are responsible for requesting and parsing information-
+- * gathering SNACs. Or something like that. This family contains the SNACs
+- * for getting and setting info, away messages, directory profile thingy, etc.
+- */
+-
+-#include "oscar.h"
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#endif
+-
+-/* Define to log unknown TLVs */
+-/* #define LOG_UNKNOWN_TLV */
+-
+-/*
+- * Capability blocks.
+- *
+- * These are CLSIDs. They should actually be of the form:
+- *
+- * {0x0946134b, 0x4c7f, 0x11d1,
+- * {0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}}},
+- *
+- * But, eh.
+- */
+-static const struct {
+- guint64 flag;
+- guint8 data[16];
+-} aim_caps[] = {
+-
+- /*
+- * These are in ascending numerical order.
+- */
+-
+- /* Client understands short caps, a UUID of the form
+- * 0946XXYY-4C7F-11D1-8222-444553540000 where XXYY is the short cap. */
+- {OSCAR_CAPABILITY_SHORTCAPS,
+- {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_SECUREIM,
+- {0x09, 0x46, 0x00, 0x01, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* OSCAR_CAPABILITY_XHTML_IM */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x00, 0x02, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_VIDEO,
+- {0x09, 0x46, 0x01, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* "Live Video" (SIP/RTC Video) support in Windows AIM 5.5.3501 and newer */
+- {OSCAR_CAPABILITY_LIVEVIDEO,
+- {0x09, 0x46, 0x01, 0x01, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* "Camera" support in Windows AIM 5.5.3501 and newer */
+- {OSCAR_CAPABILITY_CAMERA,
+- {0x09, 0x46, 0x01, 0x02, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* "Microphone" support in Windows AIM 5.5.3501 and newer */
+- /* OSCAR_CAPABILITY_MICROPHONE */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x01, 0x03, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* Supports RTC Audio */
+- /* OSCAR_CAPABILITY_RTCAUDIO */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x01, 0x04, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* In iChatAV (version numbers...?) */
+- {OSCAR_CAPABILITY_ICHATAV,
+- {0x09, 0x46, 0x01, 0x05, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x45, 0x53, 0x54, 0x00}},
+-
+- /* Supports "new status message features" (Who advertises this one?) */
+- /* OSCAR_CAPABILITY_HOST_STATUS_TEXT_AWARE */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x01, 0x0a, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* Supports "see as I type" (Who advertises this one?) */
+- /* OSCAR_CAPABILITY_SEE_AS_I_TYPE */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x01, 0x0b, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* Client only asserts caps for services in which it is participating */
+- /* OSCAR_CAPABILITY_SMARTCAPS */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0x01, 0xff, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_HIPTOP,
+- {0x09, 0x46, 0x13, 0x23, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_TALK,
+- {0x09, 0x46, 0x13, 0x41, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_SENDFILE,
+- {0x09, 0x46, 0x13, 0x43, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_ICQ_DIRECT,
+- {0x09, 0x46, 0x13, 0x44, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_DIRECTIM,
+- {0x09, 0x46, 0x13, 0x45, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_BUDDYICON,
+- {0x09, 0x46, 0x13, 0x46, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_ADDINS,
+- {0x09, 0x46, 0x13, 0x47, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_GETFILE,
+- {0x09, 0x46, 0x13, 0x48, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_ICQSERVERRELAY,
+- {0x09, 0x46, 0x13, 0x49, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /*
+- * Indeed, there are two of these. The former appears to be correct,
+- * but in some versions of winaim, the second one is set. Either they
+- * forgot to fix endianness, or they made a typo. It really doesn't
+- * matter which.
+- */
+- {OSCAR_CAPABILITY_GAMES,
+- {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+- {OSCAR_CAPABILITY_GAMES2,
+- {0x09, 0x46, 0x13, 0x4a, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x22, 0x82, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* New format of caps (xtraz icons) */
+- {OSCAR_CAPABILITY_NEWCAPS,
+- {0x09, 0x46, 0x00, 0x00, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* Support xtraz statuses */
+- {OSCAR_CAPABILITY_XTRAZ,
+- {0x1a, 0x09, 0x3c, 0x6c, 0xd7, 0xFD, 0x4e, 0xc5,
+- 0x9d, 0x51, 0xa6, 0x47, 0x4e, 0x34, 0xf5, 0xa0}},
+-
+- {OSCAR_CAPABILITY_SENDBUDDYLIST,
+- {0x09, 0x46, 0x13, 0x4b, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /*
+- * Setting this lets AIM users receive messages from ICQ users, and ICQ
+- * users receive messages from AIM users. It also lets ICQ users show
+- * up in buddy lists for AIM users, and AIM users show up in buddy lists
+- * for ICQ users. And ICQ privacy/invisibility acts like AIM privacy,
+- * in that if you add a user to your deny list, you will not be able to
+- * see them as online (previous you could still see them, but they
+- * couldn't see you.
+- */
+- {OSCAR_CAPABILITY_INTEROPERATE,
+- {0x09, 0x46, 0x13, 0x4d, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_UNICODE,
+- {0x09, 0x46, 0x13, 0x4e, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0xf0, 0x03, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_ICHAT_SCREENSHARE,
+- {0x09, 0x46, 0xf0, 0x04, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x09, 0x46, 0xf0, 0x05, 0x4c, 0x7f, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_UNICODEOLD,
+- {0x2e, 0x7a, 0x64, 0x75, 0xfa, 0xdf, 0x4d, 0xc8,
+- 0x88, 0x6f, 0xea, 0x35, 0x95, 0xfd, 0xb6, 0xdf}},
+-
+- {OSCAR_CAPABILITY_TYPING,
+- {0x56, 0x3f, 0xc8, 0x09, 0x0b, 0x6f, 0x41, 0xbd,
+- 0x9f, 0x79, 0x42, 0x26, 0x09, 0xdf, 0xa2, 0xf3}},
+-
+- /*
+- * Chat is oddball.
+- */
+- {OSCAR_CAPABILITY_CHAT,
+- {0x74, 0x8f, 0x24, 0x20, 0x62, 0x87, 0x11, 0xd1,
+- 0x82, 0x22, 0x44, 0x45, 0x53, 0x54, 0x00, 0x00}},
+-
+- /* This is added by the servers and it only shows up for ourselves... */
+- {OSCAR_CAPABILITY_GENERICUNKNOWN,
+- {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
+- 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x09}},
+-
+- {OSCAR_CAPABILITY_ICQRTF,
+- {0x97, 0xb1, 0x27, 0x51, 0x24, 0x3c, 0x43, 0x34,
+- 0xad, 0x22, 0xd6, 0xab, 0xf7, 0x3f, 0x14, 0x92}},
+-
+- {OSCAR_CAPABILITY_APINFO,
+- {0xaa, 0x4a, 0x32, 0xb5, 0xf8, 0x84, 0x48, 0xc6,
+- 0xa3, 0xd7, 0x8c, 0x50, 0x97, 0x19, 0xfd, 0x5b}},
+-
+- {OSCAR_CAPABILITY_TRILLIANCRYPT,
+- {0xf2, 0xe7, 0xc7, 0xf4, 0xfe, 0xad, 0x4d, 0xfb,
+- 0xb2, 0x35, 0x36, 0x79, 0x8b, 0xdf, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_EMPTY,
+- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+-
+- {OSCAR_CAPABILITY_HTML_MSGS,
+- {0x01, 0x38, 0xca, 0x7b, 0x76, 0x9a, 0x49, 0x15,
+- 0x88, 0xf2, 0x13, 0xfc, 0x00, 0x97, 0x9e, 0xa8}},
+-
+- {OSCAR_CAPABILITY_LAST,
+- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}},
+-};
+-
+-/* Keep this array synchronized with icq_purple_moods. */
+-static const struct {
+- const char *mood;
+- guint8 data[16];
+-} icq_custom_icons[] = {
+-
+- {"thinking",
+- {0x3f, 0xb0, 0xbd, 0x36, 0xaf, 0x3b, 0x4a, 0x60,
+- 0x9e, 0xef, 0xcf, 0x19, 0x0f, 0x6a, 0x5a, 0x7f}},
+-
+- {"busy",
+- {0x48, 0x8e, 0x14, 0x89, 0x8a, 0xca, 0x4a, 0x08,
+- 0x82, 0xaa, 0x77, 0xce, 0x7a, 0x16, 0x52, 0x08}},
+-
+- {"shopping",
+- {0x63, 0x62, 0x73, 0x37, 0xa0, 0x3f, 0x49, 0xff,
+- 0x80, 0xe5, 0xf7, 0x09, 0xcd, 0xe0, 0xa4, 0xee}},
+-
+- /* This was in the original patch, but isn't what the official client
+- * (ICQ 6) sets when you choose its typewriter icon. */
+- {"typing",
+- {0x63, 0x4f, 0x6b, 0xd8 ,0xad, 0xd2, 0x4a, 0xa1,
+- 0xaa, 0xb9, 0x11, 0x5b, 0xc2, 0x6d, 0x05, 0xa1}},
+-
+- {"question",
+- {0x63, 0x14, 0x36, 0xff, 0x3f, 0x8a, 0x40, 0xd0,
+- 0xa5, 0xcb, 0x7b, 0x66, 0xe0, 0x51, 0xb3, 0x64}},
+-
+- {"angry",
+- {0x01, 0xd8, 0xd7, 0xee, 0xac, 0x3b, 0x49, 0x2a,
+- 0xa5, 0x8d, 0xd3, 0xd8, 0x77, 0xe6, 0x6b, 0x92}},
+-
+- {"plate",
+- {0xf8, 0xe8, 0xd7, 0xb2, 0x82, 0xc4, 0x41, 0x42,
+- 0x90, 0xf8, 0x10, 0xc6, 0xce, 0x0a, 0x89, 0xa6}},
+-
+- {"cinema",
+- {0x10, 0x7a, 0x9a, 0x18, 0x12, 0x32, 0x4d, 0xa4,
+- 0xb6, 0xcd, 0x08, 0x79, 0xdb, 0x78, 0x0f, 0x09}},
+-
+- {"sick",
+- {0x1f, 0x7a, 0x40, 0x71, 0xbf, 0x3b, 0x4e, 0x60,
+- 0xbc, 0x32, 0x4c, 0x57, 0x87, 0xb0, 0x4c, 0xf1}},
+-
+- {"typing",
+- {0x2c, 0xe0, 0xe4, 0xe5, 0x7c, 0x64, 0x43, 0x70,
+- 0x9c, 0x3a, 0x7a, 0x1c, 0xe8, 0x78, 0xa7, 0xdc}},
+-
+- {"suit",
+- {0xb7, 0x08, 0x67, 0xf5, 0x38, 0x25, 0x43, 0x27,
+- 0xa1, 0xff, 0xcf, 0x4c, 0xc1, 0x93, 0x97, 0x97}},
+-
+- {"bathing",
+- {0x5a, 0x58, 0x1e, 0xa1, 0xe5, 0x80, 0x43, 0x0c,
+- 0xa0, 0x6f, 0x61, 0x22, 0x98, 0xb7, 0xe4, 0xc7}},
+-
+- {"tv",
+- {0x80, 0x53, 0x7d, 0xe2, 0xa4, 0x67, 0x4a, 0x76,
+- 0xb3, 0x54, 0x6d, 0xfd, 0x07, 0x5f, 0x5e, 0xc6}},
+-
+- {"excited",
+- {0x6f, 0x49, 0x30, 0x98, 0x4f, 0x7c, 0x4a, 0xff,
+- 0xa2, 0x76, 0x34, 0xa0, 0x3b, 0xce, 0xae, 0xa7}},
+-
+- {"sleeping",
+- {0x78, 0x5e, 0x8c, 0x48, 0x40, 0xd3, 0x4c, 0x65,
+- 0x88, 0x6f, 0x04, 0xcf, 0x3f, 0x3f, 0x43, 0xdf}},
+-
+- {"hiptop",
+- {0x10, 0x11, 0x17, 0xc9, 0xa3, 0xb0, 0x40, 0xf9,
+- 0x81, 0xac, 0x49, 0xe1, 0x59, 0xfb, 0xd5, 0xd4}},
+-
+- {"in_love",
+- {0xdd, 0xcf, 0x0e, 0xa9, 0x71, 0x95, 0x40, 0x48,
+- 0xa9, 0xc6, 0x41, 0x32, 0x06, 0xd6, 0xf2, 0x80}},
+-
+- {"sleepy",
+- {0x83, 0xc9, 0xb7, 0x8e, 0x77, 0xe7, 0x43, 0x78,
+- 0xb2, 0xc5, 0xfb, 0x6c, 0xfc, 0xc3, 0x5b, 0xec}},
+-
+- {"meeting",
+- {0xf1, 0x8a, 0xb5, 0x2e, 0xdc, 0x57, 0x49, 0x1d,
+- 0x99, 0xdc, 0x64, 0x44, 0x50, 0x24, 0x57, 0xaf}},
+-
+- {"phone",
+- {0x12, 0x92, 0xe5, 0x50, 0x1b, 0x64, 0x4f, 0x66,
+- 0xb2, 0x06, 0xb2, 0x9a, 0xf3, 0x78, 0xe4, 0x8d}},
+-
+- {"surfing",
+- {0xa6, 0xed, 0x55, 0x7e, 0x6b, 0xf7, 0x44, 0xd4,
+- 0xa5, 0xd4, 0xd2, 0xe7, 0xd9, 0x5c, 0xe8, 0x1f}},
+-
+- {"mobile",
+- {0x16, 0x0c, 0x60, 0xbb, 0xdd, 0x44, 0x43, 0xf3,
+- 0x91, 0x40, 0x05, 0x0f, 0x00, 0xe6, 0xc0, 0x09}},
+-
+- {"search",
+- {0xd4, 0xe2, 0xb0, 0xba, 0x33, 0x4e, 0x4f, 0xa5,
+- 0x98, 0xd0, 0x11, 0x7d, 0xbf, 0x4d, 0x3c, 0xc8}},
+-
+- {"party",
+- {0xe6, 0x01, 0xe4, 0x1c, 0x33, 0x73, 0x4b, 0xd1,
+- 0xbc, 0x06, 0x81, 0x1d, 0x6c, 0x32, 0x3d, 0x81}},
+-
+- {"coffee",
+- {0x1b, 0x78, 0xae, 0x31, 0xfa, 0x0b, 0x4d, 0x38,
+- 0x93, 0xd1, 0x99, 0x7e, 0xee, 0xaf, 0xb2, 0x18}},
+-
+- {"console",
+- {0xd4, 0xa6, 0x11, 0xd0, 0x8f, 0x01, 0x4e, 0xc0,
+- 0x92, 0x23, 0xc5, 0xb6, 0xbe, 0xc6, 0xcc, 0xf0}},
+-
+- {"internet",
+- {0x12, 0xd0, 0x7e, 0x3e, 0xf8, 0x85, 0x48, 0x9e,
+- 0x8e, 0x97, 0xa7, 0x2a, 0x65, 0x51, 0xe5, 0x8d}},
+-
+- {"cigarette",
+- {0x64, 0x43, 0xc6, 0xaf, 0x22, 0x60, 0x45, 0x17,
+- 0xb5, 0x8c, 0xd7, 0xdf, 0x8e, 0x29, 0x03, 0x52}},
+-
+- {"writing",
+- {0x00, 0x72, 0xd9, 0x08, 0x4a, 0xd1, 0x43, 0xdd,
+- 0x91, 0x99, 0x6f, 0x02, 0x69, 0x66, 0x02, 0x6f}},
+-
+- {"beer",
+- {0x8c, 0x50, 0xdb, 0xae, 0x81, 0xed, 0x47, 0x86,
+- 0xac, 0xca, 0x16, 0xcc, 0x32, 0x13, 0xc7, 0xb7}},
+-
+- {"music",
+- {0x61, 0xbe, 0xe0, 0xdd, 0x8b, 0xdd, 0x47, 0x5d,
+- 0x8d, 0xee, 0x5f, 0x4b, 0xaa, 0xcf, 0x19, 0xa7}},
+-
+- {"studying",
+- {0x60, 0x9d, 0x52, 0xf8, 0xa2, 0x9a, 0x49, 0xa6,
+- 0xb2, 0xa0, 0x25, 0x24, 0xc5, 0xe9, 0xd2, 0x60}},
+-
+- {"working",
+- {0xba, 0x74, 0xdb, 0x3e, 0x9e, 0x24, 0x43, 0x4b,
+- 0x87, 0xb6, 0x2f, 0x6b, 0x8d, 0xfe, 0xe5, 0x0f}},
+-
+- {"restroom",
+- {0x16, 0xf5, 0xb7, 0x6f, 0xa9, 0xd2, 0x40, 0x35,
+- 0x8c, 0xc5, 0xc0, 0x84, 0x70, 0x3c, 0x98, 0xfa}},
+-
+- {NULL,
+- {0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+- 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}}
+-};
+-
+-/* Keep this array synchronized with icq_custom_icons. */
+-static PurpleMood icq_purple_moods[] = {
+- {"thinking", N_("Thinking"), NULL},
+- {"busy", N_("Busy"), NULL},
+- {"shopping", N_("Shopping"), NULL},
+- /* This was in the original patch, but isn't what the official client
+- * (ICQ 6) sets when you choose its typewriter icon. */
+- {"typing", NULL, NULL},
+- {"question", N_("Questioning"), NULL},
+- {"angry", N_("Angry"), NULL},
+- {"plate", N_("Eating"), NULL},
+- {"cinema", N_("Watching a movie"), NULL},
+- {"sick", N_("Sick"), NULL},
+- {"typing", N_("Typing"), NULL},
+- {"suit", N_("At the office"), NULL},
+- {"bathing", N_("Taking a bath"), NULL},
+- {"tv", N_("Watching TV"), NULL},
+- {"excited", N_("Having fun"), NULL},
+- {"sleeping", N_("Sleeping"), NULL},
+- {"hiptop", N_("Using a PDA"), NULL},
+- {"in_love", N_("In love"), NULL},
+- /* Sleepy / Tired */
+- {"sleepy", N_("Sleepy"), NULL},
+- {"meeting", N_("Meeting friends"), NULL},
+- {"phone", N_("On the phone"), NULL},
+- {"surfing", N_("Surfing"), NULL},
+- /* "I am mobile." / "John is mobile." */
+- {"mobile", N_("Mobile"), NULL},
+- {"search", N_("Searching the web"), NULL},
+- {"party", N_("At a party"), NULL},
+- {"coffee", N_("Having Coffee"), NULL},
+- /* Playing video games */
+- {"console", N_("Gaming"), NULL},
+- {"internet", N_("Browsing the web"), NULL},
+- {"cigarette", N_("Smoking"), NULL},
+- {"writing", N_("Writing"), NULL},
+- /* Drinking [Alcohol] */
+- {"beer", N_("Drinking"), NULL},
+- {"music", N_("Listening to music"), NULL},
+- {"studying", N_("Studying"), NULL},
+- {"working", N_("Working"), NULL},
+- {"restroom", N_("In the restroom"), NULL},
+- /* Mark the last record. */
+- {NULL, NULL, NULL},
+-};
+-
+-
+-/*
+- * Add the userinfo to our linked list. If we already have userinfo
+- * for this buddy, then just overwrite parts of the old data.
+- *
+- * @param userinfo Contains the new information for the buddy.
+- */
+-static void
+-aim_locate_adduserinfo(OscarData *od, aim_userinfo_t *userinfo)
+-{
+- aim_userinfo_t *cur;
+-
+- cur = aim_locate_finduserinfo(od, userinfo->bn);
+-
+- if (cur == NULL) {
+- cur = (aim_userinfo_t *)g_new0(aim_userinfo_t, 1);
+- cur->bn = g_strdup(userinfo->bn);
+- cur->next = od->locate.userinfo;
+- od->locate.userinfo = cur;
+- }
+-
+- cur->warnlevel = userinfo->warnlevel;
+- cur->idletime = userinfo->idletime;
+- if (userinfo->flags != 0)
+- cur->flags = userinfo->flags;
+- if (userinfo->createtime != 0)
+- cur->createtime = userinfo->createtime;
+- if (userinfo->membersince != 0)
+- cur->membersince = userinfo->membersince;
+- if (userinfo->onlinesince != 0)
+- cur->onlinesince = userinfo->onlinesince;
+- if (userinfo->sessionlen != 0)
+- cur->sessionlen = userinfo->sessionlen;
+- if (userinfo->capabilities != 0)
+- cur->capabilities = userinfo->capabilities;
+-
+- cur->present |= userinfo->present;
+-
+- if (userinfo->iconcsumlen > 0) {
+- g_free(cur->iconcsum);
+- cur->iconcsum = (guint8 *)g_malloc(userinfo->iconcsumlen);
+- memcpy(cur->iconcsum, userinfo->iconcsum, userinfo->iconcsumlen);
+- cur->iconcsumlen = userinfo->iconcsumlen;
+- }
+-
+- if (userinfo->info != NULL) {
+- g_free(cur->info);
+- g_free(cur->info_encoding);
+- if (userinfo->info_len > 0) {
+- cur->info = (char *)g_malloc(userinfo->info_len);
+- memcpy(cur->info, userinfo->info, userinfo->info_len);
+- } else
+- cur->info = NULL;
+- cur->info_encoding = g_strdup(userinfo->info_encoding);
+- cur->info_len = userinfo->info_len;
+- }
+-
+- if (userinfo->status != NULL) {
+- g_free(cur->status);
+- g_free(cur->status_encoding);
+- if (userinfo->status_len > 0) {
+- cur->status = (char *)g_malloc(userinfo->status_len);
+- memcpy(cur->status, userinfo->status, userinfo->status_len);
+- } else
+- cur->status = NULL;
+- if (userinfo->status_encoding != NULL)
+- cur->status_encoding = g_strdup(userinfo->status_encoding);
+- else
+- cur->status_encoding = NULL;
+- cur->status_len = userinfo->status_len;
+- }
+-
+- if (userinfo->itmsurl != NULL) {
+- g_free(cur->itmsurl);
+- g_free(cur->itmsurl_encoding);
+- if (userinfo->itmsurl_len > 0) {
+- cur->itmsurl = (char *)g_malloc(userinfo->itmsurl_len);
+- memcpy(cur->itmsurl, userinfo->itmsurl, userinfo->itmsurl_len);
+- } else
+- cur->itmsurl = NULL;
+- if (userinfo->itmsurl_encoding != NULL)
+- cur->itmsurl_encoding = g_strdup(userinfo->itmsurl_encoding);
+- else
+- cur->itmsurl_encoding = NULL;
+- cur->itmsurl_len = userinfo->itmsurl_len;
+- }
+-
+- if (userinfo->away != NULL) {
+- g_free(cur->away);
+- g_free(cur->away_encoding);
+- if (userinfo->away_len > 0) {
+- cur->away = (char *)g_malloc(userinfo->away_len);
+- memcpy(cur->away, userinfo->away, userinfo->away_len);
+- } else
+- cur->away = NULL;
+- cur->away_encoding = g_strdup(userinfo->away_encoding);
+- cur->away_len = userinfo->away_len;
+-
+- } else {
+- /*
+- * We don't have an away message specified in this user_info
+- * block, so clear any cached away message now.
+- */
+- if (cur->away) {
+- g_free(cur->away);
+- cur->away = NULL;
+- }
+- if (cur->away_encoding) {
+- g_free(cur->away_encoding);
+- cur->away_encoding = NULL;
+- }
+- cur->away_len = 0;
+- }
+-}
+-
+-aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn) {
+- aim_userinfo_t *cur = NULL;
+-
+- if (bn == NULL)
+- return NULL;
+-
+- cur = od->locate.userinfo;
+-
+- while (cur != NULL) {
+- if (oscar_util_name_compare(cur->bn, bn) == 0)
+- return cur;
+- cur = cur->next;
+- }
+-
+- return NULL;
+-}
+-
+-guint64
+-aim_locate_getcaps(OscarData *od, ByteStream *bs, int len)
+-{
+- guint64 flags = 0;
+- int offset;
+-
+- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) {
+- guint8 *cap;
+- int i, identified;
+-
+- cap = byte_stream_getraw(bs, 0x10);
+-
+- for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) {
+- if (memcmp(&aim_caps[i].data, cap, 0x10) == 0) {
+- flags |= aim_caps[i].flag;
+- identified++;
+- break; /* should only match once... */
+- }
+- }
+-
+- if (!identified)
+- purple_debug_misc("oscar", "unknown capability: {%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x}\n",
+- cap[0], cap[1], cap[2], cap[3],
+- cap[4], cap[5],
+- cap[6], cap[7],
+- cap[8], cap[9],
+- cap[10], cap[11], cap[12], cap[13],
+- cap[14], cap[15]);
+- g_free(cap);
+- }
+-
+- return flags;
+-}
+-
+-static const char *
+-aim_receive_custom_icon(OscarData *od, ByteStream *bs, int len)
+-{
+- int offset;
+- const char *result = NULL;
+-
+- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x10) {
+- /* check wheather this capability is a custom user icon */
+- guint8 *cap;
+- int i;
+-
+- cap = byte_stream_getraw(bs, 0x10);
+-
+- for (i = 0; icq_custom_icons[i].mood; i++) {
+- if (memcmp(&icq_custom_icons[i].data, cap, 0x10) == 0) {
+- purple_debug_misc("oscar", "Custom status icon: %s\n", icq_purple_moods[i].description);
+- result = icq_custom_icons[i].mood;
+- break; /* should only match once... */
+- }
+- }
+- g_free(cap);
+- }
+-
+- return result;
+-}
+-
+-guint64
+-aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len)
+-{
+- guint64 flags = 0;
+- int offset;
+-
+- for (offset = 0; byte_stream_bytes_left(bs) && (offset < len); offset += 0x02) {
+- guint8 *cap;
+- int i, identified;
+-
+- cap = byte_stream_getraw(bs, 0x02);
+-
+- for (i = 0, identified = 0; !(aim_caps[i].flag & OSCAR_CAPABILITY_LAST); i++) {
+- if (memcmp(&aim_caps[i].data[2], cap, 0x02) == 0) {
+- flags |= aim_caps[i].flag;
+- identified++;
+- break; /* should only match once... */
+- }
+- }
+-
+- if (!identified)
+- purple_debug_misc("oscar", "unknown short capability: {%02x%02x}\n", cap[0], cap[1]);
+-
+- g_free(cap);
+- }
+-
+- return flags;
+-}
+-
+-int
+-byte_stream_putcaps(ByteStream *bs, guint64 caps)
+-{
+- int i;
+-
+- if (!bs)
+- return -EINVAL;
+-
+- for (i = 0; byte_stream_bytes_left(bs); i++) {
+- if (aim_caps[i].flag == OSCAR_CAPABILITY_LAST)
+- break;
+-
+- if (caps & aim_caps[i].flag)
+- byte_stream_putraw(bs, aim_caps[i].data, 0x10);
+- }
+- return 0;
+-}
+-
+-#ifdef LOG_UNKNOWN_TLV
+-static void
+-dumptlv(OscarData *od, guint16 type, ByteStream *bs, guint8 len)
+-{
+- int i;
+-
+- if (!od || !bs || !len)
+- return;
+-
+- purple_debug_misc("oscar", "userinfo: type =0x%04x\n", type);
+- purple_debug_misc("oscar", "userinfo: length=0x%04x\n", len);
+- purple_debug_misc("oscar", "userinfo: value:\n");
+-
+- for (i = 0; i < len; i++) {
+- if ((i % 8) == 0)
+- purple_debug_misc("oscar", "\nuserinfo: ");
+- purple_debug_misc("oscar", "0x%2x ", byte_stream_get8(bs));
+- }
+-
+- purple_debug_misc("oscar", "\n");
+-
+- return;
+-}
+-#endif
+-
+-void
+-aim_info_free(aim_userinfo_t *info)
+-{
+- g_free(info->bn);
+- g_free(info->iconcsum);
+- g_free(info->info);
+- g_free(info->info_encoding);
+- g_free(info->status);
+- g_free(info->status_encoding);
+- g_free(info->itmsurl);
+- g_free(info->itmsurl_encoding);
+- g_free(info->away);
+- g_free(info->away_encoding);
+-}
+-
+-static const struct {
+- char *icqmood;
+- const char *mood;
+-} icqmoods[] = {
+- {"icqmood0", "shopping"},
+- {"icqmood1", "bathing"},
+- {"icqmood2", "sleepy"},
+- {"icqmood3", "party"},
+- {"icqmood4", "beer"},
+- {"icqmood5", "thinking"},
+- {"icqmood6", "plate"},
+- {"icqmood7", "tv"},
+- {"icqmood8", "meeting"},
+- {"icqmood9", "coffee"},
+- {"icqmood10", "music"},
+- {"icqmood11", "suit"},
+- {"icqmood12", "cinema"},
+- {"icqmood13", "smile-big"},
+- {"icqmood14", "phone"},
+- {"icqmood15", "console"},
+- {"icqmood16", "studying"},
+- {"icqmood17", "sick"},
+- {"icqmood18", "sleeping"},
+- {"icqmood19", "surfing"},
+- {"icqmood20", "internet"},
+- {"icqmood21", "working"},
+- {"icqmood22", "typing"},
+- {"icqmood23", "angry"},
+- {NULL, 0}
+-
+-};
+-
+-/*
+- * AIM is fairly regular about providing user info. This is a generic
+- * routine to extract it in its standard form.
+- */
+-int
+-aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *outinfo)
+-{
+- int curtlv, tlvcnt;
+- guint8 bnlen;
+-
+- if (!bs || !outinfo)
+- return -EINVAL;
+-
+- /* Clear out old data first */
+- memset(outinfo, 0x00, sizeof(aim_userinfo_t));
+-
+- /*
+- * Username. Stored as an unterminated string prepended with a
+- * byte containing its length.
+- */
+- bnlen = byte_stream_get8(bs);
+- outinfo->bn = byte_stream_getstr(bs, bnlen);
+-
+- /*
+- * Warning Level. Stored as an unsigned short.
+- */
+- outinfo->warnlevel = byte_stream_get16(bs);
+-
+- /*
+- * TLV Count. Unsigned short representing the number of
+- * Type-Length-Value triples that follow.
+- */
+- tlvcnt = byte_stream_get16(bs);
+-
+- /*
+- * Parse out the Type-Length-Value triples as they're found.
+- */
+- for (curtlv = 0; curtlv < tlvcnt; curtlv++) {
+- guint16 type, length;
+- int endpos;
+- int curpos;
+-
+- type = byte_stream_get16(bs);
+- length = byte_stream_get16(bs);
+- curpos = byte_stream_curpos(bs);
+- endpos = curpos + MIN(length, byte_stream_bytes_left(bs));
+-
+- if (type == 0x0001) {
+- /*
+- * User flags
+- *
+- * Specified as any of the following ORed together:
+- * 0x0001 Unconfirmed account
+- * 0x0002 Unknown bit 2
+- * 0x0004 AOL Main Service user
+- * 0x0008 Unknown bit 4
+- * 0x0010 Free (AIM) user
+- * 0x0020 Away
+- * 0x0040 ICQ user (AIM bit also set)
+- * 0x0080 Mobile device
+- * 0x0400 Bot (like ActiveBuddy)
+- */
+- outinfo->flags = byte_stream_get16(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_FLAGS;
+-
+- } else if (type == 0x0002) {
+- /*
+- * Account creation time
+- *
+- * The time/date that the user originally registered for
+- * the service, stored in time_t format.
+- *
+- * I'm not sure how this differs from type 5 ("member
+- * since").
+- *
+- * Note: This is the field formerly known as "member
+- * since". All these years and I finally found out
+- * that I got the name wrong.
+- */
+- outinfo->createtime = byte_stream_get32(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_CREATETIME;
+-
+- } else if (type == 0x0003) {
+- /*
+- * On-Since date
+- *
+- * The time/date that the user started their current
+- * session, stored in time_t format.
+- */
+- outinfo->onlinesince = byte_stream_get32(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_ONLINESINCE;
+-
+- } else if (type == 0x0004) {
+- /*
+- * Idle time
+- *
+- * Number of minutes since the user actively used the
+- * service.
+- *
+- * Note that the client tells the server when to start
+- * counting idle times, so this may or may not be
+- * related to reality.
+- */
+- outinfo->idletime = byte_stream_get16(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_IDLE;
+-
+- } else if (type == 0x0005) {
+- /*
+- * Member since date
+- *
+- * The time/date that the user originally registered for
+- * the service, stored in time_t format.
+- *
+- * This is sometimes sent instead of type 2 ("account
+- * creation time"), particularly in the self-info.
+- * And particularly for ICQ?
+- */
+- outinfo->membersince = byte_stream_get32(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_MEMBERSINCE;
+-
+- } else if (type == 0x0006) {
+- /*
+- * ICQ Online Status
+- *
+- * ICQ's Away/DND/etc "enriched" status. Some decoding
+- * of values done by Scott <darkagl@pcnet.com>
+- */
+- byte_stream_get16(bs);
+- outinfo->icqinfo.status = byte_stream_get16(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_ICQEXTSTATUS;
+-
+- } else if (type == 0x0008) {
+- /*
+- * Client type, or some such.
+- */
+-
+- } else if (type == 0x000a) {
+- /*
+- * ICQ User IP Address
+- *
+- * Ahh, the joy of ICQ security.
+- */
+- outinfo->icqinfo.ipaddr = byte_stream_get32(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_ICQIPADDR;
+-
+- } else if (type == 0x000c) {
+- /*
+- * Random crap containing the IP address,
+- * apparently a port number, and some Other Stuff.
+- *
+- * Format is:
+- * 4 bytes - Our IP address, 0xc0 a8 01 2b for 192.168.1.43
+- */
+- byte_stream_getrawbuf(bs, outinfo->icqinfo.crap, 0x25);
+- outinfo->present |= AIM_USERINFO_PRESENT_ICQDATA;
+-
+- } else if (type == 0x000d) {
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- const char *mood;
+-
+- /*
+- * OSCAR Capability information
+- */
+- outinfo->capabilities |= aim_locate_getcaps(od, bs, length);
+- outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
+- byte_stream_setpos(bs, curpos);
+-
+- mood = aim_receive_custom_icon(od, bs, length);
+- if (mood)
+- purple_prpl_got_user_status(account, outinfo->bn, "mood",
+- PURPLE_MOOD_NAME, mood,
+- NULL);
+- else
+- purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
+-
+- } else if (type == 0x000e) {
+- /*
+- * AOL capability information
+- */
+-
+- } else if ((type == 0x000f) || (type == 0x0010)) {
+- /*
+- * Type = 0x000f: Session Length. (AIM)
+- * Type = 0x0010: Session Length. (AOL)
+- *
+- * The duration, in seconds, of the user's current
+- * session.
+- *
+- * Which TLV type this comes in depends on the
+- * service the user is using (AIM or AOL).
+- */
+- outinfo->sessionlen = byte_stream_get32(bs);
+- outinfo->present |= AIM_USERINFO_PRESENT_SESSIONLEN;
+-
+- } else if (type == 0x0014) {
+- /*
+- * My instance number.
+- */
+- guint8 instance_number;
+- instance_number = byte_stream_get8(bs);
+-
+- } else if (type == 0x0019) {
+- /*
+- * OSCAR short capability information. A shortened
+- * form of the normal capabilities.
+- */
+- outinfo->capabilities |= aim_locate_getcaps_short(od, bs, length);
+- outinfo->present |= AIM_USERINFO_PRESENT_CAPABILITIES;
+-
+- } else if (type == 0x001a) {
+- /*
+- * Type = 0x001a
+- *
+- * AOL short capability information. A shortened
+- * form of the normal capabilities.
+- */
+-
+- } else if (type == 0x001b) {
+- /*
+- * Encryption certification MD5 checksum.
+- */
+-
+- } else if (type == 0x001d) {
+- /*
+- * Buddy icon information and status/available messages.
+- *
+- * This almost seems like the AIM protocol guys gave
+- * the iChat guys a Type, and the iChat guys tried to
+- * cram as much cool shit into it as possible. Then
+- * the Windows AIM guys were like, "hey, that's
+- * pretty neat, let's copy those prawns."
+- *
+- * In that spirit, this can contain a custom message,
+- * kind of like an away message, but you're not away
+- * (it's called an "available" message). Or it can
+- * contain information about the buddy icon the user
+- * has stored on the server.
+- */
+- guint16 type2;
+- guint8 number2, length2;
+- int endpos2;
+-
+- /*
+- * Continue looping as long as we're able to read type2,
+- * number2, and length2.
+- */
+- while (byte_stream_curpos(bs) + 4 <= endpos) {
+- type2 = byte_stream_get16(bs);
+- number2 = byte_stream_get8(bs);
+- length2 = byte_stream_get8(bs);
+-
+- endpos2 = byte_stream_curpos(bs) + MIN(length2, byte_stream_bytes_left(bs));
+-
+- switch (type2) {
+- case 0x0000: { /* This is an official buddy icon? */
+- /* This is always 5 bytes of "0x02 01 d2 04 72"? */
+- } break;
+-
+- case 0x0001: { /* A buddy icon checksum */
+- if ((length2 > 0) && ((number2 == 0x00) || (number2 == 0x01))) {
+- g_free(outinfo->iconcsum);
+- outinfo->iconcsumtype = number2;
+- outinfo->iconcsum = byte_stream_getraw(bs, length2);
+- outinfo->iconcsumlen = length2;
+- }
+- } break;
+-
+- case 0x0002: { /* A status/available message */
+- g_free(outinfo->status);
+- g_free(outinfo->status_encoding);
+- if (length2 >= 4) {
+- outinfo->status_len = byte_stream_get16(bs);
+- outinfo->status = byte_stream_getstr(bs, outinfo->status_len);
+- if (byte_stream_get16(bs) == 0x0001) { /* We have an encoding */
+- byte_stream_get16(bs);
+- outinfo->status_encoding = byte_stream_getstr(bs, byte_stream_get16(bs));
+- } else {
+- /* No explicit encoding, client should use UTF-8 */
+- outinfo->status_encoding = NULL;
+- }
+- } else {
+- byte_stream_advance(bs, length2);
+- outinfo->status_len = 0;
+- outinfo->status = g_strdup("");
+- outinfo->status_encoding = NULL;
+- }
+- } break;
+-
+- case 0x0009: { /* An iTunes Music Store link */
+- g_free(outinfo->itmsurl);
+- g_free(outinfo->itmsurl_encoding);
+- if (length2 >= 4) {
+- outinfo->itmsurl_len = byte_stream_get16(bs);
+- outinfo->itmsurl = byte_stream_getstr(bs, outinfo->itmsurl_len);
+- if (byte_stream_get16(bs) == 0x0001) {
+- /* We have an encoding */
+- byte_stream_get16(bs);
+- outinfo->itmsurl_encoding = byte_stream_getstr(bs, byte_stream_get16(bs));
+- } else {
+- /* No explicit encoding, client should use UTF-8 */
+- outinfo->itmsurl_encoding = NULL;
+- }
+- } else {
+- byte_stream_advance(bs, length2);
+- outinfo->itmsurl_len = 0;
+- outinfo->itmsurl = g_strdup("");
+- outinfo->itmsurl_encoding = NULL;
+- }
+- } break;
+-
+- case 0x000e: { /* ICQ mood */
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- char *icqmood;
+- gint32 i;
+- const char *mood = NULL;
+-
+- icqmood = byte_stream_getstr(bs, length2);
+-
+- /* icqmood = "" means X-Status
+- * with no mood icon. */
+- if (*icqmood) {
+- for (i = 0; icqmoods[i].icqmood; i++) {
+- if (!strcmp(icqmood, icqmoods[i].icqmood)) {
+- mood = icqmoods[i].mood;
+- break; /* should only match once... */
+- }
+- }
+-
+- if (!mood)
+- purple_debug_warning("oscar", "Unknown icqmood: %s\n", icqmood);
+- }
+- g_free(icqmood);
+-
+- if (mood)
+- purple_prpl_got_user_status(account, outinfo->bn, "mood",
+- PURPLE_MOOD_NAME, mood,
+- NULL);
+- else
+- purple_prpl_got_user_status_deactive(account, outinfo->bn, "mood");
+- } break;
+- }
+-
+- /* Save ourselves. */
+- byte_stream_setpos(bs, endpos2);
+- }
+-
+- } else if (type == 0x001e) {
+- /*
+- * Always four bytes, but it doesn't look like an int.
+- */
+-
+- } else if (type == 0x001f) {
+- /*
+- * Upper bytes of user flags. Can be any size
+- *
+- * Seen on a buddy using DeadAIM. Data was 4 bytes:
+- * 0x00 00 00 10
+- */
+-
+- } else if (type == 0x0023) {
+- /*
+- * Last Buddy Feed update time, in seconds since the epoch.
+- */
+-
+- } else if (type == 0x0026) {
+- /*
+- * Time that the profile was set, in seconds since the epoch.
+- */
+-
+- } else if (type == 0x0027) {
+- /*
+- * Time that the away message was set, in seconds since the epoch.
+- */
+-
+- } else if (type == 0x002a) {
+- /*
+- * Country code based on GeoIP data.
+- */
+-
+- } else {
+-
+- /*
+- * Reaching here indicates that either AOL has
+- * added yet another TLV for us to deal with,
+- * or the parsing has gone Terribly Wrong.
+- *
+- * Either way, inform the owner and attempt
+- * recovery.
+- *
+- */
+-#ifdef LOG_UNKNOWN_TLV
+- purple_debug_misc("oscar", "userinfo: **warning: unexpected TLV:\n");
+- purple_debug_misc("oscar", "userinfo: bn =%s\n", outinfo->bn);
+- dumptlv(od, type, bs, length);
+-#endif
+- }
+-
+- /* Save ourselves. */
+- byte_stream_setpos(bs, endpos);
+- }
+-
+- aim_locate_adduserinfo(od, outinfo);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0001
+- */
+-static int
+-error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_snac_t *snac2;
+- guint16 reason;
+- char *bn;
+-
+- snac2 = aim_remsnac(od, snac->id);
+- if (!snac2) {
+- purple_debug_misc("oscar", "locate error: received response from unknown request!\n");
+- return 0;
+- }
+-
+- if ((snac2->family != SNAC_FAMILY_LOCATE) && (snac2->type != 0x0015)) {
+- purple_debug_misc("oscar", "locate error: received response from invalid request! %d\n", snac2->family);
+- g_free(snac2->data);
+- g_free(snac2);
+- return 0;
+- }
+-
+- bn = snac2->data;
+- if (!bn) {
+- purple_debug_misc("oscar", "locate error: received response from request without a buddy name!\n");
+- g_free(snac2);
+- return 0;
+- }
+-
+- reason = byte_stream_get16(bs);
+-
+- oscar_user_info_display_error(od, reason, bn);
+-
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- return 1;
+-}
+-
+-/*
+- * Subtype 0x0002
+- *
+- * Request Location services rights.
+- *
+- */
+-int
+-aim_locate_reqrights(OscarData *od)
+-{
+- FlapConnection *conn;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
+- return -EINVAL;
+-
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_REQRIGHTS);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0003
+- *
+- * Normally contains:
+- * t(0001) - short containing max profile length (value = 1024)
+- * t(0002) - short - unknown (value = 16) [max MIME type length?]
+- * t(0003) - short - unknown (value = 10)
+- * t(0004) - short - unknown (value = 2048) [ICQ only?]
+- */
+-static int
+-rights(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- GSList *tlvlist;
+- aim_rxcallback_t userfunc;
+- int ret = 0;
+- guint16 maxsiglen = 0;
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x0001, 1))
+- maxsiglen = aim_tlv_get16(tlvlist, 0x0001, 1);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, maxsiglen);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0004
+- *
+- * Gives BOS your profile.
+- *
+- * profile_encoding and awaymsg_encoding MUST be set if profile or
+- * away are set, respectively, and their value may or may not be
+- * restricted to a few choices. I am currently aware of:
+- *
+- * us-ascii Just that
+- * unicode-2-0 UTF-16BE
+- *
+- * profile_len and awaymsg_len MUST be set similarly, and they MUST
+- * be the length of their respective strings in bytes.
+- *
+- * To get the previous behavior of awaymsg == "" un-setting the away
+- * message, set awaymsg non-NULL and awaymsg_len to 0 (this is the
+- * obvious equivalent).
+- *
+- */
+-int
+-aim_locate_setprofile(OscarData *od,
+- const char *profile_encoding, const gchar *profile, const int profile_len,
+- const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+- char *encoding;
+- static const char defencoding[] = {"text/aolrtf; charset=\"%s\""};
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
+- return -EINVAL;
+-
+- if (!profile && !awaymsg)
+- return -EINVAL;
+-
+- if ((profile && profile_encoding == NULL) || (awaymsg && awaymsg_len && awaymsg_encoding == NULL)) {
+- return -EINVAL;
+- }
+-
+- /* Build the packet first to get real length */
+- if (profile) {
+- /* 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(&tlvlist, 0x0001, encoding);
+- aim_tlvlist_add_raw(&tlvlist, 0x0002, profile_len, (const guchar *)profile);
+- g_free(encoding);
+- }
+-
+- /*
+- * So here's how this works:
+- * - You are away when you have a non-zero-length type 4 TLV stored.
+- * - You become unaway when you clear the TLV with a zero-length
+- * type 4 TLV.
+- * - If you do not send the type 4 TLV, your status does not change
+- * (that is, if you were away, you'll remain away).
+- */
+- if (awaymsg) {
+- if (awaymsg_len) {
+- encoding = g_malloc(strlen(defencoding) + strlen(awaymsg_encoding));
+- snprintf(encoding, strlen(defencoding) + strlen(awaymsg_encoding), defencoding, awaymsg_encoding);
+- 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(&tlvlist, 0x0004);
+- }
+-
+- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0004 - Set your client's capabilities.
+- */
+-int
+-aim_locate_setcaps(OscarData *od, guint64 caps)
+-{
+- FlapConnection *conn;
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- PurplePresence *presence = purple_account_get_presence(account);
+- PurpleStatus *status = purple_presence_get_status(presence, "mood");
+- const char *mood = purple_status_get_attr_string(status, PURPLE_MOOD_NAME);
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)))
+- return -EINVAL;
+-
+- aim_tlvlist_add_caps(&tlvlist, 0x0005, caps, mood);
+-
+- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0004, 0x0000, NULL, 0);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_LOCATE, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/* Subtype 0x0006 */
+-static int
+-userinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_userinfo_t *userinfo, *userinfo2;
+- GSList *tlvlist;
+- aim_tlv_t *tlv = NULL;
+-
+- userinfo = (aim_userinfo_t *)g_malloc(sizeof(aim_userinfo_t));
+- aim_info_extract(od, bs, userinfo);
+- tlvlist = aim_tlvlist_read(bs);
+-
+- /* Profile will be 1 and 2 */
+- userinfo->info_encoding = aim_tlv_getstr(tlvlist, 0x0001, 1);
+- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0002, 1))) {
+- userinfo->info = (char *)g_malloc(tlv->length);
+- memcpy(userinfo->info, tlv->value, tlv->length);
+- userinfo->info_len = tlv->length;
+- }
+-
+- /* Away message will be 3 and 4 */
+- userinfo->away_encoding = aim_tlv_getstr(tlvlist, 0x0003, 1);
+- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0004, 1))) {
+- userinfo->away = (char *)g_malloc(tlv->length);
+- memcpy(userinfo->away, tlv->value, tlv->length);
+- userinfo->away_len = tlv->length;
+- }
+-
+- /* Caps will be 5 */
+- if ((tlv = aim_tlv_gettlv(tlvlist, 0x0005, 1))) {
+- ByteStream cbs;
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- const char *mood;
+-
+- byte_stream_init(&cbs, tlv->value, tlv->length);
+- userinfo->capabilities = aim_locate_getcaps(od, &cbs, tlv->length);
+- byte_stream_rewind(&cbs);
+- userinfo->present = AIM_USERINFO_PRESENT_CAPABILITIES;
+-
+- mood = aim_receive_custom_icon(od, &cbs, tlv->length);
+- if (mood)
+- purple_prpl_got_user_status(account, userinfo->bn, "mood",
+- PURPLE_MOOD_NAME, mood,
+- NULL);
+- else
+- purple_prpl_got_user_status_deactive(account, userinfo->bn, "mood");
+- }
+- aim_tlvlist_free(tlvlist);
+-
+- aim_locate_adduserinfo(od, userinfo);
+- userinfo2 = aim_locate_finduserinfo(od, userinfo->bn);
+- aim_info_free(userinfo);
+- g_free(userinfo);
+-
+- /* Show the info to the user */
+- oscar_user_info_display_aim(od, userinfo2);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0015 - Request the info of a user using the short method. This is
+- * what iChat uses. It normally is VERY leniently rate limited.
+- *
+- * @param bn The buddy name whose info you wish to request.
+- * @param flags The bitmask which specifies the type of info you wish to request.
+- * 0x00000001 - Info/profile.
+- * 0x00000002 - Away message.
+- * 0x00000004 - Capabilities.
+- * 0x00000008 - Certification.
+- * @return Return 0 if no errors, otherwise return the error number.
+- */
+-int
+-aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_LOCATE)) || !bn)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 4 + 1 + strlen(bn));
+- byte_stream_put32(&bs, flags);
+- byte_stream_put8(&bs, strlen(bn));
+- byte_stream_putstr(&bs, bn);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_LOCATE, 0x0015, 0x0000, bn, strlen(bn)+1);
+- flap_connection_send_snac_with_priority(od, conn, SNAC_FAMILY_LOCATE, 0x0015, snacid, &bs, FALSE);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return error(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0003)
+- return rights(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0006)
+- return userinfo(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-static void
+-locate_shutdown(OscarData *od, aim_module_t *mod)
+-{
+- aim_userinfo_t *del;
+-
+- while (od->locate.userinfo) {
+- del = od->locate.userinfo;
+- od->locate.userinfo = od->locate.userinfo->next;
+- aim_info_free(del);
+- g_free(del);
+- }
+-}
+-
+-int
+-locate_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_LOCATE;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "locate", sizeof(mod->name));
+- mod->snachandler = snachandler;
+- mod->shutdown = locate_shutdown;
+-
+- return 0;
+-}
+-
+-const char*
+-icq_get_custom_icon_description(const char *mood)
+-{
+- int i;
+-
+- if (!(mood && *mood))
+- return NULL;
+-
+- for (i = 0; icq_custom_icons[i].mood; i++) {
+- /* We check that description is not NULL to exclude
+- * duplicates, like the typing duplicate. */
+- if (icq_purple_moods[i].description &&
+- !strcmp(mood, icq_custom_icons[i].mood)) {
+- return icq_purple_moods[i].description;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-guint8*
+-icq_get_custom_icon_data(const char *mood)
+-{
+- int i;
+-
+- if (!(mood && *mood))
+- return NULL;
+-
+- for (i = 0; icq_custom_icons[i].mood; i++) {
+- /* We check that description is not NULL to exclude
+- * duplicates, like the typing duplicate. */
+- if (icq_purple_moods[i].description &&
+- !strcmp(mood, icq_custom_icons[i].mood)) {
+- return (guint8 *)icq_custom_icons[i].data;
+- }
+- }
+- return NULL;
+-}
+-
+-PurpleMood*
+-icq_get_purple_moods(PurpleAccount *account)
+-{
+- return icq_purple_moods;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_oservice.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_oservice.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_oservice.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_oservice.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1132 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0001 - This is a very special group. All connections support
+- * this group, as it does some particularly good things (like rate limiting).
+- */
+-
+-#include "oscar.h"
+-
+-#include "cipher.h"
+-
+-/*
+- * Each time we make a FLAP connection to an oscar server the server gives
+- * us a list of rate classes. Each rate class has different properties for
+- * how frequently we can send SNACs in that rate class before we become
+- * throttled or disconnected.
+- *
+- * The server also gives us a list of every available SNAC and tells us which
+- * rate class it's in. There are a lot of different SNACs, so this list can be
+- * fairly large. One important characteristic of these rate classes is that
+- * currently (and since at least 2004) most SNACs are in the same rate class.
+- *
+- * One optimization we can do to save memory is to only keep track of SNACs
+- * that are in classes other than this default rate class. So if we try to
+- * look up a SNAC and it's not in our hash table then we can assume that it's
+- * in the default rate class.
+- */
+-#define OSCAR_DEFAULT_RATECLASS 1
+-
+-/* Subtype 0x0002 - Client Online */
+-void
+-aim_srv_clientready(OscarData *od, FlapConnection *conn)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *cur;
+-
+- byte_stream_new(&bs, 1142);
+-
+- /*
+- * Send only the tool versions that the server cares about (that it
+- * marked as supporting in the server ready SNAC).
+- */
+- for (cur = conn->groups; cur != NULL; cur = cur->next)
+- {
+- aim_module_t *mod;
+-
+- if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
+- {
+- byte_stream_put16(&bs, mod->family);
+- byte_stream_put16(&bs, mod->version);
+- byte_stream_put16(&bs, mod->toolid);
+- byte_stream_put16(&bs, mod->toolversion);
+- }
+- }
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0002, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/*
+- * Subtype 0x0003 - Host Online
+- *
+- * See comments in conn.c about how the group associations are supposed
+- * to work, and how they really work.
+- *
+- * This info probably doesn't even need to make it to the client.
+- *
+- * We don't actually call the client here. This starts off the connection
+- * initialization routine required by all AIM connections. The next time
+- * the client is called is the CONNINITDONE callback, which should be
+- * shortly after the rate information is acknowledged.
+- *
+- */
+-static int
+-hostonline(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int group;
+-
+- while (byte_stream_bytes_left(bs))
+- {
+- group = byte_stream_get16(bs);
+- conn->groups = g_slist_prepend(conn->groups, GUINT_TO_POINTER(group));
+- }
+-
+- /*
+- * Next step is in the Host Versions handler.
+- *
+- * Note that we must send this before we request rates, since
+- * the format of the rate information depends on the versions we
+- * give it.
+- *
+- */
+- aim_srv_setversions(od, conn);
+-
+- return 1;
+-}
+-
+-/* Subtype 0x0004 - Service request */
+-void
+-aim_srv_requestnew(OscarData *od, guint16 serviceid)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
+- if(!conn)
+- return;
+-
+- byte_stream_new(&bs, 6);
+-
+- byte_stream_put16(&bs, serviceid);
+-
+- if (od->use_ssl)
+- /* Request SSL Connection */
+- aim_tlvlist_add_noval(&tlvlist, 0x008c);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/*
+- * Join a room of name roomname. This is the first step to joining an
+- * already created room. It's basically a Service Request for
+- * family 0x000e, with a little added on to specify the exchange and room
+- * name.
+- */
+-int
+-aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+- struct chatsnacinfo csi;
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
+- if (!conn || !roomname || roomname[0] == '\0')
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 506);
+-
+- memset(&csi, 0, sizeof(csi));
+- csi.exchange = exchange;
+- g_strlcpy(csi.name, roomname, sizeof(csi.name));
+- csi.instance = instance;
+-
+- /*
+- * Requesting service chat (0x000e)
+- */
+- byte_stream_put16(&bs, 0x000e);
+-
+- aim_tlvlist_add_chatroom(&tlvlist, 0x0001, exchange, roomname, instance);
+-
+- if (od->use_ssl)
+- /* Request SSL Connection */
+- aim_tlvlist_add_noval(&tlvlist, 0x008c);
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0004, 0x0000, &csi, sizeof(csi));
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0004, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/* Subtype 0x0005 - Redirect */
+-static int
+-redirect(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- struct aim_redirect_data redir;
+- aim_rxcallback_t userfunc;
+- GSList *tlvlist;
+- aim_snac_t *origsnac = NULL;
+- int ret = 0;
+-
+- memset(&redir, 0, sizeof(redir));
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- if (!aim_tlv_gettlv(tlvlist, 0x000d, 1) ||
+- !aim_tlv_gettlv(tlvlist, 0x0005, 1) ||
+- !aim_tlv_gettlv(tlvlist, 0x0006, 1)) {
+- aim_tlvlist_free(tlvlist);
+- return 0;
+- }
+-
+- redir.group = aim_tlv_get16(tlvlist, 0x000d, 1);
+- redir.ip = aim_tlv_getstr(tlvlist, 0x0005, 1);
+- redir.cookielen = aim_tlv_gettlv(tlvlist, 0x0006, 1)->length;
+- redir.cookie = (guchar *)aim_tlv_getstr(tlvlist, 0x0006, 1);
+- redir.ssl_cert_cn = aim_tlv_getstr(tlvlist, 0x008d, 1);
+- redir.use_ssl = aim_tlv_get8(tlvlist, 0x008e, 1);
+-
+- /* Fetch original SNAC so we can get csi if needed */
+- origsnac = aim_remsnac(od, snac->id);
+-
+- if ((redir.group == SNAC_FAMILY_CHAT) && origsnac) {
+- struct chatsnacinfo *csi = (struct chatsnacinfo *)origsnac->data;
+-
+- redir.chat.exchange = csi->exchange;
+- redir.chat.room = csi->name;
+- redir.chat.instance = csi->instance;
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, &redir);
+-
+- g_free((void *)redir.ip);
+- g_free((void *)redir.cookie);
+- g_free((void *)redir.ssl_cert_cn);
+-
+- if (origsnac)
+- g_free(origsnac->data);
+- g_free(origsnac);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x0006 - Request Rate Information. */
+-void
+-aim_srv_reqrates(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x0006);
+-}
+-
+-/*
+- * OSCAR defines several 'rate classes'. Each class has separate
+- * rate limiting properties (limit level, alert level, disconnect
+- * level, etc), and a set of SNAC family/type pairs associated with
+- * it. The rate classes, their limiting properties, and the definitions
+- * of which SNACs belong to which class are defined in the
+- * Rate Response packet at login to each host.
+- *
+- * Logically, all rate offenses within one class count against further
+- * offenses for other SNACs in the same class (ie, sending messages
+- * too fast will limit the number of user info requests you can send,
+- * since those two SNACs are in the same rate class).
+- *
+- * Since the rate classes are defined dynamically at login, the values
+- * below may change. But they seem to be fairly constant.
+- *
+- * Currently, BOS defines five rate classes, with the commonly used
+- * members as follows...
+- *
+- * Rate class 0x0001:
+- * - Everything thats not in any of the other classes
+- *
+- * Rate class 0x0002:
+- * - Buddy list add/remove
+- * - Permit list add/remove
+- * - Deny list add/remove
+- *
+- * Rate class 0x0003:
+- * - User information requests
+- * - Outgoing ICBMs
+- *
+- * Rate class 0x0004:
+- * - A few unknowns: 2/9, 2/b, and f/2
+- *
+- * Rate class 0x0005:
+- * - Chat room create
+- * - Outgoing chat ICBMs
+- *
+- * The only other thing of note is that class 5 (chat) has slightly looser
+- * limiting properties than class 3 (normal messages). But thats just a
+- * small bit of trivia for you.
+- *
+- * The last thing that needs to be learned about the rate limiting
+- * system is how the actual numbers relate to the passing of time. This
+- * seems to be a big mystery.
+- *
+- * See joscar's javadoc for the RateClassInfo class for a great
+- * explanation. You might be able to find it at
+- * http://dscoder.com/RateClassInfo.html
+- */
+-
+-static struct rateclass *
+-rateclass_find(GSList *rateclasses, guint16 id)
+-{
+- GSList *tmp;
+-
+- for (tmp = rateclasses; tmp != NULL; tmp = tmp->next)
+- {
+- struct rateclass *rateclass;
+- rateclass = tmp->data;
+- if (rateclass->classid == id)
+- return rateclass;
+- }
+-
+- return NULL;
+-}
+-
+-/* Subtype 0x0007 - Rate Parameters */
+-static int
+-rateresp(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- guint16 numclasses, i;
+- aim_rxcallback_t userfunc;
+-
+- /*
+- * First are the parameters for each rate class.
+- */
+- numclasses = byte_stream_get16(bs);
+- for (i = 0; i < numclasses; i++)
+- {
+- struct rateclass *rateclass;
+- guint32 delta;
+- struct timeval now;
+-
+- gettimeofday(&now, NULL);
+- rateclass = g_new(struct rateclass, 1);
+-
+- rateclass->classid = byte_stream_get16(bs);
+- rateclass->windowsize = byte_stream_get32(bs);
+- rateclass->clear = byte_stream_get32(bs);
+- rateclass->alert = byte_stream_get32(bs);
+- rateclass->limit = byte_stream_get32(bs);
+- rateclass->disconnect = byte_stream_get32(bs);
+- rateclass->current = byte_stream_get32(bs);
+- rateclass->max = byte_stream_get32(bs);
+- if (mod->version >= 3) {
+- delta = byte_stream_get32(bs);
+- rateclass->dropping_snacs = byte_stream_get8(bs);
+- } else {
+- delta = 0;
+- rateclass->dropping_snacs = 0;
+- }
+-
+- rateclass->last.tv_sec = now.tv_sec - delta / 1000;
+- rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000;
+-
+- conn->rateclasses = g_slist_prepend(conn->rateclasses, rateclass);
+-
+- if (rateclass->classid == OSCAR_DEFAULT_RATECLASS)
+- conn->default_rateclass = rateclass;
+- }
+- conn->rateclasses = g_slist_reverse(conn->rateclasses);
+-
+- /*
+- * Then the members of each class.
+- */
+- for (i = 0; i < numclasses; i++)
+- {
+- guint16 classid, count;
+- struct rateclass *rateclass;
+- int j;
+-
+- classid = byte_stream_get16(bs);
+- count = byte_stream_get16(bs);
+-
+- if (classid == OSCAR_DEFAULT_RATECLASS) {
+- /*
+- * Don't bother adding these SNACs to the hash table. See the
+- * comment for OSCAR_DEFAULT_RATECLASS at the top of this file.
+- */
+- byte_stream_advance(bs, 4 * count);
+- continue;
+- }
+-
+- rateclass = rateclass_find(conn->rateclasses, classid);
+-
+- for (j = 0; j < count; j++)
+- {
+- guint16 group, subtype;
+-
+- group = byte_stream_get16(bs);
+- subtype = byte_stream_get16(bs);
+-
+- if (rateclass != NULL)
+- g_hash_table_insert(conn->rateclass_members,
+- GUINT_TO_POINTER((group << 16) + subtype),
+- rateclass);
+- }
+- }
+-
+- /*
+- * We don't pass the rate information up to the client, as it really
+- * doesn't care. The information is stored in the connection, however
+- * so that we can do rate limiting management when sending SNACs.
+- */
+-
+- /*
+- * Subscribe to rate change information for all rate classes.
+- */
+- aim_srv_rates_addparam(od, conn);
+-
+- /*
+- * Finally, tell the client it's ready to go...
+- */
+- if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE)))
+- userfunc(od, conn, frame);
+-
+- return 1;
+-}
+-
+-/* Subtype 0x0008 - Add Rate Parameter */
+-void
+-aim_srv_rates_addparam(OscarData *od, FlapConnection *conn)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tmp;
+-
+- byte_stream_new(&bs, 502);
+-
+- for (tmp = conn->rateclasses; tmp != NULL; tmp = tmp->next)
+- {
+- struct rateclass *rateclass;
+- rateclass = tmp->data;
+- byte_stream_put16(&bs, rateclass->classid);
+- }
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0008, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0008, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/* Subtype 0x000a - Rate Change */
+-static int
+-ratechange(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- guint16 code, classid;
+- struct rateclass *rateclass;
+- guint32 delta;
+- struct timeval now;
+- static const char *codes[5] = {
+- "invalid",
+- "change",
+- "warning",
+- "limit",
+- "limit cleared",
+- };
+-
+- gettimeofday(&now, NULL);
+- code = byte_stream_get16(bs);
+- classid = byte_stream_get16(bs);
+-
+- rateclass = rateclass_find(conn->rateclasses, classid);
+- if (rateclass == NULL)
+- /* This should never really happen */
+- return 0;
+-
+- rateclass->windowsize = byte_stream_get32(bs);
+- rateclass->clear = byte_stream_get32(bs);
+- rateclass->alert = byte_stream_get32(bs);
+- rateclass->limit = byte_stream_get32(bs);
+- rateclass->disconnect = byte_stream_get32(bs);
+- rateclass->current = byte_stream_get32(bs);
+- rateclass->max = byte_stream_get32(bs);
+- if (mod->version >= 3) {
+- delta = byte_stream_get32(bs);
+- rateclass->dropping_snacs = byte_stream_get8(bs);
+- } else {
+- delta = 0;
+- rateclass->dropping_snacs = 0;
+- }
+-
+- rateclass->last.tv_sec = now.tv_sec - delta / 1000;
+- rateclass->last.tv_usec = now.tv_usec - (delta % 1000) * 1000;
+-
+- purple_debug_misc("oscar", "rate %s (param ID 0x%04hx): curavg = %u, "
+- "maxavg = %u, alert at %u, clear warning at %u, limit at %u, "
+- "disconnect at %u, delta is %u, dropping is %u (window size = %u)\n",
+- (code < 5) ? codes[code] : codes[0], rateclass->classid,
+- rateclass->current, rateclass->max, rateclass->alert,
+- rateclass->clear, rateclass->limit, rateclass->disconnect,
+- delta, rateclass->dropping_snacs, rateclass->windowsize);
+-
+- if (code == AIM_RATE_CODE_LIMIT) {
+- purple_debug_warning("oscar", "The last action you attempted "
+- "could not be performed because you are over the rate "
+- "limit. Please wait 10 seconds and try again.\n");
+- }
+-
+- return 1;
+-}
+-
+-/*
+- * How Migrations work.
+- *
+- * The server sends a Server Pause message, which the client should respond to
+- * with a Server Pause Ack, which contains the families it needs on this
+- * connection. The server will send a Migration Notice with an IP address, and
+- * then disconnect. Next the client should open the connection and send the
+- * cookie. Repeat the normal login process and pretend this never happened.
+- *
+- * The Server Pause contains no data.
+- *
+- */
+-
+-/* Subtype 0x000b - Service Pause */
+-static int
+-serverpause(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x000d - Service Resume */
+-static int
+-serverresume(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x000e - Request self-info */
+-void
+-aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn)
+-{
+- aim_genericreq_n_snacid(od, conn, SNAC_FAMILY_OSERVICE, 0x000e);
+-}
+-
+-/* Subtype 0x000f - Self User Info */
+-static int
+-selfinfo(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- aim_userinfo_t userinfo;
+-
+- aim_info_extract(od, bs, &userinfo);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, &userinfo);
+-
+- aim_info_free(&userinfo);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x0010 - Evil Notification */
+-static int
+-evilnotify(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 newevil;
+- aim_userinfo_t userinfo;
+-
+- memset(&userinfo, 0, sizeof(aim_userinfo_t));
+-
+- newevil = byte_stream_get16(bs);
+-
+- if (byte_stream_bytes_left(bs))
+- aim_info_extract(od, bs, &userinfo);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, newevil, &userinfo);
+-
+- aim_info_free(&userinfo);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0011 - Idle Notification
+- *
+- * Should set your current idle time in seconds. Note that this should
+- * never be called consecutively with a non-zero idle time. That makes
+- * OSCAR do funny things. Instead, just set it once you go idle, and then
+- * call it again with zero when you're back.
+- *
+- */
+-void
+-aim_srv_setidle(OscarData *od, guint32 idletime)
+-{
+- FlapConnection *conn;
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_BOS);
+- if(!conn)
+- return;
+-
+- aim_genericreq_l(od, conn, SNAC_FAMILY_OSERVICE, 0x0011, &idletime);
+-}
+-
+-/*
+- * Subtype 0x0012 - Service Migrate
+- *
+- * This is the final SNAC sent on the original connection during a migration.
+- * It contains the IP and cookie used to connect to the new server, and
+- * optionally a list of the SNAC groups being migrated.
+- *
+- */
+-static int
+-migrate(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- int ret = 0;
+- guint16 groupcount, i;
+- GSList *tlvlist;
+- char *ip = NULL;
+- aim_tlv_t *cktlv;
+-
+- /*
+- * Apparently there's some fun stuff that can happen right here. The
+- * migration can actually be quite selective about what groups it
+- * moves to the new server. When not all the groups for a connection
+- * are migrated, or they are all migrated but some groups are moved
+- * to a different server than others, it is called a bifurcated
+- * migration.
+- *
+- * Let's play dumb and not support that.
+- *
+- */
+- groupcount = byte_stream_get16(bs);
+- for (i = 0; i < groupcount; i++) {
+- guint16 group;
+-
+- group = byte_stream_get16(bs);
+-
+- purple_debug_misc("oscar", "bifurcated migration unsupported -- group 0x%04x\n", group);
+- }
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x0005, 1))
+- ip = aim_tlv_getstr(tlvlist, 0x0005, 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(tlvlist);
+- g_free(ip);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x0013 - Message of the Day */
+-static int
+-motd(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- char *msg = NULL;
+- int ret = 0;
+- GSList *tlvlist;
+- guint16 id;
+-
+- /*
+- * Code.
+- *
+- * Valid values:
+- * 1 Mandatory upgrade
+- * 2 Advisory upgrade
+- * 3 System bulletin
+- * 4 Nothing's wrong ("top o the world" -- normal)
+- * 5 Lets-break-something.
+- *
+- */
+- id = byte_stream_get16(bs);
+-
+- /*
+- * TLVs follow
+- */
+- tlvlist = aim_tlvlist_read(bs);
+-
+- msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, id, msg);
+-
+- g_free(msg);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0017 - Set client versions
+- *
+- * If you've seen the clientonline/clientready SNAC you're probably
+- * wondering what the point of this one is. And that point seems to be
+- * that the versions in the client online SNAC are sent too late for the
+- * server to be able to use them to change the protocol for the earlier
+- * login packets (client versions are sent right after Host Online is
+- * received, but client online versions aren't sent until quite a bit later).
+- * We can see them already making use of this by changing the format of
+- * the rate information based on what version of group 1 we advertise here.
+- *
+- */
+-void
+-aim_srv_setversions(OscarData *od, FlapConnection *conn)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *cur;
+-
+- byte_stream_new(&bs, 1142);
+-
+- /*
+- * Send only the versions that the server cares about (that it
+- * marked as supporting in the server ready SNAC).
+- */
+- for (cur = conn->groups; cur != NULL; cur = cur->next)
+- {
+- aim_module_t *mod;
+-
+- if ((mod = aim__findmodulebygroup(od, GPOINTER_TO_UINT(cur->data))))
+- {
+- byte_stream_put16(&bs, mod->family);
+- byte_stream_put16(&bs, mod->version);
+- }
+- }
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0017, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0017, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/* Subtype 0x0018 - Host versions */
+-static int
+-hostversions(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int vercount;
+- guint8 *versions;
+-
+- /* This is frivolous. (Thank you SmarterChild.) */
+- vercount = byte_stream_bytes_left(bs)/4;
+- versions = byte_stream_getraw(bs, byte_stream_bytes_left(bs));
+- g_free(versions);
+-
+- /*
+- * Now request rates.
+- */
+- aim_srv_reqrates(od, conn);
+-
+- return 1;
+-}
+-
+-/**
+- * Subtype 0x001e - Extended Status/Extra Info.
+- *
+- * These settings are transient, not server-stored (i.e. they only
+- * apply to this session, and must be re-set the next time you sign
+- * on).
+- *
+- * You can set your ICQ status (available, away, do not disturb,
+- * etc.), or whether your IP address should be hidden or not, or
+- * if your status is visible on ICQ web sites, and you can set
+- * your IP address info and what not.
+- *
+- * You can also set your "available" message. This is currently
+- * only supported by iChat, Purple and other 3rd party clients.
+- *
+- * These are the same TLVs seen in user info. You can
+- * also set 0x0008 and 0x000c.
+- */
+-int
+-aim_srv_setextrainfo(OscarData *od,
+- gboolean seticqstatus, guint32 icqstatus,
+- gboolean setstatusmsg, const char *statusmsg, const char *itmsurl)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- if (!od || !(conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM)))
+- return -EINVAL;
+-
+- if (seticqstatus)
+- {
+- aim_tlvlist_add_32(&tlvlist, 0x0006, icqstatus |
+- AIM_ICQ_STATE_HIDEIP | AIM_ICQ_STATE_DIRECTREQUIREAUTH);
+- }
+-
+- if (setstatusmsg)
+- {
+- size_t statusmsglen, itmsurllen;
+- ByteStream tmpbs;
+-
+- statusmsglen = (statusmsg != NULL) ? strlen(statusmsg) : 0;
+- itmsurllen = (itmsurl != NULL) ? strlen(itmsurl) : 0;
+-
+- byte_stream_new(&tmpbs, statusmsglen + 8 + itmsurllen + 8);
+- byte_stream_put_bart_asset_str(&tmpbs, 0x0002, statusmsg);
+- byte_stream_put_bart_asset_str(&tmpbs, 0x0009, itmsurl);
+-
+- aim_tlvlist_add_raw(&tlvlist, 0x001d,
+- byte_stream_curpos(&tmpbs), tmpbs.data);
+- byte_stream_destroy(&tmpbs);
+- }
+-
+- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
+-
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x001e, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/* Send dummy DC (direct connect) information to the server.
+- * Direct connect is ICQ's counterpart for AIM's DirectIM,
+- * as far as I can tell. Anyway, we don't support it;
+- * the reason to send this packet is that some clients
+- * (Miranda, QIP) won't send us channel 2 ICBM messages
+- * unless we specify DC version >= 8.
+- *
+- * See #12044 for more information.
+- */
+-void
+-aim_srv_set_dc_info(OscarData *od)
+-{
+- ByteStream bs, tlv0c;
+- aim_snacid_t snacid;
+- GSList *tlvlist = NULL;
+-
+- /* http://iserverd.khstu.ru/oscar/snac_01_1e.html has a nice analysis of what goes in 0xc tlv.
+- * Kopete sends a dummy DC info, too, so I just copied the values from them.
+- */
+- byte_stream_new(&tlv0c, 4*2 + 1 + 2 + 4*6 + 2);
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put8(&tlv0c, 0x0); /* We don't support DC */
+- byte_stream_put16(&tlv0c, 8); /* DC version */
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put32(&tlv0c, 0x50);
+- byte_stream_put32(&tlv0c, 0x3);
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put32(&tlv0c, 0x0);
+- byte_stream_put16(&tlv0c, 0x0);
+- aim_tlvlist_add_raw(&tlvlist, 0x000c, byte_stream_curpos(&tlv0c), tlv0c.data);
+- byte_stream_destroy(&tlv0c);
+-
+- byte_stream_new(&bs, aim_tlvlist_size(tlvlist));
+- aim_tlvlist_write(&bs, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x001e, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, flap_connection_findbygroup(od, SNAC_FAMILY_ICBM), SNAC_FAMILY_OSERVICE, 0x001e, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Starting this past week (26 Mar 2001, say), AOL has started sending
+- * this nice little extra SNAC. AFAIK, it has never been used until now.
+- *
+- * The request contains eight bytes. The first four are an offset, the
+- * second four are a length.
+- *
+- * The offset is an offset into aim.exe when it is mapped during execution
+- * on Win32. So far, AOL has only been requesting bytes in static regions
+- * of memory. (I won't put it past them to start requesting data in
+- * less static regions -- regions that are initialized at run time, but still
+- * before the client receives this request.)
+- *
+- * When the client receives the request, it adds it to the current ds
+- * (0x00400000) and dereferences it, copying the data into a buffer which
+- * it then runs directly through the MD5 hasher. The 16 byte output of
+- * the hash is then sent back to the server.
+- *
+- * If the client does not send any data back, or the data does not match
+- * the data that the specific client should have, the client will get the
+- * following message from "AOL Instant Messenger":
+- * "You have been disconnected from the AOL Instant Message Service (SM)
+- * for accessing the AOL network using unauthorized software. You can
+- * download a FREE, fully featured, and authorized client, here
+- * http://www.aol.com/aim/download2.html"
+- * The connection is then closed, receiving disconnect code 1, URL
+- * http://www.aim.aol.com/errors/USER_LOGGED_OFF_NEW_LOGIN.html.
+- *
+- * Note, however, that numerous inconsistencies can cause the above error,
+- * not just sending back a bad hash. Do not immediatly suspect this code
+- * if you get disconnected. AOL and the open/free software community have
+- * played this game for a couple years now, generating the above message
+- * on numerous ocassions.
+- *
+- * Anyway, neener. We win again.
+- *
+- */
+-/* Subtype 0x001f - Client verification */
+-static int
+-memrequest(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint32 offset, len;
+- GSList *tlvlist;
+- char *modname;
+-
+- offset = byte_stream_get32(bs);
+- len = byte_stream_get32(bs);
+- tlvlist = aim_tlvlist_read(bs);
+-
+- modname = aim_tlv_getstr(tlvlist, 0x0001, 1);
+-
+- purple_debug_info("oscar", "Got memory request for data at 0x%08x (%u bytes) of requested %s\n", offset, len, modname ? modname : "aim.exe");
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, offset, len, modname);
+-
+- g_free(modname);
+- aim_tlvlist_free(tlvlist);
+-
+- return ret;
+-}
+-
+-/* Subtype 0x0020 - Client verification reply */
+-int
+-aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!od || !conn)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, 2+16);
+-
+- byte_stream_put16(&bs, 0x0010); /* md5 is always 16 bytes */
+-
+- if ((flag == AIM_SENDMEMBLOCK_FLAG_ISHASH) && buf && (len == 0x10)) { /* we're getting a hash */
+-
+- byte_stream_putraw(&bs, buf, 0x10);
+-
+- } else if (buf && (len > 0)) { /* use input buffer */
+- PurpleCipherContext *context;
+- guchar digest[16];
+-
+- context = purple_cipher_context_new_by_name("md5", NULL);
+- purple_cipher_context_append(context, buf, len);
+- purple_cipher_context_digest(context, 16, digest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- byte_stream_putraw(&bs, digest, 0x10);
+-
+- } else if (len == 0) { /* no length, just hash NULL (buf is optional) */
+- PurpleCipherContext *context;
+- guchar digest[16];
+- guint8 nil = '\0';
+-
+- /*
+- * I'm not sure if we really need the empty append with the
+- * new MD5 functions, so I'll leave it in, just in case.
+- */
+- context = purple_cipher_context_new_by_name("md5", NULL);
+- purple_cipher_context_append(context, &nil, 0);
+- purple_cipher_context_digest(context, 16, digest, NULL);
+- purple_cipher_context_destroy(context);
+-
+- byte_stream_putraw(&bs, digest, 0x10);
+-
+- } else {
+-
+- /*
+- * This data is correct for AIM 3.5.1670.
+- *
+- * Using these blocks is as close to "legal" as you can get
+- * without using an AIM binary.
+- *
+- */
+- if ((offset == 0x03ffffff) && (len == 0x03ffffff)) {
+-
+-#if 1 /* with "AnrbnrAqhfzcd" */
+- byte_stream_put32(&bs, 0x44a95d26);
+- byte_stream_put32(&bs, 0xd2490423);
+- byte_stream_put32(&bs, 0x93b8821f);
+- byte_stream_put32(&bs, 0x51c54b01);
+-#else /* no filename */
+- byte_stream_put32(&bs, 0x1df8cbae);
+- byte_stream_put32(&bs, 0x5523b839);
+- byte_stream_put32(&bs, 0xa0e10db3);
+- byte_stream_put32(&bs, 0xa46d3b39);
+-#endif
+-
+- } else
+- purple_debug_warning("oscar", "sendmemblock: unknown hash request\n");
+-
+- }
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_OSERVICE, 0x0020, 0x0000, NULL, 0);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_OSERVICE, 0x0020, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0021 - Receive our extended status
+- *
+- * This is used for iChat's "available" messages, and maybe ICQ extended
+- * status messages? It's also used to tell the client whether or not it
+- * needs to upload an SSI buddy icon... who engineers this stuff, anyway?
+- */
+-static int
+-aim_parse_extstatus(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- guint16 type = byte_stream_get16(bs);
+- if (type == 0x0000 || type == 0x0001) {
+- /* buddy icon checksum */
+- /* not sure what the difference between 1 and 0 is */
+- guint8 flags = byte_stream_get8(bs);
+- guint8 length = byte_stream_get8(bs);
+- guint8 *md5 = byte_stream_getraw(bs, length);
+-
+- if ((flags == 0x00) || (flags == 0x41)) {
+- if (!flap_connection_getbytype(od, SNAC_FAMILY_BART) && !od->iconconnecting) {
+- od->iconconnecting = TRUE;
+- od->set_icon = TRUE;
+- aim_srv_requestnew(od, SNAC_FAMILY_BART);
+- } else {
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
+- if (img == NULL) {
+- aim_ssi_delicon(od);
+- } else {
+-
+- purple_debug_info("oscar",
+- "Uploading icon to icon server\n");
+- aim_bart_upload(od, purple_imgstore_get_data(img),
+- purple_imgstore_get_size(img));
+- purple_imgstore_unref(img);
+- }
+- }
+- } else if (flags == 0x81) {
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
+- if (img == NULL)
+- aim_ssi_delicon(od);
+- else {
+- aim_ssi_seticon(od, md5, length);
+- purple_imgstore_unref(img);
+- }
+- }
+-
+- g_free(md5);
+- }
+-
+- return 0;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0003)
+- return hostonline(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0005)
+- return redirect(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0007)
+- return rateresp(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000a)
+- return ratechange(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000b)
+- return serverpause(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000d)
+- return serverresume(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x000f)
+- return selfinfo(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0010)
+- return evilnotify(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0012)
+- return migrate(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0013)
+- return motd(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0018)
+- return hostversions(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x001f)
+- return memrequest(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0021)
+- return aim_parse_extstatus(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int service_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_OSERVICE;
+- mod->version = 0x0003;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "oservice", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_popup.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_popup.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_popup.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_popup.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,84 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x0008 - Popups.
+- *
+- * Popups are just what it sounds like. They're a way for the server to
+- * open up an informative box on the client's screen.
+- */
+-
+-#include <oscar.h>
+-
+-/*
+- * This is all there is to it.
+- *
+- * The message is probably HTML.
+- *
+- */
+-static int
+-parsepopup(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- aim_rxcallback_t userfunc;
+- GSList *tlvlist;
+- int ret = 0;
+- char *msg, *url;
+- guint16 width, height, delay;
+-
+- tlvlist = aim_tlvlist_read(bs);
+-
+- 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(tlvlist);
+- g_free(msg);
+- g_free(url);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0002)
+- return parsepopup(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-popups_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_POPUP;
+- mod->version = 0x0001;
+- mod->toolid = 0x0104;
+- mod->toolversion = 0x0001;
+- mod->flags = 0;
+- strncpy(mod->name, "popup", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_stats.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_stats.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_stats.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_stats.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,64 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x000b - Statistics.
+- *
+- */
+-
+-#include <oscar.h>
+-
+-static int
+-reportinterval(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- guint16 interval;
+-
+- interval = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, interval);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0002)
+- return reportinterval(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-stats_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_STATS;
+- mod->version = 0x0001;
+- mod->toolid = 0x0104;
+- mod->toolversion = 0x0001;
+- mod->flags = 0;
+- strncpy(mod->name, "stats", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/family_userlookup.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_userlookup.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/family_userlookup.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/family_userlookup.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,157 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Family 0x000a - User Search.
+- *
+- * TODO: Add aim_usersearch_name()
+- *
+- */
+-
+-#include "oscar.h"
+-
+-/*
+- * Subtype 0x0001
+- *
+- * XXX can this be integrated with the rest of the error handling?
+- */
+-static int error(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- aim_rxcallback_t userfunc;
+- aim_snac_t *snac2;
+-
+- /* XXX the modules interface should have already retrieved this for us */
+- if (!(snac2 = aim_remsnac(od, snac->id))) {
+- purple_debug_misc("oscar", "search error: couldn't get a snac for 0x%08x\n", snac->id);
+- return 0;
+- }
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, snac2->data /* address */);
+-
+- /* XXX freesnac()? */
+- if (snac2)
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- return ret;
+-}
+-
+-/*
+- * Subtype 0x0002
+- *
+- */
+-int aim_search_address(OscarData *od, const char *address)
+-{
+- FlapConnection *conn;
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- conn = flap_connection_findbygroup(od, SNAC_FAMILY_USERLOOKUP);
+-
+- if (!conn || !address)
+- return -EINVAL;
+-
+- byte_stream_new(&bs, strlen(address));
+-
+- byte_stream_putstr(&bs, address);
+-
+- snacid = aim_cachesnac(od, SNAC_FAMILY_USERLOOKUP, 0x0002, 0x0000, address, strlen(address)+1);
+- flap_connection_send_snac(od, conn, SNAC_FAMILY_USERLOOKUP, 0x0002, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-
+- return 0;
+-}
+-
+-/*
+- * Subtype 0x0003
+- *
+- */
+-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;
+- GSList *tlvlist;
+- char *cur = NULL, *buf = NULL;
+- aim_rxcallback_t userfunc;
+- aim_snac_t *snac2;
+- const char *searchaddr = NULL;
+-
+- if ((snac2 = aim_remsnac(od, snac->id)))
+- searchaddr = (const char *)snac2->data;
+-
+- tlvlist = aim_tlvlist_read(bs);
+- m = aim_tlvlist_count(tlvlist);
+-
+- /* XXX uhm.
+- * This is the only place that uses something other than 1 for the 3rd
+- * parameter to aim_tlv_gettlv_whatever().
+- */
+- while ((cur = aim_tlv_getstr(tlvlist, 0x0001, j+1)) && j < m)
+- {
+- buf = g_realloc(buf, (j+1) * (MAXSNLEN+1));
+-
+- strncpy(&buf[j * (MAXSNLEN+1)], cur, MAXSNLEN);
+- g_free(cur);
+-
+- j++;
+- }
+- g_free(cur);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, searchaddr, j, buf);
+-
+- /* XXX freesnac()? */
+- if (snac2)
+- g_free(snac2->data);
+- g_free(snac2);
+-
+- g_free(buf);
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return error(od, conn, mod, frame, snac, bs);
+- else if (snac->subtype == 0x0003)
+- return reply(od, conn, mod, frame, snac, bs);
+-
+- return 0;
+-}
+-
+-int
+-search_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = SNAC_FAMILY_USERLOOKUP;
+- mod->version = 0x0001;
+- mod->toolid = 0x0110;
+- mod->toolversion = 0x0629;
+- mod->flags = 0;
+- strncpy(mod->name, "userlookup", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/flap_connection.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/flap_connection.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/flap_connection.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/flap_connection.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1127 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "oscar.h"
+-
+-#include "eventloop.h"
+-#include "proxy.h"
+-
+-#ifndef _WIN32
+-#include <netdb.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#endif
+-
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#endif
+-
+-/**
+- * This sends a channel 1 SNAC containing the FLAP version.
+- * The FLAP version is sent by itself at the beginning of every
+- * connection to a FLAP server. It is always the very first
+- * packet sent by both the server and the client after the SYN,
+- * SYN/ACK, ACK handshake.
+- */
+-void
+-flap_connection_send_version(OscarData *od, FlapConnection *conn)
+-{
+- FlapFrame *frame;
+-
+- frame = flap_frame_new(od, 0x01, 4);
+- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
+- flap_connection_send(conn, frame);
+-}
+-
+-/**
+- * This sends a channel 1 FLAP containing the FLAP version and
+- * the authentication cookie. This is sent when connecting to
+- * any FLAP server after the initial connection to the auth
+- * server. It is always the very first packet sent by both the
+- * server and the client after the SYN, SYN/ACK, ACK handshake.
+- */
+-void
+-flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy)
+-{
+- FlapFrame *frame;
+- GSList *tlvlist = NULL;
+-
+- frame = flap_frame_new(od, 0x01, 4 + 2 + 2 + length);
+- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
+- aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
+- aim_tlvlist_write(&frame->data, &tlvlist);
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send(conn, frame);
+-}
+-
+-void
+-flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_logins)
+-{
+- FlapFrame *frame;
+- GSList *tlvlist = NULL;
+-
+- frame = flap_frame_new(od, 0x01, 1152 + length);
+-
+- byte_stream_put32(&frame->data, 0x00000001); /* FLAP Version */
+- aim_tlvlist_add_raw(&tlvlist, 0x0006, length, chipsahoy);
+-
+- if (ci->clientstring != NULL)
+- aim_tlvlist_add_str(&tlvlist, 0x0003, ci->clientstring);
+- else {
+- gchar *clientstring = oscar_get_clientstring();
+- aim_tlvlist_add_str(&tlvlist, 0x0003, clientstring);
+- g_free(clientstring);
+- }
+- 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_8(&tlvlist, 0x004a, (allow_multiple_logins ? 0x01 : 0x03));
+-
+- aim_tlvlist_write(&frame->data, &tlvlist);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- flap_connection_send(conn, frame);
+-}
+-
+-static struct rateclass *
+-flap_connection_get_rateclass(FlapConnection *conn, guint16 family, guint16 subtype)
+-{
+- gconstpointer key;
+- gpointer rateclass;
+-
+- key = GUINT_TO_POINTER((family << 16) + subtype);
+- rateclass = g_hash_table_lookup(conn->rateclass_members, key);
+- if (rateclass != NULL)
+- return rateclass;
+-
+- return conn->default_rateclass;
+-}
+-
+-/*
+- * Attempt to calculate what our new current average would be if we
+- * were to send a SNAC in this rateclass at the given time.
+- */
+-static guint32
+-rateclass_get_new_current(FlapConnection *conn, struct rateclass *rateclass, struct timeval *now)
+-{
+- unsigned long timediff; /* In milliseconds */
+- guint32 current;
+-
+- /* This formula is documented at http://dev.aol.com/aim/oscar/#RATELIMIT */
+- timediff = (now->tv_sec - rateclass->last.tv_sec) * 1000 + (now->tv_usec - rateclass->last.tv_usec) / 1000;
+- current = ((rateclass->current * (rateclass->windowsize - 1)) + timediff) / rateclass->windowsize;
+-
+- return MIN(current, rateclass->max);
+-}
+-
+-/*
+- * Attempt to send the contents of a given queue
+- *
+- * @return TRUE if the queue was completely emptied or was initially
+- * empty; FALSE if rate limiting prevented it from being
+- * emptied.
+- */
+-static gboolean flap_connection_send_snac_queue(FlapConnection *conn, struct timeval now, GQueue *queue)
+-{
+- while (!g_queue_is_empty(queue))
+- {
+- QueuedSnac *queued_snac;
+- struct rateclass *rateclass;
+-
+- queued_snac = g_queue_peek_head(queue);
+-
+- rateclass = flap_connection_get_rateclass(conn, queued_snac->family, queued_snac->subtype);
+- if (rateclass != NULL)
+- {
+- guint32 new_current;
+-
+- new_current = rateclass_get_new_current(conn, rateclass, &now);
+-
+- if (rateclass->dropping_snacs || new_current <= rateclass->alert)
+- /* Not ready to send this SNAC yet--keep waiting. */
+- return FALSE;
+-
+- rateclass->current = new_current;
+- rateclass->last.tv_sec = now.tv_sec;
+- rateclass->last.tv_usec = now.tv_usec;
+- }
+-
+- flap_connection_send(conn, queued_snac->frame);
+- g_free(queued_snac);
+- g_queue_pop_head(queue);
+- }
+-
+- /* We emptied the queue */
+- return TRUE;
+-}
+-
+-static gboolean flap_connection_send_queued(gpointer data)
+-{
+- FlapConnection *conn;
+- struct timeval now;
+-
+- conn = data;
+- gettimeofday(&now, NULL);
+-
+- purple_debug_info("oscar", "Attempting to send %u queued SNACs and %u queued low-priority SNACs for %p\n",
+- (conn->queued_snacs ? conn->queued_snacs->length : 0),
+- (conn->queued_lowpriority_snacs ? conn->queued_lowpriority_snacs->length : 0),
+- conn);
+- if (!conn->queued_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_snacs)) {
+- if (!conn->queued_lowpriority_snacs || flap_connection_send_snac_queue(conn, now, conn->queued_lowpriority_snacs)) {
+- /* Both queues emptied. */
+- conn->queued_timeout = 0;
+- return FALSE;
+- }
+- }
+-
+- /* We couldn't send all our SNACs. Keep trying */
+- return TRUE;
+-}
+-
+-/**
+- * This sends a channel 2 FLAP containing a SNAC. The SNAC family and
+- * subtype are looked up in the rate info for this connection, and if
+- * sending this SNAC will induce rate limiting then we delay sending
+- * of the SNAC by putting it into an outgoing holding queue.
+- *
+- * @param data The optional bytestream that makes up the data portion
+- * of this SNAC. For empty SNACs this should be NULL.
+- * @param high_priority If TRUE, the SNAC will be queued normally if
+- * needed. If FALSE, it will be queued separately, to be sent
+- * only if all high priority SNACs have been sent.
+- */
+-void
+-flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data, gboolean high_priority)
+-{
+- FlapFrame *frame;
+- guint32 length;
+- gboolean enqueue = FALSE;
+- struct rateclass *rateclass;
+-
+- length = data != NULL ? data->offset : 0;
+-
+- frame = flap_frame_new(od, 0x02, 10 + length);
+- aim_putsnac(&frame->data, family, subtype, snacid);
+-
+- if (length > 0)
+- {
+- byte_stream_rewind(data);
+- byte_stream_putbs(&frame->data, data, length);
+- }
+-
+- if (conn->queued_timeout != 0)
+- enqueue = TRUE;
+- else if ((rateclass = flap_connection_get_rateclass(conn, family, subtype)) != NULL)
+- {
+- struct timeval now;
+- guint32 new_current;
+-
+- gettimeofday(&now, NULL);
+- new_current = rateclass_get_new_current(conn, rateclass, &now);
+-
+- if (rateclass->dropping_snacs || new_current <= rateclass->alert)
+- {
+- purple_debug_info("oscar", "Current rate for conn %p would be %u, but we alert at %u; enqueueing\n", conn, new_current, rateclass->alert);
+-
+- enqueue = TRUE;
+- }
+- else
+- {
+- rateclass->current = new_current;
+- rateclass->last.tv_sec = now.tv_sec;
+- rateclass->last.tv_usec = now.tv_usec;
+- }
+- }
+-
+- if (enqueue)
+- {
+- /* We've been sending too fast, so delay this message */
+- QueuedSnac *queued_snac;
+-
+- queued_snac = g_new(QueuedSnac, 1);
+- queued_snac->family = family;
+- queued_snac->subtype = subtype;
+- queued_snac->frame = frame;
+-
+- if (high_priority) {
+- if (!conn->queued_snacs)
+- conn->queued_snacs = g_queue_new();
+- g_queue_push_tail(conn->queued_snacs, queued_snac);
+- } else {
+- if (!conn->queued_lowpriority_snacs)
+- conn->queued_lowpriority_snacs = g_queue_new();
+- g_queue_push_tail(conn->queued_lowpriority_snacs, queued_snac);
+- }
+-
+- if (conn->queued_timeout == 0)
+- conn->queued_timeout = purple_timeout_add(500, flap_connection_send_queued, conn);
+-
+- return;
+- }
+-
+- flap_connection_send(conn, frame);
+-}
+-
+-void
+-flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data)
+-{
+- flap_connection_send_snac_with_priority(od, conn, family, subtype, snacid, data, TRUE);
+-}
+-
+-/**
+- * This sends an empty channel 4 FLAP. This is sent to signify
+- * that we're logging off. This shouldn't really be necessary--
+- * usually the AIM server will detect that the TCP connection has
+- * been destroyed--but it's good practice.
+- */
+-static void
+-flap_connection_send_close(OscarData *od, FlapConnection *conn)
+-{
+- FlapFrame *frame;
+-
+- frame = flap_frame_new(od, 0x04, 0);
+- flap_connection_send(conn, frame);
+-}
+-
+-/**
+- * This sends an empty channel 5 FLAP. This is used as a keepalive
+- * packet in FLAP connections. WinAIM 4.x and higher send these
+- * _every minute_ to keep the connection alive.
+- */
+-void
+-flap_connection_send_keepalive(OscarData *od, FlapConnection *conn)
+-{
+- FlapFrame *frame;
+-
+- frame = flap_frame_new(od, 0x05, 0);
+- flap_connection_send(conn, frame);
+-
+- /* clean out SNACs over 60sec old */
+- aim_cleansnacs(od, 60);
+-}
+-
+-/**
+- * Allocate a new empty connection structure.
+- *
+- * @param od The oscar session associated with this connection.
+- * @param type Type of connection to create
+- *
+- * @return Returns the new connection structure.
+- */
+-FlapConnection *
+-flap_connection_new(OscarData *od, int type)
+-{
+- FlapConnection *conn;
+-
+- conn = g_new0(FlapConnection, 1);
+- conn->od = od;
+- conn->buffer_outgoing = purple_circ_buffer_new(0);
+- conn->fd = -1;
+- conn->subtype = -1;
+- conn->type = type;
+- conn->rateclass_members = g_hash_table_new(g_direct_hash, g_direct_equal);
+-
+- od->oscar_connections = g_slist_prepend(od->oscar_connections, conn);
+-
+- return conn;
+-}
+-
+-/**
+- * Close (but not free) a connection.
+- *
+- * This cancels any currently pending connection attempt,
+- * closes any open fd and frees the auth cookie.
+- *
+- * @param conn The connection to close.
+- */
+-void
+-flap_connection_close(OscarData *od, FlapConnection *conn)
+-{
+- if (conn->connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(conn->connect_data);
+- conn->connect_data = NULL;
+- }
+-
+- if (conn->gsc != NULL && conn->gsc->connect_data != NULL)
+- {
+- purple_ssl_close(conn->gsc);
+- conn->gsc = NULL;
+- }
+-
+- if (conn->new_conn_data != NULL)
+- {
+- if (conn->type == SNAC_FAMILY_CHAT)
+- {
+- oscar_chat_destroy(conn->new_conn_data);
+- conn->new_conn_data = NULL;
+- }
+- }
+-
+- if ((conn->fd >= 0 || conn->gsc != NULL)
+- && conn->type == SNAC_FAMILY_LOCATE)
+- flap_connection_send_close(od, conn);
+-
+- if (conn->watcher_incoming != 0)
+- {
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+- }
+-
+- if (conn->watcher_outgoing != 0)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- }
+-
+- if (conn->fd >= 0)
+- {
+- close(conn->fd);
+- conn->fd = -1;
+- }
+-
+- if (conn->gsc != NULL)
+- {
+- purple_ssl_close(conn->gsc);
+- conn->gsc = NULL;
+- }
+-
+- g_free(conn->buffer_incoming.data.data);
+- conn->buffer_incoming.data.data = NULL;
+-
+- purple_circ_buffer_destroy(conn->buffer_outgoing);
+- conn->buffer_outgoing = NULL;
+-}
+-
+-/**
+- * Free a FlapFrame
+- *
+- * @param frame The frame to free.
+- */
+-static void
+-flap_frame_destroy(FlapFrame *frame)
+-{
+- g_free(frame->data.data);
+- g_free(frame);
+-}
+-
+-static gboolean
+-flap_connection_destroy_cb(gpointer data)
+-{
+- FlapConnection *conn;
+- OscarData *od;
+- PurpleAccount *account;
+- aim_rxcallback_t userfunc;
+-
+- conn = data;
+- /* Explicitly added for debugging #5927. Don't re-order this, only
+- * consider removing it.
+- */
+- purple_debug_info("oscar", "Destroying FLAP connection %p\n", conn);
+-
+- od = conn->od;
+- account = purple_connection_get_account(od->gc);
+-
+- purple_debug_info("oscar", "Destroying oscar connection (%p) of "
+- "type 0x%04hx. Disconnect reason is %d\n", conn,
+- conn->type, conn->disconnect_reason);
+-
+- od->oscar_connections = g_slist_remove(od->oscar_connections, conn);
+-
+- if ((userfunc = aim_callhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR)))
+- userfunc(od, conn, NULL, conn->disconnect_code, conn->error_message);
+-
+- /*
+- * TODO: If we don't have a SNAC_FAMILY_LOCATE connection then
+- * we should try to request one instead of disconnecting.
+- */
+- if (!account->disconnecting && ((od->oscar_connections == NULL)
+- || (!flap_connection_getbytype(od, SNAC_FAMILY_LOCATE))))
+- {
+- /* No more FLAP connections! Sign off this PurpleConnection! */
+- gchar *tmp;
+- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+-
+- if (conn->disconnect_code == 0x0001) {
+- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
+- tmp = g_strdup(_("You have signed on from another location"));
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- } else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)
+- tmp = g_strdup(_("Server closed the connection"));
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)
+- tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- conn->error_message);
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)
+- tmp = g_strdup(_("Received invalid data on connection with server"));
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)
+- tmp = g_strdup_printf(_("Unable to connect: %s"),
+- conn->error_message);
+- else
+- /*
+- * We shouldn't print a message for some disconnect_reasons.
+- * Like OSCAR_DISCONNECT_LOCAL_CLOSED.
+- */
+- tmp = NULL;
+-
+- if (tmp != NULL)
+- {
+- purple_connection_error_reason(od->gc, reason, tmp);
+- g_free(tmp);
+- }
+- }
+-
+- flap_connection_close(od, conn);
+-
+- g_free(conn->error_message);
+- g_free(conn->cookie);
+-
+- /*
+- * Free conn->internal, if necessary
+- */
+- if (conn->type == SNAC_FAMILY_CHAT)
+- flap_connection_destroy_chat(od, conn);
+-
+- g_slist_free(conn->groups);
+- while (conn->rateclasses != NULL)
+- {
+- g_free(conn->rateclasses->data);
+- conn->rateclasses = g_slist_delete_link(conn->rateclasses, conn->rateclasses);
+- }
+-
+- g_hash_table_destroy(conn->rateclass_members);
+-
+- if (conn->queued_snacs) {
+- while (!g_queue_is_empty(conn->queued_snacs))
+- {
+- QueuedSnac *queued_snac;
+- queued_snac = g_queue_pop_head(conn->queued_snacs);
+- flap_frame_destroy(queued_snac->frame);
+- g_free(queued_snac);
+- }
+- g_queue_free(conn->queued_snacs);
+- }
+-
+- if (conn->queued_lowpriority_snacs) {
+- while (!g_queue_is_empty(conn->queued_lowpriority_snacs))
+- {
+- QueuedSnac *queued_snac;
+- queued_snac = g_queue_pop_head(conn->queued_lowpriority_snacs);
+- flap_frame_destroy(queued_snac->frame);
+- g_free(queued_snac);
+- }
+- g_queue_free(conn->queued_lowpriority_snacs);
+- }
+-
+- if (conn->queued_timeout > 0)
+- purple_timeout_remove(conn->queued_timeout);
+-
+- g_free(conn);
+-
+- return FALSE;
+-}
+-
+-/**
+- * See the comments for the parameters of
+- * flap_connection_schedule_destroy().
+- */
+-void
+-flap_connection_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
+-{
+- if (conn->destroy_timeout != 0)
+- purple_timeout_remove(conn->destroy_timeout);
+- conn->disconnect_reason = reason;
+- g_free(conn->error_message);
+- conn->error_message = g_strdup(error_message);
+- flap_connection_destroy_cb(conn);
+-}
+-
+-/**
+- * Schedule Purple to destroy the given FlapConnection as soon as we
+- * return control back to the program's main loop. We must do this
+- * if we want to destroy the connection but we are still using it
+- * for some reason.
+- *
+- * @param reason The reason for the disconnection.
+- * @param error_message A brief error message that gives more detail
+- * regarding the reason for the disconnecting. This should
+- * be NULL for everything except OSCAR_DISCONNECT_LOST_CONNECTION,
+- * in which case it should contain the value of g_strerror(errno),
+- * and OSCAR_DISCONNECT_COULD_NOT_CONNECT, in which case it
+- * should contain the error_message passed back from the call
+- * to purple_proxy_connect().
+- */
+-void
+-flap_connection_schedule_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
+-{
+- if (conn->destroy_timeout != 0)
+- /* Already taken care of */
+- return;
+-
+- purple_debug_info("oscar", "Scheduling destruction of FLAP "
+- "connection %p of type 0x%04hx\n", conn, conn->type);
+- conn->disconnect_reason = reason;
+- g_free(conn->error_message);
+- conn->error_message = g_strdup(error_message);
+- conn->destroy_timeout = purple_timeout_add(0, flap_connection_destroy_cb, conn);
+-}
+-
+-/**
+- * In OSCAR, every connection has a set of SNAC groups associated
+- * with it. These are the groups that you can send over this connection
+- * without being guaranteed a "Not supported" SNAC error.
+- *
+- * The grand theory of things says that these associations transcend
+- * what libfaim calls "connection types" (conn->type). You can probably
+- * see the elegance here, but since I want to revel in it for a bit, you
+- * get to hear it all spelled out.
+- *
+- * So let us say that you have your core BOS connection running. One
+- * of your modules has just given you a SNAC of the group 0x0004 to send
+- * you. Maybe an IM destined for some twit in Greenland. So you start
+- * at the top of your connection list, looking for a connection that
+- * claims to support group 0x0004. You find one. Why, that neat BOS
+- * connection of yours can do that. So you send it on its way.
+- *
+- * Now, say, that fellow from Greenland has friends and they all want to
+- * meet up with you in a lame chat room. This has landed you a SNAC
+- * in the family 0x000e and you have to admit you're a bit lost. You've
+- * searched your connection list for someone who wants to make your life
+- * easy and deliver this SNAC for you, but there isn't one there.
+- *
+- * Here comes the good bit. Without even letting anyone know, particularly
+- * the module that decided to send this SNAC, and definitely not that twit
+- * in Greenland, you send out a service request. In this request, you have
+- * marked the need for a connection supporting group 0x000e. A few seconds
+- * later, you receive a service redirect with an IP address and a cookie in
+- * it. Great, you say. Now I have something to do. Off you go, making
+- * that connection. One of the first things you get from this new server
+- * is a message saying that indeed it does support the group you were looking
+- * for. So you continue and send rate confirmation and all that.
+- *
+- * Then you remember you had that SNAC to send, and now you have a means to
+- * do it, and you do, and everyone is happy. Except the Greenlander, who is
+- * still stuck in the bitter cold.
+- *
+- * Oh, and this is useful for building the Migration SNACs, too. In the
+- * future, this may help convince me to implement rate limit mitigation
+- * for real. We'll see.
+- *
+- * Just to make me look better, I'll say that I've known about this great
+- * scheme for quite some time now. But I still haven't convinced myself
+- * to make libfaim work that way. It would take a fair amount of effort,
+- * and probably some client API changes as well. (Whenever I don't want
+- * to do something, I just say it would change the client API. Then I
+- * instantly have a couple of supporters of not doing it.)
+- *
+- * Generally, addgroup is only called by the internal handling of the
+- * server ready SNAC. So if you want to do something before that, you'll
+- * have to be more creative. That is done rather early, though, so I don't
+- * think you have to worry about it. Unless you're me. I care deeply
+- * about such inane things.
+- *
+- */
+-
+-/**
+- * Find a FlapConnection that supports the given oscar
+- * family.
+- */
+-FlapConnection *
+-flap_connection_findbygroup(OscarData *od, guint16 group)
+-{
+- GSList *cur;
+-
+- for (cur = od->oscar_connections; cur != NULL; cur = cur->next)
+- {
+- FlapConnection *conn;
+- GSList *l;
+-
+- conn = cur->data;
+-
+- for (l = conn->groups; l != NULL; l = l->next)
+- {
+- if (GPOINTER_TO_UINT(l->data) == group)
+- return conn;
+- }
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Locates a connection of the specified type in the
+- * specified session.
+- *
+- * TODO: Use flap_connection_findbygroup everywhere and get rid of this.
+- *
+- * @param od The session to search.
+- * @param type The type of connection to look for.
+- *
+- * @return Returns the first connection found of the given target type,
+- * or NULL if none could be found.
+- */
+-FlapConnection *
+-flap_connection_getbytype(OscarData *od, int type)
+-{
+- GSList *cur;
+-
+- for (cur = od->oscar_connections; cur != NULL; cur = cur->next)
+- {
+- FlapConnection *conn;
+- conn = cur->data;
+- if ((conn->type == type) && (conn->connected))
+- return conn;
+- }
+-
+- return NULL;
+-}
+-
+-FlapConnection *
+-flap_connection_getbytype_all(OscarData *od, int type)
+-{
+- GSList *cur;
+-
+- for (cur = od->oscar_connections; cur; cur = cur->next)
+- {
+- FlapConnection *conn;
+- conn = cur->data;
+- if (conn->type == type)
+- return conn;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Allocate a new FLAP frame.
+- *
+- * @param channel The FLAP channel. This is almost always 2.
+- */
+-FlapFrame *
+-flap_frame_new(OscarData *od, guint16 channel, int datalen)
+-{
+- FlapFrame *frame;
+-
+- frame = g_new0(FlapFrame, 1);
+- frame->channel = channel;
+-
+- if (datalen > 0)
+- byte_stream_new(&frame->data, datalen);
+-
+- return frame;
+-}
+-
+-static void
+-parse_snac(OscarData *od, FlapConnection *conn, FlapFrame *frame)
+-{
+- aim_module_t *cur;
+- aim_modsnac_t snac;
+-
+- if (byte_stream_bytes_left(&frame->data) < 10)
+- return;
+-
+- snac.family = byte_stream_get16(&frame->data);
+- snac.subtype = byte_stream_get16(&frame->data);
+- snac.flags = byte_stream_get16(&frame->data);
+- snac.id = byte_stream_get32(&frame->data);
+-
+- /* SNAC flags are apparently uniform across all SNACs, so we handle them here */
+- if (snac.flags & 0x0001) {
+- /*
+- * This means the SNAC will be followed by another SNAC with
+- * related information. We don't need to do anything about
+- * this here.
+- */
+- }
+- if (snac.flags & 0x8000) {
+- /*
+- * This packet contains the version of the family that this SNAC is
+- * in. You get this when your SSI module is version 2 or higher.
+- * For now we have no need for this, but you could always save
+- * it as a part of aim_modnsac_t, or something. The format is...
+- * 2 byte length of total mini-header (which is 6 bytes), then TLV
+- * of type 0x0001, length 0x0002, value is the 2 byte version
+- * number
+- */
+- byte_stream_advance(&frame->data, byte_stream_get16(&frame->data));
+- }
+-
+- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
+-
+- if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
+- (cur->family != snac.family))
+- continue;
+-
+- if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data))
+- return;
+- }
+-}
+-
+-static void
+-parse_fakesnac(OscarData *od, FlapConnection *conn, FlapFrame *frame, guint16 family, guint16 subtype)
+-{
+- aim_module_t *cur;
+- aim_modsnac_t snac;
+-
+- snac.family = family;
+- snac.subtype = subtype;
+- snac.flags = snac.id = 0;
+-
+- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
+-
+- if (!(cur->flags & AIM_MODFLAG_MULTIFAMILY) &&
+- (cur->family != snac.family))
+- continue;
+-
+- if (cur->snachandler(od, conn, cur, frame, &snac, &frame->data))
+- return;
+- }
+-}
+-
+-static void
+-parse_flap_ch4(OscarData *od, FlapConnection *conn, FlapFrame *frame)
+-{
+- GSList *tlvlist;
+- char *msg = NULL;
+-
+- if (byte_stream_bytes_left(&frame->data) == 0) {
+- /* XXX should do something with this */
+- return;
+- }
+-
+- /* An ICQ account is logging in */
+- if (conn->type == SNAC_FAMILY_AUTH)
+- {
+- parse_fakesnac(od, conn, frame, 0x0017, 0x0003);
+- return;
+- }
+-
+- tlvlist = aim_tlvlist_read(&frame->data);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x0009, 1))
+- conn->disconnect_code = aim_tlv_get16(tlvlist, 0x0009, 1);
+-
+- if (aim_tlv_gettlv(tlvlist, 0x000b, 1))
+- msg = aim_tlv_getstr(tlvlist, 0x000b, 1);
+-
+- /*
+- * The server ended this FLAP connnection, so let's be nice and
+- * close the physical TCP connection
+- */
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_REMOTE_CLOSED, msg);
+-
+- aim_tlvlist_free(tlvlist);
+-
+- g_free(msg);
+-}
+-
+-/**
+- * Takes a new incoming FLAP frame and sends it to the appropriate
+- * handler function to be parsed.
+- */
+-static void
+-parse_flap(OscarData *od, FlapConnection *conn, FlapFrame *frame)
+-{
+- if (frame->channel == 0x01) {
+- guint32 flap_version = byte_stream_get32(&frame->data);
+- if (flap_version != 0x00000001)
+- {
+- /* Error! */
+- purple_debug_warning("oscar", "Expecting FLAP version "
+- "0x00000001 but received FLAP version %08x. Closing connection.\n",
+- flap_version);
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- }
+- else
+- conn->connected = TRUE;
+-
+- } else if (frame->channel == 0x02) {
+- parse_snac(od, conn, frame);
+-
+- } else if (frame->channel == 0x04) {
+- parse_flap_ch4(od, conn, frame);
+-
+- } else if (frame->channel == 0x05) {
+- /* TODO: Reset our keepalive watchdog? */
+-
+- }
+-}
+-
+-/**
+- * Read in all available data on the socket for a given connection.
+- * All complete FLAPs handled immedate after they're received.
+- * Incomplete FLAP data is stored locally and appended to the next
+- * time this callback is triggered.
+- *
+- * This is called by flap_connection_recv_cb and
+- * flap_connection_recv_cb_ssl for unencrypted/encrypted connections.
+- */
+-static void
+-flap_connection_recv(FlapConnection *conn)
+-{
+- gpointer buf;
+- gsize buflen;
+- gssize read;
+-
+- /* Read data until we run out of data and break out of the loop */
+- while (TRUE)
+- {
+- /* Start reading a new FLAP */
+- if (conn->buffer_incoming.data.data == NULL)
+- {
+- buf = conn->header + conn->header_received;
+- buflen = 6 - conn->header_received;
+-
+- /* Read the first 6 bytes (the FLAP header) */
+- if (conn->gsc)
+- read = purple_ssl_read(conn->gsc, buf, buflen);
+- else
+- read = recv(conn->fd, buf, buflen, 0);
+-
+- /* Check if the FLAP server closed the connection */
+- if (read == 0)
+- {
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- break;
+- }
+-
+- /* If there was an error then close the connection */
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- break;
+-
+- /* Error! */
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- break;
+- }
+- conn->od->gc->last_received = time(NULL);
+-
+- /* If we don't even have a complete FLAP header then do nothing */
+- conn->header_received += read;
+- if (conn->header_received < 6)
+- break;
+-
+- /* All FLAP frames must start with the byte 0x2a */
+- if (aimutil_get8(&conn->header[0]) != 0x2a)
+- {
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- break;
+- }
+-
+- /* Initialize a new temporary FlapFrame for incoming data */
+- conn->buffer_incoming.channel = aimutil_get8(&conn->header[1]);
+- conn->buffer_incoming.seqnum = aimutil_get16(&conn->header[2]);
+- conn->buffer_incoming.data.len = aimutil_get16(&conn->header[4]);
+- conn->buffer_incoming.data.data = g_new(guint8, conn->buffer_incoming.data.len);
+- conn->buffer_incoming.data.offset = 0;
+- }
+-
+- buflen = conn->buffer_incoming.data.len - conn->buffer_incoming.data.offset;
+- if (buflen)
+- {
+- buf = &conn->buffer_incoming.data.data[conn->buffer_incoming.data.offset];
+- /* Read data into the temporary FlapFrame until it is complete */
+- if (conn->gsc)
+- read = purple_ssl_read(conn->gsc, buf, buflen);
+- else
+- read = recv(conn->fd, buf, buflen, 0);
+-
+- /* Check if the FLAP server closed the connection */
+- if (read == 0)
+- {
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- break;
+- }
+-
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- break;
+-
+- /* Error! */
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- break;
+- }
+-
+- conn->buffer_incoming.data.offset += read;
+- if (conn->buffer_incoming.data.offset < conn->buffer_incoming.data.len)
+- /* Waiting for more data to arrive */
+- break;
+- }
+-
+- /* We have a complete FLAP! Handle it and continue reading */
+- byte_stream_rewind(&conn->buffer_incoming.data);
+- parse_flap(conn->od, conn, &conn->buffer_incoming);
+- conn->lastactivity = time(NULL);
+-
+- g_free(conn->buffer_incoming.data.data);
+- conn->buffer_incoming.data.data = NULL;
+-
+- conn->header_received = 0;
+- }
+-}
+-
+-void
+-flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- FlapConnection *conn = data;
+-
+- flap_connection_recv(conn);
+-}
+-
+-void
+-flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond)
+-{
+- FlapConnection *conn = data;
+-
+- flap_connection_recv(conn);
+-}
+-
+-/**
+- * @param source When this function is called as a callback source is
+- * set to the fd that triggered the callback. But this function
+- * is also called directly from flap_connection_send_byte_stream(),
+- * in which case source will be -1. So don't use source--use
+- * conn->gsc or conn->fd instead.
+- */
+-static void
+-send_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- FlapConnection *conn;
+- int writelen, ret;
+-
+- conn = data;
+- writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing);
+-
+- if (writelen == 0)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- return;
+- }
+-
+- if (conn->gsc)
+- ret = purple_ssl_write(conn->gsc, conn->buffer_outgoing->outptr,
+- writelen);
+- else
+- ret = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
+- if (ret <= 0)
+- {
+- if (ret < 0 && (errno == EAGAIN || errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- /* Error! */
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- if (conn->gsc) {
+- purple_ssl_close(conn->gsc);
+- conn->gsc = NULL;
+- } else {
+- close(conn->fd);
+- conn->fd = -1;
+- }
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(conn->buffer_outgoing, ret);
+-}
+-
+-static void
+-flap_connection_send_byte_stream(ByteStream *bs, FlapConnection *conn, size_t count)
+-{
+- if (conn == NULL)
+- return;
+-
+- /* Make sure we don't send past the end of the bs */
+- if (count > byte_stream_bytes_left(bs))
+- count = byte_stream_bytes_left(bs); /* truncate to remaining space */
+-
+- if (count == 0)
+- return;
+-
+- /* Add everything to our outgoing buffer */
+- 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)
+- {
+- if (conn->gsc) {
+- conn->watcher_outgoing = purple_input_add(conn->gsc->fd,
+- PURPLE_INPUT_WRITE, send_cb, conn);
+- send_cb(conn, -1, 0);
+- } else if (conn->fd >= 0) {
+- conn->watcher_outgoing = purple_input_add(conn->fd,
+- PURPLE_INPUT_WRITE, send_cb, conn);
+- send_cb(conn, -1, 0);
+- }
+- }
+-}
+-
+-static void
+-sendframe_flap(FlapConnection *conn, FlapFrame *frame)
+-{
+- ByteStream bs;
+- int payloadlen, bslen;
+-
+- payloadlen = byte_stream_curpos(&frame->data);
+-
+- byte_stream_new(&bs, 6 + payloadlen);
+-
+- /* FLAP header */
+- byte_stream_put8(&bs, 0x2a);
+- byte_stream_put8(&bs, frame->channel);
+- byte_stream_put16(&bs, frame->seqnum);
+- byte_stream_put16(&bs, payloadlen);
+-
+- /* Payload */
+- byte_stream_rewind(&frame->data);
+- byte_stream_putbs(&bs, &frame->data, payloadlen);
+-
+- bslen = byte_stream_curpos(&bs);
+- byte_stream_rewind(&bs);
+- flap_connection_send_byte_stream(&bs, conn, bslen);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-void
+-flap_connection_send(FlapConnection *conn, FlapFrame *frame)
+-{
+- frame->seqnum = ++(conn->seqnum_out);
+- sendframe_flap(conn, frame);
+- flap_frame_destroy(frame);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/libaim.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libaim.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/libaim.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libaim.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,151 +0,0 @@
+-/* 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/* libaim is the AIM protocol plugin. It is linked against liboscar,
+- * which contains all the shared implementation code with libicq
+- */
+-
+-#include "oscarcommon.h"
+-#include "oscar.h"
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+- oscar_list_icon_aim, /* list_icon */
+- oscar_list_emblem, /* list_emblems */
+- oscar_status_text, /* status_text */
+- oscar_tooltip_text, /* tooltip_text */
+- oscar_status_types, /* status_types */
+- oscar_blist_node_menu, /* blist_node_menu */
+- oscar_chat_info, /* chat_info */
+- oscar_chat_info_defaults, /* chat_info_defaults */
+- oscar_login, /* login */
+- oscar_close, /* close */
+- oscar_send_im, /* send_im */
+- oscar_set_info, /* set_info */
+- oscar_send_typing, /* send_typing */
+- oscar_get_info, /* get_info */
+- oscar_set_status, /* set_status */
+- oscar_set_idle, /* set_idle */
+- oscar_change_passwd, /* change_passwd */
+- NULL, /* add_buddy */
+- NULL, /* add_buddies */
+- oscar_remove_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- oscar_add_permit, /* add_permit */
+- oscar_add_deny, /* add_deny */
+- oscar_rem_permit, /* rem_permit */
+- oscar_rem_deny, /* rem_deny */
+- oscar_set_aim_permdeny, /* set_permit_deny */
+- oscar_join_chat, /* join_chat */
+- NULL, /* reject_chat */
+- oscar_get_chat_name, /* get_chat_name */
+- oscar_chat_invite, /* chat_invite */
+- oscar_chat_leave, /* chat_leave */
+- NULL, /* chat_whisper */
+- oscar_send_chat, /* chat_send */
+- oscar_keepalive, /* keepalive */
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- oscar_alias_buddy, /* alias_buddy */
+- oscar_move_buddy, /* group_buddy */
+- oscar_rename_group, /* rename_group */
+- NULL, /* buddy_free */
+- oscar_convo_closed, /* convo_closed */
+- oscar_normalize, /* normalize */
+- oscar_set_icon, /* set_buddy_icon */
+- oscar_remove_group, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- oscar_can_receive_file, /* can_receive_file */
+- oscar_send_file, /* send_file */
+- oscar_new_xfer, /* new_xfer */
+- oscar_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- NULL, /* send_attention */
+- NULL, /* get_attention_types */
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- NULL, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- oscar_add_buddy, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-aim", /**< id */
+- "AIM", /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("AIM Protocol Plugin"),
+- /** description */
+- N_("AIM Protocol Plugin"),
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+-
+- NULL, /**< load */
+- NULL, /**< unload */
+- NULL, /**< destroy */
+-
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL,
+- oscar_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- oscar_init(plugin, FALSE);
+-}
+-
+-PURPLE_INIT_PLUGIN(aim, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/libicq.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libicq.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/libicq.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/libicq.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,166 +0,0 @@
+-/* 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/* libicq is the ICQ protocol plugin. It is linked against liboscar,
+- * which contains all the shared implementation code with libaim
+- */
+-
+-
+-#include "oscarcommon.h"
+-
+-static GHashTable *
+-icq_get_account_text_table(PurpleAccount *account)
+-{
+- GHashTable *table;
+- table = g_hash_table_new(g_str_hash, g_str_equal);
+- g_hash_table_insert(table, "login_label", (gpointer)_("ICQ UIN..."));
+- return table;
+-}
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_MAIL_CHECK | OPT_PROTO_IM_IMAGE | OPT_PROTO_INVITE_MESSAGE,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"gif,jpeg,bmp,ico", 0, 0, 64, 64, 7168, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
+- oscar_list_icon_icq, /* list_icon */
+- oscar_list_emblem, /* list_emblems */
+- oscar_status_text, /* status_text */
+- oscar_tooltip_text, /* tooltip_text */
+- oscar_status_types, /* status_types */
+- oscar_blist_node_menu, /* blist_node_menu */
+- oscar_chat_info, /* chat_info */
+- oscar_chat_info_defaults, /* chat_info_defaults */
+- oscar_login, /* login */
+- oscar_close, /* close */
+- oscar_send_im, /* send_im */
+- oscar_set_info, /* set_info */
+- oscar_send_typing, /* send_typing */
+- oscar_get_info, /* get_info */
+- oscar_set_status, /* set_status */
+- oscar_set_idle, /* set_idle */
+- oscar_change_passwd, /* change_passwd */
+- NULL, /* add_buddy */
+- NULL, /* add_buddies */
+- oscar_remove_buddy, /* remove_buddy */
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- oscar_add_deny, /* add_deny */
+- NULL, /* rem_permit */
+- oscar_rem_deny, /* rem_deny */
+- NULL, /* set_permit_deny */
+- oscar_join_chat, /* join_chat */
+- NULL, /* reject_chat */
+- oscar_get_chat_name, /* get_chat_name */
+- oscar_chat_invite, /* chat_invite */
+- oscar_chat_leave, /* chat_leave */
+- NULL, /* chat_whisper */
+- oscar_send_chat, /* chat_send */
+- oscar_keepalive, /* keepalive */
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- oscar_alias_buddy, /* alias_buddy */
+- oscar_move_buddy, /* group_buddy */
+- oscar_rename_group, /* rename_group */
+- NULL, /* buddy_free */
+- oscar_convo_closed, /* convo_closed */
+- oscar_normalize, /* normalize */
+- oscar_set_icon, /* set_buddy_icon */
+- oscar_remove_group, /* remove_group */
+- NULL, /* get_cb_real_name */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- NULL, /* roomlist_get_list */
+- NULL, /* roomlist_cancel */
+- NULL, /* roomlist_expand_category */
+- oscar_can_receive_file, /* can_receive_file */
+- oscar_send_file, /* send_file */
+- oscar_new_xfer, /* new_xfer */
+- oscar_offline_message, /* offline_message */
+- NULL, /* whiteboard_prpl_ops */
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+- NULL, /* send_attention */
+- NULL, /* get_attention_types */
+-
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- icq_get_account_text_table, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* can_do_media */
+- oscar_get_purple_moods, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- oscar_add_buddy, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-icq", /**< id */
+- "ICQ", /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("ICQ Protocol Plugin"),
+- /** description */
+- N_("ICQ Protocol Plugin"),
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+-
+- NULL, /**< load */
+- NULL, /**< unload */
+- NULL, /**< destroy */
+-
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL,
+- oscar_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- PurpleAccountOption *option;
+-
+- oscar_init(plugin, TRUE);
+-
+- option = purple_account_option_string_new(_("Encoding"), "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-}
+-
+-PURPLE_INIT_PLUGIN(icq, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,81 +0,0 @@
+-EXTRA_DIST = \
+- COPYING \
+- AUTHORS \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-OSCARSOURCES = \
+- authorization.c \
+- bstream.c \
+- clientlogin.c \
+- encoding.c \
+- encoding.h \
+- family_admin.c \
+- family_alert.c \
+- family_auth.c \
+- family_bart.c \
+- family_bos.c \
+- family_buddy.c \
+- family_chat.c \
+- family_chatnav.c \
+- family_icq.c \
+- family_icbm.c \
+- family_locate.c \
+- family_oservice.c \
+- family_popup.c \
+- family_feedbag.c \
+- family_stats.c \
+- family_userlookup.c \
+- flap_connection.c \
+- misc.c \
+- msgcookie.c \
+- odc.c \
+- oft.c \
+- oscar.c \
+- oscar.h \
+- oscarcommon.h \
+- oscar_data.c \
+- peer.c \
+- peer.h \
+- peer_proxy.c \
+- rxhandlers.c \
+- snac.c \
+- snactypes.h \
+- tlv.c \
+- userinfo.c \
+- util.c \
+- visibility.c \
+- visibility.h
+-
+-AM_CFLAGS = $(st)
+-
+-libaim_la_LDFLAGS = -module -avoid-version
+-libicq_la_LDFLAGS = -module -avoid-version
+-if STATIC_OSCAR
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = liboscar.la
+-liboscar_la_SOURCES = $(OSCARSOURCES) libaim.c libicq.c
+-liboscar_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = liboscar.la libaim.la libicq.la
+-liboscar_la_SOURCES = $(OSCARSOURCES)
+-liboscar_la_LIBADD = $(GLIB_LIBS)
+-
+-libaim_la_SOURCES = libaim.c
+-libaim_la_LIBADD = liboscar.la
+-
+-libicq_la_SOURCES = libicq.c
+-libicq_la_LIBADD = liboscar.la
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1133 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/oscar
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in AUTHORS \
+- COPYING
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-@STATIC_OSCAR_FALSE@libaim_la_DEPENDENCIES = liboscar.la
+-am__libaim_la_SOURCES_DIST = libaim.c
+-@STATIC_OSCAR_FALSE@am_libaim_la_OBJECTS = libaim.lo
+-libaim_la_OBJECTS = $(am_libaim_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libaim_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(libaim_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_OSCAR_FALSE@am_libaim_la_rpath = -rpath $(pkgdir)
+-@STATIC_OSCAR_FALSE@libicq_la_DEPENDENCIES = liboscar.la
+-am__libicq_la_SOURCES_DIST = libicq.c
+-@STATIC_OSCAR_FALSE@am_libicq_la_OBJECTS = libicq.lo
+-libicq_la_OBJECTS = $(am_libicq_la_OBJECTS)
+-libicq_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(libicq_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_OSCAR_FALSE@am_libicq_la_rpath = -rpath $(pkgdir)
+-am__DEPENDENCIES_1 =
+-@STATIC_OSCAR_FALSE@liboscar_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+-am__liboscar_la_SOURCES_DIST = authorization.c bstream.c clientlogin.c \
+- encoding.c encoding.h family_admin.c family_alert.c \
+- family_auth.c family_bart.c family_bos.c family_buddy.c \
+- family_chat.c family_chatnav.c family_icq.c family_icbm.c \
+- family_locate.c family_oservice.c family_popup.c \
+- family_feedbag.c family_stats.c family_userlookup.c \
+- flap_connection.c misc.c msgcookie.c odc.c oft.c oscar.c \
+- oscar.h oscarcommon.h oscar_data.c peer.c peer.h peer_proxy.c \
+- rxhandlers.c snac.c snactypes.h tlv.c userinfo.c util.c \
+- visibility.c visibility.h libaim.c libicq.c
+-am__objects_1 = liboscar_la-authorization.lo liboscar_la-bstream.lo \
+- liboscar_la-clientlogin.lo liboscar_la-encoding.lo \
+- liboscar_la-family_admin.lo liboscar_la-family_alert.lo \
+- liboscar_la-family_auth.lo liboscar_la-family_bart.lo \
+- liboscar_la-family_bos.lo liboscar_la-family_buddy.lo \
+- liboscar_la-family_chat.lo liboscar_la-family_chatnav.lo \
+- liboscar_la-family_icq.lo liboscar_la-family_icbm.lo \
+- liboscar_la-family_locate.lo liboscar_la-family_oservice.lo \
+- liboscar_la-family_popup.lo liboscar_la-family_feedbag.lo \
+- liboscar_la-family_stats.lo liboscar_la-family_userlookup.lo \
+- liboscar_la-flap_connection.lo liboscar_la-misc.lo \
+- liboscar_la-msgcookie.lo liboscar_la-odc.lo liboscar_la-oft.lo \
+- liboscar_la-oscar.lo liboscar_la-oscar_data.lo \
+- liboscar_la-peer.lo liboscar_la-peer_proxy.lo \
+- liboscar_la-rxhandlers.lo liboscar_la-snac.lo \
+- liboscar_la-tlv.lo liboscar_la-userinfo.lo liboscar_la-util.lo \
+- liboscar_la-visibility.lo
+-@STATIC_OSCAR_FALSE@am_liboscar_la_OBJECTS = $(am__objects_1)
+-@STATIC_OSCAR_TRUE@am_liboscar_la_OBJECTS = $(am__objects_1) \
+-@STATIC_OSCAR_TRUE@ liboscar_la-libaim.lo liboscar_la-libicq.lo
+-liboscar_la_OBJECTS = $(am_liboscar_la_OBJECTS)
+-liboscar_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(liboscar_la_CFLAGS) \
+- $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_OSCAR_FALSE@am_liboscar_la_rpath = -rpath $(pkgdir)
+-@STATIC_OSCAR_TRUE@am_liboscar_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libaim_la_SOURCES) $(libicq_la_SOURCES) \
+- $(liboscar_la_SOURCES)
+-DIST_SOURCES = $(am__libaim_la_SOURCES_DIST) \
+- $(am__libicq_la_SOURCES_DIST) $(am__liboscar_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- COPYING \
+- AUTHORS \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-OSCARSOURCES = \
+- authorization.c \
+- bstream.c \
+- clientlogin.c \
+- encoding.c \
+- encoding.h \
+- family_admin.c \
+- family_alert.c \
+- family_auth.c \
+- family_bart.c \
+- family_bos.c \
+- family_buddy.c \
+- family_chat.c \
+- family_chatnav.c \
+- family_icq.c \
+- family_icbm.c \
+- family_locate.c \
+- family_oservice.c \
+- family_popup.c \
+- family_feedbag.c \
+- family_stats.c \
+- family_userlookup.c \
+- flap_connection.c \
+- misc.c \
+- msgcookie.c \
+- odc.c \
+- oft.c \
+- oscar.c \
+- oscar.h \
+- oscarcommon.h \
+- oscar_data.c \
+- peer.c \
+- peer.h \
+- peer_proxy.c \
+- rxhandlers.c \
+- snac.c \
+- snactypes.h \
+- tlv.c \
+- userinfo.c \
+- util.c \
+- visibility.c \
+- visibility.h
+-
+-AM_CFLAGS = $(st)
+-libaim_la_LDFLAGS = -module -avoid-version
+-libicq_la_LDFLAGS = -module -avoid-version
+-@STATIC_OSCAR_FALSE@st =
+-@STATIC_OSCAR_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_OSCAR_TRUE@noinst_LTLIBRARIES = liboscar.la
+-@STATIC_OSCAR_FALSE@liboscar_la_SOURCES = $(OSCARSOURCES)
+-@STATIC_OSCAR_TRUE@liboscar_la_SOURCES = $(OSCARSOURCES) libaim.c libicq.c
+-@STATIC_OSCAR_TRUE@liboscar_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_OSCAR_FALSE@pkg_LTLIBRARIES = liboscar.la libaim.la libicq.la
+-@STATIC_OSCAR_FALSE@liboscar_la_LIBADD = $(GLIB_LIBS)
+-@STATIC_OSCAR_FALSE@libaim_la_SOURCES = libaim.c
+-@STATIC_OSCAR_FALSE@libaim_la_LIBADD = liboscar.la
+-@STATIC_OSCAR_FALSE@libicq_la_SOURCES = libicq.c
+-@STATIC_OSCAR_FALSE@libicq_la_LIBADD = liboscar.la
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/oscar/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/oscar/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libaim.la: $(libaim_la_OBJECTS) $(libaim_la_DEPENDENCIES) $(EXTRA_libaim_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libaim_la_LINK) $(am_libaim_la_rpath) $(libaim_la_OBJECTS) $(libaim_la_LIBADD) $(LIBS)
+-libicq.la: $(libicq_la_OBJECTS) $(libicq_la_DEPENDENCIES) $(EXTRA_libicq_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libicq_la_LINK) $(am_libicq_la_rpath) $(libicq_la_OBJECTS) $(libicq_la_LIBADD) $(LIBS)
+-liboscar.la: $(liboscar_la_OBJECTS) $(liboscar_la_DEPENDENCIES) $(EXTRA_liboscar_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(liboscar_la_LINK) $(am_liboscar_la_rpath) $(liboscar_la_OBJECTS) $(liboscar_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libaim.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libicq.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-authorization.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-bstream.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-clientlogin.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-encoding.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_admin.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_alert.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_auth.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_bart.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_bos.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_buddy.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_chat.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_chatnav.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_feedbag.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_icbm.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_icq.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_locate.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_oservice.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_popup.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_stats.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-family_userlookup.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-flap_connection.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-libaim.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-libicq.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-misc.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-msgcookie.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-odc.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oft.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oscar.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-oscar_data.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-peer.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-peer_proxy.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-rxhandlers.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-snac.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-tlv.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-userinfo.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-util.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/liboscar_la-visibility.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-liboscar_la-authorization.lo: authorization.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-authorization.lo -MD -MP -MF $(DEPDIR)/liboscar_la-authorization.Tpo -c -o liboscar_la-authorization.lo `test -f 'authorization.c' || echo '$(srcdir)/'`authorization.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-authorization.Tpo $(DEPDIR)/liboscar_la-authorization.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='authorization.c' object='liboscar_la-authorization.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-authorization.lo `test -f 'authorization.c' || echo '$(srcdir)/'`authorization.c
+-
+-liboscar_la-bstream.lo: bstream.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-bstream.lo -MD -MP -MF $(DEPDIR)/liboscar_la-bstream.Tpo -c -o liboscar_la-bstream.lo `test -f 'bstream.c' || echo '$(srcdir)/'`bstream.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-bstream.Tpo $(DEPDIR)/liboscar_la-bstream.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='bstream.c' object='liboscar_la-bstream.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-bstream.lo `test -f 'bstream.c' || echo '$(srcdir)/'`bstream.c
+-
+-liboscar_la-clientlogin.lo: clientlogin.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-clientlogin.lo -MD -MP -MF $(DEPDIR)/liboscar_la-clientlogin.Tpo -c -o liboscar_la-clientlogin.lo `test -f 'clientlogin.c' || echo '$(srcdir)/'`clientlogin.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-clientlogin.Tpo $(DEPDIR)/liboscar_la-clientlogin.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='clientlogin.c' object='liboscar_la-clientlogin.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-clientlogin.lo `test -f 'clientlogin.c' || echo '$(srcdir)/'`clientlogin.c
+-
+-liboscar_la-encoding.lo: encoding.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-encoding.lo -MD -MP -MF $(DEPDIR)/liboscar_la-encoding.Tpo -c -o liboscar_la-encoding.lo `test -f 'encoding.c' || echo '$(srcdir)/'`encoding.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-encoding.Tpo $(DEPDIR)/liboscar_la-encoding.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='encoding.c' object='liboscar_la-encoding.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-encoding.lo `test -f 'encoding.c' || echo '$(srcdir)/'`encoding.c
+-
+-liboscar_la-family_admin.lo: family_admin.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_admin.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_admin.Tpo -c -o liboscar_la-family_admin.lo `test -f 'family_admin.c' || echo '$(srcdir)/'`family_admin.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_admin.Tpo $(DEPDIR)/liboscar_la-family_admin.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_admin.c' object='liboscar_la-family_admin.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_admin.lo `test -f 'family_admin.c' || echo '$(srcdir)/'`family_admin.c
+-
+-liboscar_la-family_alert.lo: family_alert.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_alert.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_alert.Tpo -c -o liboscar_la-family_alert.lo `test -f 'family_alert.c' || echo '$(srcdir)/'`family_alert.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_alert.Tpo $(DEPDIR)/liboscar_la-family_alert.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_alert.c' object='liboscar_la-family_alert.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_alert.lo `test -f 'family_alert.c' || echo '$(srcdir)/'`family_alert.c
+-
+-liboscar_la-family_auth.lo: family_auth.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_auth.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_auth.Tpo -c -o liboscar_la-family_auth.lo `test -f 'family_auth.c' || echo '$(srcdir)/'`family_auth.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_auth.Tpo $(DEPDIR)/liboscar_la-family_auth.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_auth.c' object='liboscar_la-family_auth.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_auth.lo `test -f 'family_auth.c' || echo '$(srcdir)/'`family_auth.c
+-
+-liboscar_la-family_bart.lo: family_bart.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_bart.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_bart.Tpo -c -o liboscar_la-family_bart.lo `test -f 'family_bart.c' || echo '$(srcdir)/'`family_bart.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_bart.Tpo $(DEPDIR)/liboscar_la-family_bart.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_bart.c' object='liboscar_la-family_bart.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_bart.lo `test -f 'family_bart.c' || echo '$(srcdir)/'`family_bart.c
+-
+-liboscar_la-family_bos.lo: family_bos.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_bos.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_bos.Tpo -c -o liboscar_la-family_bos.lo `test -f 'family_bos.c' || echo '$(srcdir)/'`family_bos.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_bos.Tpo $(DEPDIR)/liboscar_la-family_bos.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_bos.c' object='liboscar_la-family_bos.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_bos.lo `test -f 'family_bos.c' || echo '$(srcdir)/'`family_bos.c
+-
+-liboscar_la-family_buddy.lo: family_buddy.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_buddy.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_buddy.Tpo -c -o liboscar_la-family_buddy.lo `test -f 'family_buddy.c' || echo '$(srcdir)/'`family_buddy.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_buddy.Tpo $(DEPDIR)/liboscar_la-family_buddy.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_buddy.c' object='liboscar_la-family_buddy.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_buddy.lo `test -f 'family_buddy.c' || echo '$(srcdir)/'`family_buddy.c
+-
+-liboscar_la-family_chat.lo: family_chat.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_chat.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_chat.Tpo -c -o liboscar_la-family_chat.lo `test -f 'family_chat.c' || echo '$(srcdir)/'`family_chat.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_chat.Tpo $(DEPDIR)/liboscar_la-family_chat.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_chat.c' object='liboscar_la-family_chat.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_chat.lo `test -f 'family_chat.c' || echo '$(srcdir)/'`family_chat.c
+-
+-liboscar_la-family_chatnav.lo: family_chatnav.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_chatnav.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_chatnav.Tpo -c -o liboscar_la-family_chatnav.lo `test -f 'family_chatnav.c' || echo '$(srcdir)/'`family_chatnav.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_chatnav.Tpo $(DEPDIR)/liboscar_la-family_chatnav.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_chatnav.c' object='liboscar_la-family_chatnav.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_chatnav.lo `test -f 'family_chatnav.c' || echo '$(srcdir)/'`family_chatnav.c
+-
+-liboscar_la-family_icq.lo: family_icq.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_icq.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_icq.Tpo -c -o liboscar_la-family_icq.lo `test -f 'family_icq.c' || echo '$(srcdir)/'`family_icq.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_icq.Tpo $(DEPDIR)/liboscar_la-family_icq.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_icq.c' object='liboscar_la-family_icq.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_icq.lo `test -f 'family_icq.c' || echo '$(srcdir)/'`family_icq.c
+-
+-liboscar_la-family_icbm.lo: family_icbm.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_icbm.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_icbm.Tpo -c -o liboscar_la-family_icbm.lo `test -f 'family_icbm.c' || echo '$(srcdir)/'`family_icbm.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_icbm.Tpo $(DEPDIR)/liboscar_la-family_icbm.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_icbm.c' object='liboscar_la-family_icbm.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_icbm.lo `test -f 'family_icbm.c' || echo '$(srcdir)/'`family_icbm.c
+-
+-liboscar_la-family_locate.lo: family_locate.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_locate.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_locate.Tpo -c -o liboscar_la-family_locate.lo `test -f 'family_locate.c' || echo '$(srcdir)/'`family_locate.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_locate.Tpo $(DEPDIR)/liboscar_la-family_locate.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_locate.c' object='liboscar_la-family_locate.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_locate.lo `test -f 'family_locate.c' || echo '$(srcdir)/'`family_locate.c
+-
+-liboscar_la-family_oservice.lo: family_oservice.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_oservice.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_oservice.Tpo -c -o liboscar_la-family_oservice.lo `test -f 'family_oservice.c' || echo '$(srcdir)/'`family_oservice.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_oservice.Tpo $(DEPDIR)/liboscar_la-family_oservice.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_oservice.c' object='liboscar_la-family_oservice.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_oservice.lo `test -f 'family_oservice.c' || echo '$(srcdir)/'`family_oservice.c
+-
+-liboscar_la-family_popup.lo: family_popup.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_popup.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_popup.Tpo -c -o liboscar_la-family_popup.lo `test -f 'family_popup.c' || echo '$(srcdir)/'`family_popup.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_popup.Tpo $(DEPDIR)/liboscar_la-family_popup.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_popup.c' object='liboscar_la-family_popup.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_popup.lo `test -f 'family_popup.c' || echo '$(srcdir)/'`family_popup.c
+-
+-liboscar_la-family_feedbag.lo: family_feedbag.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_feedbag.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_feedbag.Tpo -c -o liboscar_la-family_feedbag.lo `test -f 'family_feedbag.c' || echo '$(srcdir)/'`family_feedbag.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_feedbag.Tpo $(DEPDIR)/liboscar_la-family_feedbag.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_feedbag.c' object='liboscar_la-family_feedbag.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_feedbag.lo `test -f 'family_feedbag.c' || echo '$(srcdir)/'`family_feedbag.c
+-
+-liboscar_la-family_stats.lo: family_stats.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_stats.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_stats.Tpo -c -o liboscar_la-family_stats.lo `test -f 'family_stats.c' || echo '$(srcdir)/'`family_stats.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_stats.Tpo $(DEPDIR)/liboscar_la-family_stats.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_stats.c' object='liboscar_la-family_stats.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_stats.lo `test -f 'family_stats.c' || echo '$(srcdir)/'`family_stats.c
+-
+-liboscar_la-family_userlookup.lo: family_userlookup.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-family_userlookup.lo -MD -MP -MF $(DEPDIR)/liboscar_la-family_userlookup.Tpo -c -o liboscar_la-family_userlookup.lo `test -f 'family_userlookup.c' || echo '$(srcdir)/'`family_userlookup.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-family_userlookup.Tpo $(DEPDIR)/liboscar_la-family_userlookup.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='family_userlookup.c' object='liboscar_la-family_userlookup.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-family_userlookup.lo `test -f 'family_userlookup.c' || echo '$(srcdir)/'`family_userlookup.c
+-
+-liboscar_la-flap_connection.lo: flap_connection.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-flap_connection.lo -MD -MP -MF $(DEPDIR)/liboscar_la-flap_connection.Tpo -c -o liboscar_la-flap_connection.lo `test -f 'flap_connection.c' || echo '$(srcdir)/'`flap_connection.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-flap_connection.Tpo $(DEPDIR)/liboscar_la-flap_connection.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='flap_connection.c' object='liboscar_la-flap_connection.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-flap_connection.lo `test -f 'flap_connection.c' || echo '$(srcdir)/'`flap_connection.c
+-
+-liboscar_la-misc.lo: misc.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-misc.lo -MD -MP -MF $(DEPDIR)/liboscar_la-misc.Tpo -c -o liboscar_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-misc.Tpo $(DEPDIR)/liboscar_la-misc.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='misc.c' object='liboscar_la-misc.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-misc.lo `test -f 'misc.c' || echo '$(srcdir)/'`misc.c
+-
+-liboscar_la-msgcookie.lo: msgcookie.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-msgcookie.lo -MD -MP -MF $(DEPDIR)/liboscar_la-msgcookie.Tpo -c -o liboscar_la-msgcookie.lo `test -f 'msgcookie.c' || echo '$(srcdir)/'`msgcookie.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-msgcookie.Tpo $(DEPDIR)/liboscar_la-msgcookie.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='msgcookie.c' object='liboscar_la-msgcookie.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-msgcookie.lo `test -f 'msgcookie.c' || echo '$(srcdir)/'`msgcookie.c
+-
+-liboscar_la-odc.lo: odc.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-odc.lo -MD -MP -MF $(DEPDIR)/liboscar_la-odc.Tpo -c -o liboscar_la-odc.lo `test -f 'odc.c' || echo '$(srcdir)/'`odc.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-odc.Tpo $(DEPDIR)/liboscar_la-odc.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='odc.c' object='liboscar_la-odc.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-odc.lo `test -f 'odc.c' || echo '$(srcdir)/'`odc.c
+-
+-liboscar_la-oft.lo: oft.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oft.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oft.Tpo -c -o liboscar_la-oft.lo `test -f 'oft.c' || echo '$(srcdir)/'`oft.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oft.Tpo $(DEPDIR)/liboscar_la-oft.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oft.c' object='liboscar_la-oft.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oft.lo `test -f 'oft.c' || echo '$(srcdir)/'`oft.c
+-
+-liboscar_la-oscar.lo: oscar.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oscar.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oscar.Tpo -c -o liboscar_la-oscar.lo `test -f 'oscar.c' || echo '$(srcdir)/'`oscar.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oscar.Tpo $(DEPDIR)/liboscar_la-oscar.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oscar.c' object='liboscar_la-oscar.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oscar.lo `test -f 'oscar.c' || echo '$(srcdir)/'`oscar.c
+-
+-liboscar_la-oscar_data.lo: oscar_data.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-oscar_data.lo -MD -MP -MF $(DEPDIR)/liboscar_la-oscar_data.Tpo -c -o liboscar_la-oscar_data.lo `test -f 'oscar_data.c' || echo '$(srcdir)/'`oscar_data.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-oscar_data.Tpo $(DEPDIR)/liboscar_la-oscar_data.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='oscar_data.c' object='liboscar_la-oscar_data.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-oscar_data.lo `test -f 'oscar_data.c' || echo '$(srcdir)/'`oscar_data.c
+-
+-liboscar_la-peer.lo: peer.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-peer.lo -MD -MP -MF $(DEPDIR)/liboscar_la-peer.Tpo -c -o liboscar_la-peer.lo `test -f 'peer.c' || echo '$(srcdir)/'`peer.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-peer.Tpo $(DEPDIR)/liboscar_la-peer.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='peer.c' object='liboscar_la-peer.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-peer.lo `test -f 'peer.c' || echo '$(srcdir)/'`peer.c
+-
+-liboscar_la-peer_proxy.lo: peer_proxy.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-peer_proxy.lo -MD -MP -MF $(DEPDIR)/liboscar_la-peer_proxy.Tpo -c -o liboscar_la-peer_proxy.lo `test -f 'peer_proxy.c' || echo '$(srcdir)/'`peer_proxy.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-peer_proxy.Tpo $(DEPDIR)/liboscar_la-peer_proxy.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='peer_proxy.c' object='liboscar_la-peer_proxy.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-peer_proxy.lo `test -f 'peer_proxy.c' || echo '$(srcdir)/'`peer_proxy.c
+-
+-liboscar_la-rxhandlers.lo: rxhandlers.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-rxhandlers.lo -MD -MP -MF $(DEPDIR)/liboscar_la-rxhandlers.Tpo -c -o liboscar_la-rxhandlers.lo `test -f 'rxhandlers.c' || echo '$(srcdir)/'`rxhandlers.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-rxhandlers.Tpo $(DEPDIR)/liboscar_la-rxhandlers.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='rxhandlers.c' object='liboscar_la-rxhandlers.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-rxhandlers.lo `test -f 'rxhandlers.c' || echo '$(srcdir)/'`rxhandlers.c
+-
+-liboscar_la-snac.lo: snac.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-snac.lo -MD -MP -MF $(DEPDIR)/liboscar_la-snac.Tpo -c -o liboscar_la-snac.lo `test -f 'snac.c' || echo '$(srcdir)/'`snac.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-snac.Tpo $(DEPDIR)/liboscar_la-snac.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='snac.c' object='liboscar_la-snac.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-snac.lo `test -f 'snac.c' || echo '$(srcdir)/'`snac.c
+-
+-liboscar_la-tlv.lo: tlv.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-tlv.lo -MD -MP -MF $(DEPDIR)/liboscar_la-tlv.Tpo -c -o liboscar_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-tlv.Tpo $(DEPDIR)/liboscar_la-tlv.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='tlv.c' object='liboscar_la-tlv.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-tlv.lo `test -f 'tlv.c' || echo '$(srcdir)/'`tlv.c
+-
+-liboscar_la-userinfo.lo: userinfo.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-userinfo.lo -MD -MP -MF $(DEPDIR)/liboscar_la-userinfo.Tpo -c -o liboscar_la-userinfo.lo `test -f 'userinfo.c' || echo '$(srcdir)/'`userinfo.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-userinfo.Tpo $(DEPDIR)/liboscar_la-userinfo.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='userinfo.c' object='liboscar_la-userinfo.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-userinfo.lo `test -f 'userinfo.c' || echo '$(srcdir)/'`userinfo.c
+-
+-liboscar_la-util.lo: util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-util.lo -MD -MP -MF $(DEPDIR)/liboscar_la-util.Tpo -c -o liboscar_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-util.Tpo $(DEPDIR)/liboscar_la-util.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='liboscar_la-util.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
+-
+-liboscar_la-visibility.lo: visibility.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-visibility.lo -MD -MP -MF $(DEPDIR)/liboscar_la-visibility.Tpo -c -o liboscar_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-visibility.Tpo $(DEPDIR)/liboscar_la-visibility.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='visibility.c' object='liboscar_la-visibility.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-visibility.lo `test -f 'visibility.c' || echo '$(srcdir)/'`visibility.c
+-
+-liboscar_la-libaim.lo: libaim.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-libaim.lo -MD -MP -MF $(DEPDIR)/liboscar_la-libaim.Tpo -c -o liboscar_la-libaim.lo `test -f 'libaim.c' || echo '$(srcdir)/'`libaim.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-libaim.Tpo $(DEPDIR)/liboscar_la-libaim.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libaim.c' object='liboscar_la-libaim.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-libaim.lo `test -f 'libaim.c' || echo '$(srcdir)/'`libaim.c
+-
+-liboscar_la-libicq.lo: libicq.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -MT liboscar_la-libicq.lo -MD -MP -MF $(DEPDIR)/liboscar_la-libicq.Tpo -c -o liboscar_la-libicq.lo `test -f 'libicq.c' || echo '$(srcdir)/'`libicq.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/liboscar_la-libicq.Tpo $(DEPDIR)/liboscar_la-libicq.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libicq.c' object='liboscar_la-libicq.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(liboscar_la_CFLAGS) $(CFLAGS) -c -o liboscar_la-libicq.lo `test -f 'libicq.c' || echo '$(srcdir)/'`libicq.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/oscar/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,129 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of liboscar
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = liboscar
+-AIM_TARGET = libaim
+-ICQ_TARGET = libicq
+-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) \
+- -L.
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = \
+- authorization.c \
+- bstream.c \
+- clientlogin.c \
+- encoding.c \
+- family_admin.c \
+- family_alert.c \
+- family_auth.c \
+- family_bart.c \
+- family_bos.c \
+- family_buddy.c \
+- family_chat.c \
+- family_chatnav.c \
+- family_feedbag.c \
+- family_icbm.c \
+- family_icq.c \
+- family_locate.c \
+- family_oservice.c \
+- family_popup.c \
+- family_stats.c \
+- family_userlookup.c \
+- flap_connection.c \
+- misc.c \
+- msgcookie.c \
+- odc.c \
+- oft.c \
+- oscar.c \
+- oscar_data.c \
+- peer.c \
+- peer_proxy.c \
+- rxhandlers.c \
+- snac.c \
+- tlv.c \
+- userinfo.c \
+- util.c \
+- visibility.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-AIM_C_SRC = libaim.c
+-AIM_OBJECTS = $(AIM_C_SRC:%.c=%.o)
+-
+-ICQ_C_SRC = libicq.c
+-ICQ_OBJECTS = $(ICQ_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 $(AIM_TARGET).dll $(ICQ_TARGET).dll
+-
+-install: all $(DLL_INSTALL_DIR)
+- cp $(AIM_TARGET).dll $(ICQ_TARGET).dll $(DLL_INSTALL_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-$(TARGET).dll.a $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+-
+-$(AIM_TARGET).dll: $(TARGET).dll.a $(AIM_OBJECTS)
+- $(CC) -shared $(AIM_OBJECTS) $(LIB_PATHS) $(LIBS) -loscar $(DLL_LD_FLAGS) -o $(AIM_TARGET).dll
+-
+-$(ICQ_TARGET).dll: $(TARGET).dll.a $(ICQ_OBJECTS)
+- $(CC) -shared $(ICQ_OBJECTS) $(LIB_PATHS) $(LIBS) -loscar $(DLL_LD_FLAGS) -o $(ICQ_TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
+- rm -f $(AIM_OBJECTS) $(AIM_TARGET).dll
+- rm -f $(ICQ_OBJECTS) $(ICQ_TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/misc.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/misc.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/misc.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/misc.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,133 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Random stuff. Basically just a few functions for sending
+- * simple SNACs, and then the generic error handler.
+- */
+-
+-#include "oscar.h"
+-
+-/*
+- * Generic routine for sending commands.
+- *
+- * I know I can do this in a smarter way...but I'm not thinking straight
+- * right now...
+- *
+- * I had one big function that handled all three cases, but then it broke
+- * and I split it up into three. But then I fixed it. I just never went
+- * back to the single. I don't see any advantage to doing it either way.
+- *
+- */
+-void
+-aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
+-{
+- aim_snacid_t snacid = 0x00000000;
+-
+- flap_connection_send_snac(od, conn, family, subtype, snacid, NULL);
+-}
+-
+-void
+-aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype)
+-{
+- aim_snacid_t snacid;
+-
+- snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0);
+-
+- flap_connection_send_snac(od, conn, family, subtype, snacid, NULL);
+-}
+-
+-void
+-aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *longdata)
+-{
+- ByteStream bs;
+- aim_snacid_t snacid;
+-
+- if (!longdata)
+- {
+- aim_genericreq_n(od, conn, family, subtype);
+- return;
+- }
+-
+- byte_stream_new(&bs, 4);
+-
+- snacid = aim_cachesnac(od, family, subtype, 0x0000, NULL, 0);
+-
+- byte_stream_put32(&bs, *longdata);
+-
+- flap_connection_send_snac(od, conn, family, subtype, snacid, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/*
+- * Should be generic enough to handle the errors for all groups.
+- *
+- */
+-static int
+-generror(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- int ret = 0;
+- int error = 0;
+- aim_rxcallback_t userfunc;
+- aim_snac_t *snac2;
+-
+- snac2 = aim_remsnac(od, snac->id);
+-
+- if (byte_stream_bytes_left(bs))
+- error = byte_stream_get16(bs);
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- ret = userfunc(od, conn, frame, error, snac2 ? snac2->data : NULL);
+-
+- if (snac2) {
+- g_free(snac2->data);
+- g_free(snac2);
+- }
+-
+- return ret;
+-}
+-
+-static int
+-snachandler(OscarData *od, FlapConnection *conn, aim_module_t *mod, FlapFrame *frame, aim_modsnac_t *snac, ByteStream *bs)
+-{
+- if (snac->subtype == 0x0001)
+- return generror(od, conn, mod, frame, snac, bs);
+- else if ((snac->family == 0xffff) && (snac->subtype == 0xffff)) {
+- aim_rxcallback_t userfunc;
+-
+- if ((userfunc = aim_callhandler(od, snac->family, snac->subtype)))
+- return userfunc(od, conn, frame);
+- }
+-
+- return 0;
+-}
+-
+-int
+-misc_modfirst(OscarData *od, aim_module_t *mod)
+-{
+- mod->family = 0xffff;
+- mod->version = 0x0000;
+- mod->flags = AIM_MODFLAG_MULTIFAMILY;
+- strncpy(mod->name, "misc", sizeof(mod->name));
+- mod->snachandler = snachandler;
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/msgcookie.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/msgcookie.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/msgcookie.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/msgcookie.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,179 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Cookie Caching stuff. Adam wrote this, apparently just some
+- * derivatives of n's SNAC work. I cleaned it up, added comments.
+- *
+- */
+-
+-/*
+- * I'm assuming that cookies are type-specific. that is, we can have
+- * "1234578" for type 1 and type 2 concurrently. if i'm wrong, then we
+- * lose some error checking. if we assume cookies are not type-specific and are
+- * wrong, we get quirky behavior when cookies step on each others' toes.
+- */
+-
+-#include "oscar.h"
+-
+-/**
+- * aim_cachecookie - appends a cookie to the cookie list
+- *
+- * if cookie->cookie for type cookie->type is found, updates the
+- * ->addtime of the found structure; otherwise adds the given cookie
+- * to the cache
+- *
+- * @param od session to add to
+- * @param cookie pointer to struct to append
+- * @return returns -1 on error, 0 on append, 1 on update. the cookie you pass
+- * in may be free'd, so don't count on its value after calling this!
+- */
+-int aim_cachecookie(OscarData *od, IcbmCookie *cookie)
+-{
+- IcbmCookie *newcook;
+-
+- if (!od || !cookie)
+- return -EINVAL;
+-
+- newcook = aim_checkcookie(od, cookie->cookie, cookie->type);
+-
+- if (newcook == cookie) {
+- newcook->addtime = time(NULL);
+- return 1;
+- } else if (newcook)
+- aim_cookie_free(od, newcook);
+-
+- cookie->addtime = time(NULL);
+-
+- cookie->next = od->msgcookies;
+- od->msgcookies = cookie;
+-
+- return 0;
+-}
+-
+-/**
+- * aim_uncachecookie - grabs a cookie from the cookie cache (removes it from the list)
+- *
+- * takes a cookie string and a cookie type and finds the cookie struct associated with that duple, removing it from the cookie list ikn the process.
+- *
+- * @param od session to grab cookie from
+- * @param cookie cookie string to look for
+- * @param type cookie type to look for
+- * @return if found, returns the struct; if none found (or on error), returns NULL:
+- */
+-IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type)
+-{
+- IcbmCookie *cur, **prev;
+-
+- if (!cookie || !od->msgcookies)
+- return NULL;
+-
+- for (prev = &od->msgcookies; (cur = *prev); ) {
+- if ((cur->type == type) &&
+- (memcmp(cur->cookie, cookie, 8) == 0)) {
+- *prev = cur->next;
+- return cur;
+- }
+- prev = &cur->next;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * aim_mkcookie - generate an IcbmCookie *struct from a cookie string, a type, and a data pointer.
+- *
+- * @param c pointer to the cookie string array
+- * @param type cookie type to use
+- * @param data data to be cached with the cookie
+- * @return returns NULL on error, a pointer to the newly-allocated
+- * cookie on success.
+- */
+-IcbmCookie *aim_mkcookie(guint8 *c, int type, void *data)
+-{
+- IcbmCookie *cookie;
+-
+- if (!c)
+- return NULL;
+-
+- cookie = g_new0(IcbmCookie, 1);
+-
+- cookie->data = data;
+- cookie->type = type;
+- memcpy(cookie->cookie, c, 8);
+-
+- return cookie;
+-}
+-
+-/**
+- * aim_checkcookie - check to see if a cookietuple has been cached
+- *
+- * @param od session to check for the cookie in
+- * @param cookie pointer to the cookie string array
+- * @param type type of the cookie to look for
+- * @return returns a pointer to the cookie struct (still in the list)
+- * on success; returns NULL on error/not found
+- */
+-
+-IcbmCookie *aim_checkcookie(OscarData *od, const guint8 *cookie, const int type)
+-{
+- IcbmCookie *cur;
+-
+- for (cur = od->msgcookies; cur; cur = cur->next) {
+- if ((cur->type == type) &&
+- (memcmp(cur->cookie, cookie, 8) == 0))
+- return cur;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * aim_cookie_free - free an IcbmCookie struct
+- *
+- * this function removes the cookie *cookie from the list of cookies
+- * in od, and then frees all memory associated with it. including
+- * its data! if you want to use the private data after calling this,
+- * make sure you copy it first.
+- *
+- * @param od session to remove the cookie from
+- * @param cookie the address of a pointer to the cookie struct to remove
+- * @return returns -1 on error, 0 on success.
+- *
+- */
+-int aim_cookie_free(OscarData *od, IcbmCookie *cookie)
+-{
+- IcbmCookie *cur, **prev;
+-
+- if (!od || !cookie)
+- return -EINVAL;
+-
+- for (prev = &od->msgcookies; (cur = *prev); ) {
+- if (cur == cookie)
+- *prev = cur->next;
+- else
+- prev = &cur->next;
+- }
+-
+- g_free(cookie->data);
+- g_free(cookie);
+-
+- return 0;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/odc.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/odc.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/odc.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/odc.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,625 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/* From the oscar PRPL */
+-#include "encoding.h"
+-#include "oscar.h"
+-#include "peer.h"
+-
+-/* From Purple */
+-#include "conversation.h"
+-#include "imgstore.h"
+-#include "util.h"
+-
+-#define DIRECTIM_MAX_FILESIZE 52428800
+-
+-/**
+- * Free any ODC related data and print a message to the conversation
+- * window based on conn->disconnect_reason.
+- */
+-void
+-peer_odc_close(PeerConnection *conn)
+-{
+- gchar *tmp;
+-
+- if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED)
+- tmp = g_strdup(_("The remote user has closed the connection."));
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED)
+- tmp = g_strdup(_("The remote user has declined your request."));
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_LOST_CONNECTION)
+- tmp = g_strdup_printf(_("Lost connection with the remote user:<br>%s"),
+- conn->error_message);
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_INVALID_DATA)
+- tmp = g_strdup(_("Received invalid data on connection with remote user."));
+- else if (conn->disconnect_reason == OSCAR_DISCONNECT_COULD_NOT_CONNECT)
+- tmp = g_strdup(_("Unable to establish a connection with the remote user."));
+- else
+- /*
+- * We shouldn't print a message for some disconnect_reasons.
+- * Like OSCAR_DISCONNECT_LOCAL_CLOSED.
+- */
+- tmp = NULL;
+-
+- if (tmp != NULL)
+- {
+- PurpleAccount *account;
+- PurpleConversation *conv;
+-
+- account = purple_connection_get_account(conn->od->gc);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+- }
+-
+- if (conn->frame != NULL)
+- {
+- OdcFrame *frame;
+- frame = conn->frame;
+- g_free(frame->payload.data);
+- g_free(frame);
+- }
+-}
+-
+-/**
+- * Write the given OdcFrame to a ByteStream and send it out
+- * on the established PeerConnection.
+- */
+-static void
+-peer_odc_send(PeerConnection *conn, OdcFrame *frame)
+-{
+- PurpleAccount *account;
+- const char *username;
+- size_t length;
+- ByteStream bs;
+-
+- purple_debug_info("oscar", "Outgoing ODC frame to %s with "
+- "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n",
+- conn->bn, frame->type, frame->flags, frame->payload.len);
+-
+- account = purple_connection_get_account(conn->od->gc);
+- username = purple_account_get_username(account);
+- memcpy(frame->bn, username, strlen(username));
+- memcpy(frame->cookie, conn->cookie, 8);
+-
+- length = 76;
+- byte_stream_new(&bs, length + frame->payload.len);
+- byte_stream_putraw(&bs, conn->magic, 4);
+- byte_stream_put16(&bs, length);
+- byte_stream_put16(&bs, frame->type);
+- byte_stream_put16(&bs, frame->subtype);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_putraw(&bs, frame->cookie, 8);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put32(&bs, frame->payload.len);
+- byte_stream_put16(&bs, frame->encoding);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, frame->flags);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_put16(&bs, 0x0000);
+- byte_stream_putraw(&bs, frame->bn, 32);
+- byte_stream_putraw(&bs, frame->payload.data, frame->payload.len);
+-
+- peer_connection_send(conn, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Send a very basic ODC frame (which contains the cookie) so that the
+- * remote user can verify that we are the person they were expecting.
+- * If we made an outgoing connection to then remote user, then we send
+- * this immediately. If the remote user connected to us, then we wait
+- * for the other person to send this to us, then we send one to them.
+- */
+-void
+-peer_odc_send_cookie(PeerConnection *conn)
+-{
+- OdcFrame frame;
+-
+- memset(&frame, 0, sizeof(OdcFrame));
+- frame.type = 0x0001;
+- frame.subtype = 0x0006;
+- frame.flags = 0x0060; /* Maybe this means "we're sending the cookie"? */
+-
+- peer_odc_send(conn, &frame);
+-}
+-
+-/**
+- * Send client-to-client typing notification over an established direct connection.
+- */
+-void
+-peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing)
+-{
+- OdcFrame frame;
+-
+- memset(&frame, 0, sizeof(OdcFrame));
+- frame.type = 0x0001;
+- frame.subtype = 0x0006;
+- if (typing == PURPLE_TYPING)
+- frame.flags = 0x0002 | 0x0008;
+- else if (typing == PURPLE_TYPED)
+- frame.flags = 0x0002 | 0x0004;
+- else
+- frame.flags = 0x0002;
+-
+- peer_odc_send(conn, &frame);
+-}
+-
+-/**
+- * Send client-to-client IM over an established direct connection.
+- * To send a direct IM, call this just like you would aim_send_im.
+- *
+- * @param conn The already-connected ODC connection.
+- * @param msg Null-terminated string to send.
+- * @param len The length of the message to send, including binary data.
+- * @param encoding See the AIM_CHARSET_* defines in oscar.h
+- * @param autoreply TRUE if this is any auto-reply.
+- */
+-void
+-peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply)
+-{
+- OdcFrame frame;
+-
+- g_return_if_fail(msg != NULL);
+- g_return_if_fail(len > 0);
+-
+- memset(&frame, 0, sizeof(OdcFrame));
+- frame.type = 0x0001;
+- frame.subtype = 0x0006;
+- frame.payload.len = len;
+- frame.encoding = encoding;
+- frame.flags = autoreply;
+- byte_stream_new(&frame.payload, len);
+- byte_stream_putraw(&frame.payload, (guint8 *)msg, len);
+-
+- peer_odc_send(conn, &frame);
+-
+- g_free(frame.payload.data);
+-}
+-
+-struct embedded_data
+-{
+- size_t size;
+- const guint8 *data;
+-};
+-
+-/**
+- * This is called after a direct IM has been received in its entirety. This
+- * function is passed a long chunk of data which contains the IM with any
+- * data chunks (images) appended to it.
+- *
+- * This function rips out all the data chunks and creates an imgstore for
+- * each one. In order to do this, it first goes through the IM and takes
+- * out all the IMG tags. When doing so, it rewrites the original IMG tag
+- * with one compatible with the imgstore Purple core code. For each one, we
+- * then read in chunks of data from the end of the message and actually
+- * create the img store using the given data.
+- *
+- * For somewhat easy reference, here's a sample message
+- * (with added whitespace):
+- *
+- * <HTML><BODY BGCOLOR="#ffffff">
+- * <FONT LANG="0">
+- * This is a really stupid picture:<BR>
+- * <IMG SRC="Sample.jpg" ID="1" WIDTH="283" HEIGHT="212" DATASIZE="9894"><BR>
+- * Yeah it is<BR>
+- * Here is another one:<BR>
+- * <IMG SRC="Soap Bubbles.bmp" ID="2" WIDTH="256" HEIGHT="256" DATASIZE="65978">
+- * </FONT>
+- * </BODY></HTML>
+- * <BINARY>
+- * <DATA ID="1" SIZE="9894">datadatadatadata</DATA>
+- * <DATA ID="2" SIZE="65978">datadatadatadata</DATA>
+- * </BINARY>
+- */
+-static void
+-peer_odc_handle_payload(PeerConnection *conn, const char *msg, size_t len, int encoding, gboolean autoreply)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- const char *msgend, *binary_start, *dataend;
+- const char *tmp, *start, *end, *idstr, *src, *sizestr;
+- GData *attributes;
+- GHashTable *embedded_datas;
+- struct embedded_data *embedded_data;
+- GSList *images;
+- gchar *utf8;
+- GString *newmsg;
+- PurpleMessageFlags imflags;
+-
+- gc = conn->od->gc;
+- account = purple_connection_get_account(gc);
+-
+- dataend = msg + len;
+-
+- /*
+- * Create a hash table containing references to each embedded
+- * data chunk. The key is the "ID" and the value is an
+- * embedded_data struct.
+- */
+- embedded_datas = g_hash_table_new_full(g_direct_hash,
+- g_direct_equal, NULL, g_free);
+-
+- /*
+- * Create an index of any binary chunks. If we run into any
+- * problems while parsing the binary data section then we stop
+- * parsing it, and the local user will see broken image icons.
+- */
+- /* TODO: Use a length argument when looking for the <binary> tag! */
+- binary_start = purple_strcasestr(msg, "<binary>");
+- if (binary_start == NULL)
+- msgend = dataend;
+- else
+- {
+- msgend = binary_start;
+-
+- /* Move our pointer to immediately after the <binary> tag */
+- tmp = binary_start + 8;
+-
+- /* The embedded binary markup has a mimimum length of 29 bytes */
+- /* TODO: Use a length argument when looking for the <data> tag! */
+- while ((tmp + 29 <= dataend) &&
+- purple_markup_find_tag("data", tmp, &start, &tmp, &attributes))
+- {
+- unsigned int id;
+- size_t size;
+-
+- /* Move the binary pointer from ">" to the start of the data */
+- tmp++;
+-
+- /* Get the ID */
+- idstr = g_datalist_get_data(&attributes, "id");
+- if (idstr == NULL)
+- {
+- g_datalist_clear(&attributes);
+- break;
+- }
+- id = atoi(idstr);
+-
+- /* Get the size */
+- sizestr = g_datalist_get_data(&attributes, "size");
+- if (sizestr == NULL)
+- {
+- g_datalist_clear(&attributes);
+- break;
+- }
+- size = atol(sizestr);
+-
+- g_datalist_clear(&attributes);
+-
+- if ((size > 0) && (tmp + size > dataend))
+- break;
+-
+- embedded_data = g_new(struct embedded_data, 1);
+- embedded_data->size = size;
+- embedded_data->data = (const guint8 *)tmp;
+- tmp += size;
+-
+- /* Skip past the closing </data> tag */
+- if (g_ascii_strncasecmp(tmp, "</data>", 7))
+- {
+- g_free(embedded_data);
+- break;
+- }
+- tmp += 7;
+-
+- g_hash_table_insert(embedded_datas,
+- GINT_TO_POINTER(id), embedded_data);
+- }
+- }
+-
+- /*
+- * Loop through the message, replacing OSCAR img tags with the
+- * equivalent Purple img tag.
+- */
+- images = NULL;
+- newmsg = g_string_new("");
+- tmp = msg;
+- while (purple_markup_find_tag("img", tmp, &start, &end, &attributes))
+- {
+- int imgid = 0;
+-
+- idstr = g_datalist_get_data(&attributes, "id");
+- src = g_datalist_get_data(&attributes, "src");
+- sizestr = g_datalist_get_data(&attributes, "datasize");
+-
+- if ((idstr != NULL) && (src != NULL) && (sizestr!= NULL))
+- {
+- unsigned int id;
+- size_t size;
+-
+- id = atoi(idstr);
+- size = atol(sizestr);
+- embedded_data = g_hash_table_lookup(embedded_datas,
+- GINT_TO_POINTER(id));
+-
+- if ((embedded_data != NULL) && (embedded_data->size == size))
+- {
+- imgid = purple_imgstore_add_with_id(g_memdup(embedded_data->data, size), size, src);
+-
+- /* Record the image number */
+- images = g_slist_append(images, GINT_TO_POINTER(imgid));
+- }
+- }
+-
+- /* Delete the attribute list */
+- g_datalist_clear(&attributes);
+-
+- /* Append the message up to the tag */
+- utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, start - tmp);
+- if (utf8 != NULL) {
+- g_string_append(newmsg, utf8);
+- g_free(utf8);
+- }
+-
+- if (imgid != 0)
+- {
+- /* Write the new image tag */
+- g_string_append_printf(newmsg, "<IMG ID=\"%d\">", imgid);
+- }
+-
+- /* Continue from the end of the tag */
+- tmp = end + 1;
+- }
+-
+- /* Append any remaining message data */
+- if (tmp <= msgend)
+- {
+- utf8 = oscar_decode_im(account, conn->bn, encoding, tmp, msgend - tmp);
+- if (utf8 != NULL) {
+- g_string_append(newmsg, utf8);
+- g_free(utf8);
+- }
+- }
+-
+- /* Display the message we received */
+- imflags = 0;
+- if (images != NULL)
+- imflags |= PURPLE_MESSAGE_IMAGES;
+- if (autoreply)
+- imflags |= PURPLE_MESSAGE_AUTO_RESP;
+- serv_got_im(gc, conn->bn, newmsg->str, imflags, time(NULL));
+- g_string_free(newmsg, TRUE);
+-
+- /* unref any images we allocated */
+- if (images)
+- {
+- GSList *l;
+- for (l = images; l != NULL; l = l->next)
+- purple_imgstore_unref_by_id(GPOINTER_TO_INT(l->data));
+- g_slist_free(images);
+- }
+-
+- /* Delete our list of pointers to embedded images */
+- g_hash_table_destroy(embedded_datas);
+-}
+-
+-/**
+- * This is a purple_input_add() watcher callback function for reading
+- * direct IM payload data. "Payload data" is always an IM and
+- * maybe some embedded images or files or something. The actual
+- * ODC frame is read using peer_connection_recv_cb(). We temporarily
+- * switch to this watcher callback ONLY to read the payload, and we
+- * switch back once we're done.
+- */
+-static void
+-peer_odc_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PeerConnection *conn;
+- OdcFrame *frame;
+- ByteStream *bs;
+- gssize read;
+-
+- conn = data;
+- frame = conn->frame;
+- bs = &frame->payload;
+-
+- /* Read data into the temporary buffer until it is complete */
+- read = recv(conn->fd,
+- &bs->data[bs->offset],
+- bs->len - bs->offset,
+- 0);
+-
+- /* Check if the remote user closed the connection */
+- if (read == 0)
+- {
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- return;
+- }
+-
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- peer_connection_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- return;
+- }
+-
+- bs->offset += read;
+- if (bs->offset < bs->len)
+- /* Waiting for more data to arrive */
+- return;
+-
+- /* We have a complete ODC/OFT frame! Handle it and continue reading */
+- byte_stream_rewind(bs);
+- peer_odc_handle_payload(conn, (const char *)bs->data,
+- bs->len, frame->encoding, frame->flags & 0x0001);
+- g_free(bs->data);
+- bs->data = NULL;
+- g_free(frame);
+- conn->frame = NULL;
+-
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
+-}
+-
+-/**
+- * Handle an incoming OdcFrame. If there is a payload associated
+- * with this frame, then we remove the old watcher and add the
+- * ODC watcher to read in the payload.
+- */
+-void
+-peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs)
+-{
+- PurpleConnection *gc;
+- OdcFrame *frame;
+-
+- gc = conn->od->gc;
+-
+- frame = g_new0(OdcFrame, 1);
+- frame->type = byte_stream_get16(bs);
+- frame->subtype = byte_stream_get16(bs);
+- byte_stream_advance(bs, 2);
+- byte_stream_getrawbuf(bs, frame->cookie, 8);
+- byte_stream_advance(bs, 8);
+- frame->payload.len = byte_stream_get32(bs);
+- frame->encoding = byte_stream_get16(bs);
+- byte_stream_advance(bs, 4);
+- frame->flags = byte_stream_get16(bs);
+- byte_stream_advance(bs, 4);
+- byte_stream_getrawbuf(bs, frame->bn, 32);
+-
+- purple_debug_info("oscar", "Incoming ODC frame from %s with "
+- "type=0x%04x, flags=0x%04x, payload length=%" G_GSIZE_FORMAT "\n",
+- frame->bn, frame->type, frame->flags, frame->payload.len);
+-
+- if (!conn->ready)
+- {
+- /*
+- * We need to verify the cookie so that we know we are
+- * connected to our friend and not a malicious middle man.
+- */
+-
+- PurpleAccount *account;
+- PurpleConversation *conv;
+-
+- if (conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING)
+- {
+- if (memcmp(conn->cookie, frame->cookie, 8))
+- {
+- /*
+- * Oh no! The user that connected to us did not send
+- * the correct cookie! They are not our friend. Go try
+- * to accept another connection?
+- */
+- purple_debug_info("oscar", "Received an incorrect cookie. "
+- "Closing connection.\n");
+- peer_connection_destroy(conn,
+- OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- g_free(frame);
+- return;
+- }
+-
+- /*
+- * Ok, we know they are legit. Now be courteous and
+- * send them our cookie. Note: This doesn't seem
+- * to be necessary, but it also doesn't seem to hurt.
+- */
+- peer_odc_send_cookie(conn);
+- }
+-
+- conn->ready = TRUE;
+-
+- /*
+- * If they connected to us then close the listener socket
+- * and send them our cookie.
+- */
+- if (conn->listenerfd != -1)
+- {
+- close(conn->listenerfd);
+- conn->listenerfd = -1;
+- }
+-
+- /* Tell the local user that we are connected */
+- account = purple_connection_get_account(gc);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- purple_conversation_write(conv, NULL, _("Direct IM established"),
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+-
+- if ((frame->type != 0x0001) && (frame->subtype != 0x0006))
+- {
+- purple_debug_info("oscar", "Unknown ODC frame type 0x%04hx, "
+- "subtype 0x%04hx.\n", frame->type, frame->subtype);
+- g_free(frame);
+- return;
+- }
+-
+- if (frame->flags & 0x0008)
+- {
+- /* I had to leave this. It's just too funny. It reminds me of my sister. */
+- purple_debug_info("oscar", "ohmigod! %s has started typing "
+- "(DirectIM). He's going to send you a message! "
+- "*squeal*\n", conn->bn);
+- serv_got_typing(gc, conn->bn, 0, PURPLE_TYPING);
+- }
+- else if (frame->flags & 0x0004)
+- {
+- serv_got_typing(gc, conn->bn, 0, PURPLE_TYPED);
+- }
+- else
+- {
+- serv_got_typing_stopped(gc, conn->bn);
+- }
+-
+- if (frame->payload.len > 0)
+- {
+- if (frame->payload.len > DIRECTIM_MAX_FILESIZE)
+- {
+- gchar *tmp, *size1, *size2;
+- PurpleAccount *account;
+- PurpleConversation *conv;
+-
+- size1 = purple_str_size_to_units(frame->payload.len);
+- size2 = purple_str_size_to_units(DIRECTIM_MAX_FILESIZE);
+- tmp = g_strdup_printf(_("%s tried to send you a %s file, but we only allow files up to %s over Direct IM. Try using file transfer instead.\n"), conn->bn, size1, size2);
+- g_free(size1);
+- g_free(size2);
+-
+- account = purple_connection_get_account(conn->od->gc);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+-
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+- g_free(frame);
+- return;
+- }
+-
+- /* We have payload data! Switch to the ODC watcher to read it. */
+- frame->payload.data = g_new(guint8, frame->payload.len);
+- frame->payload.offset = 0;
+- conn->frame = frame;
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, peer_odc_recv_cb, conn);
+- return;
+- }
+-
+- g_free(frame);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oft.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oft.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/oft.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oft.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,823 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * I feel like this is a good place to explain OFT, so I'm going to
+- * do just that. Each OFT packet has a header type. I guess this
+- * is pretty similar to the subtype of a SNAC packet. The type
+- * basically tells the other client the meaning of the OFT packet.
+- * There are two distinct types of file transfer, which I usually
+- * call "sendfile" and "getfile." Sendfile is when you send a file
+- * to another AIM user. Getfile is when you share a group of files,
+- * and other users request that you send them the files.
+- *
+- * A typical sendfile file transfer goes like this:
+- * 1) Sender sends a channel 2 ICBM telling the other user that
+- * we want to send them a file. At the same time, we open a
+- * listener socket (this should be done before sending the
+- * ICBM) on some port, and wait for them to connect to us.
+- * The ICBM we sent should contain our IP address and the port
+- * number that we're listening on.
+- * 2) The receiver connects to the sender on the given IP address
+- * and port. After the connection is established, the receiver
+- * sends an ICBM signifying that we are ready and waiting.
+- * 3) The sender sends an OFT PROMPT message over the OFT
+- * connection.
+- * 4) The receiver of the file sends back an exact copy of this
+- * OFT packet, except the cookie is filled in with the cookie
+- * from the ICBM. I think this might be an attempt to verify
+- * that the user that is connected is actually the guy that
+- * we sent the ICBM to. Oh, I've been calling this the ACK.
+- * 5) The sender starts sending raw data across the connection
+- * until the entire file has been sent.
+- * 6) The receiver knows the file is finished because the sender
+- * sent the file size in an earlier OFT packet. So then the
+- * receiver sends the DONE thingy (after filling in the
+- * "received" checksum and size) and closes the connection.
+- */
+-
+-#include "oscar.h"
+-#include "peer.h"
+-
+-#include "util.h"
+-
+-#define CHECKSUM_BUFFER_SIZE 256 * 1024
+-
+-struct _ChecksumData
+-{
+- PeerConnection *conn;
+- PurpleXfer *xfer;
+- GSourceFunc callback;
+- size_t size;
+- guint32 checksum;
+- size_t total;
+- FILE *file;
+- guint8 buffer[CHECKSUM_BUFFER_SIZE];
+- guint timer;
+-};
+-
+-void
+-peer_oft_checksum_destroy(ChecksumData *checksum_data)
+-{
+- checksum_data->conn->checksum_data = NULL;
+- fclose(checksum_data->file);
+- if (checksum_data->timer > 0)
+- purple_timeout_remove(checksum_data->timer);
+- g_free(checksum_data);
+-}
+-
+-/**
+- * Calculate oft checksum of buffer
+- *
+- * Prevcheck should be 0xFFFF0000 when starting a checksum of a file. The
+- * checksum is kind of a rolling checksum thing, so each time you get bytes
+- * of a file you just call this puppy and it updates the checksum. You can
+- * calculate the checksum of an entire file by calling this in a while or a
+- * for loop, or something.
+- *
+- * Thanks to Graham Booker for providing this improved checksum routine,
+- * which is simpler and should be more accurate than Josh Myer's original
+- * code. -- wtm
+- *
+- * This algorithm works every time I have tried it. The other fails
+- * sometimes. So, AOL who thought this up? It has got to be the weirdest
+- * checksum I have ever seen.
+- *
+- * @param buffer Buffer of data to checksum. Man I'd like to buff her...
+- * @param bufsize Size of buffer.
+- * @param prevchecksum Previous checksum.
+- * @param odd Whether an odd number of bytes have been processed before this call
+- */
+-static guint32
+-peer_oft_checksum_chunk(const guint8 *buffer, int bufferlen, guint32 prevchecksum, int odd)
+-{
+- guint32 checksum, oldchecksum;
+- int i = 0;
+- unsigned short val;
+-
+- checksum = (prevchecksum >> 16) & 0xffff;
+- if (odd)
+- {
+- /*
+- * This is one hell of a hack, but it should always work.
+- * Essentially, I am reindexing the array so that index 1
+- * is the first element. Since the odd and even bytes are
+- * detected by the index number.
+- */
+- i = 1;
+- bufferlen++;
+- buffer--;
+- }
+- for (; i < bufferlen; i++)
+- {
+- oldchecksum = checksum;
+- if (i & 1)
+- val = buffer[i];
+- else
+- val = buffer[i] << 8;
+- checksum -= val;
+- /*
+- * The following appears to be necessary.... It happens
+- * every once in a while and the checksum doesn't fail.
+- */
+- if (checksum > oldchecksum)
+- checksum--;
+- }
+- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
+- checksum = ((checksum & 0x0000ffff) + (checksum >> 16));
+- return checksum << 16;
+-}
+-
+-static gboolean
+-peer_oft_checksum_file_piece(gpointer data)
+-{
+- ChecksumData *checksum_data;
+- gboolean repeat;
+-
+- checksum_data = data;
+- repeat = FALSE;
+-
+- if (checksum_data->total < checksum_data->size)
+- {
+- size_t bytes = MIN(CHECKSUM_BUFFER_SIZE,
+- checksum_data->size - checksum_data->total);
+-
+- bytes = fread(checksum_data->buffer, 1, bytes, checksum_data->file);
+- if (bytes != 0)
+- {
+- checksum_data->checksum = peer_oft_checksum_chunk(checksum_data->buffer, bytes, checksum_data->checksum, checksum_data->total & 1);
+- checksum_data->total += bytes;
+- repeat = TRUE;
+- }
+- }
+-
+- if (!repeat)
+- {
+- purple_debug_info("oscar", "Checksum of %s calculated\n",
+- purple_xfer_get_local_filename(checksum_data->xfer));
+- if (checksum_data->callback != NULL)
+- checksum_data->callback(checksum_data);
+- peer_oft_checksum_destroy(checksum_data);
+- }
+-
+- return repeat;
+-}
+-
+-/**
+- * Calculate oft checksum of a file in a series of calls to
+- * peer_oft_checksum_file_piece(). We do it this way because
+- * calculating the checksum on large files can take a long time,
+- * and we want to return control to the UI so that the application
+- * doesn't appear completely frozen.
+- *
+- * @param conn The connection used for this file transfer.
+- * @param xfer The file transfer needing this checksum.
+- * @param callback The function to call upon calculation of the checksum.
+- * @param size The maximum size to check.
+- */
+-
+-static void
+-peer_oft_checksum_file(PeerConnection *conn, PurpleXfer *xfer, GSourceFunc callback, size_t size)
+-{
+- ChecksumData *checksum_data;
+-
+- purple_debug_info("oscar", "Calculating checksum of %s\n",
+- purple_xfer_get_local_filename(xfer));
+-
+- checksum_data = g_malloc0(sizeof(ChecksumData));
+- checksum_data->conn = conn;
+- checksum_data->xfer = xfer;
+- checksum_data->callback = callback;
+- checksum_data->size = size;
+- checksum_data->checksum = 0xffff0000;
+- checksum_data->file = g_fopen(purple_xfer_get_local_filename(xfer), "rb");
+-
+- if (checksum_data->file == NULL)
+- {
+- purple_debug_error("oscar", "Unable to open %s for checksumming: %s\n",
+- purple_xfer_get_local_filename(xfer), g_strerror(errno));
+- callback(checksum_data);
+- g_free(checksum_data);
+- }
+- else
+- {
+- checksum_data->timer = purple_timeout_add(10,
+- peer_oft_checksum_file_piece, checksum_data);
+- conn->checksum_data = checksum_data;
+- }
+-}
+-
+-static void
+-peer_oft_copy_xfer_data(PeerConnection *conn, OftFrame *frame)
+-{
+- g_free(conn->xferdata.name);
+-
+- memcpy(&(conn->xferdata), frame, sizeof(OftFrame));
+- conn->xferdata.name = g_memdup(frame->name, frame->name_length);
+-}
+-
+-/**
+- * Free any OFT related data.
+- */
+-void
+-peer_oft_close(PeerConnection *conn)
+-{
+- /*
+- * If cancelled by local user, and we're receiving a file, and
+- * we're not connected/ready then send an ICBM cancel message.
+- */
+- if ((purple_xfer_get_status(conn->xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL) &&
+- !conn->ready)
+- {
+- aim_im_sendch2_cancel(conn);
+- }
+-
+- if (conn->sending_data_timer != 0)
+- {
+- purple_timeout_remove(conn->sending_data_timer);
+- conn->sending_data_timer = 0;
+- }
+-}
+-
+-/**
+- * Write the given OftFrame to a ByteStream and send it out
+- * on the established PeerConnection.
+- */
+-static void
+-peer_oft_send(PeerConnection *conn, OftFrame *frame)
+-{
+- size_t length;
+- ByteStream bs;
+-
+- length = 192 + frame->name_length;
+- byte_stream_new(&bs, length);
+- byte_stream_putraw(&bs, conn->magic, 4);
+- byte_stream_put16(&bs, length);
+- byte_stream_put16(&bs, frame->type);
+- byte_stream_putraw(&bs, frame->cookie, 8);
+- byte_stream_put16(&bs, frame->encrypt);
+- byte_stream_put16(&bs, frame->compress);
+- byte_stream_put16(&bs, frame->totfiles);
+- byte_stream_put16(&bs, frame->filesleft);
+- byte_stream_put16(&bs, frame->totparts);
+- byte_stream_put16(&bs, frame->partsleft);
+- byte_stream_put32(&bs, frame->totsize);
+- byte_stream_put32(&bs, frame->size);
+- byte_stream_put32(&bs, frame->modtime);
+- byte_stream_put32(&bs, frame->checksum);
+- byte_stream_put32(&bs, frame->rfrcsum);
+- byte_stream_put32(&bs, frame->rfsize);
+- byte_stream_put32(&bs, frame->cretime);
+- byte_stream_put32(&bs, frame->rfcsum);
+- byte_stream_put32(&bs, frame->nrecvd);
+- byte_stream_put32(&bs, frame->recvcsum);
+- byte_stream_putraw(&bs, frame->idstring, 32);
+- byte_stream_put8(&bs, frame->flags);
+- byte_stream_put8(&bs, frame->lnameoffset);
+- byte_stream_put8(&bs, frame->lsizeoffset);
+- byte_stream_putraw(&bs, frame->dummy, 69);
+- byte_stream_putraw(&bs, frame->macfileinfo, 16);
+- byte_stream_put16(&bs, frame->nencode);
+- byte_stream_put16(&bs, frame->nlanguage);
+- /*
+- * The name can be more than 64 characters, but if it is less than
+- * 64 characters it is padded with NULLs.
+- */
+- byte_stream_putraw(&bs, frame->name, frame->name_length);
+-
+- peer_connection_send(conn, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-void
+-peer_oft_send_prompt(PeerConnection *conn)
+-{
+- conn->xferdata.type = PEER_TYPE_PROMPT;
+- peer_oft_send(conn, &conn->xferdata);
+-}
+-
+-static void
+-peer_oft_send_ack(PeerConnection *conn)
+-{
+- conn->xferdata.type = PEER_TYPE_ACK;
+-
+- /* Fill in the cookie */
+- memcpy(conn->xferdata.cookie, conn->cookie, 8);
+-
+- peer_oft_send(conn, &conn->xferdata);
+-}
+-
+-static void
+-peer_oft_send_resume_accept(PeerConnection *conn)
+-{
+- conn->xferdata.type = PEER_TYPE_RESUMEACCEPT;
+-
+- /* Fill in the cookie */
+- memcpy(conn->xferdata.cookie, conn->cookie, 8);
+-
+- peer_oft_send(conn, &conn->xferdata);
+-}
+-
+-static void
+-peer_oft_send_done(PeerConnection *conn)
+-{
+- conn->xferdata.type = PEER_TYPE_DONE;
+- conn->xferdata.rfrcsum = 0xffff0000;
+- conn->xferdata.nrecvd = purple_xfer_get_bytes_sent(conn->xfer);
+- peer_oft_send(conn, &conn->xferdata);
+-}
+-
+-/**
+- * This function exists so that we don't remove the outgoing
+- * data watcher while we're still sending data. In most cases
+- * any data we're sending will be instantly wisked away to a TCP
+- * buffer maintained by our operating system... but we want to
+- * make sure the core doesn't start sending file data while
+- * we're still sending OFT frame data. That would be bad.
+- */
+-static gboolean
+-start_transfer_when_done_sending_data(gpointer data)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0)
+- {
+- conn->sending_data_timer = 0;
+- conn->xfer->fd = conn->fd;
+- conn->fd = -1;
+- purple_xfer_start(conn->xfer, conn->xfer->fd, NULL, 0);
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-/**
+- * This function is similar to the above function, except instead
+- * of starting the xfer it will destroy the connection. This is
+- * used when you want to send one final message across the peer
+- * connection, and then close everything.
+- */
+-static gboolean
+-destroy_connection_when_done_sending_data(gpointer data)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- if (purple_circ_buffer_get_max_read(conn->buffer_outgoing) == 0)
+- {
+- conn->sending_data_timer = 0;
+- peer_connection_destroy(conn, conn->disconnect_reason, NULL);
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-/*
+- * This is called when a buddy sends us some file info. This happens when they
+- * are sending a file to you, and you have just established a connection to them.
+- * You should send them the exact same info except use the real cookie. We also
+- * get like totally ready to like, receive the file, kay?
+- */
+-static void
+-peer_oft_recv_frame_prompt(PeerConnection *conn, OftFrame *frame)
+-{
+- /* Record the file information and send an ack */
+- peer_oft_copy_xfer_data(conn, frame);
+- peer_oft_send_ack(conn);
+-
+- /* Remove our watchers and use the file transfer watchers in the core */
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+- conn->sending_data_timer = purple_timeout_add(100,
+- start_transfer_when_done_sending_data, conn);
+-}
+-
+-/**
+- * We are sending a file to someone else. They have just acknowledged our
+- * prompt, so we want to start sending data like there's no tomorrow.
+- */
+-static void
+-peer_oft_recv_frame_ack(PeerConnection *conn, OftFrame *frame)
+-{
+- if (memcmp(conn->cookie, frame->cookie, 8) != 0)
+- {
+- purple_debug_info("oscar", "Received an incorrect cookie. "
+- "Closing connection.\n");
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- return;
+- }
+-
+- /* Remove our watchers and use the file transfer watchers in the core */
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+- conn->sending_data_timer = purple_timeout_add(100,
+- start_transfer_when_done_sending_data, conn);
+-}
+-
+-static gboolean
+-peer_oft_recv_frame_resume_checksum_calculated_cb(gpointer data)
+-{
+- ChecksumData *checksum_data;
+- PeerConnection *conn;
+-
+- checksum_data = data;
+- conn = checksum_data->conn;
+-
+- /* Check the checksums here. If not match, don't allow resume */
+- if (checksum_data->checksum != conn->xferdata.recvcsum || checksum_data->total != conn->xferdata.nrecvd)
+- {
+- /* Reset internal structure */
+- conn->xferdata.recvcsum = 0xffff0000;
+- conn->xferdata.rfrcsum = 0xffff0000;
+- conn->xferdata.nrecvd = 0;
+- }
+- else
+- /* Accept the change */
+- purple_xfer_set_bytes_sent(checksum_data->xfer, conn->xferdata.nrecvd);
+-
+- peer_oft_send_resume_accept(conn);
+-
+- return FALSE;
+-}
+-
+-/**
+- * We are sending a file to someone else. They have just acknowledged our
+- * prompt and are asking to resume, so we accept their resume and await
+- * a resume ack.
+- */
+-static void
+-peer_oft_recv_frame_resume(PeerConnection *conn, OftFrame *frame)
+-{
+- if (memcmp(conn->cookie, frame->cookie, 8) != 0)
+- {
+- purple_debug_info("oscar", "Received an incorrect cookie. "
+- "Closing connection.\n");
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- return;
+- }
+-
+- /* Copy resume data into internal structure */
+- conn->xferdata.recvcsum = frame->recvcsum;
+- conn->xferdata.rfrcsum = frame->rfrcsum;
+- conn->xferdata.nrecvd = frame->nrecvd;
+-
+- peer_oft_checksum_file(conn, conn->xfer,
+- peer_oft_recv_frame_resume_checksum_calculated_cb,
+- frame->nrecvd);
+-}
+-
+-/*
+- * We just sent a file to someone. They said they got it and everything,
+- * so we can close our direct connection and what not.
+- */
+-static void
+-peer_oft_recv_frame_done(PeerConnection *conn, OftFrame *frame)
+-{
+- /*
+- * The core ft code sets the xfer to completed automatically if we've
+- * sent all bytes to the other user. But this function can be called
+- * even if we haven't sent all bytes to the other user (in the case
+- * where the user already has this file on their computer and the
+- * checksum matches).
+- */
+- if (!purple_xfer_is_completed(conn->xfer))
+- purple_xfer_set_completed(conn->xfer, TRUE);
+-
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+- conn->xfer->fd = conn->fd;
+- conn->fd = -1;
+- conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
+- peer_connection_schedule_destroy(conn, conn->disconnect_reason, NULL);
+-}
+-
+-/**
+- * Handle an incoming OftFrame. If there is a payload associated
+- * with this frame, then we remove the old watcher and add the
+- * OFT watcher to read in the payload.
+- */
+-void
+-peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs)
+-{
+- OftFrame frame;
+-
+- frame.type = byte_stream_get16(bs);
+- byte_stream_getrawbuf(bs, frame.cookie, 8);
+- frame.encrypt = byte_stream_get16(bs);
+- frame.compress = byte_stream_get16(bs);
+- frame.totfiles = byte_stream_get16(bs);
+- frame.filesleft = byte_stream_get16(bs);
+- frame.totparts = byte_stream_get16(bs);
+- frame.partsleft = byte_stream_get16(bs);
+- frame.totsize = byte_stream_get32(bs);
+- frame.size = byte_stream_get32(bs);
+- frame.modtime = byte_stream_get32(bs);
+- frame.checksum = byte_stream_get32(bs);
+- frame.rfrcsum = byte_stream_get32(bs);
+- frame.rfsize = byte_stream_get32(bs);
+- frame.cretime = byte_stream_get32(bs);
+- frame.rfcsum = byte_stream_get32(bs);
+- frame.nrecvd = byte_stream_get32(bs);
+- frame.recvcsum = byte_stream_get32(bs);
+- byte_stream_getrawbuf(bs, frame.idstring, 32);
+- frame.flags = byte_stream_get8(bs);
+- frame.lnameoffset = byte_stream_get8(bs);
+- frame.lsizeoffset = byte_stream_get8(bs);
+- byte_stream_getrawbuf(bs, frame.dummy, 69);
+- byte_stream_getrawbuf(bs, frame.macfileinfo, 16);
+- frame.nencode = byte_stream_get16(bs);
+- frame.nlanguage = byte_stream_get16(bs);
+- frame.name_length = bs->len - 186;
+- frame.name = byte_stream_getraw(bs, frame.name_length);
+-
+- purple_debug_info("oscar", "Incoming OFT frame from %s with "
+- "type=0x%04x\n", conn->bn, frame.type);
+-
+- /* TODOFT: peer_oft_dirconvert_fromstupid(frame->name); */
+-
+- switch(frame.type)
+- {
+- case PEER_TYPE_PROMPT:
+- peer_oft_recv_frame_prompt(conn, &frame);
+- break;
+- case PEER_TYPE_ACK:
+- case PEER_TYPE_RESUMEACK:
+- peer_oft_recv_frame_ack(conn, &frame);
+- break;
+- case PEER_TYPE_RESUME:
+- peer_oft_recv_frame_resume(conn, &frame);
+- break;
+- case PEER_TYPE_DONE:
+- peer_oft_recv_frame_done(conn, &frame);
+- break;
+- default:
+- break;
+- }
+-
+- g_free(frame.name);
+-}
+-
+-/*******************************************************************/
+-/* Begin PurpleXfer callbacks for use when receiving a file */
+-/*******************************************************************/
+-
+-void
+-peer_oft_recvcb_init(PurpleXfer *xfer)
+-{
+- PeerConnection *conn;
+-
+- conn = xfer->data;
+- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
+- peer_connection_trynext(conn);
+-}
+-
+-void
+-peer_oft_recvcb_end(PurpleXfer *xfer)
+-{
+- PeerConnection *conn;
+-
+- conn = xfer->data;
+-
+- /* Tell the other person that we've received everything */
+- conn->fd = conn->xfer->fd;
+- conn->xfer->fd = -1;
+- peer_oft_send_done(conn);
+-
+- conn->disconnect_reason = OSCAR_DISCONNECT_DONE;
+- conn->sending_data_timer = purple_timeout_add(100,
+- destroy_connection_when_done_sending_data, conn);
+-}
+-
+-void
+-peer_oft_recvcb_ack_recv(PurpleXfer *xfer, const guchar *buffer, size_t size)
+-{
+- PeerConnection *conn;
+-
+- /* Update our rolling checksum. Like Walmart, yo. */
+- conn = xfer->data;
+- conn->xferdata.recvcsum = peer_oft_checksum_chunk(buffer,
+- size, conn->xferdata.recvcsum, purple_xfer_get_bytes_sent(xfer) & 1);
+-}
+-
+-/*******************************************************************/
+-/* End PurpleXfer callbacks for use when receiving a file */
+-/*******************************************************************/
+-
+-/*******************************************************************/
+-/* Begin PurpleXfer callbacks for use when sending a file */
+-/*******************************************************************/
+-
+-static gboolean
+-peer_oft_checksum_calculated_cb(gpointer data)
+-{
+- ChecksumData *checksum_data;
+- PeerConnection *conn;
+-
+- checksum_data = data;
+- conn = checksum_data->conn;
+-
+- conn->xferdata.checksum = checksum_data->checksum;
+-
+- /* Start the connection process */
+- peer_connection_trynext(checksum_data->conn);
+-
+- return FALSE;
+-}
+-
+-void
+-peer_oft_sendcb_init(PurpleXfer *xfer)
+-{
+- PeerConnection *conn;
+- size_t size;
+-
+- conn = xfer->data;
+- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
+-
+- /* Make sure the file size can be represented in 32 bits */
+- size = purple_xfer_get_size(xfer);
+- if (size > G_MAXUINT32)
+- {
+- gchar *tmp, *size1, *size2;
+- size1 = purple_str_size_to_units(size);
+- size2 = purple_str_size_to_units(G_MAXUINT32);
+- tmp = g_strdup_printf(_("File %s is %s, which is larger than "
+- "the maximum size of %s."),
+- xfer->local_filename, size1, size2);
+- purple_xfer_error(purple_xfer_get_type(xfer),
+- purple_xfer_get_account(xfer), xfer->who, tmp);
+- g_free(size1);
+- g_free(size2);
+- g_free(tmp);
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+- return;
+- }
+-
+- /* Keep track of file transfer info */
+- conn->xferdata.totfiles = 1;
+- conn->xferdata.filesleft = 1;
+- conn->xferdata.totparts = 1;
+- conn->xferdata.partsleft = 1;
+- conn->xferdata.totsize = size;
+- conn->xferdata.size = size;
+- conn->xferdata.checksum = 0xffff0000;
+- conn->xferdata.rfrcsum = 0xffff0000;
+- conn->xferdata.rfcsum = 0xffff0000;
+- conn->xferdata.recvcsum = 0xffff0000;
+- strncpy((gchar *)conn->xferdata.idstring, "Cool FileXfer", 31);
+- conn->xferdata.modtime = 0;
+- conn->xferdata.cretime = 0;
+- xfer->filename = g_path_get_basename(xfer->local_filename);
+- conn->xferdata.name_length = MAX(64, strlen(xfer->filename) + 1);
+- conn->xferdata.name = (guchar *)g_strndup(xfer->filename, conn->xferdata.name_length - 1);
+-
+- peer_oft_checksum_file(conn, xfer,
+- peer_oft_checksum_calculated_cb, G_MAXUINT32);
+-}
+-
+-/*
+- * AIM file transfers aren't really meant to be thought
+- * of as a transferring just a single file. The rendezvous
+- * establishes a connection between two computers, and then
+- * those computers can use the same connection for transferring
+- * multiple files. So we don't want the Purple core up and closing
+- * the socket all willy-nilly. We want to do that in the oscar
+- * prpl, whenever one side or the other says they're finished
+- * using the connection. There might be a better way to intercept
+- * the socket from the core...
+- */
+-void
+-peer_oft_sendcb_ack(PurpleXfer *xfer, const guchar *buffer, size_t size)
+-{
+- PeerConnection *conn;
+-
+- conn = xfer->data;
+-
+- /*
+- * If we're done sending, intercept the socket from the core ft code
+- * and wait for the other guy to send the "done" OFT packet.
+- */
+- if (purple_xfer_get_bytes_remaining(xfer) <= 0)
+- {
+- purple_input_remove(xfer->watcher);
+- conn->fd = xfer->fd;
+- xfer->fd = -1;
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
+- }
+-}
+-
+-/*******************************************************************/
+-/* End PurpleXfer callbacks for use when sending a file */
+-/*******************************************************************/
+-
+-/*******************************************************************/
+-/* Begin PurpleXfer callbacks for use when sending and receiving */
+-/*******************************************************************/
+-
+-void
+-peer_oft_cb_generic_cancel(PurpleXfer *xfer)
+-{
+- PeerConnection *conn;
+-
+- conn = xfer->data;
+-
+- if (conn == NULL)
+- return;
+-
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+-}
+-
+-/*******************************************************************/
+-/* End PurpleXfer callbacks for use when sending and receiving */
+-/*******************************************************************/
+-
+-#ifdef TODOFT
+-/*
+- * This little area in oscar.c is the nexus of file transfer code,
+- * so I wrote a little explanation of what happens. I am such a
+- * ninja.
+- *
+- * The series of events for a file send is:
+- * -Create xfer and call purple_xfer_request (this happens in oscar_ask_sendfile)
+- * -User chooses a file and oscar_xfer_init is called. It establishes a
+- * listening socket, then asks the remote user to connect to us (and
+- * gives them the file name, port, IP, etc.)
+- * -They connect to us and we send them an PEER_TYPE_PROMPT (this happens
+- * in peer_oft_recv_frame_established)
+- * -They send us an PEER_TYPE_ACK and then we start sending data
+- * -When we finish, they send us an PEER_TYPE_DONE and they close the
+- * connection.
+- * -We get drunk because file transfer kicks ass.
+- *
+- * The series of events for a file receive is:
+- * -Create xfer and call purple_xfer request (this happens in incomingim_chan2)
+- * -Purple user selects file to name and location to save file to and
+- * oscar_xfer_init is called
+- * -It connects to the remote user using the IP they gave us earlier
+- * -After connecting, they send us an PEER_TYPE_PROMPT. In reply, we send
+- * them an PEER_TYPE_ACK.
+- * -They begin to send us lots of raw data.
+- * -When they finish sending data we send an PEER_TYPE_DONE and then close
+- * the connection.
+- *
+- * Update August 2005:
+- * The series of events for transfers has been seriously complicated by the addition
+- * of transfer redirects and proxied connections. I could throw a whole lot of words
+- * at trying to explain things here, but it probably wouldn't do much good. To get
+- * a better idea of what happens, take a look at the diagrams and documentation
+- * from my Summer of Code project. -- Jonathan Clark
+- */
+-
+-/**
+- * Convert the directory separator from / (0x2f) to ^A (0x01)
+- *
+- * @param name The filename to convert.
+- */
+-static void
+-peer_oft_dirconvert_tostupid(char *name)
+-{
+- while (name[0]) {
+- if (name[0] == 0x01)
+- name[0] = G_DIR_SEPARATOR;
+- name++;
+- }
+-}
+-
+-/**
+- * Convert the directory separator from ^A (0x01) to / (0x2f)
+- *
+- * @param name The filename to convert.
+- */
+-static void
+-peer_oft_dirconvert_fromstupid(char *name)
+-{
+- while (name[0]) {
+- if (name[0] == G_DIR_SEPARATOR)
+- name[0] = 0x01;
+- name++;
+- }
+-}
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/oscar.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,5818 +0,0 @@
+-/*
+- * purple
+- *
+- * Some code copyright (C) 1998-1999, Mark Spencer <markster@marko.net>
+- * Some code copyright (C) 1999-2001, Eric Warmenhoven
+- * Some code copyright (C) 2001-2003, Sean Egan
+- * Some code copyright (C) 2001-2007, Mark Doliner <thekingant@users.sourceforge.net>
+- * Some code copyright (C) 2005, Jonathan Clark <ardentlygnarly@users.sourceforge.net>
+- * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) <foss@combots.com>
+- * Some code copyright (C) 2008, Aman Gupta
+- *
+- * Most libfaim code copyright (C) 1998-2001 Adam Fritzler <afritz@auk.cx>
+- * Some libfaim code copyright (C) 2001-2004 Mark Doliner <thekingant@users.sourceforge.net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "buddyicon.h"
+-#include "cipher.h"
+-#include "conversation.h"
+-#include "core.h"
+-#include "debug.h"
+-#include "encoding.h"
+-#include "imgstore.h"
+-#include "network.h"
+-#include "notify.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-#include "proxy.h"
+-#include "request.h"
+-#include "util.h"
+-#include "version.h"
+-#include "visibility.h"
+-
+-#include "oscarcommon.h"
+-#include "oscar.h"
+-#include "peer.h"
+-
+-#define AIMHASHDATA "http://pidgin.im/aim_data.php3"
+-
+-#define OSCAR_CONNECT_STEPS 6
+-
+-static guint64 purple_caps =
+- OSCAR_CAPABILITY_CHAT
+- | OSCAR_CAPABILITY_BUDDYICON
+- | OSCAR_CAPABILITY_DIRECTIM
+- | OSCAR_CAPABILITY_SENDFILE
+- | OSCAR_CAPABILITY_UNICODE
+- | OSCAR_CAPABILITY_INTEROPERATE
+- | OSCAR_CAPABILITY_SHORTCAPS
+- | OSCAR_CAPABILITY_TYPING
+- | OSCAR_CAPABILITY_ICQSERVERRELAY
+- | OSCAR_CAPABILITY_NEWCAPS
+- | OSCAR_CAPABILITY_XTRAZ
+- | OSCAR_CAPABILITY_HTML_MSGS;
+-
+-static guint8 features_aim[] = {0x01, 0x01, 0x01, 0x02};
+-static guint8 features_icq[] = {0x01};
+-
+-struct create_room {
+- char *name;
+- int exchange;
+-};
+-
+-struct oscar_ask_directim_data
+-{
+- OscarData *od;
+- char *who;
+-};
+-
+-/* All the libfaim->purple callback functions */
+-
+-/* Only used when connecting with the old-style BUCP login */
+-static int purple_parse_auth_resp (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_login (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_auth_securid_request(OscarData *, FlapConnection *, FlapFrame *, ...);
+-
+-static int purple_handle_redirect (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_info_change (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_account_confirm (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_oncoming (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_offgoing (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_incoming_im(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_misses (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_clientauto (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_motd (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_chatnav_info (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_conv_chat_join (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_conv_chat_leave (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_conv_chat_info_update (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_conv_chat_incoming_msg(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_email_parseupdate(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_icon_parseicon (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_searcherror(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_searchreply(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_bosrights (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_connerr (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_mtn (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_locaterights(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_buddyrights(OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_parse_genericerr (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_memrequest (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_selfinfo (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_popup (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_parseerr (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_parserights (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_parselist (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_parseack (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_parseaddmod (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_authgiven (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_authrequest (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_authreply (OscarData *, FlapConnection *, FlapFrame *, ...);
+-static int purple_ssi_gotadded (OscarData *, FlapConnection *, FlapFrame *, ...);
+-
+-static void purple_icons_fetch(PurpleConnection *gc);
+-
+-void oscar_set_info(PurpleConnection *gc, const char *info);
+-static void oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo, gboolean setstatus, PurpleStatus *status);
+-static void oscar_set_extended_status(PurpleConnection *gc);
+-static gboolean purple_ssi_rerequestdata(gpointer data);
+-
+-void oscar_free_name_data(struct name_data *data) {
+- g_free(data->name);
+- g_free(data->nick);
+- g_free(data);
+-}
+-
+-#ifdef _WIN32
+-const char *oscar_get_locale_charset(void) {
+- static const char *charset = NULL;
+- if (charset == NULL)
+- g_get_charset(&charset);
+- return charset;
+-}
+-#endif
+-
+-static char *oscar_icqstatus(int state) {
+- /* Make a cute little string that shows the status of the dude or dudet */
+- if (state & AIM_ICQ_STATE_CHAT)
+- return g_strdup(_("Free For Chat"));
+- else if (state & AIM_ICQ_STATE_DND)
+- return g_strdup(_("Do Not Disturb"));
+- else if (state & AIM_ICQ_STATE_OUT)
+- return g_strdup(_("Not Available"));
+- else if (state & AIM_ICQ_STATE_BUSY)
+- return g_strdup(_("Occupied"));
+- else if (state & AIM_ICQ_STATE_AWAY)
+- return g_strdup(_("Away"));
+- else if (state & AIM_ICQ_STATE_WEBAWARE)
+- return g_strdup(_("Web Aware"));
+- else if (state & AIM_ICQ_STATE_INVISIBLE)
+- return g_strdup(_("Invisible"));
+- else if (state & AIM_ICQ_STATE_EVIL)
+- return g_strdup(_("Evil"));
+- else if (state & AIM_ICQ_STATE_DEPRESSION)
+- return g_strdup(_("Depression"));
+- else if (state & AIM_ICQ_STATE_ATHOME)
+- return g_strdup(_("At home"));
+- else if (state & AIM_ICQ_STATE_ATWORK)
+- return g_strdup(_("At work"));
+- else if (state & AIM_ICQ_STATE_LUNCH)
+- return g_strdup(_("At lunch"));
+- else
+- return g_strdup(_("Online"));
+-}
+-
+-static char *extract_name(const char *name) {
+- char *tmp, *x;
+- int i, j;
+-
+- if (!name)
+- return NULL;
+-
+- x = strchr(name, '-');
+- if (!x)
+- return NULL;
+-
+- x = strchr(x + 1, '-');
+- if (!x)
+- return NULL;
+-
+- tmp = g_strdup(++x);
+-
+- for (i = 0, j = 0; x[i]; i++) {
+- char hex[3];
+- if (x[i] != '%') {
+- tmp[j++] = x[i];
+- continue;
+- }
+- strncpy(hex, x + ++i, 2);
+- hex[2] = 0;
+- i++;
+- tmp[j++] = strtol(hex, NULL, 16);
+- }
+-
+- tmp[j] = 0;
+- return tmp;
+-}
+-
+-static struct chat_connection *
+-find_oscar_chat(PurpleConnection *gc, int id)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- GSList *cur;
+- struct chat_connection *cc;
+-
+- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
+- {
+- cc = (struct chat_connection *)cur->data;
+- if (cc->id == id)
+- return cc;
+- }
+-
+- return NULL;
+-}
+-
+-static struct chat_connection *
+-find_oscar_chat_by_conn(PurpleConnection *gc, FlapConnection *conn)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- GSList *cur;
+- struct chat_connection *cc;
+-
+- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
+- {
+- cc = (struct chat_connection *)cur->data;
+- if (cc->conn == conn)
+- return cc;
+- }
+-
+- return NULL;
+-}
+-
+-static struct chat_connection *
+-find_oscar_chat_by_conv(PurpleConnection *gc, PurpleConversation *conv)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- GSList *cur;
+- struct chat_connection *cc;
+-
+- for (cur = od->oscar_chats; cur != NULL; cur = cur->next)
+- {
+- cc = (struct chat_connection *)cur->data;
+- if (cc->conv == conv)
+- return cc;
+- }
+-
+- return NULL;
+-}
+-
+-void
+-oscar_chat_destroy(struct chat_connection *cc)
+-{
+- g_free(cc->name);
+- g_free(cc->show);
+- g_free(cc);
+-}
+-
+-static void
+-oscar_chat_kill(PurpleConnection *gc, struct chat_connection *cc)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- /* Notify the conversation window that we've left the chat */
+- serv_got_chat_left(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(cc->conv)));
+-
+- /* Destroy the chat_connection */
+- od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
+- oscar_chat_destroy(cc);
+-}
+-
+-/**
+- * This is called from the callback functions for establishing
+- * a TCP connection with an oscar host if an error occurred.
+- */
+-static void
+-connection_common_error_cb(FlapConnection *conn, const gchar *error_message)
+-{
+- OscarData *od;
+- PurpleConnection *gc;
+-
+- od = conn->od;
+- gc = od->gc;
+-
+- purple_debug_error("oscar", "unable to connect to FLAP "
+- "server of type 0x%04hx\n", conn->type);
+-
+- if (conn->type == SNAC_FAMILY_AUTH)
+- {
+- /* This only happens when connecting with the old-style BUCP login */
+- gchar *msg;
+- msg = g_strdup_printf(_("Unable to connect to authentication server: %s"),
+- error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- }
+- else if (conn->type == SNAC_FAMILY_LOCATE)
+- {
+- gchar *msg;
+- msg = g_strdup_printf(_("Unable to connect to BOS server: %s"),
+- error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, msg);
+- g_free(msg);
+- }
+- else
+- {
+- /* Maybe we should call this for BOS connections, too? */
+- flap_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_COULD_NOT_CONNECT, error_message);
+- }
+-}
+-
+-/**
+- * This is called from the callback functions for establishing
+- * a TCP connection with an oscar host. Depending on the type
+- * of host, we do a few different things here.
+- */
+-static void
+-connection_common_established_cb(FlapConnection *conn)
+-{
+- OscarData *od;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+-
+- od = conn->od;
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- purple_debug_info("oscar", "connected to FLAP server of type 0x%04hx\n",
+- conn->type);
+-
+- if (conn->cookie == NULL)
+- flap_connection_send_version(od, conn);
+- else
+- {
+- if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN))
+- {
+- ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM;
+- ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ;
+- flap_connection_send_version_with_cookie_and_clientinfo(od,
+- conn, conn->cookielen, conn->cookie,
+- od->icq ? &icqinfo : &aiminfo,
+- purple_account_get_bool(account, "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS));
+- } else {
+- flap_connection_send_version_with_cookie(od, conn,
+- conn->cookielen, conn->cookie);
+- }
+-
+-
+- g_free(conn->cookie);
+- conn->cookie = NULL;
+- }
+-
+- if (conn->type == SNAC_FAMILY_AUTH)
+- {
+- /* This only happens when connecting with the old-style BUCP login */
+- aim_request_login(od, conn, purple_account_get_username(account));
+- purple_debug_info("oscar", "Username sent, waiting for response\n");
+- purple_connection_update_progress(gc, _("Username sent"), 1, OSCAR_CONNECT_STEPS);
+- }
+- else if (conn->type == SNAC_FAMILY_LOCATE)
+- {
+- purple_connection_update_progress(gc, _("Connection established, cookie sent"), 4, OSCAR_CONNECT_STEPS);
+- }
+- else if (conn->type == SNAC_FAMILY_CHAT)
+- {
+- od->oscar_chats = g_slist_prepend(od->oscar_chats, conn->new_conn_data);
+- conn->new_conn_data = NULL;
+- }
+-}
+-
+-static void
+-connection_established_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- FlapConnection *conn;
+-
+- conn = data;
+-
+- conn->connect_data = NULL;
+- conn->fd = source;
+-
+- if (source < 0)
+- {
+- connection_common_error_cb(conn, error_message);
+- return;
+- }
+-
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, flap_connection_recv_cb, conn);
+- connection_common_established_cb(conn);
+-}
+-
+-static void
+-ssl_connection_established_cb(gpointer data, PurpleSslConnection *gsc,
+- PurpleInputCondition cond)
+-{
+- FlapConnection *conn;
+-
+- conn = data;
+-
+- purple_ssl_input_add(gsc, flap_connection_recv_cb_ssl, conn);
+- connection_common_established_cb(conn);
+-}
+-
+-static void
+-ssl_connection_error_cb(PurpleSslConnection *gsc, PurpleSslErrorType error,
+- gpointer data)
+-{
+- FlapConnection *conn;
+-
+- conn = data;
+-
+- if (conn->watcher_outgoing)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- }
+-
+- /* sslconn frees the connection on error */
+- conn->gsc = NULL;
+-
+- connection_common_error_cb(conn, purple_ssl_strerror(error));
+-}
+-
+-static void
+-flap_connection_established_bos(OscarData *od, FlapConnection *conn)
+-{
+- PurpleConnection *gc = od->gc;
+-
+- aim_srv_reqpersonalinfo(od, conn);
+-
+- purple_debug_info("oscar", "ssi: requesting rights and list\n");
+- aim_ssi_reqrights(od);
+- aim_ssi_reqdata(od);
+- if (od->getblisttimer > 0)
+- purple_timeout_remove(od->getblisttimer);
+- od->getblisttimer = purple_timeout_add_seconds(30, purple_ssi_rerequestdata, od);
+-
+- aim_locate_reqrights(od);
+- aim_buddylist_reqrights(od, conn);
+- aim_im_reqparams(od);
+- aim_bos_reqrights(od, conn); /* TODO: Don't call this with ssi */
+-
+- purple_connection_update_progress(gc, _("Finalizing connection"), 5, OSCAR_CONNECT_STEPS);
+-}
+-
+-static void
+-flap_connection_established_admin(OscarData *od, FlapConnection *conn)
+-{
+- aim_srv_clientready(od, conn);
+- purple_debug_info("oscar", "connected to admin\n");
+-
+- if (od->chpass) {
+- purple_debug_info("oscar", "changing password\n");
+- aim_admin_changepasswd(od, conn, od->newp, od->oldp);
+- g_free(od->oldp);
+- od->oldp = NULL;
+- g_free(od->newp);
+- od->newp = NULL;
+- od->chpass = FALSE;
+- }
+- if (od->setnick) {
+- purple_debug_info("oscar", "formatting username\n");
+- aim_admin_setnick(od, conn, od->newformatting);
+- g_free(od->newformatting);
+- od->newformatting = NULL;
+- od->setnick = FALSE;
+- }
+- if (od->conf) {
+- purple_debug_info("oscar", "confirming account\n");
+- aim_admin_reqconfirm(od, conn);
+- od->conf = FALSE;
+- }
+- if (od->reqemail) {
+- purple_debug_info("oscar", "requesting email address\n");
+- aim_admin_getinfo(od, conn, 0x0011);
+- od->reqemail = FALSE;
+- }
+- if (od->setemail) {
+- purple_debug_info("oscar", "setting email address\n");
+- aim_admin_setemail(od, conn, od->email);
+- g_free(od->email);
+- od->email = NULL;
+- od->setemail = FALSE;
+- }
+-}
+-
+-static void
+-flap_connection_established_chat(OscarData *od, FlapConnection *conn)
+-{
+- PurpleConnection *gc = od->gc;
+- struct chat_connection *chatcon;
+- static int id = 1;
+-
+- aim_srv_clientready(od, conn);
+-
+- chatcon = find_oscar_chat_by_conn(gc, conn);
+- if (chatcon) {
+- chatcon->id = id;
+- chatcon->conv = serv_got_joined_chat(gc, id++, chatcon->show);
+- }
+-}
+-
+-static void
+-flap_connection_established_chatnav(OscarData *od, FlapConnection *conn)
+-{
+- aim_srv_clientready(od, conn);
+- aim_chatnav_reqrights(od, conn);
+-}
+-
+-static void
+-flap_connection_established_alert(OscarData *od, FlapConnection *conn)
+-{
+- aim_email_sendcookies(od);
+- aim_email_activate(od);
+- aim_srv_clientready(od, conn);
+-}
+-
+-static void
+-flap_connection_established_bart(OscarData *od, FlapConnection *conn)
+-{
+- PurpleConnection *gc = od->gc;
+-
+- aim_srv_clientready(od, conn);
+-
+- od->iconconnecting = FALSE;
+-
+- purple_icons_fetch(gc);
+-}
+-
+-static int
+-flap_connection_established(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- purple_debug_info("oscar", "FLAP connection of type 0x%04hx is "
+- "now fully connected\n", conn->type);
+- if (conn->type == SNAC_FAMILY_LOCATE)
+- flap_connection_established_bos(od, conn);
+- else if (conn->type == SNAC_FAMILY_ADMIN)
+- flap_connection_established_admin(od, conn);
+- else if (conn->type == SNAC_FAMILY_CHAT)
+- flap_connection_established_chat(od, conn);
+- else if (conn->type == SNAC_FAMILY_CHATNAV)
+- flap_connection_established_chatnav(od, conn);
+- else if (conn->type == SNAC_FAMILY_ALERT)
+- flap_connection_established_alert(od, conn);
+- else if (conn->type == SNAC_FAMILY_BART)
+- flap_connection_established_bart(od, conn);
+-
+- return 1;
+-}
+-
+-static void
+-idle_reporting_pref_cb(const char *name, PurplePrefType type,
+- gconstpointer value, gpointer data)
+-{
+- PurpleConnection *gc;
+- OscarData *od;
+- gboolean report_idle;
+- guint32 presence;
+-
+- gc = data;
+- od = purple_connection_get_protocol_data(gc);
+- report_idle = strcmp((const char *)value, "none") != 0;
+- presence = aim_ssi_getpresence(od->ssi.local);
+-
+- if (report_idle)
+- aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
+- else
+- aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
+-}
+-
+-/**
+- * Should probably make a "Use recent buddies group" account preference
+- * so that this option is surfaced to the user.
+- */
+-static void
+-recent_buddies_pref_cb(const char *name, PurplePrefType type,
+- gconstpointer value, gpointer data)
+-{
+- PurpleConnection *gc;
+- OscarData *od;
+- guint32 presence;
+-
+- gc = data;
+- od = purple_connection_get_protocol_data(gc);
+- presence = aim_ssi_getpresence(od->ssi.local);
+-
+- if (value)
+- aim_ssi_setpresence(od, presence & ~AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
+- else
+- aim_ssi_setpresence(od, presence | AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES);
+-}
+-
+-static const gchar *login_servers[] = {
+- AIM_DEFAULT_LOGIN_SERVER,
+- AIM_DEFAULT_SSL_LOGIN_SERVER,
+- ICQ_DEFAULT_LOGIN_SERVER,
+- ICQ_DEFAULT_SSL_LOGIN_SERVER,
+-};
+-
+-static const gchar *
+-get_login_server(gboolean is_icq, gboolean use_ssl)
+-{
+- return login_servers[(is_icq ? 2 : 0) + (use_ssl ? 1 : 0)];
+-}
+-
+-static gint
+-compare_handlers(gconstpointer a, gconstpointer b)
+-{
+- guint aa = GPOINTER_TO_UINT(a);
+- guint bb = GPOINTER_TO_UINT(b);
+- guint family1 = aa >> 16;
+- guint family2 = bb >> 16;
+- guint subtype1 = aa & 0xFFFF;
+- guint subtype2 = bb & 0xFFFF;
+- if (family1 != family2) {
+- return family1 - family2;
+- }
+- return subtype1 - subtype2;
+-}
+-
+-#if !GLIB_CHECK_VERSION(2,14,0)
+-static void hash_table_get_list_of_keys(gpointer key, gpointer value, gpointer user_data)
+-{
+- GList **handlers = (GList **)user_data;
+-
+- *handlers = g_list_prepend(*handlers, key);
+-}
+-#endif /* GLIB < 2.14.0 */
+-
+-void
+-oscar_login(PurpleAccount *account)
+-{
+- PurpleConnection *gc;
+- OscarData *od;
+- const gchar *encryption_type;
+- GList *handlers;
+- GList *sorted_handlers;
+- GList *cur;
+- GString *msg = g_string_new("");
+-
+- gc = purple_account_get_connection(account);
+- od = oscar_data_new();
+- od->gc = gc;
+- purple_connection_set_protocol_data(gc, od);
+-
+- oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNERR, purple_connerr, 0);
+- oscar_data_addhandler(od, AIM_CB_FAM_SPECIAL, AIM_CB_SPECIAL_CONNINITDONE, flap_connection_established, 0);
+-
+- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0003, purple_info_change, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0005, purple_info_change, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ADMIN, 0x0007, purple_account_confirm, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ALERT, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ALERT, SNAC_SUBTYPE_ALERT_MAILSTATUS, purple_email_parseupdate, 0);
+-
+- /* These are only needed when connecting with the old-style BUCP login */
+- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0003, purple_parse_auth_resp, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, 0x0007, purple_parse_login, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_AUTH, SNAC_SUBTYPE_AUTH_SECURID_REQUEST, purple_parse_auth_securid_request, 0);
+-
+- oscar_data_addhandler(od, SNAC_FAMILY_BART, SNAC_SUBTYPE_BART_RESPONSE, purple_icon_parseicon, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BOS, 0x0003, purple_bosrights, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_RIGHTSINFO, purple_parse_buddyrights, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_ONCOMING, purple_parse_oncoming, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_BUDDY, SNAC_SUBTYPE_BUDDY_OFFGOING, purple_parse_offgoing, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERJOIN, purple_conv_chat_join, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_USERLEAVE, purple_conv_chat_leave, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE, purple_conv_chat_info_update, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHAT, SNAC_SUBTYPE_CHAT_INCOMINGMSG, purple_conv_chat_incoming_msg, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_CHATNAV, SNAC_SUBTYPE_CHATNAV_INFO, purple_chatnav_info, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ERROR, purple_ssi_parseerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO, purple_ssi_parserights, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_LIST, purple_ssi_parselist, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_SRVACK, purple_ssi_parseack, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADD, purple_ssi_parseaddmod, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_MOD, purple_ssi_parseaddmod, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTH, purple_ssi_authgiven, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ, purple_ssi_authrequest, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP, purple_ssi_authreply, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_FEEDBAG, SNAC_SUBTYPE_FEEDBAG_ADDED, purple_ssi_gotadded, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_INCOMING, purple_parse_incoming_im, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MISSEDCALL, purple_parse_misses, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_CLIENTAUTORESP, purple_parse_clientauto, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_ICBM, SNAC_SUBTYPE_ICBM_MTN, purple_parse_mtn, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_LOCATE, SNAC_SUBTYPE_LOCATE_RIGHTSINFO, purple_parse_locaterights, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x0001, purple_parse_genericerr, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x000f, purple_selfinfo, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, 0x001f, purple_memrequest, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_REDIRECT, purple_handle_redirect, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_OSERVICE, SNAC_SUBTYPE_OSERVICE_MOTD, purple_parse_motd, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_POPUP, 0x0002, purple_popup, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, SNAC_SUBTYPE_USERLOOKUP_ERROR, purple_parse_searcherror, 0);
+- oscar_data_addhandler(od, SNAC_FAMILY_USERLOOKUP, 0x0003, purple_parse_searchreply, 0);
+-
+- g_string_append(msg, "Registered handlers: ");
+-#if GLIB_CHECK_VERSION(2,14,0)
+- handlers = g_hash_table_get_keys(od->handlerlist);
+-#else
+- handlers = NULL;
+- g_hash_table_foreach(od->handlerlist, hash_table_get_list_of_keys, &handlers);
+-#endif /* GLIB < 2.14.0 */
+- sorted_handlers = g_list_sort(g_list_copy(handlers), compare_handlers);
+- for (cur = sorted_handlers; cur; cur = cur->next) {
+- guint x = GPOINTER_TO_UINT(cur->data);
+- g_string_append_printf(msg, "%04x/%04x, ", x >> 16, x & 0xFFFF);
+- }
+- g_list_free(sorted_handlers);
+- g_list_free(handlers);
+- purple_debug_misc("oscar", "%s\n", msg->str);
+- g_string_free(msg, TRUE);
+-
+- purple_debug_misc("oscar", "oscar_login: gc = %p\n", gc);
+-
+- if (!oscar_util_valid_name(purple_account_get_username(account))) {
+- gchar *buf;
+- buf = g_strdup_printf(_("Unable to sign on as %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), purple_account_get_username(account));
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_SETTINGS, buf);
+- g_free(buf);
+- return;
+- }
+-
+- gc->flags |= PURPLE_CONNECTION_HTML;
+- if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq")) {
+- od->icq = TRUE;
+- } else {
+- gc->flags |= PURPLE_CONNECTION_AUTO_RESP;
+- }
+-
+- /* Set this flag based on the protocol_id rather than the username,
+- because that is what's tied to the get_moods prpl callback. */
+- if (g_str_equal(purple_account_get_protocol_id(account), "prpl-icq"))
+- gc->flags |= PURPLE_CONNECTION_SUPPORT_MOODS;
+-
+- od->default_port = purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT);
+-
+- encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
+- if (!purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
+- purple_connection_error_reason(
+- gc,
+- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+- _("You required encryption in your account settings, but encryption is not supported by your system."));
+- return;
+- }
+- od->use_ssl = purple_ssl_is_supported() && strcmp(encryption_type, OSCAR_NO_ENCRYPTION) != 0;
+-
+- /* Connect to core Purple signals */
+- purple_prefs_connect_callback(gc, "/purple/away/idle_reporting", idle_reporting_pref_cb, gc);
+- purple_prefs_connect_callback(gc, "/plugins/prpl/oscar/recent_buddies", recent_buddies_pref_cb, gc);
+-
+- /*
+- * On 2008-03-05 AOL released some documentation on the OSCAR protocol
+- * which includes a new login method called clientLogin. It is similar
+- * (though not the same?) as what the AIM 6.0 series uses to
+- * authenticate.
+- *
+- * AIM 5.9 and lower use an MD5-based login procedure called "BUCP".
+- * This authentication method is used for both ICQ and AIM when
+- * clientLogin is not enabled.
+- */
+- if (purple_account_get_bool(account, "use_clientlogin", OSCAR_DEFAULT_USE_CLIENTLOGIN)) {
+- send_client_login(od, purple_account_get_username(account));
+- } else {
+- FlapConnection *newconn;
+- const char *server;
+-
+- newconn = flap_connection_new(od, SNAC_FAMILY_AUTH);
+-
+- if (od->use_ssl) {
+- server = purple_account_get_string(account, "server", get_login_server(od->icq, TRUE));
+-
+- /*
+- * If the account's server is what the oscar prpl has offered as
+- * the default login server through the vast eons (all two of
+- * said default options, AFAIK) and the user wants SSL, we'll
+- * do what we know is best for them and change the setting out
+- * from under them to the SSL login server.
+- */
+- if (!strcmp(server, get_login_server(od->icq, FALSE)) || !strcmp(server, AIM_ALT_LOGIN_SERVER)) {
+- purple_debug_info("oscar", "Account uses SSL, so changing server to default SSL server\n");
+- purple_account_set_string(account, "server", get_login_server(od->icq, TRUE));
+- server = get_login_server(od->icq, TRUE);
+- }
+-
+- newconn->gsc = purple_ssl_connect(account, server,
+- purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
+- ssl_connection_established_cb, ssl_connection_error_cb, newconn);
+- } else {
+- server = purple_account_get_string(account, "server", get_login_server(od->icq, FALSE));
+-
+- /*
+- * See the comment above. We do the reverse here. If they don't want
+- * SSL but their server is set to OSCAR_DEFAULT_SSL_LOGIN_SERVER,
+- * set it back to the default.
+- */
+- if (!strcmp(server, get_login_server(od->icq, TRUE))) {
+- purple_debug_info("oscar", "Account does not use SSL, so changing server back to non-SSL\n");
+- purple_account_set_string(account, "server", get_login_server(od->icq, FALSE));
+- server = get_login_server(od->icq, FALSE);
+- }
+-
+- newconn->connect_data = purple_proxy_connect(NULL, account, server,
+- purple_account_get_int(account, "port", OSCAR_DEFAULT_LOGIN_PORT),
+- connection_established_cb, newconn);
+- }
+-
+- if (newconn->gsc == NULL && newconn->connect_data == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- return;
+- }
+- }
+-
+- purple_connection_update_progress(gc, _("Connecting"), 0, OSCAR_CONNECT_STEPS);
+-}
+-
+-void
+-oscar_close(PurpleConnection *gc)
+-{
+- OscarData *od;
+-
+- od = purple_connection_get_protocol_data(gc);
+-
+- while (od->oscar_chats)
+- {
+- struct chat_connection *cc = od->oscar_chats->data;
+- od->oscar_chats = g_slist_remove(od->oscar_chats, cc);
+- oscar_chat_destroy(cc);
+- }
+- while (od->create_rooms)
+- {
+- struct create_room *cr = od->create_rooms->data;
+- g_free(cr->name);
+- od->create_rooms = g_slist_remove(od->create_rooms, cr);
+- g_free(cr);
+- }
+- oscar_data_destroy(od);
+- purple_connection_set_protocol_data(gc, NULL);
+-
+- purple_prefs_disconnect_by_handle(gc);
+-
+- purple_debug_info("oscar", "Signed off.\n");
+-}
+-
+-/* XXX - Should use purple_util_fetch_url for the below stuff */
+-struct pieceofcrap {
+- PurpleConnection *gc;
+- unsigned long offset;
+- unsigned long len;
+- char *modname;
+- int fd;
+- FlapConnection *conn;
+- unsigned int inpa;
+-};
+-
+-static void damn_you(gpointer data, gint source, PurpleInputCondition c)
+-{
+- struct pieceofcrap *pos = data;
+- OscarData *od = purple_connection_get_protocol_data(pos->gc);
+- char in = '\0';
+- int x = 0;
+- unsigned char m[17];
+- GString *msg;
+-
+- while (read(pos->fd, &in, 1) == 1) {
+- if (in == '\n')
+- x++;
+- else if (in != '\r')
+- x = 0;
+- if (x == 2)
+- break;
+- in = '\0';
+- }
+- if (in != '\n') {
+- char buf[256];
+- g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. "
+- "If so, check %s for updates."),
+- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
+- purple_notify_warning(pos->gc, NULL,
+- _("Unable to get a valid AIM login hash."),
+- buf);
+- purple_input_remove(pos->inpa);
+- close(pos->fd);
+- g_free(pos);
+- return;
+- }
+- if (read(pos->fd, m, 16) != 16)
+- {
+- purple_debug_warning("oscar", "Could not read full AIM login hash "
+- "from " AIMHASHDATA "--that's bad.\n");
+- }
+- m[16] = '\0';
+-
+- msg = g_string_new("Sending hash: ");
+- for (x = 0; x < 16; x++)
+- g_string_append_printf(msg, "%02hhx ", (unsigned char)m[x]);
+- g_string_append(msg, "\n");
+- purple_debug_misc("oscar", "%s", msg->str);
+- g_string_free(msg, TRUE);
+-
+- purple_input_remove(pos->inpa);
+- close(pos->fd);
+- aim_sendmemblock(od, pos->conn, 0, 16, m, AIM_SENDMEMBLOCK_FLAG_ISHASH);
+- g_free(pos);
+-}
+-
+-static void
+-straight_to_hell(gpointer data, gint source, const gchar *error_message)
+-{
+- struct pieceofcrap *pos = data;
+- gchar *buf;
+- gssize result;
+-
+- pos->fd = source;
+-
+- if (source < 0) {
+- buf = g_strdup_printf(_("You may be disconnected shortly. "
+- "If so, check %s for updates."),
+- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
+- purple_notify_warning(pos->gc, NULL,
+- _("Unable to get a valid AIM login hash."),
+- buf);
+- g_free(buf);
+- g_free(pos->modname);
+- g_free(pos);
+- return;
+- }
+-
+- buf = g_strdup_printf("GET " AIMHASHDATA "?offset=%ld&len=%ld&modname=%s HTTP/1.0\n\n",
+- pos->offset, pos->len, pos->modname ? pos->modname : "");
+- result = send(pos->fd, buf, strlen(buf), 0);
+- if (result != strlen(buf)) {
+- if (result < 0)
+- purple_debug_error("oscar", "Error writing %" G_GSIZE_FORMAT
+- " bytes to fetch AIM hash data: %s\n",
+- strlen(buf), g_strerror(errno));
+- else
+- purple_debug_error("oscar", "Tried to write %"
+- G_GSIZE_FORMAT " bytes to fetch AIM hash data but "
+- "instead wrote %" G_GSSIZE_FORMAT " bytes\n",
+- strlen(buf), result);
+- }
+- g_free(buf);
+- g_free(pos->modname);
+- pos->inpa = purple_input_add(pos->fd, PURPLE_INPUT_READ, damn_you, pos);
+- return;
+-}
+-
+-/* size of icbmui.ocm, the largest module in AIM 3.5 */
+-#define AIM_MAX_FILE_SIZE 98304
+-
+-static int purple_memrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- va_list ap;
+- struct pieceofcrap *pos;
+- guint32 offset, len;
+- char *modname;
+-
+- va_start(ap, fr);
+- offset = va_arg(ap, guint32);
+- len = va_arg(ap, guint32);
+- modname = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_misc("oscar", "offset: %u, len: %u, file: %s\n",
+- offset, len, (modname ? modname : "aim.exe"));
+-
+- if (len == 0) {
+- purple_debug_misc("oscar", "len is 0, hashing NULL\n");
+- aim_sendmemblock(od, conn, offset, len, NULL,
+- AIM_SENDMEMBLOCK_FLAG_ISREQUEST);
+- return 1;
+- }
+-
+- pos = g_new0(struct pieceofcrap, 1);
+- pos->gc = od->gc;
+- pos->conn = conn;
+-
+- pos->offset = offset;
+- pos->len = len;
+- pos->modname = g_strdup(modname);
+-
+- if (purple_proxy_connect(pos->gc, pos->gc->account, "pidgin.im", 80,
+- straight_to_hell, pos) == NULL)
+- {
+- char buf[256];
+- g_free(pos->modname);
+- g_free(pos);
+-
+- g_snprintf(buf, sizeof(buf), _("You may be disconnected shortly. "
+- "If so, check %s for updates."),
+- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
+- purple_notify_warning(pos->gc, NULL,
+- _("Unable to get a valid login hash."),
+- buf);
+- }
+-
+- return 1;
+-}
+-
+-int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname)
+-{
+- PurpleAccount *account;
+- FlapConnection *conn;
+-
+- account = purple_connection_get_account(gc);
+-
+- conn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
+- conn->cookielen = cookielen;
+- conn->cookie = g_memdup(cookie, cookielen);
+-
+- /*
+- * Use TLS only if the server provided us with a tls_certname. The server might not specify a tls_certname even if we requested to use TLS,
+- * and that is something we should be prepared to.
+- */
+- if (tls_certname)
+- {
+- conn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
+- ssl_connection_established_cb, ssl_connection_error_cb,
+- tls_certname, conn);
+- }
+- else
+- {
+- conn->connect_data = purple_proxy_connect(NULL,
+- account, host, port,
+- connection_established_cb, conn);
+- }
+-
+- if (conn->gsc == NULL && conn->connect_data == NULL)
+- {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
+- return 0;
+- }
+-
+- od->default_port = port;
+-
+- purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
+-
+- return 1;
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static int
+-purple_parse_auth_resp(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- char *host; int port;
+- int i;
+- FlapConnection *newconn;
+- va_list ap;
+- struct aim_authresp_info *info;
+-
+- port = purple_account_get_int(account, "port", od->default_port);
+-
+- va_start(ap, fr);
+- info = va_arg(ap, struct aim_authresp_info *);
+- va_end(ap);
+-
+- purple_debug_info("oscar",
+- "inside auth_resp (Username: %s)\n", info->bn);
+-
+- if (info->errorcode || !info->bosip || !info->cookielen || !info->cookie) {
+- char buf[256];
+- switch (info->errorcode) {
+- case 0x01:
+- /* Unregistered username */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_INVALID_USERNAME, _("Username does not exist"));
+- break;
+- case 0x05:
+- /* Incorrect password */
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Incorrect password"));
+- break;
+- case 0x11:
+- /* Suspended account */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Your account is currently suspended"));
+- break;
+- case 0x02:
+- case 0x14:
+- /* service temporarily unavailable */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("The AOL Instant Messenger service is temporarily unavailable."));
+- break;
+- case 0x18:
+- /* username connecting too frequently */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your username has been connecting and disconnecting too frequently. Wait ten minutes and try again. If you continue to try, you will need to wait even longer."));
+- break;
+- case 0x1c:
+- {
+- /* client too old */
+- g_snprintf(buf, sizeof(buf), _("The client version you are using is too old. Please upgrade at %s"),
+- oscar_get_ui_info_string("website", PURPLE_WEBSITE));
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, buf);
+- break;
+- }
+- case 0x1d:
+- /* IP address connecting too frequently */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_OTHER_ERROR, _("Your IP address has been connecting and disconnecting too frequently. Wait a minute and try again. If you continue to try, you will need to wait even longer."));
+- break;
+- default:
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED, _("Unknown reason"));
+- break;
+- }
+- purple_debug_info("oscar", "Login Error Code 0x%04hx\n", info->errorcode);
+- purple_debug_info("oscar", "Error URL: %s\n", info->errorurl ? info->errorurl : "");
+- return 1;
+- }
+-
+- purple_debug_misc("oscar", "Reg status: %hu\n"
+- "Email: %s\n"
+- "BOSIP: %s\n",
+- info->regstatus,
+- info->email ? info->email : "null",
+- info->bosip ? info->bosip : "null");
+- purple_debug_info("oscar", "Closing auth connection...\n");
+- flap_connection_schedule_destroy(conn, OSCAR_DISCONNECT_DONE, NULL);
+-
+- for (i = 0; i < strlen(info->bosip); i++) {
+- if (info->bosip[i] == ':') {
+- port = atoi(&(info->bosip[i+1]));
+- break;
+- }
+- }
+- host = g_strndup(info->bosip, i);
+- newconn = flap_connection_new(od, SNAC_FAMILY_LOCATE);
+- newconn->cookielen = info->cookielen;
+- newconn->cookie = g_memdup(info->cookie, info->cookielen);
+-
+- if (od->use_ssl)
+- {
+- /*
+- * This shouldn't be hardcoded to "bos.oscar.aol.com" except that
+- * the server isn't sending us a name to use for comparing the
+- * certificate common name.
+- */
+- newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
+- ssl_connection_established_cb, ssl_connection_error_cb,
+- "bos.oscar.aol.com", newconn);
+- }
+- else
+- {
+- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
+- connection_established_cb, newconn);
+- }
+-
+- g_free(host);
+- if (newconn->gsc == NULL && newconn->connect_data == NULL)
+- {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _("Unable to connect"));
+- return 0;
+- }
+-
+- purple_connection_update_progress(gc, _("Received authorization"), 3, OSCAR_CONNECT_STEPS);
+-
+- return 1;
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static void
+-purple_parse_auth_securid_request_yes_cb(gpointer user_data, const char *msg)
+-{
+- PurpleConnection *gc = user_data;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- aim_auth_securid_send(od, msg);
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static void
+-purple_parse_auth_securid_request_no_cb(gpointer user_data, const char *value)
+-{
+- PurpleConnection *gc = user_data;
+-
+- /* Disconnect */
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED,
+- _("The SecurID key entered is invalid"));
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static int
+-purple_parse_auth_securid_request(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- gchar *primary;
+-
+- purple_debug_info("oscar", "Got SecurID request\n");
+-
+- primary = g_strdup_printf("Enter the SecurID key for %s.", purple_account_get_username(account));
+- purple_request_input(gc, NULL, _("Enter SecurID"), primary,
+- _("Enter the 6 digit number from the digital display."),
+- FALSE, FALSE, NULL,
+- _("_OK"), G_CALLBACK(purple_parse_auth_securid_request_yes_cb),
+- _("_Cancel"), G_CALLBACK(purple_parse_auth_securid_request_no_cb),
+- account, NULL, NULL,
+- gc);
+- g_free(primary);
+-
+- return 1;
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static int
+-purple_parse_login(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- ClientInfo aiminfo = CLIENTINFO_PURPLE_AIM;
+- ClientInfo icqinfo = CLIENTINFO_PURPLE_ICQ;
+- va_list ap;
+- char *key;
+- gboolean truncate_pass;
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- key = va_arg(ap, char *);
+- truncate_pass = va_arg(ap, int);
+- va_end(ap);
+-
+- aim_send_login(od, conn, purple_account_get_username(account),
+- purple_connection_get_password(gc), truncate_pass,
+- od->icq ? &icqinfo : &aiminfo, key,
+- purple_account_get_bool(account, "allow_multiple_logins", OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS));
+-
+- purple_connection_update_progress(gc, _("Password sent"), 2, OSCAR_CONNECT_STEPS);
+-
+- return 1;
+-}
+-
+-static int
+-purple_handle_redirect(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- char *host, *separator;
+- int port;
+- FlapConnection *newconn;
+- va_list ap;
+- struct aim_redirect_data *redir;
+-
+- va_start(ap, fr);
+- redir = va_arg(ap, struct aim_redirect_data *);
+- va_end(ap);
+-
+- port = od->default_port;
+- separator = strchr(redir->ip, ':');
+- if (separator != NULL)
+- {
+- host = g_strndup(redir->ip, separator - redir->ip);
+- port = atoi(separator + 1);
+- }
+- else
+- host = g_strdup(redir->ip);
+-
+- if (!redir->use_ssl) {
+- const gchar *encryption_type = purple_account_get_string(account, "encryption", OSCAR_DEFAULT_ENCRYPTION);
+- if (strcmp(encryption_type, OSCAR_OPPORTUNISTIC_ENCRYPTION) == 0) {
+- purple_debug_warning("oscar", "We won't use SSL for FLAP type 0x%04hx.\n", redir->group);
+- } else if (strcmp(encryption_type, OSCAR_REQUIRE_ENCRYPTION) == 0) {
+- purple_debug_error("oscar", "FLAP server %s:%d of type 0x%04hx doesn't support encryption.", host, port, redir->group);
+- purple_connection_error_reason(
+- gc,
+- PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT,
+- _("You required encryption in your account settings, but one of the servers doesn't support it."));
+- return 0;
+- }
+- }
+-
+- /*
+- * These FLAP servers advertise SSL (type "0x02"), but SSL connections to these hosts
+- * die a painful death. iChat and Miranda, when using SSL, still do these in plaintext.
+- */
+- if (redir->use_ssl && (redir->group == SNAC_FAMILY_ADMIN ||
+- redir->group == SNAC_FAMILY_BART))
+- {
+- purple_debug_info("oscar", "Ignoring broken SSL for FLAP type 0x%04hx.\n", redir->group);
+- redir->use_ssl = 0;
+- }
+-
+- purple_debug_info("oscar", "Connecting to FLAP server %s:%d of type 0x%04hx\n", host, port, redir->group);
+-
+- newconn = flap_connection_new(od, redir->group);
+- newconn->cookielen = redir->cookielen;
+- newconn->cookie = g_memdup(redir->cookie, redir->cookielen);
+- if (newconn->type == SNAC_FAMILY_CHAT)
+- {
+- struct chat_connection *cc;
+- cc = g_new0(struct chat_connection, 1);
+- cc->conn = newconn;
+- cc->gc = gc;
+- cc->name = g_strdup(redir->chat.room);
+- cc->exchange = redir->chat.exchange;
+- cc->instance = redir->chat.instance;
+- cc->show = extract_name(redir->chat.room);
+- newconn->new_conn_data = cc;
+- purple_debug_info("oscar", "Connecting to chat room %s exchange %hu\n", cc->name, cc->exchange);
+- }
+-
+-
+- if (redir->use_ssl)
+- {
+- newconn->gsc = purple_ssl_connect_with_ssl_cn(account, host, port,
+- ssl_connection_established_cb, ssl_connection_error_cb,
+- redir->ssl_cert_cn, newconn);
+- }
+- else
+- {
+- newconn->connect_data = purple_proxy_connect(NULL, account, host, port,
+- connection_established_cb, newconn);
+- }
+-
+- if (newconn->gsc == NULL && newconn->connect_data == NULL)
+- {
+- flap_connection_schedule_destroy(newconn,
+- OSCAR_DISCONNECT_COULD_NOT_CONNECT,
+- _("Unable to initialize connection"));
+- purple_debug_error("oscar", "Unable to connect to FLAP server "
+- "of type 0x%04hx\n", redir->group);
+- }
+- g_free(host);
+-
+- return 1;
+-}
+-
+-
+-static int purple_parse_oncoming(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PurpleBuddy *buddy = NULL;
+- PurpleStatus *previous_status = NULL;
+- struct buddyinfo *bi;
+- time_t time_idle = 0, signon = 0;
+- int type = 0;
+- gboolean buddy_is_away = FALSE;
+- const char *status_id;
+- va_list ap;
+- aim_userinfo_t *info;
+- char *message;
+- char *itmsurl = NULL;
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- info = va_arg(ap, aim_userinfo_t *);
+- va_end(ap);
+-
+- g_return_val_if_fail(info != NULL, 1);
+- g_return_val_if_fail(info->bn != NULL, 1);
+-
+- buddy = purple_find_buddy(account, info->bn);
+- if (buddy) {
+- previous_status = purple_presence_get_active_status(purple_buddy_get_presence(buddy));
+- }
+-
+- /*
+- * If this is an AIM buddy and their name has formatting, set their
+- * server alias.
+- */
+- if (!oscar_util_valid_name_icq(info->bn)) {
+- gboolean bn_has_formatting = FALSE;
+- char *c;
+- for (c = info->bn; *c != '\0'; c++) {
+- if (!islower(*c)) {
+- bn_has_formatting = TRUE;
+- break;
+- }
+- }
+- serv_got_alias(gc, info->bn,
+- bn_has_formatting ? info->bn : NULL);
+- }
+-
+- if (info->present & AIM_USERINFO_PRESENT_FLAGS) {
+- if (info->flags & AIM_FLAG_AWAY)
+- buddy_is_away = TRUE;
+- }
+- if (info->present & AIM_USERINFO_PRESENT_ICQEXTSTATUS) {
+- type = info->icqinfo.status;
+- if (!(info->icqinfo.status & AIM_ICQ_STATE_CHAT) &&
+- (info->icqinfo.status != AIM_ICQ_STATE_NORMAL)) {
+- buddy_is_away = TRUE;
+- }
+- }
+-
+- if (oscar_util_valid_name_icq(info->bn)) {
+- if (type & AIM_ICQ_STATE_CHAT)
+- status_id = OSCAR_STATUS_ID_FREE4CHAT;
+- else if (type & AIM_ICQ_STATE_DND)
+- status_id = OSCAR_STATUS_ID_DND;
+- else if (type & AIM_ICQ_STATE_OUT)
+- status_id = OSCAR_STATUS_ID_NA;
+- else if (type & AIM_ICQ_STATE_BUSY)
+- status_id = OSCAR_STATUS_ID_OCCUPIED;
+- else if (type & AIM_ICQ_STATE_AWAY)
+- status_id = OSCAR_STATUS_ID_AWAY;
+- else if (type & AIM_ICQ_STATE_INVISIBLE)
+- status_id = OSCAR_STATUS_ID_INVISIBLE;
+- else if (type & AIM_ICQ_STATE_EVIL)
+- status_id = OSCAR_STATUS_ID_EVIL;
+- else if (type & AIM_ICQ_STATE_DEPRESSION)
+- status_id = OSCAR_STATUS_ID_DEPRESSION;
+- else if (type & AIM_ICQ_STATE_ATHOME)
+- status_id = OSCAR_STATUS_ID_ATHOME;
+- else if (type & AIM_ICQ_STATE_ATWORK)
+- status_id = OSCAR_STATUS_ID_ATWORK;
+- else if (type & AIM_ICQ_STATE_LUNCH)
+- status_id = OSCAR_STATUS_ID_LUNCH;
+- else
+- status_id = OSCAR_STATUS_ID_AVAILABLE;
+- } else {
+- if (type & AIM_ICQ_STATE_INVISIBLE)
+- status_id = OSCAR_STATUS_ID_INVISIBLE;
+- else if (buddy_is_away)
+- status_id = OSCAR_STATUS_ID_AWAY;
+- else
+- status_id = OSCAR_STATUS_ID_AVAILABLE;
+- }
+-
+- if (info->flags & AIM_FLAG_WIRELESS) {
+- purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_MOBILE, NULL);
+- } else {
+- purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
+- }
+-
+- message = (info->status && info->status_len > 0)
+- ? oscar_encoding_to_utf8(info->status_encoding, info->status, info->status_len)
+- : NULL;
+-
+- if (strcmp(status_id, OSCAR_STATUS_ID_AVAILABLE) == 0) {
+- /* TODO: If itmsurl is NULL, does that mean the URL has been
+- cleared? Or does it mean the URL should remain unchanged? */
+- if (info->itmsurl != NULL) {
+- itmsurl = (info->itmsurl_len > 0) ? oscar_encoding_to_utf8(info->itmsurl_encoding, info->itmsurl, info->itmsurl_len) : NULL;
+- } else if (previous_status != NULL && purple_status_is_available(previous_status)) {
+- itmsurl = g_strdup(purple_status_get_attr_string(previous_status, "itmsurl"));
+- }
+- purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s', itmsurl = '%s'\n", status_id, info->bn, message ? message : "(null)", itmsurl ? itmsurl : "(null)");
+- purple_prpl_got_user_status(account, info->bn, status_id, "message", message, "itmsurl", itmsurl, NULL);
+- } else {
+- purple_debug_info("oscar", "Activating status '%s' for buddy %s, message = '%s'\n", status_id, info->bn, message ? message : "(null)");
+- purple_prpl_got_user_status(account, info->bn, status_id, "message", message, NULL);
+- }
+-
+- g_free(message);
+- g_free(itmsurl);
+-
+- /* Login time stuff */
+- if (info->present & AIM_USERINFO_PRESENT_ONLINESINCE)
+- signon = info->onlinesince;
+- else if (info->present & AIM_USERINFO_PRESENT_SESSIONLEN)
+- signon = time(NULL) - info->sessionlen;
+- purple_prpl_got_user_login_time(account, info->bn, signon);
+-
+- /* Idle time stuff */
+- /* info->idletime is the number of minutes that this user has been idle */
+- if (info->present & AIM_USERINFO_PRESENT_IDLE)
+- time_idle = time(NULL) - info->idletime * 60;
+-
+- if (time_idle > 0)
+- purple_prpl_got_user_idle(account, info->bn, TRUE, time_idle);
+- else
+- purple_prpl_got_user_idle(account, info->bn, FALSE, 0);
+-
+- /* Server stored icon stuff */
+- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, info->bn));
+- if (!bi) {
+- bi = g_new0(struct buddyinfo, 1);
+- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, info->bn)), bi);
+- }
+- bi->typingnot = FALSE;
+- bi->ico_informed = FALSE;
+- bi->ipaddr = info->icqinfo.ipaddr;
+-
+- if (info->iconcsumlen) {
+- const char *saved_b16 = NULL;
+- char *b16 = NULL;
+- PurpleBuddy *b = NULL;
+-
+- b16 = purple_base16_encode(info->iconcsum, info->iconcsumlen);
+- b = purple_find_buddy(account, info->bn);
+- if (b != NULL)
+- saved_b16 = purple_buddy_icons_get_checksum_for_user(b);
+-
+- if (!b16 || !saved_b16 || strcmp(b16, saved_b16)) {
+- /* Invalidate the old icon for this user */
+- purple_buddy_icons_set_for_user(account, info->bn, NULL, 0, NULL);
+-
+- /* Fetch the new icon (if we're not already doing so) */
+- if (g_slist_find_custom(od->requesticon, info->bn,
+- (GCompareFunc)oscar_util_name_compare) == NULL)
+- {
+- od->requesticon = g_slist_prepend(od->requesticon,
+- g_strdup(purple_normalize(account, info->bn)));
+- purple_icons_fetch(gc);
+- }
+- }
+- g_free(b16);
+- }
+-
+- return 1;
+-}
+-
+-static int purple_parse_offgoing(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- va_list ap;
+- aim_userinfo_t *info;
+-
+- va_start(ap, fr);
+- info = va_arg(ap, aim_userinfo_t *);
+- va_end(ap);
+-
+- purple_prpl_got_user_status(account, info->bn, OSCAR_STATUS_ID_OFFLINE, NULL);
+- purple_prpl_got_user_status_deactive(account, info->bn, OSCAR_STATUS_ID_MOBILE);
+- g_hash_table_remove(od->buddyinfo, purple_normalize(gc->account, info->bn));
+-
+- return 1;
+-}
+-
+-static int incomingim_chan1(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch1_args *args) {
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleMessageFlags flags = 0;
+- struct buddyinfo *bi;
+- PurpleStoredImage *img;
+- gchar *tmp;
+- const char *start, *end;
+- GData *attribs;
+-
+- purple_debug_misc("oscar", "Received IM from %s\n", userinfo->bn);
+-
+- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
+- if (!bi) {
+- bi = g_new0(struct buddyinfo, 1);
+- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, userinfo->bn)), bi);
+- }
+-
+- if (args->icbmflags & AIM_IMFLAGS_AWAY)
+- flags |= PURPLE_MESSAGE_AUTO_RESP;
+-
+- if (args->icbmflags & AIM_IMFLAGS_TYPINGNOT)
+- bi->typingnot = TRUE;
+- else
+- bi->typingnot = FALSE;
+-
+- if ((args->icbmflags & AIM_IMFLAGS_HASICON) && (args->iconlen) && (args->iconsum) && (args->iconstamp)) {
+- purple_debug_misc("oscar", "%s has an icon\n", userinfo->bn);
+- if ((args->iconlen != bi->ico_len) || (args->iconsum != bi->ico_csum) || (args->iconstamp != bi->ico_time)) {
+- bi->ico_need = TRUE;
+- bi->ico_len = args->iconlen;
+- bi->ico_csum = args->iconsum;
+- bi->ico_time = args->iconstamp;
+- }
+- }
+-
+- img = purple_buddy_icons_find_account_icon(account);
+- if ((img != NULL) &&
+- (args->icbmflags & AIM_IMFLAGS_BUDDYREQ) && !bi->ico_sent && bi->ico_informed) {
+- gconstpointer data = purple_imgstore_get_data(img);
+- size_t len = purple_imgstore_get_size(img);
+- purple_debug_info("oscar",
+- "Sending buddy icon to %s (%" G_GSIZE_FORMAT " bytes)\n",
+- userinfo->bn, len);
+- aim_im_sendch2_icon(od, userinfo->bn, data, len,
+- purple_buddy_icons_get_account_icon_timestamp(account),
+- aimutil_iconsum(data, len));
+- }
+- purple_imgstore_unref(img);
+-
+- tmp = g_strdup(args->msg);
+-
+- /*
+- * Convert iChat color tags to normal font tags.
+- */
+- if (purple_markup_find_tag("body", tmp, &start, &end, &attribs))
+- {
+- int len;
+- char *tmp2, *body;
+- const char *ichattextcolor, *ichatballooncolor;
+- const char *slash_body_start, *slash_body_end = NULL; /* </body> */
+- GData *unused;
+-
+- /*
+- * Find the ending </body> so we can strip off the outer <html/>
+- * and <body/>
+- */
+- if (purple_markup_find_tag("/body", end + 1, &slash_body_start, &slash_body_end, &unused))
+- {
+- body = g_strndup(start, slash_body_end - start + 1);
+- g_datalist_clear(&unused);
+- }
+- else
+- {
+- purple_debug_warning("oscar", "Broken message contains <body> but not </body>!\n");
+- /* Take everything after <body> */
+- body = g_strdup(start);
+- }
+-
+- ichattextcolor = g_datalist_get_data(&attribs, "ichattextcolor");
+- if (ichattextcolor != NULL)
+- {
+- tmp2 = g_strdup_printf("<font color=\"%s\">%s</font>", ichattextcolor, body);
+- g_free(body);
+- body = tmp2;
+- }
+-
+- ichatballooncolor = g_datalist_get_data(&attribs, "ichatballooncolor");
+- if (ichatballooncolor != NULL)
+- {
+- tmp2 = g_strdup_printf("<font back=\"%s\">%s</font>", ichatballooncolor, body);
+- g_free(body);
+- body = tmp2;
+- }
+-
+- g_datalist_clear(&attribs);
+-
+- len = start - tmp;
+- tmp2 = g_strdup_printf("%.*s%s%s", len, tmp, body, slash_body_end ? slash_body_end + 1: "</body>");
+- g_free(tmp);
+- g_free(body);
+-
+- tmp = tmp2;
+- }
+-
+- /*
+- * Are there <html/> surrounding tags? If so, strip them out, too.
+- */
+- if (purple_markup_find_tag("html", tmp, &start, &end, &attribs))
+- {
+- gchar *tmp2;
+- int len;
+-
+- g_datalist_clear(&attribs);
+-
+- len = start - tmp;
+- tmp2 = g_strdup_printf("%.*s%s", len, tmp, end + 1);
+- g_free(tmp);
+- tmp = tmp2;
+- }
+-
+- if (purple_markup_find_tag("/html", tmp, &start, &end, &attribs))
+- {
+- gchar *tmp2;
+- int len;
+-
+- g_datalist_clear(&attribs);
+-
+- len = start - tmp;
+- tmp2 = g_strdup_printf("%.*s%s", len, tmp, end + 1);
+- g_free(tmp);
+- tmp = tmp2;
+- }
+-
+- serv_got_im(gc, userinfo->bn, tmp, flags, (args->icbmflags & AIM_IMFLAGS_OFFLINE) ? args->timestamp : time(NULL));
+- g_free(tmp);
+-
+- return 1;
+-}
+-
+-static int
+-incomingim_chan2(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, IcbmArgsCh2 *args)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PurpleMessageFlags flags = 0;
+- char *message = NULL;
+-
+- g_return_val_if_fail(od != NULL, 0);
+- g_return_val_if_fail(od->gc != NULL, 0);
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+- od = purple_connection_get_protocol_data(gc);
+-
+- if (args == NULL)
+- return 0;
+-
+- purple_debug_misc("oscar", "Incoming rendezvous message of type %"
+- G_GUINT64_FORMAT ", user %s, status %hu\n",
+- args->type, userinfo->bn, args->status);
+-
+- if (args->msg != NULL) {
+- message = oscar_encoding_to_utf8(args->encoding, args->msg, args->msglen);
+- }
+-
+- if (args->type & OSCAR_CAPABILITY_CHAT)
+- {
+- char *utf8name, *tmp;
+- GHashTable *components;
+-
+- if (!args->info.chat.roominfo.name || !args->info.chat.roominfo.exchange) {
+- g_free(message);
+- return 1;
+- }
+- utf8name = oscar_encoding_to_utf8(args->encoding, args->info.chat.roominfo.name, args->info.chat.roominfo.namelen);
+-
+- tmp = extract_name(utf8name);
+- if (tmp != NULL)
+- {
+- g_free(utf8name);
+- utf8name = tmp;
+- }
+-
+- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+- g_free);
+- g_hash_table_replace(components, g_strdup("room"), utf8name);
+- g_hash_table_replace(components, g_strdup("exchange"),
+- g_strdup_printf("%d", args->info.chat.roominfo.exchange));
+- serv_got_chat_invite(gc,
+- utf8name,
+- userinfo->bn,
+- message,
+- components);
+- }
+-
+- else if ((args->type & OSCAR_CAPABILITY_SENDFILE) || (args->type & OSCAR_CAPABILITY_DIRECTIM))
+- {
+- if (args->status == AIM_RENDEZVOUS_PROPOSE)
+- {
+- peer_connection_got_proposition(od, userinfo->bn, message, args);
+- }
+- else if (args->status == AIM_RENDEZVOUS_CANCEL)
+- {
+- /* The other user cancelled a peer request */
+- PeerConnection *conn;
+-
+- conn = peer_connection_find_by_cookie(od, userinfo->bn, args->cookie);
+- /*
+- * If conn is NULL it means we haven't tried to create
+- * a connection with that user. They may be trying to
+- * do something malicious.
+- */
+- if (conn != NULL)
+- {
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- }
+- }
+- else if (args->status == AIM_RENDEZVOUS_CONNECTED)
+- {
+- /*
+- * Remote user has accepted our peer request. If we
+- * wanted to we could look up the PeerConnection using
+- * args->cookie, but we don't need to do anything here.
+- */
+- }
+- }
+-
+- else if (args->type & OSCAR_CAPABILITY_GETFILE)
+- {
+- }
+-
+- else if (args->type & OSCAR_CAPABILITY_TALK)
+- {
+- }
+-
+- else if (args->type & OSCAR_CAPABILITY_BUDDYICON)
+- {
+- purple_buddy_icons_set_for_user(account, userinfo->bn,
+- g_memdup(args->info.icon.icon, args->info.icon.length),
+- args->info.icon.length,
+- NULL);
+- }
+-
+- else if (args->type & OSCAR_CAPABILITY_ICQSERVERRELAY)
+- {
+- purple_debug_info("oscar", "Got an ICQ Server Relay message of "
+- "type %d\n", args->info.rtfmsg.msgtype);
+-
+- if (args->info.rtfmsg.msgtype == 1) {
+- if (args->info.rtfmsg.msg != NULL) {
+- char *rtfmsg;
+- const char *encoding = args->encoding;
+- size_t len = strlen(args->info.rtfmsg.msg);
+- char *tmp, *tmp2;
+-
+- if (encoding == NULL && !g_utf8_validate(args->info.rtfmsg.msg, len, NULL)) {
+- /* Yet another wonderful Miranda-related hack. If their user disables the "Send Unicode messages" setting,
+- * Miranda sends us ch2 messages in whatever Windows codepage is set as default on their user's system (instead of UTF-8).
+- * Of course, they don't bother to specify that codepage. Let's just fallback to the encoding OUR users can
+- * specify in account options as a last resort.
+- */
+- encoding = purple_account_get_string(account, "encoding", OSCAR_DEFAULT_CUSTOM_ENCODING);
+- purple_debug_info("oscar", "Miranda, is that you? Using '%s' as encoding\n", encoding);
+- }
+-
+- rtfmsg = oscar_encoding_to_utf8(encoding, args->info.rtfmsg.msg, len);
+-
+- /* Channel 2 messages are supposed to be plain-text (never mind the name "rtfmsg", even
+- * the official client doesn't parse them as RTF). Therefore, we should escape them before
+- * showing to the user. */
+- tmp = g_markup_escape_text(rtfmsg, -1);
+- g_free(rtfmsg);
+- tmp2 = purple_strreplace(tmp, "\r\n", "<br>");
+- g_free(tmp);
+-
+- serv_got_im(gc, userinfo->bn, tmp2, flags, time(NULL));
+- aim_im_send_icq_confirmation(od, userinfo->bn, args->cookie);
+- g_free(tmp2);
+- }
+- } else if (args->info.rtfmsg.msgtype == 26) {
+- purple_debug_info("oscar", "Sending X-Status Reply\n");
+- icq_relay_xstatus(od, userinfo->bn, args->cookie);
+- }
+- }
+- else
+- {
+- purple_debug_error("oscar", "Unknown request class %"
+- G_GUINT64_FORMAT "\n", args->type);
+- }
+-
+- g_free(message);
+-
+- return 1;
+-}
+-
+-/* When someone sends you buddies */
+-static void
+-purple_icq_buddyadd(struct name_data *data)
+-{
+- PurpleConnection *gc = data->gc;
+-
+- purple_blist_request_add_buddy(purple_connection_get_account(gc), data->name, NULL, data->nick);
+-
+- oscar_free_name_data(data);
+-}
+-
+-static int
+-incomingim_chan4(OscarData *od, FlapConnection *conn, aim_userinfo_t *userinfo, struct aim_incomingim_ch4_args *args, time_t t)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- gchar **msg1, **msg2;
+- int i, numtoks;
+-
+- if (!args->type || !args->msg || !args->uin)
+- return 1;
+-
+- purple_debug_info("oscar",
+- "Received a channel 4 message of type 0x%02hx.\n",
+- args->type);
+-
+- /*
+- * Split up the message at the delimeter character, then convert each
+- * string to UTF-8. Unless, of course, this is a type 1 message. If
+- * this is a type 1 message, then the delimiter 0xfe could be a valid
+- * character in whatever encoding the message was sent in. Type 1
+- * messages are always made up of only one part, so we can easily account
+- * for this suck-ass part of the protocol by splitting the string into at
+- * most 1 baby string.
+- */
+- msg1 = g_strsplit(args->msg, "\376", (args->type == 0x01 ? 1 : 0));
+- for (numtoks=0; msg1[numtoks]; numtoks++);
+- msg2 = (gchar **)g_malloc((numtoks+1)*sizeof(gchar *));
+- for (i=0; msg1[i]; i++) {
+- gchar *uin = g_strdup_printf("%u", args->uin);
+-
+- purple_str_strip_char(msg1[i], '\r');
+- /* TODO: Should use an encoding other than ASCII? */
+- msg2[i] = oscar_decode_im(account, uin, AIM_CHARSET_ASCII, msg1[i], strlen(msg1[i]));
+- g_free(uin);
+- }
+- msg2[i] = NULL;
+-
+- switch (args->type) {
+- case 0x01: { /* MacICQ message or basic offline message */
+- if (i >= 1) {
+- gchar *uin = g_strdup_printf("%u", args->uin);
+- gchar *tmp;
+-
+- /* If the message came from an ICQ user then escape any HTML */
+- tmp = g_markup_escape_text(msg2[0], -1);
+-
+- if (t) { /* This is an offline message */
+- /* The timestamp is UTC-ish, so we need to get the offset */
+-#ifdef HAVE_TM_GMTOFF
+- time_t now;
+- struct tm *tm;
+- now = time(NULL);
+- tm = localtime(&now);
+- t += tm->tm_gmtoff;
+-#else
+-# ifdef HAVE_TIMEZONE
+- tzset();
+- t -= timezone;
+-# endif
+-#endif
+- serv_got_im(gc, uin, tmp, 0, t);
+- } else { /* This is a message from MacICQ/Miranda */
+- serv_got_im(gc, uin, tmp, 0, time(NULL));
+- }
+- g_free(uin);
+- g_free(tmp);
+- }
+- } break;
+-
+- case 0x04: { /* Someone sent you a URL */
+- if (i >= 2) {
+- if (msg2[1] != NULL) {
+- gchar *uin = g_strdup_printf("%u", args->uin);
+- gchar *message = g_strdup_printf("<A HREF=\"%s\">%s</A>",
+- msg2[1],
+- (msg2[0] && msg2[0][0]) ? msg2[0] : msg2[1]);
+- serv_got_im(gc, uin, message, 0, time(NULL));
+- g_free(uin);
+- g_free(message);
+- }
+- }
+- } break;
+-
+- case 0x06: { /* Someone requested authorization */
+- if (i >= 6) {
+- gchar *bn = g_strdup_printf("%u", args->uin);
+- gchar *reason = NULL;
+-
+- if (msg2[5] != NULL)
+- reason = oscar_decode_im(account, bn, AIM_CHARSET_LATIN_1, msg2[5], strlen(msg2[5]));
+-
+- purple_debug_info("oscar",
+- "Received an authorization request from UIN %u\n",
+- args->uin);
+- aim_icq_getalias(od, bn, TRUE, reason);
+- g_free(bn);
+- g_free(reason);
+- }
+- } break;
+-
+- case 0x07: { /* Someone has denied you authorization */
+- if (i >= 1) {
+- gchar *dialog_msg = g_strdup_printf(_("The user %u has denied your request to add them to your buddy list for the following reason:\n%s"), args->uin, msg2[0] ? msg2[0] : _("No reason given."));
+- purple_notify_info(gc, NULL, _("ICQ authorization denied."),
+- dialog_msg);
+- g_free(dialog_msg);
+- }
+- } break;
+-
+- case 0x08: { /* Someone has granted you authorization */
+- gchar *dialog_msg = g_strdup_printf(_("The user %u has granted your request to add them to your buddy list."), args->uin);
+- purple_notify_info(gc, NULL, "ICQ authorization accepted.",
+- dialog_msg);
+- g_free(dialog_msg);
+- } break;
+-
+- case 0x09: { /* Message from the Godly ICQ server itself, I think */
+- if (i >= 5) {
+- gchar *dialog_msg = g_strdup_printf(_("You have received a special message\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
+- purple_notify_info(gc, NULL, "ICQ Server Message", dialog_msg);
+- g_free(dialog_msg);
+- }
+- } break;
+-
+- case 0x0d: { /* Someone has sent you a pager message from http://www.icq.com/your_uin */
+- if (i >= 6) {
+- gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ page\n\nFrom: %s [%s]\n%s"), msg2[0], msg2[3], msg2[5]);
+- purple_notify_info(gc, NULL, "ICQ Page", dialog_msg);
+- g_free(dialog_msg);
+- }
+- } break;
+-
+- case 0x0e: { /* Someone has emailed you at your_uin@pager.icq.com */
+- if (i >= 6) {
+- gchar *dialog_msg = g_strdup_printf(_("You have received an ICQ email from %s [%s]\n\nMessage is:\n%s"), msg2[0], msg2[3], msg2[5]);
+- purple_notify_info(gc, NULL, "ICQ Email", dialog_msg);
+- g_free(dialog_msg);
+- }
+- } break;
+-
+- case 0x12: {
+- /* Ack for authorizing/denying someone. Or possibly an ack for sending any system notice */
+- /* Someone added you to their buddy list? */
+- } break;
+-
+- case 0x13: { /* Someone has sent you some ICQ buddies */
+- guint i, num;
+- gchar **text;
+- text = g_strsplit(args->msg, "\376", 0);
+- if (text) {
+- /* Read the number of contacts that we were sent */
+- errno = 0;
+- num = text[0] ? strtoul(text[0], NULL, 10) : 0;
+-
+- if (num > 0 && errno == 0) {
+- for (i=0; i<num; i++) {
+- struct name_data *data;
+- gchar *message;
+-
+- if (!text[i*2 + 1] || !text[i*2 + 2]) {
+- /* We're missing the contact name or nickname. Bail out. */
+- gchar *tmp = g_strescape(args->msg, NULL);
+- purple_debug_error("oscar", "Unknown syntax parsing "
+- "ICQ buddies. args->msg=%s\n", tmp);
+- g_free(tmp);
+- break;
+- }
+-
+- message = g_strdup_printf(_("ICQ user %u has sent you a buddy: %s (%s)"), args->uin, text[i*2+2], text[i*2+1]);
+-
+- data = g_new(struct name_data, 1);
+- data->gc = gc;
+- data->name = g_strdup(text[i*2+1]);
+- data->nick = g_strdup(text[i*2+2]);
+-
+- purple_request_action(gc, NULL, message,
+- _("Do you want to add this buddy "
+- "to your buddy list?"),
+- PURPLE_DEFAULT_ACTION_NONE,
+- purple_connection_get_account(gc), data->name, NULL,
+- data, 2,
+- _("_Add"), G_CALLBACK(purple_icq_buddyadd),
+- _("_Decline"), G_CALLBACK(oscar_free_name_data));
+- g_free(message);
+- }
+- } else {
+- gchar *tmp = g_strescape(args->msg, NULL);
+- purple_debug_error("oscar", "Unknown syntax parsing "
+- "ICQ buddies. args->msg=%s\n", tmp);
+- g_free(tmp);
+- }
+- g_strfreev(text);
+- }
+- } break;
+-
+- case 0x1a: { /* Handle SMS or someone has sent you a greeting card or requested buddies? */
+- ByteStream qbs;
+- guint16 smstype;
+- guint32 taglen, smslen;
+- char *tagstr = NULL, *smsmsg = NULL;
+- xmlnode *xmlroot = NULL, *xmltmp = NULL;
+- gchar *uin = NULL, *message = NULL;
+-
+- /* From libicq2000-0.3.2/src/ICQ.cpp */
+- byte_stream_init(&qbs, (guint8 *)args->msg, args->msglen);
+- byte_stream_advance(&qbs, 21);
+- /* expected: 01 00 00 20 00 0e 28 f6 00 11 e7 d3 11 bc f3 00 04 ac 96 9d c2 | 00 00 | 06 00 00 00 | 49 43 51 53 43 53 ...*/
+- /* unexpected: 00 00 26 00 81 1a 18 bc 0e 6c 18 47 a5 91 6f 18 dc c7 6f 1a | 00 00 | 0d 00 00 00 | 49 43 51 57 65 62 4d 65 73 73 61 67 65 ... */
+- smstype = byte_stream_getle16(&qbs);
+- if (smstype != 0)
+- break;
+- taglen = byte_stream_getle32(&qbs);
+- if (taglen > 2000) {
+- /* Avoid trying to allocate large amounts of memory, in
+- case we get something unexpected. */
+- break;
+- }
+- tagstr = byte_stream_getstr(&qbs, taglen);
+- if (tagstr == NULL)
+- break;
+- byte_stream_advance(&qbs, 3);
+- byte_stream_advance(&qbs, 4);
+- smslen = byte_stream_getle32(&qbs);
+- if (smslen > 2000) {
+- /* Avoid trying to allocate large amounts of memory, in
+- case we get something unexpected. */
+- g_free(tagstr);
+- break;
+- }
+- smsmsg = byte_stream_getstr(&qbs, smslen);
+-
+- /* Check if this is an SMS being sent from server */
+- if ((smstype == 0) && (!strcmp(tagstr, "ICQSMS")) && (smsmsg != NULL))
+- {
+- xmlroot = xmlnode_from_str(smsmsg, -1);
+- if (xmlroot != NULL)
+- {
+- xmltmp = xmlnode_get_child(xmlroot, "sender");
+- if (xmltmp != NULL)
+- uin = xmlnode_get_data(xmltmp);
+-
+- xmltmp = xmlnode_get_child(xmlroot, "text");
+- if (xmltmp != NULL)
+- message = xmlnode_get_data(xmltmp);
+-
+- if ((uin != NULL) && (message != NULL))
+- serv_got_im(gc, uin, message, 0, time(NULL));
+-
+- g_free(uin);
+- g_free(message);
+- xmlnode_free(xmlroot);
+- }
+- }
+- g_free(tagstr);
+- g_free(smsmsg);
+- } break;
+-
+- default: {
+- purple_debug_info("oscar",
+- "Received a channel 4 message of unknown type "
+- "(type 0x%02hhx).\n", args->type);
+- } break;
+- }
+-
+- g_strfreev(msg1);
+- g_strfreev(msg2);
+-
+- return 1;
+-}
+-
+-static int purple_parse_incoming_im(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- guint16 channel;
+- int ret = 0;
+- aim_userinfo_t *userinfo;
+- va_list ap;
+-
+- va_start(ap, fr);
+- channel = (guint16)va_arg(ap, unsigned int);
+- userinfo = va_arg(ap, aim_userinfo_t *);
+-
+- switch (channel) {
+- case 1: { /* standard message */
+- struct aim_incomingim_ch1_args *args;
+- args = va_arg(ap, struct aim_incomingim_ch1_args *);
+- ret = incomingim_chan1(od, conn, userinfo, args);
+- } break;
+-
+- case 2: { /* rendezvous */
+- IcbmArgsCh2 *args;
+- args = va_arg(ap, IcbmArgsCh2 *);
+- ret = incomingim_chan2(od, conn, userinfo, args);
+- } break;
+-
+- case 4: { /* ICQ */
+- struct aim_incomingim_ch4_args *args;
+- args = va_arg(ap, struct aim_incomingim_ch4_args *);
+- ret = incomingim_chan4(od, conn, userinfo, args, 0);
+- } break;
+-
+- default: {
+- purple_debug_warning("oscar",
+- "ICBM received on unsupported channel (channel "
+- "0x%04hx).", channel);
+- } break;
+- }
+-
+- va_end(ap);
+-
+- return ret;
+-}
+-
+-static int purple_parse_misses(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- char *buf;
+- va_list ap;
+- guint16 chan, nummissed, reason;
+- aim_userinfo_t *userinfo;
+-
+- va_start(ap, fr);
+- chan = (guint16)va_arg(ap, unsigned int);
+- userinfo = va_arg(ap, aim_userinfo_t *);
+- nummissed = (guint16)va_arg(ap, unsigned int);
+- reason = (guint16)va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- switch(reason) {
+- case 0: /* Invalid (0) */
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s because it was invalid.",
+- "You missed %hu messages from %s because they were invalid.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- case 1: /* Message too large */
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s because it was too large.",
+- "You missed %hu messages from %s because they were too large.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- case 2: /* Rate exceeded */
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s because the rate limit has been exceeded.",
+- "You missed %hu messages from %s because the rate limit has been exceeded.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- case 3: /* Evil Sender */
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s because his/her warning level is too high.",
+- "You missed %hu messages from %s because his/her warning level is too high.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- case 4: /* Evil Receiver */
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s because your warning level is too high.",
+- "You missed %hu messages from %s because your warning level is too high.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- default:
+- buf = g_strdup_printf(
+- dngettext(PACKAGE,
+- "You missed %hu message from %s for an unknown reason.",
+- "You missed %hu messages from %s for an unknown reason.",
+- nummissed),
+- nummissed,
+- userinfo->bn);
+- break;
+- }
+-
+- if (!purple_conv_present_error(userinfo->bn, account, buf))
+- purple_notify_error(od->gc, NULL, buf, NULL);
+- g_free(buf);
+-
+- return 1;
+-}
+-
+-static int
+-purple_parse_clientauto_ch2(OscarData *od, const char *who, guint16 reason, const guchar *cookie)
+-{
+- if (reason == 0x0003)
+- {
+- /* Rendezvous was refused. */
+- PeerConnection *conn;
+-
+- conn = peer_connection_find_by_cookie(od, who, cookie);
+-
+- if (conn == NULL)
+- {
+- purple_debug_info("oscar", "Received a rendezvous cancel message "
+- "for a nonexistant connection from %s.\n", who);
+- }
+- else
+- {
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_REFUSED, NULL);
+- }
+- }
+- else
+- {
+- purple_debug_warning("oscar", "Received an unknown rendezvous "
+- "message from %s. Type 0x%04hx\n", who, reason);
+- }
+-
+- return 0;
+-}
+-
+-static int purple_parse_clientauto_ch4(OscarData *od, char *who, guint16 reason, guint32 state, char *msg) {
+- PurpleConnection *gc = od->gc;
+-
+- switch(reason) {
+- case 0x0003: { /* Reply from an ICQ status message request */
+- char *statusmsg, **splitmsg;
+- PurpleNotifyUserInfo *user_info;
+-
+- /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
+- statusmsg = oscar_icqstatus(state);
+- splitmsg = g_strsplit(msg, "\r\n", 0);
+-
+- user_info = purple_notify_user_info_new();
+-
+- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+- purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+-
+- g_free(statusmsg);
+- g_strfreev(splitmsg);
+-
+- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-
+- } break;
+-
+- case 0x0006: { /* Reply from an ICQ status message request */
+- char *statusmsg, **splitmsg;
+- PurpleNotifyUserInfo *user_info;
+-
+- /* Split at (carriage return/newline)'s, then rejoin later with BRs between. */
+- statusmsg = oscar_icqstatus(state);
+- splitmsg = g_strsplit(msg, "\r\n", 0);
+-
+- user_info = purple_notify_user_info_new();
+-
+- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+- purple_notify_user_info_add_pair(user_info, _("Status"), statusmsg);
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_pair(user_info, NULL, g_strjoinv("<BR>", splitmsg));
+-
+- g_free(statusmsg);
+- g_strfreev(splitmsg);
+-
+- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-
+- } break;
+-
+- default: {
+- purple_debug_warning("oscar",
+- "Received an unknown client auto-response from %s. "
+- "Type 0x%04hx\n", who, reason);
+- } break;
+- } /* end of switch */
+-
+- return 0;
+-}
+-
+-static int purple_parse_clientauto(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- guint16 chan, reason;
+- char *who;
+- int ret = 1;
+-
+- va_start(ap, fr);
+- chan = (guint16)va_arg(ap, unsigned int);
+- who = va_arg(ap, char *);
+- reason = (guint16)va_arg(ap, unsigned int);
+-
+- if (chan == 0x0002) { /* File transfer declined */
+- guchar *cookie = va_arg(ap, guchar *);
+- ret = purple_parse_clientauto_ch2(od, who, reason, cookie);
+- } else if (chan == 0x0004) { /* ICQ message */
+- guint32 state = 0;
+- char *msg = NULL;
+- if (reason == 0x0003) {
+- state = va_arg(ap, guint32);
+- msg = va_arg(ap, char *);
+- }
+- ret = purple_parse_clientauto_ch4(od, who, reason, state, msg);
+- }
+-
+- va_end(ap);
+-
+- return ret;
+-}
+-
+-static int purple_parse_genericerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- guint16 reason;
+-
+- va_start(ap, fr);
+- reason = (guint16) va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- purple_debug_error("oscar", "snac threw error (reason 0x%04hx: %s)\n",
+- reason, oscar_get_msgerr_reason(reason));
+- return 1;
+-}
+-
+-static int purple_parse_mtn(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- guint16 channel, event;
+- char *bn;
+-
+- va_start(ap, fr);
+- channel = (guint16) va_arg(ap, unsigned int);
+- bn = va_arg(ap, char *);
+- event = (guint16) va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- switch (event) {
+- case 0x0000: { /* Text has been cleared */
+- serv_got_typing_stopped(gc, bn);
+- } break;
+-
+- case 0x0001: { /* Paused typing */
+- serv_got_typing(gc, bn, 0, PURPLE_TYPED);
+- } break;
+-
+- case 0x0002: { /* Typing */
+- serv_got_typing(gc, bn, 0, PURPLE_TYPING);
+- } break;
+-
+- case 0x000f: { /* Closed IM window */
+- serv_got_typing_stopped(gc, bn);
+- } break;
+-
+- default: {
+- purple_debug_info("oscar", "Received unknown typing "
+- "notification message from %s. Channel is 0x%04x "
+- "and event is 0x%04hx.\n", bn, channel, event);
+- } break;
+- }
+-
+- return 1;
+-}
+-
+-static int purple_parse_motd(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- char *msg;
+- guint16 id;
+- va_list ap;
+-
+- va_start(ap, fr);
+- id = (guint16) va_arg(ap, unsigned int);
+- msg = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "MOTD: %s (%hu)\n", msg ? msg : "Unknown", id);
+- if (id < 4)
+- purple_notify_warning(od->gc, NULL,
+- _("Your AIM connection may be lost."), NULL);
+-
+- return 1;
+-}
+-
+-static int purple_chatnav_info(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- guint16 type;
+-
+- va_start(ap, fr);
+- type = (guint16) va_arg(ap, unsigned int);
+-
+- switch(type) {
+- case 0x0002: {
+- GString *msg = g_string_new("");
+- guint8 maxrooms;
+- struct aim_chat_exchangeinfo *exchanges;
+- int exchangecount, i;
+-
+- maxrooms = (guint8) va_arg(ap, unsigned int);
+- exchangecount = va_arg(ap, int);
+- exchanges = va_arg(ap, struct aim_chat_exchangeinfo *);
+-
+- g_string_append_printf(msg, "chat info: Max Concurrent Rooms: %hhd, Exchange List (%d total): ", maxrooms, exchangecount);
+- for (i = 0; i < exchangecount; i++) {
+- g_string_append_printf(msg, "%hu", exchanges[i].number);
+- if (exchanges[i].name) {
+- g_string_append_printf(msg, " %s", exchanges[i].name);
+- }
+- g_string_append(msg, ", ");
+- }
+- purple_debug_misc("oscar", "%s\n", msg->str);
+- g_string_free(msg, TRUE);
+-
+- while (od->create_rooms) {
+- struct create_room *cr = od->create_rooms->data;
+- purple_debug_info("oscar",
+- "creating room %s\n", cr->name);
+- aim_chatnav_createroom(od, conn, cr->name, cr->exchange);
+- g_free(cr->name);
+- od->create_rooms = g_slist_remove(od->create_rooms, cr);
+- g_free(cr);
+- }
+- }
+- break;
+- case 0x0008: {
+- char *fqcn, *name, *ck;
+- guint16 instance, flags, maxmsglen, maxoccupancy, unknown, exchange;
+- guint8 createperms;
+- guint32 createtime;
+-
+- fqcn = va_arg(ap, char *);
+- instance = (guint16)va_arg(ap, unsigned int);
+- exchange = (guint16)va_arg(ap, unsigned int);
+- flags = (guint16)va_arg(ap, unsigned int);
+- createtime = va_arg(ap, guint32);
+- maxmsglen = (guint16)va_arg(ap, unsigned int);
+- maxoccupancy = (guint16)va_arg(ap, unsigned int);
+- createperms = (guint8)va_arg(ap, unsigned int);
+- unknown = (guint16)va_arg(ap, unsigned int);
+- name = va_arg(ap, char *);
+- ck = va_arg(ap, char *);
+-
+- purple_debug_misc("oscar",
+- "created room: %s %hu %hu %hu %u %hu %hu %hhu %hu %s %s\n",
+- fqcn ? fqcn : "(null)", exchange, instance, flags, createtime,
+- maxmsglen, maxoccupancy, createperms, unknown,
+- name ? name : "(null)", ck);
+- aim_chat_join(od, exchange, ck, instance);
+- }
+- break;
+- default:
+- purple_debug_warning("oscar",
+- "chatnav info: unknown type (%04hx)\n", type);
+- break;
+- }
+-
+- va_end(ap);
+-
+- return 1;
+-}
+-
+-static int purple_conv_chat_join(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- int count, i;
+- aim_userinfo_t *info;
+- PurpleConnection *gc = od->gc;
+-
+- struct chat_connection *c = NULL;
+-
+- va_start(ap, fr);
+- count = va_arg(ap, int);
+- info = va_arg(ap, aim_userinfo_t *);
+- va_end(ap);
+-
+- c = find_oscar_chat_by_conn(gc, conn);
+- if (!c)
+- return 1;
+-
+- for (i = 0; i < count; i++)
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-
+- return 1;
+-}
+-
+-static int purple_conv_chat_leave(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- int count, i;
+- aim_userinfo_t *info;
+- PurpleConnection *gc = od->gc;
+-
+- struct chat_connection *c = NULL;
+-
+- va_start(ap, fr);
+- count = va_arg(ap, int);
+- info = va_arg(ap, aim_userinfo_t *);
+- va_end(ap);
+-
+- c = find_oscar_chat_by_conn(gc, conn);
+- if (!c)
+- return 1;
+-
+- for (i = 0; i < count; i++)
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c->conv), info[i].bn, NULL);
+-
+- return 1;
+-}
+-
+-static int purple_conv_chat_info_update(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- guint16 maxmsglen, maxvisiblemsglen;
+- PurpleConnection *gc = od->gc;
+- struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn);
+-
+- if (!ccon)
+- return 1;
+-
+- va_start(ap, fr);
+- maxmsglen = (guint16)va_arg(ap, unsigned int);
+- maxvisiblemsglen = (guint16)va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "inside chat_info_update (maxmsglen = %hu, maxvislen = %hu)\n",
+- maxmsglen, maxvisiblemsglen);
+-
+- ccon->maxlen = maxmsglen;
+- ccon->maxvis = maxvisiblemsglen;
+-
+- return 1;
+-}
+-
+-static int purple_conv_chat_incoming_msg(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- struct chat_connection *ccon = find_oscar_chat_by_conn(gc, conn);
+- gchar *utf8;
+- va_list ap;
+- aim_userinfo_t *info;
+- int len;
+- char *msg;
+- char *charset;
+-
+- if (!ccon)
+- return 1;
+-
+- va_start(ap, fr);
+- info = va_arg(ap, aim_userinfo_t *);
+- len = va_arg(ap, int);
+- msg = va_arg(ap, char *);
+- charset = va_arg(ap, char *);
+- va_end(ap);
+-
+- utf8 = oscar_encoding_to_utf8(charset, msg, len);
+- serv_got_chat_in(gc, ccon->id, info->bn, 0, utf8, time(NULL));
+- g_free(utf8);
+-
+- return 1;
+-}
+-
+-static int purple_email_parseupdate(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- struct aim_emailinfo *emailinfo;
+- int havenewmail;
+- char *alertitle, *alerturl;
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- emailinfo = va_arg(ap, struct aim_emailinfo *);
+- havenewmail = va_arg(ap, int);
+- alertitle = va_arg(ap, char *);
+- alerturl = va_arg(ap, char *);
+- va_end(ap);
+-
+- if (account != NULL && emailinfo != NULL && purple_account_get_check_mail(account) &&
+- emailinfo->unread && havenewmail) {
+- gchar *to = g_strdup_printf("%s%s%s",
+- purple_account_get_username(account),
+- emailinfo->domain ? "@" : "",
+- emailinfo->domain ? emailinfo->domain : "");
+- const char *tos[2] = { to };
+- const char *urls[2] = { emailinfo->url };
+- purple_notify_emails(gc, emailinfo->nummsgs, FALSE, NULL, NULL,
+- tos, urls, NULL, NULL);
+- g_free(to);
+- }
+-
+- if (alertitle)
+- purple_debug_misc("oscar", "Got an alert '%s' %s\n", alertitle, alerturl ? alerturl : "");
+-
+- return 1;
+-}
+-
+-static int purple_icon_parseicon(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- char *bn;
+- guint8 iconcsumtype, *iconcsum, *icon;
+- guint16 iconcsumlen, iconlen;
+-
+- va_start(ap, fr);
+- bn = va_arg(ap, char *);
+- iconcsumtype = va_arg(ap, int);
+- iconcsum = va_arg(ap, guint8 *);
+- iconcsumlen = va_arg(ap, int);
+- icon = va_arg(ap, guint8 *);
+- iconlen = va_arg(ap, int);
+- va_end(ap);
+-
+- /*
+- * Some AIM clients will send a blank GIF image with iconlen 90 when
+- * no icon is set. Ignore these.
+- */
+- if ((iconlen > 0) && (iconlen != 90)) {
+- char *b16 = purple_base16_encode(iconcsum, iconcsumlen);
+- purple_buddy_icons_set_for_user(purple_connection_get_account(gc),
+- bn, g_memdup(icon, iconlen), iconlen, b16);
+- g_free(b16);
+- }
+-
+- return 1;
+-}
+-
+-static void
+-purple_icons_fetch(PurpleConnection *gc)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- aim_userinfo_t *userinfo;
+- FlapConnection *conn;
+-
+- conn = flap_connection_getbytype(od, SNAC_FAMILY_BART);
+- if (!conn) {
+- if (!od->iconconnecting) {
+- aim_srv_requestnew(od, SNAC_FAMILY_BART);
+- od->iconconnecting = TRUE;
+- }
+- return;
+- }
+-
+- if (od->set_icon) {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
+- if (img == NULL) {
+- aim_ssi_delicon(od);
+- } else {
+- purple_debug_info("oscar",
+- "Uploading icon to icon server\n");
+- aim_bart_upload(od, purple_imgstore_get_data(img),
+- purple_imgstore_get_size(img));
+- purple_imgstore_unref(img);
+- }
+- od->set_icon = FALSE;
+- }
+-
+- while (od->requesticon != NULL)
+- {
+- userinfo = aim_locate_finduserinfo(od, (char *)od->requesticon->data);
+- if ((userinfo != NULL) && (userinfo->iconcsumlen > 0))
+- aim_bart_request(od, od->requesticon->data, userinfo->iconcsumtype, userinfo->iconcsum, userinfo->iconcsumlen);
+-
+- g_free(od->requesticon->data);
+- od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon);
+- }
+-
+- purple_debug_misc("oscar", "no more icons to request\n");
+-}
+-
+-static int purple_selfinfo(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- int warning_level;
+- va_list ap;
+- aim_userinfo_t *info;
+-
+- va_start(ap, fr);
+- info = va_arg(ap, aim_userinfo_t *);
+- va_end(ap);
+-
+- purple_connection_set_display_name(od->gc, info->bn);
+-
+- /*
+- * What's with the + 0.5?
+- * The 0.5 is basically poor-man's rounding. Normally
+- * casting "13.7" to an int will truncate to "13," but
+- * with 13.7 + 0.5 = 14.2, which becomes "14" when
+- * truncated.
+- */
+- warning_level = info->warnlevel/10.0 + 0.5;
+-
+- return 1;
+-}
+-
+-static int purple_connerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- guint16 code;
+- char *msg;
+-
+- va_start(ap, fr);
+- code = (guint16)va_arg(ap, int);
+- msg = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_info("oscar", "Disconnected. Code is 0x%04x and msg is %s\n",
+- code, (msg != NULL ? msg : ""));
+-
+- g_return_val_if_fail(conn != NULL, 1);
+-
+- if (conn->type == SNAC_FAMILY_CHAT) {
+- struct chat_connection *cc;
+- PurpleConversation *conv = NULL;
+-
+- cc = find_oscar_chat_by_conn(gc, conn);
+- if (cc != NULL)
+- {
+- conv = purple_find_chat(gc, cc->id);
+-
+- if (conv != NULL)
+- {
+- /*
+- * TOOD: Have flap_connection_destroy_cb() send us the
+- * error message stored in 'tmp', which should be
+- * human-friendly, and print that to the chat room.
+- */
+- gchar *buf;
+- buf = g_strdup_printf(_("You have been disconnected from chat "
+- "room %s."), cc->name);
+- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_ERROR, time(NULL));
+- g_free(buf);
+- }
+- oscar_chat_kill(gc, cc);
+- }
+- }
+-
+- return 1;
+-}
+-
+-static int purple_parse_locaterights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- va_list ap;
+- guint16 maxsiglen;
+-
+- va_start(ap, fr);
+- maxsiglen = (guint16) va_arg(ap, int);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "locate rights: max sig len = %d\n", maxsiglen);
+-
+- od->rights.maxsiglen = od->rights.maxawaymsglen = (guint)maxsiglen;
+-
+- aim_locate_setcaps(od, purple_caps);
+- oscar_set_info_and_status(account, TRUE, account->user_info, TRUE,
+- purple_account_get_active_status(account));
+-
+- return 1;
+-}
+-
+-static int purple_parse_buddyrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- guint16 maxbuddies, maxwatchers;
+-
+- va_start(ap, fr);
+- maxbuddies = (guint16) va_arg(ap, unsigned int);
+- maxwatchers = (guint16) va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "buddy list rights: Max buddies = %hu / Max watchers = %hu\n", maxbuddies, maxwatchers);
+-
+- od->rights.maxbuddies = (guint)maxbuddies;
+- od->rights.maxwatchers = (guint)maxwatchers;
+-
+- return 1;
+-}
+-
+-static void oscar_format_username(PurpleConnection *gc, const char *new_display_name)
+-{
+- OscarData *od;
+- const char *old_display_name, *username;
+- char *tmp, *at_sign;
+-
+- old_display_name = purple_connection_get_display_name(gc);
+- if (old_display_name && strchr(old_display_name, '@')) {
+- purple_debug_info("oscar", "Cowardly refusing to attempt to format "
+- "screen name because the current formatting according to "
+- "the server (%s) appears to be an email address\n",
+- old_display_name);
+- return;
+- }
+-
+- username = purple_account_get_username(purple_connection_get_account(gc));
+- if (oscar_util_name_compare(username, new_display_name)) {
+- purple_notify_error(gc, NULL, _("The new formatting is invalid."),
+- _("Username formatting can change only capitalization and whitespace."));
+- return;
+- }
+-
+- tmp = g_strdup(new_display_name);
+-
+- /*
+- * If our local username is an email address then strip off the domain.
+- * This allows formatting to work if the user entered their username as
+- * 'something@aim.com' or possibly other AOL-owned domains.
+- */
+- at_sign = strchr(tmp, '@');
+- if (at_sign)
+- at_sign[0] = '\0';
+-
+- od = purple_connection_get_protocol_data(gc);
+- if (!flap_connection_getbytype(od, SNAC_FAMILY_ADMIN)) {
+- /* We don't have a connection to an "admin" server. Make one. */
+- od->setnick = TRUE;
+- g_free(od->newformatting);
+- od->newformatting = tmp;
+- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
+- } else {
+- aim_admin_setnick(od, flap_connection_getbytype(od, SNAC_FAMILY_ADMIN), tmp);
+- g_free(tmp);
+- }
+-}
+-
+-static int purple_bosrights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PurpleStatus *status;
+- gboolean is_available;
+- PurplePresence *presence;
+- const char *username, *message, *itmsurl;
+- char *tmp;
+- va_list ap;
+- guint16 maxpermits, maxdenies;
+-
+- gc = od->gc;
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- maxpermits = (guint16) va_arg(ap, unsigned int);
+- maxdenies = (guint16) va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "BOS rights: Max permit = %hu / Max deny = %hu\n", maxpermits, maxdenies);
+-
+- od->rights.maxpermits = (guint)maxpermits;
+- od->rights.maxdenies = (guint)maxdenies;
+-
+- purple_debug_info("oscar", "buddy list loaded\n");
+-
+- if (purple_account_get_user_info(account) != NULL)
+- serv_set_info(gc, purple_account_get_user_info(account));
+-
+- username = purple_account_get_username(account);
+- if (!od->icq && strcmp(username, purple_connection_get_display_name(gc)) != 0) {
+- /*
+- * Format the username for AIM accounts if it's different
+- * than what's currently set.
+- */
+- oscar_format_username(gc, username);
+- }
+-
+- /* Set our available message based on the current status */
+- status = purple_account_get_active_status(account);
+- is_available = purple_status_is_available(status);
+- if (is_available)
+- message = purple_status_get_attr_string(status, "message");
+- else
+- message = NULL;
+- tmp = purple_markup_strip_html(message);
+- itmsurl = purple_status_get_attr_string(status, "itmsurl");
+- aim_srv_setextrainfo(od, FALSE, 0, is_available, tmp, itmsurl);
+- aim_srv_set_dc_info(od);
+- g_free(tmp);
+-
+- presence = purple_status_get_presence(status);
+- aim_srv_setidle(od, !purple_presence_is_idle(presence) ? 0 : time(NULL) - purple_presence_get_idle_time(presence));
+-
+- if (od->icq) {
+- oscar_set_extended_status(gc);
+- aim_icq_setsecurity(od,
+- purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION),
+- purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE));
+- }
+-
+- aim_srv_requestnew(od, SNAC_FAMILY_ALERT);
+- aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV);
+-
+- od->bos.have_rights = TRUE;
+-
+- /*
+- * If we've already received our feedbag data then we're not waiting on
+- * anything else, so send the server clientready.
+- *
+- * Normally we get bos rights before we get our feedbag data, so this
+- * rarely (never?) happens. And I'm not sure it actually matters if we
+- * wait for bos rights before calling clientready. But it seems safer
+- * to do it this way.
+- */
+- if (od->ssi.received_data) {
+- aim_srv_clientready(od, conn);
+-
+- /* Request offline messages for AIM and ICQ */
+- aim_im_reqofflinemsgs(od);
+-
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+- }
+-
+- return 1;
+-}
+-
+-static int purple_popup(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- gchar *text;
+- va_list ap;
+- char *msg, *url;
+- guint16 wid, hei, delay;
+-
+- va_start(ap, fr);
+- msg = va_arg(ap, char *);
+- url = va_arg(ap, char *);
+- wid = (guint16) va_arg(ap, int);
+- hei = (guint16) va_arg(ap, int);
+- delay = (guint16) va_arg(ap, int);
+- va_end(ap);
+-
+- text = g_strdup_printf("%s<br><a href=\"%s\">%s</a>", msg, url, url);
+- purple_notify_formatted(gc, NULL, _("Pop-Up Message"), NULL, text, NULL, NULL);
+- g_free(text);
+-
+- return 1;
+-}
+-
+-static void oscar_searchresults_add_buddy_cb(PurpleConnection *gc, GList *row, void *user_data)
+-{
+- purple_blist_request_add_buddy(purple_connection_get_account(gc),
+- g_list_nth_data(row, 0), NULL, NULL);
+-}
+-
+-static int purple_parse_searchreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleNotifySearchResults *results;
+- PurpleNotifySearchColumn *column;
+- gchar *secondary;
+- int i, num;
+- va_list ap;
+- char *email, *usernames;
+-
+- va_start(ap, fr);
+- email = va_arg(ap, char *);
+- num = va_arg(ap, int);
+- usernames = va_arg(ap, char *);
+- va_end(ap);
+-
+- results = purple_notify_searchresults_new();
+-
+- if (results == NULL) {
+- purple_debug_error("oscar", "purple_parse_searchreply: "
+- "Unable to display the search results.\n");
+- purple_notify_error(gc, NULL,
+- _("Unable to display the search results."),
+- NULL);
+- return 1;
+- }
+-
+- secondary = g_strdup_printf(
+- dngettext(PACKAGE, "The following username is associated with %s",
+- "The following usernames are associated with %s",
+- num),
+- email);
+-
+- column = purple_notify_searchresults_column_new(_("Username"));
+- purple_notify_searchresults_column_add(results, column);
+-
+- for (i = 0; i < num; i++) {
+- GList *row;
+- row = g_list_append(NULL, g_strdup(&usernames[i * (MAXSNLEN + 1)]));
+- purple_notify_searchresults_row_add(results, row);
+- }
+- purple_notify_searchresults_button_add(results, PURPLE_NOTIFY_BUTTON_ADD,
+- oscar_searchresults_add_buddy_cb);
+- purple_notify_searchresults(gc, NULL, NULL, secondary, results, NULL, NULL);
+-
+- g_free(secondary);
+-
+- return 1;
+-}
+-
+-static int purple_parse_searcherror(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- va_list ap;
+- char *email;
+- char *buf;
+-
+- va_start(ap, fr);
+- email = va_arg(ap, char *);
+- va_end(ap);
+-
+- buf = g_strdup_printf(_("No results found for email address %s"), email);
+- purple_notify_error(od->gc, NULL, buf, NULL);
+- g_free(buf);
+-
+- return 1;
+-}
+-
+-static int purple_account_confirm(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- guint16 status;
+- va_list ap;
+- char msg[256];
+-
+- va_start(ap, fr);
+- status = (guint16) va_arg(ap, unsigned int); /* status code of confirmation request */
+- va_end(ap);
+-
+- purple_debug_info("oscar",
+- "account confirmation returned status 0x%04x (%s)\n", status,
+- status ? "unknown" : "email sent");
+- if (!status) {
+- g_snprintf(msg, sizeof(msg), _("You should receive an email asking to confirm %s."),
+- purple_account_get_username(purple_connection_get_account(gc)));
+- purple_notify_info(gc, NULL, _("Account Confirmation Requested"), msg);
+- }
+-
+- return 1;
+-}
+-
+-static int purple_info_change(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- guint16 perms, err;
+- char *url, *bn, *email;
+- int change;
+-
+- va_start(ap, fr);
+- change = va_arg(ap, int);
+- perms = (guint16) va_arg(ap, unsigned int);
+- err = (guint16) va_arg(ap, unsigned int);
+- url = va_arg(ap, char *);
+- bn = va_arg(ap, char *);
+- email = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_misc("oscar",
+- "account info: because of %s, perms=0x%04x, err=0x%04x, url=%s, bn=%s, email=%s\n",
+- change ? "change" : "request", perms, err,
+- (url != NULL) ? url : "(null)",
+- (bn != NULL) ? bn : "(null)",
+- (email != NULL) ? email : "(null)");
+-
+- if ((err > 0) && (url != NULL)) {
+- char *dialog_msg;
+-
+- if (err == 0x0001)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name differs from the original."), err);
+- else if (err == 0x0006)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because it is invalid."), err);
+- else if (err == 0x00b)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to format username because the requested name is too long."), err);
+- else if (err == 0x001d)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because there is already a request pending for this username."), err);
+- else if (err == 0x0021)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address has too many usernames associated with it."), err);
+- else if (err == 0x0023)
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unable to change email address because the given address is invalid."), err);
+- else
+- dialog_msg = g_strdup_printf(_("Error 0x%04x: Unknown error."), err);
+- purple_notify_error(gc, NULL,
+- _("Error Changing Account Info"), dialog_msg);
+- g_free(dialog_msg);
+- return 1;
+- }
+-
+- if (email != NULL) {
+- char *dialog_msg = g_strdup_printf(_("The email address for %s is %s"),
+- purple_account_get_username(purple_connection_get_account(gc)), email);
+- purple_notify_info(gc, NULL, _("Account Info"), dialog_msg);
+- g_free(dialog_msg);
+- }
+-
+- return 1;
+-}
+-
+-void
+-oscar_keepalive(PurpleConnection *gc)
+-{
+- OscarData *od;
+- GSList *l;
+-
+- od = purple_connection_get_protocol_data(gc);
+- for (l = od->oscar_connections; l; l = l->next) {
+- flap_connection_send_keepalive(od, l->data);
+- }
+-}
+-
+-unsigned int
+-oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state)
+-{
+- OscarData *od;
+- PeerConnection *conn;
+-
+- od = purple_connection_get_protocol_data(gc);
+- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
+-
+- if ((conn != NULL) && (conn->ready))
+- {
+- peer_odc_send_typing(conn, state);
+- }
+- else {
+- /* Don't send if this turkey is in our deny list */
+- GSList *list;
+- for (list=gc->account->deny; (list && oscar_util_name_compare(name, list->data)); list=list->next);
+- if (!list) {
+- struct buddyinfo *bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(gc->account, name));
+- if (bi && bi->typingnot) {
+- if (state == PURPLE_TYPING)
+- aim_im_sendmtn(od, 0x0001, name, 0x0002);
+- else if (state == PURPLE_TYPED)
+- aim_im_sendmtn(od, 0x0001, name, 0x0001);
+- else
+- aim_im_sendmtn(od, 0x0001, name, 0x0000);
+- }
+- }
+- }
+- return 0;
+-}
+-
+-/* TODO: Move this into odc.c! */
+-static void
+-purple_odc_send_im(PeerConnection *conn, const char *message, PurpleMessageFlags imflags)
+-{
+- GString *msg;
+- GString *data;
+- gchar *tmp;
+- gsize tmplen;
+- guint16 charset;
+- GData *attribs;
+- const char *start, *end, *last;
+- int oscar_id = 0;
+-
+- msg = g_string_new("<HTML><BODY>");
+- data = g_string_new("<BINARY>");
+- last = message;
+-
+- /* for each valid IMG tag... */
+- while (last && *last && purple_markup_find_tag("img", last, &start, &end, &attribs))
+- {
+- PurpleStoredImage *image = NULL;
+- const char *id;
+-
+- if (start - last) {
+- g_string_append_len(msg, last, start - last);
+- }
+-
+- id = g_datalist_get_data(&attribs, "id");
+-
+- /* ... if it refers to a valid purple image ... */
+- if (id && (image = purple_imgstore_find_by_id(atoi(id)))) {
+- /* ... append the message from start to the tag ... */
+- unsigned long size = purple_imgstore_get_size(image);
+- const char *filename = purple_imgstore_get_filename(image);
+- gconstpointer imgdata = purple_imgstore_get_data(image);
+-
+- oscar_id++;
+-
+- /* ... insert a new img tag with the oscar id ... */
+- if (filename)
+- g_string_append_printf(msg,
+- "<IMG SRC=\"%s\" ID=\"%d\" DATASIZE=\"%lu\">",
+- filename, oscar_id, size);
+- else
+- g_string_append_printf(msg,
+- "<IMG ID=\"%d\" DATASIZE=\"%lu\">",
+- oscar_id, size);
+-
+- /* ... and append the data to the binary section ... */
+- g_string_append_printf(data, "<DATA ID=\"%d\" SIZE=\"%lu\">",
+- oscar_id, size);
+- g_string_append_len(data, imgdata, size);
+- g_string_append(data, "</DATA>");
+- }
+- /* If the tag is invalid, skip it, thus no else here */
+-
+- g_datalist_clear(&attribs);
+-
+- /* continue from the end of the tag */
+- last = end + 1;
+- }
+-
+- /* append any remaining message data */
+- if (last && *last)
+- g_string_append(msg, last);
+-
+- g_string_append(msg, "</BODY></HTML>");
+-
+- /* Convert the message to a good encoding */
+- tmp = oscar_encode_im(msg->str, &tmplen, &charset, NULL);
+- g_string_free(msg, TRUE);
+- msg = g_string_new_len(tmp, tmplen);
+- g_free(tmp);
+-
+- /* Append any binary data that we may have */
+- if (oscar_id) {
+- msg = g_string_append_len(msg, data->str, data->len);
+- msg = g_string_append(msg, "</BINARY>");
+- }
+- g_string_free(data, TRUE);
+-
+- purple_debug_info("oscar", "sending direct IM %s using charset %i", msg->str, charset);
+-
+- peer_odc_send_im(conn, msg->str, msg->len, charset,
+- imflags & PURPLE_MESSAGE_AUTO_RESP);
+- g_string_free(msg, TRUE);
+-}
+-
+-int
+-oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+- PeerConnection *conn;
+- int ret;
+- char *tmp1, *tmp2;
+- gboolean is_sms, is_html;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+- ret = 0;
+-
+- is_sms = oscar_util_valid_name_sms(name);
+-
+- if (od->icq && is_sms) {
+- /*
+- * We're sending to a phone number and this is ICQ,
+- * so send the message as an SMS using aim_icq_sendsms()
+- */
+- int ret;
+- purple_debug_info("oscar", "Sending SMS to %s.\n", name);
+- ret = aim_icq_sendsms(od, name, message, purple_account_get_username(account));
+- return (ret >= 0 ? 1 : ret);
+- }
+-
+- if (imflags & PURPLE_MESSAGE_AUTO_RESP)
+- tmp1 = oscar_util_format_string(message, name);
+- else
+- tmp1 = g_strdup(message);
+-
+- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
+- if ((conn != NULL) && (conn->ready))
+- {
+- /* If we're directly connected, send a direct IM */
+- purple_debug_info("oscar", "Sending direct IM with flags %i\n", imflags);
+- purple_odc_send_im(conn, tmp1, imflags);
+- } else {
+- struct buddyinfo *bi;
+- struct aim_sendimext_args args;
+- PurpleConversation *conv;
+- PurpleStoredImage *img;
+- PurpleBuddy *buddy;
+-
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, name, account);
+-
+- if (strstr(tmp1, "<IMG "))
+- purple_conversation_write(conv, "",
+- _("Your IM Image was not sent. "
+- "You must be Direct Connected to send IM Images."),
+- PURPLE_MESSAGE_ERROR, time(NULL));
+-
+- buddy = purple_find_buddy(account, name);
+-
+- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, name));
+- if (!bi) {
+- bi = g_new0(struct buddyinfo, 1);
+- g_hash_table_insert(od->buddyinfo, g_strdup(purple_normalize(account, name)), bi);
+- }
+-
+- args.flags = 0;
+-
+- if (!is_sms && (!buddy || !PURPLE_BUDDY_IS_ONLINE(buddy)))
+- args.flags |= AIM_IMFLAGS_OFFLINE;
+-
+- if (od->icq) {
+- args.features = features_icq;
+- args.featureslen = sizeof(features_icq);
+- } else {
+- args.features = features_aim;
+- args.featureslen = sizeof(features_aim);
+-
+- if (imflags & PURPLE_MESSAGE_AUTO_RESP)
+- args.flags |= AIM_IMFLAGS_AWAY;
+- }
+-
+- if (bi->ico_need) {
+- purple_debug_info("oscar",
+- "Sending buddy icon request with message\n");
+- args.flags |= AIM_IMFLAGS_BUDDYREQ;
+- bi->ico_need = FALSE;
+- }
+-
+- img = purple_buddy_icons_find_account_icon(account);
+- if (img) {
+- gconstpointer data = purple_imgstore_get_data(img);
+- args.iconlen = purple_imgstore_get_size(img);
+- args.iconsum = aimutil_iconsum(data, args.iconlen);
+- args.iconstamp = purple_buddy_icons_get_account_icon_timestamp(account);
+-
+- if ((args.iconlen != bi->ico_me_len) || (args.iconsum != bi->ico_me_csum) || (args.iconstamp != bi->ico_me_time)) {
+- bi->ico_informed = FALSE;
+- bi->ico_sent = FALSE;
+- }
+-
+- /*
+- * TODO:
+- * For some reason sending our icon to people only works
+- * when we're the ones who initiated the conversation. If
+- * the other person sends the first IM then they never get
+- * the icon. We should fix that.
+- */
+- if (!bi->ico_informed) {
+- purple_debug_info("oscar",
+- "Claiming to have a buddy icon\n");
+- args.flags |= AIM_IMFLAGS_HASICON;
+- bi->ico_me_len = args.iconlen;
+- bi->ico_me_csum = args.iconsum;
+- bi->ico_me_time = args.iconstamp;
+- bi->ico_informed = TRUE;
+- }
+-
+- purple_imgstore_unref(img);
+- }
+-
+- args.destbn = name;
+-
+- if (oscar_util_valid_name_sms(name)) {
+- /* Messaging an SMS (mobile) user--strip HTML */
+- tmp2 = purple_markup_strip_html(tmp1);
+- is_html = FALSE;
+- } else {
+- /* ICQ 6 wants its HTML wrapped in these tags. Oblige it. */
+- tmp2 = g_strdup_printf("<HTML><BODY>%s</BODY></HTML>", tmp1);
+- is_html = TRUE;
+- }
+- g_free(tmp1);
+- tmp1 = tmp2;
+-
+- args.msg = oscar_encode_im(tmp1, &args.msglen, &args.charset, NULL);
+- 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);
+-
+- /* re-escape the entities */
+- tmp1 = g_markup_escape_text(tmp2, -1);
+- g_free(tmp2);
+-
+- tmp2 = purple_strdup_withhtml(tmp1);
+- g_free(tmp1);
+- tmp1 = tmp2;
+-
+- args.msg = oscar_encode_im(tmp1, &args.msglen, &args.charset, NULL);
+- purple_debug_info("oscar", "Sending %s as %s because the original was too long.\n",
+- message, (char *)args.msg);
+- }
+-
+- purple_debug_info("oscar", "Sending IM, charset=0x%04hx, length=%" G_GSIZE_FORMAT "\n", args.charset, args.msglen);
+- ret = aim_im_sendch1_ext(od, &args);
+- g_free((char *)args.msg);
+- }
+-
+- g_free(tmp1);
+-
+- if (ret >= 0)
+- return 1;
+-
+- return ret;
+-}
+-
+-/*
+- * As of 26 June 2006, ICQ users can request AIM info from
+- * everyone, and can request ICQ info from ICQ users, and
+- * AIM users can only request AIM info.
+- */
+-void oscar_get_info(PurpleConnection *gc, const char *name) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->icq && oscar_util_valid_name_icq(name))
+- aim_icq_getallinfo(od, name);
+- else
+- aim_locate_getinfoshort(od, name, 0x00000003);
+-}
+-
+-void oscar_set_idle(PurpleConnection *gc, int time) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- aim_srv_setidle(od, time);
+-}
+-
+-void
+-oscar_set_info(PurpleConnection *gc, const char *rawinfo)
+-{
+- PurpleAccount *account;
+- PurpleStatus *status;
+-
+- account = purple_connection_get_account(gc);
+- status = purple_account_get_active_status(account);
+- oscar_set_info_and_status(account, TRUE, rawinfo, FALSE, status);
+-}
+-
+-static guint32
+-oscar_get_extended_status(PurpleConnection *gc)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+- PurpleStatus *status;
+- const gchar *status_id;
+- guint32 data = 0x00000000;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+- status = purple_account_get_active_status(account);
+- status_id = purple_status_get_id(status);
+-
+- data |= AIM_ICQ_STATE_HIDEIP;
+- 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))
+- data |= AIM_ICQ_STATE_NORMAL;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_AWAY))
+- data |= AIM_ICQ_STATE_AWAY;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_DND))
+- data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_DND | AIM_ICQ_STATE_BUSY;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_NA))
+- data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_OCCUPIED))
+- data |= AIM_ICQ_STATE_AWAY | AIM_ICQ_STATE_BUSY;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_FREE4CHAT))
+- data |= AIM_ICQ_STATE_CHAT;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_INVISIBLE))
+- data |= AIM_ICQ_STATE_INVISIBLE;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_EVIL))
+- data |= AIM_ICQ_STATE_EVIL;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_DEPRESSION))
+- data |= AIM_ICQ_STATE_DEPRESSION;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_ATWORK))
+- data |= AIM_ICQ_STATE_ATWORK;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_ATHOME))
+- data |= AIM_ICQ_STATE_ATHOME;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_LUNCH))
+- data |= AIM_ICQ_STATE_LUNCH;
+- else if (!strcmp(status_id, OSCAR_STATUS_ID_CUSTOM))
+- data |= AIM_ICQ_STATE_OUT | AIM_ICQ_STATE_AWAY;
+-
+- return data;
+-}
+-
+-static void
+-oscar_set_extended_status(PurpleConnection *gc)
+-{
+- aim_srv_setextrainfo(purple_connection_get_protocol_data(gc), TRUE, oscar_get_extended_status(gc), FALSE, NULL, NULL);
+-}
+-
+-static void
+-oscar_set_info_and_status(PurpleAccount *account, gboolean setinfo, const char *rawinfo,
+- gboolean setstatus, PurpleStatus *status)
+-{
+- PurpleConnection *gc = purple_account_get_connection(account);
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- PurpleStatusType *status_type;
+- PurpleStatusPrimitive primitive;
+-
+- char *info_encoding = NULL;
+- char *info = NULL;
+- gsize infolen = 0;
+-
+- char *away_encoding = NULL;
+- char *away = NULL;
+- gsize awaylen = 0;
+-
+- char *status_text = NULL;
+- const char *itmsurl = NULL;
+-
+- status_type = purple_status_get_type(status);
+- primitive = purple_status_type_get_primitive(status_type);
+-
+- if (!setinfo)
+- {
+- /* Do nothing! */
+- }
+- else if (od->rights.maxsiglen == 0)
+- {
+- purple_notify_warning(gc, NULL, _("Unable to set AIM profile."),
+- _("You have probably requested to set your "
+- "profile before the login procedure completed. "
+- "Your profile remains unset; try setting it "
+- "again when you are fully connected."));
+- }
+- else if (rawinfo != NULL)
+- {
+- char *htmlinfo = purple_strdup_withhtml(rawinfo);
+- info = oscar_encode_im(htmlinfo, &infolen, NULL, &info_encoding);
+- g_free(htmlinfo);
+-
+- if (infolen > od->rights.maxsiglen)
+- {
+- gchar *errstr;
+- errstr = g_strdup_printf(dngettext(PACKAGE, "The maximum profile length of %d byte "
+- "has been exceeded. It has been truncated for you.",
+- "The maximum profile length of %d bytes "
+- "has been exceeded. It has been truncated for you.",
+- od->rights.maxsiglen), od->rights.maxsiglen);
+- purple_notify_warning(gc, NULL, _("Profile too long."), errstr);
+- g_free(errstr);
+- }
+- }
+-
+- if (setstatus)
+- {
+- const char *status_html;
+-
+- status_html = purple_status_get_attr_string(status, "message");
+-
+- if (status_html == NULL || primitive == PURPLE_STATUS_AVAILABLE || primitive == PURPLE_STATUS_INVISIBLE)
+- {
+- /* This is needed for us to un-set any previous away message. */
+- away = g_strdup("");
+- }
+- else
+- {
+- gchar *linkified;
+-
+- /* We do this for icq too so that they work for old third party clients */
+- linkified = purple_markup_linkify(status_html);
+- away = oscar_encode_im(linkified, &awaylen, NULL, &away_encoding);
+- g_free(linkified);
+-
+- if (awaylen > od->rights.maxawaymsglen)
+- {
+- gchar *errstr;
+-
+- errstr = g_strdup_printf(dngettext(PACKAGE, "The maximum away message length of %d byte "
+- "has been exceeded. It has been truncated for you.",
+- "The maximum away message length of %d bytes "
+- "has been exceeded. It has been truncated for you.",
+- od->rights.maxawaymsglen), od->rights.maxawaymsglen);
+- purple_notify_warning(gc, NULL, _("Away message too long."), errstr);
+- g_free(errstr);
+- }
+- }
+- }
+-
+- aim_locate_setprofile(od,
+- info_encoding, info, MIN(infolen, od->rights.maxsiglen),
+- away_encoding, away, MIN(awaylen, od->rights.maxawaymsglen));
+- g_free(info);
+- g_free(away);
+-
+- if (setstatus)
+- {
+- const char *status_html;
+-
+- status_html = purple_status_get_attr_string(status, "message");
+- if (status_html != NULL)
+- {
+- status_text = purple_markup_strip_html(status_html);
+- /* If the status_text is longer than 251 characters then truncate it */
+- if (strlen(status_text) > MAXAVAILMSGLEN)
+- {
+- char *tmp = g_utf8_find_prev_char(status_text, &status_text[MAXAVAILMSGLEN - 2]);
+- strcpy(tmp, "...");
+- }
+- }
+-
+- itmsurl = purple_status_get_attr_string(status, "itmsurl");
+-
+- aim_srv_setextrainfo(od, TRUE, oscar_get_extended_status(gc), TRUE, status_text, itmsurl);
+- g_free(status_text);
+- }
+-}
+-
+-static void
+-oscar_set_icq_permdeny(PurpleAccount *account)
+-{
+- PurpleConnection *gc = purple_account_get_connection(account);
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- gboolean invisible = purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE);
+-
+- /*
+- * For ICQ the permit/deny setting controls who can see you
+- * online. Mimicking the official client's behavior, we use PURPLE_PRIVACY_ALLOW_USERS
+- * when our status is "invisible" and PURPLE_PRIVACY_DENY_USERS otherwise.
+- * In the former case, we are visible only to buddies on our "permanently visible" list.
+- * In the latter, we are invisible only to buddies on our "permanently invisible" list.
+- */
+- aim_ssi_setpermdeny(od, invisible ? PURPLE_PRIVACY_ALLOW_USERS : PURPLE_PRIVACY_DENY_USERS);
+-}
+-
+-void
+-oscar_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleConnection *pc;
+- OscarData *od;
+-
+- purple_debug_info("oscar", "Set status to %s\n", purple_status_get_name(status));
+-
+- /* Either setting a new status active or setting a status inactive.
+- * (Only possible for independent status (i.e. X-Status moods.) */
+- if (!purple_status_is_active(status) && !purple_status_is_independent(status))
+- return;
+-
+- if (!purple_account_is_connected(account))
+- return;
+-
+- pc = purple_account_get_connection(account);
+- od = purple_connection_get_protocol_data(pc);
+-
+- /* There's no need to do the stuff below for mood updates. */
+- if (purple_status_type_get_primitive(purple_status_get_type(status)) == PURPLE_STATUS_MOOD) {
+- aim_locate_setcaps(od, purple_caps);
+- return;
+- }
+-
+- if (od->icq) {
+- /* Set visibility */
+- oscar_set_icq_permdeny(account);
+- }
+-
+- /* Set the AIM-style away message for both AIM and ICQ accounts */
+- oscar_set_info_and_status(account, FALSE, NULL, TRUE, status);
+-}
+-
+-void
+-oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *msg)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+- const char *bname, *gname;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+- bname = purple_buddy_get_name(buddy);
+- gname = purple_group_get_name(group);
+-
+- if (!oscar_util_valid_name(bname)) {
+- gchar *buf;
+- buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid. Usernames must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), bname);
+- if (!purple_conv_present_error(bname, account, buf))
+- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
+- g_free(buf);
+-
+- /* Remove from local list */
+- purple_blist_remove_buddy(buddy);
+-
+- return;
+- }
+-
+- if (od->ssi.received_data) {
+- if (!aim_ssi_itemlist_finditem(od->ssi.local, gname, bname, AIM_SSI_TYPE_BUDDY)) {
+- purple_debug_info("oscar",
+- "ssi: adding buddy %s to group %s\n", bname, gname);
+- aim_ssi_addbuddy(od, bname, gname, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+-
+- /* Mobile users should always be online */
+- if (bname[0] == '+') {
+- purple_prpl_got_user_status(account, bname,
+- OSCAR_STATUS_ID_AVAILABLE, NULL);
+- purple_prpl_got_user_status(account, bname,
+- OSCAR_STATUS_ID_MOBILE, NULL);
+- }
+- } else if (aim_ssi_waitingforauth(od->ssi.local,
+- aim_ssi_itemlist_findparentname(od->ssi.local, bname),
+- bname)) {
+- /* Not authorized -- Re-request authorization */
+- oscar_auth_sendrequest(gc, bname, msg);
+- }
+- }
+-
+- /* XXX - Should this be done from AIM accounts, as well? */
+- if (od->icq)
+- aim_icq_getalias(od, bname, FALSE, NULL);
+-}
+-
+-void oscar_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->ssi.received_data) {
+- const char *gname = purple_group_get_name(group);
+- const char *bname = purple_buddy_get_name(buddy);
+- purple_debug_info("oscar",
+- "ssi: deleting buddy %s from group %s\n", bname, gname);
+- aim_ssi_delbuddy(od, bname, gname);
+- }
+-}
+-
+-void oscar_move_buddy(PurpleConnection *gc, const char *name, const char *old_group, const char *new_group) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->ssi.received_data && strcmp(old_group, new_group)) {
+- purple_debug_info("oscar",
+- "ssi: moving buddy %s from group %s to group %s\n", name, old_group, new_group);
+- aim_ssi_movebuddy(od, old_group, new_group, name);
+- }
+-}
+-
+-void oscar_alias_buddy(PurpleConnection *gc, const char *name, const char *alias) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->ssi.received_data) {
+- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+- if (gname) {
+- purple_debug_info("oscar",
+- "ssi: changing the alias for buddy %s to %s\n", name, alias ? alias : "(none)");
+- aim_ssi_aliasbuddy(od, gname, name, alias);
+- }
+- }
+-}
+-
+-/*
+- * FYI, the OSCAR SSI code removes empty groups automatically.
+- */
+-void oscar_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->ssi.received_data) {
+- const char *gname = purple_group_get_name(group);
+- if (aim_ssi_itemlist_finditem(od->ssi.local, gname, NULL, AIM_SSI_TYPE_GROUP)) {
+- GList *cur, *groups = NULL;
+- PurpleAccount *account = purple_connection_get_account(gc);
+-
+- /* Make a list of what the groups each buddy is in */
+- for (cur = moved_buddies; cur != NULL; cur = cur->next) {
+- PurpleBlistNode *node = cur->data;
+- /* node is PurpleBuddy, parent is a PurpleContact.
+- * We must go two levels up to get the Group */
+- groups = g_list_append(groups,
+- purple_buddy_get_group((PurpleBuddy*)node));
+- }
+-
+- purple_account_remove_buddies(account, moved_buddies, groups);
+- purple_account_add_buddies(account, moved_buddies);
+- g_list_free(groups);
+- purple_debug_info("oscar",
+- "ssi: moved all buddies from group %s to %s\n", old_name, gname);
+- } else {
+- aim_ssi_rename_group(od, old_name, gname);
+- purple_debug_info("oscar",
+- "ssi: renamed group %s to %s\n", old_name, gname);
+- }
+- }
+-}
+-
+-void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group)
+-{
+- aim_ssi_delgroup(purple_connection_get_protocol_data(gc), purple_group_get_name(group));
+-}
+-
+-static gboolean purple_ssi_rerequestdata(gpointer data) {
+- OscarData *od = data;
+-
+- aim_ssi_reqdata(od);
+-
+- return TRUE;
+-}
+-
+-static int purple_ssi_parseerr(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- guint16 reason;
+-
+- va_start(ap, fr);
+- reason = (guint16)va_arg(ap, unsigned int);
+- va_end(ap);
+-
+- purple_debug_error("oscar", "ssi: SNAC error %hu\n", reason);
+-
+- if (reason == 0x0005) {
+- if (od->getblisttimer > 0)
+- purple_timeout_remove(od->getblisttimer);
+- else
+- /* We only show this error the first time it happens */
+- purple_notify_error(gc, NULL,
+- _("Unable to Retrieve Buddy List"),
+- _("The AIM servers were temporarily unable to send "
+- "your buddy list. Your buddy list is not lost, and "
+- "will probably become available in a few minutes."));
+- od->getblisttimer = purple_timeout_add_seconds(30, purple_ssi_rerequestdata, od);
+- return 1;
+- }
+-
+- return 1;
+-}
+-
+-static int purple_ssi_parserights(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- int i;
+- va_list ap;
+- int numtypes;
+- guint16 *maxitems;
+- GString *msg;
+-
+- va_start(ap, fr);
+- numtypes = va_arg(ap, int);
+- maxitems = va_arg(ap, guint16 *);
+- va_end(ap);
+-
+- msg = g_string_new("ssi rights:");
+- for (i=0; i<numtypes; i++)
+- g_string_append_printf(msg, " max type 0x%04x=%hd,", i, maxitems[i]);
+- g_string_append(msg, "\n");
+- purple_debug_misc("oscar", "%s", msg->str);
+- g_string_free(msg, TRUE);
+-
+- if (numtypes >= 0)
+- od->rights.maxbuddies = maxitems[0];
+- if (numtypes >= 1)
+- od->rights.maxgroups = maxitems[1];
+- if (numtypes >= 2)
+- od->rights.maxpermits = maxitems[2];
+- if (numtypes >= 3)
+- od->rights.maxdenies = maxitems[3];
+-
+- return 1;
+-}
+-
+-static int purple_ssi_parselist(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PurpleGroup *g;
+- PurpleBuddy *b;
+- GSList *cur, *next, *buddies;
+- struct aim_ssi_item *curitem;
+- guint32 tmp;
+- PurpleStoredImage *img;
+- va_list ap;
+- guint16 fmtver, numitems;
+- guint32 timestamp;
+- guint16 deny_entry_type = aim_ssi_getdenyentrytype(od);
+-
+- gc = od->gc;
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- fmtver = (guint16)va_arg(ap, int);
+- numitems = (guint16)va_arg(ap, int);
+- timestamp = va_arg(ap, guint32);
+- va_end(ap);
+-
+- /* Don't attempt to re-request our buddy list later */
+- if (od->getblisttimer != 0) {
+- purple_timeout_remove(od->getblisttimer);
+- od->getblisttimer = 0;
+- }
+-
+- purple_debug_info("oscar", "ssi: syncing local list and server list\n");
+-
+- /* Clean the buddy list */
+- aim_ssi_cleanlist(od);
+-
+- /*** Begin code for pruning buddies from local list if they're not in server list ***/
+-
+- /* Buddies */
+- cur = NULL;
+- for (buddies = purple_find_buddies(account, NULL);
+- buddies;
+- buddies = g_slist_delete_link(buddies, buddies))
+- {
+- PurpleGroup *g;
+- const char *gname;
+- const char *bname;
+-
+- b = buddies->data;
+- g = purple_buddy_get_group(b);
+- gname = purple_group_get_name(g);
+- bname = purple_buddy_get_name(b);
+-
+- if (aim_ssi_itemlist_exists(od->ssi.local, bname)) {
+- /* If the buddy is an ICQ user then load his nickname */
+- const char *servernick = purple_blist_node_get_string((PurpleBlistNode*)b, "servernick");
+- char *alias;
+- const char *balias;
+- if (servernick)
+- serv_got_alias(gc, bname, servernick);
+-
+- /* Store local alias on server */
+- alias = aim_ssi_getalias(od->ssi.local, gname, bname);
+- balias = purple_buddy_get_local_buddy_alias(b);
+- if (!alias && balias && *balias)
+- aim_ssi_aliasbuddy(od, gname, bname, balias);
+- g_free(alias);
+- } else {
+- purple_debug_info("oscar",
+- "ssi: removing buddy %s from local list\n", bname);
+- /* Queue the buddy for removal from the local list */
+- cur = g_slist_prepend(cur, b);
+- }
+- }
+- while (cur != NULL) {
+- purple_blist_remove_buddy(cur->data);
+- cur = g_slist_delete_link(cur, cur);
+- }
+-
+- /* Permit list (ICQ doesn't have one) */
+- if (!od->icq) {
+- next = account->permit;
+- while (next != NULL) {
+- cur = next;
+- next = next->next;
+- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, AIM_SSI_TYPE_PERMIT)) {
+- purple_debug_info("oscar",
+- "ssi: removing permit %s from local list\n", (const char *)cur->data);
+- purple_privacy_permit_remove(account, cur->data, TRUE);
+- }
+- }
+- }
+-
+- /* Deny list */
+- next = account->deny;
+- while (next != NULL) {
+- cur = next;
+- next = next->next;
+- if (!aim_ssi_itemlist_finditem(od->ssi.local, NULL, cur->data, deny_entry_type)) {
+- purple_debug_info("oscar",
+- "ssi: removing deny %s from local list\n", (const char *)cur->data);
+- purple_privacy_deny_remove(account, cur->data, TRUE);
+- }
+- }
+-
+- /* Presence settings (idle time visibility) */
+- tmp = aim_ssi_getpresence(od->ssi.local);
+- if (tmp != 0xFFFFFFFF) {
+- const char *idle_reporting_pref;
+- gboolean report_idle;
+-
+- idle_reporting_pref = purple_prefs_get_string("/purple/away/idle_reporting");
+- report_idle = strcmp(idle_reporting_pref, "none") != 0;
+-
+- if (report_idle)
+- aim_ssi_setpresence(od, tmp | AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
+- else
+- aim_ssi_setpresence(od, tmp & ~AIM_SSI_PRESENCE_FLAG_SHOWIDLE);
+- }
+-
+- /*** End code for pruning buddies from local list ***/
+-
+- /*** Begin code for adding from server list to local list ***/
+-
+- for (curitem=od->ssi.local; curitem; curitem=curitem->next) {
+- if (curitem->name && !g_utf8_validate(curitem->name, -1, NULL)) {
+- /* Got node with invalid UTF-8 in the name. Skip it. */
+- purple_debug_warning("oscar", "ssi: server list contains item of "
+- "type 0x%04hhx with a non-utf8 name\n", curitem->type);
+- continue;
+- }
+-
+- switch (curitem->type) {
+- case AIM_SSI_TYPE_BUDDY: { /* Buddy */
+- if (curitem->name) {
+- struct aim_ssi_item *groupitem;
+- char *gname, *gname_utf8, *alias, *alias_utf8;
+-
+- groupitem = aim_ssi_itemlist_find(od->ssi.local, curitem->gid, 0x0000);
+- gname = groupitem ? groupitem->name : NULL;
+- gname_utf8 = oscar_utf8_try_convert(account, od, gname);
+-
+- g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans"));
+- if (g == NULL) {
+- g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+- purple_blist_add_group(g, NULL);
+- }
+-
+- alias = aim_ssi_getalias(od->ssi.local, gname, curitem->name);
+- alias_utf8 = oscar_utf8_try_convert(account, od, alias);
+-
+- b = purple_find_buddy_in_group(account, curitem->name, g);
+- if (b) {
+- /* Get server stored alias */
+- purple_blist_alias_buddy(b, alias_utf8);
+- } else {
+- b = purple_buddy_new(account, curitem->name, alias_utf8);
+-
+- purple_debug_info("oscar",
+- "ssi: adding buddy %s to group %s to local list\n", curitem->name, gname);
+- purple_blist_add_buddy(b, NULL, g, NULL);
+- }
+-
+- /* Mobile users should always be online */
+- if (curitem->name[0] == '+') {
+- purple_prpl_got_user_status(account,
+- purple_buddy_get_name(b),
+- OSCAR_STATUS_ID_AVAILABLE, NULL);
+- purple_prpl_got_user_status(account,
+- purple_buddy_get_name(b),
+- OSCAR_STATUS_ID_MOBILE, NULL);
+- }
+-
+- g_free(gname_utf8);
+- g_free(alias);
+- g_free(alias_utf8);
+- }
+- } break;
+-
+- case AIM_SSI_TYPE_GROUP: { /* Group */
+- if (curitem->name != NULL && purple_find_group(curitem->name) == NULL) {
+- g = purple_group_new(curitem->name);
+- purple_blist_add_group(g, NULL);
+- }
+- } break;
+-
+- case AIM_SSI_TYPE_PERMIT: { /* Permit buddy (unless we're on ICQ) */
+- if (!od->icq && curitem->name) {
+- for (cur = account->permit; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next);
+- if (!cur) {
+- purple_debug_info("oscar",
+- "ssi: adding permit buddy %s to local list\n", curitem->name);
+- purple_privacy_permit_add(account, curitem->name, TRUE);
+- }
+- }
+- } break;
+-
+- case AIM_SSI_TYPE_ICQDENY:
+- case AIM_SSI_TYPE_DENY: { /* Deny buddy */
+- if (curitem->type == deny_entry_type && curitem->name) {
+- for (cur = account->deny; (cur && oscar_util_name_compare(curitem->name, cur->data)); cur = cur->next);
+- if (!cur) {
+- purple_debug_info("oscar",
+- "ssi: adding deny buddy %s to local list\n", curitem->name);
+- purple_privacy_deny_add(account, curitem->name, TRUE);
+- }
+- }
+- } break;
+-
+- case AIM_SSI_TYPE_PDINFO: { /* Permit/deny setting */
+- /*
+- * We don't inherit the permit/deny setting from the server
+- * for ICQ because, for ICQ, this setting controls who can
+- * see your online status when you are invisible. Thus it is
+- * a part of your status and not really related to blocking.
+- */
+- if (!od->icq && curitem->data) {
+- guint8 perm_deny = aim_ssi_getpermdeny(od->ssi.local);
+- if (perm_deny != 0 && perm_deny != account->perm_deny)
+- {
+- purple_debug_info("oscar",
+- "ssi: changing permdeny from %d to %hhu\n", account->perm_deny, perm_deny);
+- account->perm_deny = perm_deny;
+- }
+- }
+- } break;
+-
+- case AIM_SSI_TYPE_PRESENCEPREFS: { /* Presence setting */
+- /* We don't want to change Purple's setting because it applies to all accounts */
+- } break;
+- } /* End of switch on curitem->type */
+- } /* End of for loop */
+-
+- /*** End code for adding from server list to local list ***/
+-
+- if (od->icq) {
+- oscar_set_icq_permdeny(account);
+- } else {
+- oscar_set_aim_permdeny(gc);
+- }
+-
+- /* Activate SSI */
+- /* Sending the enable causes other people to be able to see you, and you to see them */
+- /* Make sure your privacy setting/invisibility is set how you want it before this! */
+- purple_debug_info("oscar",
+- "ssi: activating server-stored buddy list\n");
+- aim_ssi_enable(od);
+-
+- /*
+- * Make sure our server-stored icon is updated correctly in
+- * the event that the local user set a new icon while this
+- * account was offline.
+- */
+- img = purple_buddy_icons_find_account_icon(account);
+- oscar_set_icon(gc, img);
+- purple_imgstore_unref(img);
+-
+- /*
+- * If we've already received our bos rights then we're not waiting on
+- * anything else, so send the server clientready.
+- */
+- if (od->bos.have_rights) {
+- aim_srv_clientready(od, conn);
+-
+- /* Request offline messages for AIM and ICQ */
+- aim_im_reqofflinemsgs(od);
+-
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+- }
+-
+- return 1;
+-}
+-
+-static int purple_ssi_parseack(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- struct aim_ssi_tmp *retval;
+-
+- va_start(ap, fr);
+- retval = va_arg(ap, struct aim_ssi_tmp *);
+- va_end(ap);
+-
+- while (retval) {
+- purple_debug_misc("oscar",
+- "ssi: status is 0x%04hx for a 0x%04hx action with name %s\n", retval->ack, retval->action, retval->item ? (retval->item->name ? retval->item->name : "no name") : "no item");
+-
+- if (retval->ack != 0xffff)
+- switch (retval->ack) {
+- case 0x0000: { /* added successfully */
+- } break;
+-
+- case 0x000c: { /* you are over the limit, the cheat is to the limit, come on fhqwhgads */
+- gchar *buf;
+- buf = g_strdup_printf(_("Unable to add the buddy %s because you have too many buddies in your buddy list. Please remove one and try again."), (retval->name ? retval->name : _("(no name)")));
+- if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
+- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
+- g_free(buf);
+- }
+-
+- case 0x000e: { /* buddy requires authorization */
+- if ((retval->action == SNAC_SUBTYPE_FEEDBAG_ADD) && (retval->name))
+- oscar_auth_sendrequest(gc, retval->name, NULL);
+- } break;
+-
+- default: { /* La la la */
+- gchar *buf;
+- purple_debug_error("oscar", "ssi: Action 0x%04hx was unsuccessful with error 0x%04hx\n", retval->action, retval->ack);
+- buf = g_strdup_printf(_("Unable to add the buddy %s for an unknown reason."),
+- (retval->name ? retval->name : _("(no name)")));
+- if ((retval->name != NULL) && !purple_conv_present_error(retval->name, purple_connection_get_account(gc), buf))
+- purple_notify_error(gc, NULL, _("Unable to Add"), buf);
+- g_free(buf);
+- } break;
+- }
+-
+- retval = retval->next;
+- }
+-
+- return 1;
+-}
+-
+-static int
+-purple_ssi_parseaddmod(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- char *gname, *gname_utf8, *alias, *alias_utf8;
+- PurpleBuddy *b;
+- PurpleGroup *g;
+- struct aim_ssi_item *ssi_item;
+- va_list ap;
+- guint16 snac_subtype, type;
+- const char *name;
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- va_start(ap, fr);
+- snac_subtype = (guint16)va_arg(ap, int);
+- type = (guint16)va_arg(ap, int);
+- name = va_arg(ap, char *);
+- va_end(ap);
+-
+- if ((type != 0x0000) || (name == NULL))
+- return 1;
+-
+- gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+- gname_utf8 = gname ? oscar_utf8_try_convert(account, od, gname) : NULL;
+-
+- alias = aim_ssi_getalias(od->ssi.local, gname, name);
+- alias_utf8 = oscar_utf8_try_convert(account, od, alias);
+- g_free(alias);
+-
+- b = purple_find_buddy(account, name);
+- if (b) {
+- /*
+- * You're logged in somewhere else and you aliased one
+- * of your buddies, so update our local buddy list with
+- * the person's new alias.
+- */
+- purple_blist_alias_buddy(b, alias_utf8);
+- } else if (snac_subtype == 0x0008) {
+- /*
+- * You're logged in somewhere else and you added a buddy to
+- * your server list, so add them to your local buddy list.
+- */
+- b = purple_buddy_new(account, name, alias_utf8);
+-
+- if (!(g = purple_find_group(gname_utf8 ? gname_utf8 : _("Orphans")))) {
+- g = purple_group_new(gname_utf8 ? gname_utf8 : _("Orphans"));
+- purple_blist_add_group(g, NULL);
+- }
+-
+- purple_debug_info("oscar",
+- "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans"));
+- purple_blist_add_buddy(b, NULL, g, NULL);
+-
+- /* Mobile users should always be online */
+- if (name[0] == '+') {
+- purple_prpl_got_user_status(account,
+- name, OSCAR_STATUS_ID_AVAILABLE, NULL);
+- purple_prpl_got_user_status(account,
+- name, OSCAR_STATUS_ID_MOBILE, NULL);
+- }
+-
+- }
+-
+- ssi_item = aim_ssi_itemlist_finditem(od->ssi.local,
+- gname, name, AIM_SSI_TYPE_BUDDY);
+- if (ssi_item == NULL)
+- {
+- purple_debug_error("oscar", "purple_ssi_parseaddmod: "
+- "Could not find ssi item for oncoming buddy %s, "
+- "group %s\n", name, gname);
+- }
+-
+- g_free(gname_utf8);
+- g_free(alias_utf8);
+-
+- return 1;
+-}
+-
+-static int purple_ssi_authgiven(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- char *bn, *msg;
+- gchar *dialog_msg, *nombre;
+- struct name_data *data;
+- PurpleBuddy *buddy;
+-
+- va_start(ap, fr);
+- bn = va_arg(ap, char *);
+- msg = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_info("oscar",
+- "ssi: %s has given you permission to add him to your buddy list\n", bn);
+-
+- buddy = purple_find_buddy(purple_connection_get_account(gc), bn);
+- if (buddy && (purple_buddy_get_alias_only(buddy)))
+- nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy));
+- else
+- nombre = g_strdup(bn);
+-
+- dialog_msg = g_strdup_printf(_("The user %s has given you permission to add him or her to your buddy list. Do you want to add this user?"), nombre);
+- g_free(nombre);
+-
+- data = g_new(struct name_data, 1);
+- data->gc = gc;
+- data->name = g_strdup(bn);
+- data->nick = (buddy ? g_strdup(purple_buddy_get_alias_only(buddy)) : NULL);
+-
+- purple_request_yes_no(gc, NULL, _("Authorization Given"), dialog_msg,
+- PURPLE_DEFAULT_ACTION_NONE,
+- purple_connection_get_account(gc), bn, NULL,
+- data,
+- G_CALLBACK(purple_icq_buddyadd),
+- G_CALLBACK(oscar_free_name_data));
+- g_free(dialog_msg);
+-
+- return 1;
+-}
+-
+-static int purple_ssi_authrequest(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...)
+-{
+- va_list ap;
+- const char *bn;
+- char *msg;
+-
+- va_start(ap, fr);
+- bn = va_arg(ap, const char *);
+- msg = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_info("oscar",
+- "ssi: received authorization request from %s\n", bn);
+-
+- if (!msg) {
+- purple_debug_warning("oscar", "Received auth request from %s with "
+- "empty message\n", bn);
+- } else if (!g_utf8_validate(msg, -1, NULL)) {
+- purple_debug_warning("oscar", "Received auth request from %s with "
+- "invalid UTF-8 message\n", bn);
+- msg = NULL;
+- }
+-
+- aim_icq_getalias(od, bn, TRUE, msg);
+- return 1;
+-}
+-
+-static int purple_ssi_authreply(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- va_list ap;
+- char *bn, *msg;
+- gchar *dialog_msg, *nombre;
+- guint8 reply;
+- PurpleBuddy *buddy;
+-
+- va_start(ap, fr);
+- bn = va_arg(ap, char *);
+- reply = (guint8)va_arg(ap, int);
+- msg = va_arg(ap, char *);
+- va_end(ap);
+-
+- purple_debug_info("oscar",
+- "ssi: received authorization reply from %s. Reply is 0x%04hhx\n", bn, reply);
+-
+- buddy = purple_find_buddy(purple_connection_get_account(gc), bn);
+- if (buddy && (purple_buddy_get_alias_only(buddy)))
+- nombre = g_strdup_printf("%s (%s)", bn, purple_buddy_get_alias_only(buddy));
+- else
+- nombre = g_strdup(bn);
+-
+- if (reply) {
+- /* Granted */
+- dialog_msg = g_strdup_printf(_("The user %s has granted your request to add them to your buddy list."), nombre);
+- purple_notify_info(gc, NULL, _("Authorization Granted"), dialog_msg);
+- } else {
+- /* Denied */
+- dialog_msg = g_strdup_printf(_("The user %s has denied your request to add them to your buddy list for the following reason:\n%s"), nombre, msg ? msg : _("No reason given."));
+- purple_notify_info(gc, NULL, _("Authorization Denied"), dialog_msg);
+- }
+- g_free(dialog_msg);
+- g_free(nombre);
+-
+- return 1;
+-}
+-
+-static int purple_ssi_gotadded(OscarData *od, FlapConnection *conn, FlapFrame *fr, ...) {
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- va_list ap;
+- char *bn;
+- PurpleBuddy *buddy;
+-
+- va_start(ap, fr);
+- bn = va_arg(ap, char *);
+- va_end(ap);
+-
+- buddy = purple_find_buddy(account, bn);
+- purple_debug_info("oscar", "ssi: %s added you to their buddy list\n", bn);
+- purple_account_notify_added(account, bn, NULL,
+- (buddy ? purple_buddy_get_alias_only(buddy) : NULL), NULL);
+-
+- return 1;
+-}
+-
+-GList *oscar_chat_info(PurpleConnection *gc) {
+- GList *m = NULL;
+- struct proto_chat_entry *pce;
+-
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _("_Room:");
+- pce->identifier = "room";
+- pce->required = TRUE;
+- m = g_list_append(m, pce);
+-
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _("_Exchange:");
+- pce->identifier = "exchange";
+- pce->required = TRUE;
+- pce->is_int = TRUE;
+- pce->min = 4;
+- pce->max = 20;
+- m = g_list_append(m, pce);
+-
+- return m;
+-}
+-
+-GHashTable *oscar_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, "room", g_strdup(chat_name));
+- g_hash_table_insert(defaults, "exchange", g_strdup("4"));
+-
+- return defaults;
+-}
+-
+-char *
+-oscar_get_chat_name(GHashTable *data)
+-{
+- return g_strdup(g_hash_table_lookup(data, "room"));
+-}
+-
+-void
+-oscar_join_chat(PurpleConnection *gc, GHashTable *data)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- FlapConnection *conn;
+- char *name, *exchange;
+- int exchange_int;
+-
+- name = g_hash_table_lookup(data, "room");
+- exchange = g_hash_table_lookup(data, "exchange");
+-
+- g_return_if_fail(name != NULL && *name != '\0');
+- g_return_if_fail(exchange != NULL);
+-
+- errno = 0;
+- exchange_int = strtol(exchange, NULL, 10);
+- g_return_if_fail(errno == 0);
+-
+- purple_debug_info("oscar", "Attempting to join chat room %s.\n", name);
+-
+- if ((conn = flap_connection_getbytype(od, SNAC_FAMILY_CHATNAV)))
+- {
+- purple_debug_info("oscar", "chatnav exists, creating room\n");
+- aim_chatnav_createroom(od, conn, name, exchange_int);
+- } else {
+- /* this gets tricky */
+- struct create_room *cr = g_new0(struct create_room, 1);
+- purple_debug_info("oscar", "chatnav does not exist, opening chatnav\n");
+- cr->exchange = exchange_int;
+- cr->name = g_strdup(name);
+- od->create_rooms = g_slist_prepend(od->create_rooms, cr);
+- aim_srv_requestnew(od, SNAC_FAMILY_CHATNAV);
+- }
+-}
+-
+-void
+-oscar_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- struct chat_connection *ccon = find_oscar_chat(gc, id);
+-
+- if (ccon == NULL)
+- return;
+-
+- aim_im_sendch2_chatinvite(od, name, message ? message : "",
+- ccon->exchange, ccon->name, 0x0);
+-}
+-
+-void
+-oscar_chat_leave(PurpleConnection *gc, int id)
+-{
+- PurpleConversation *conv;
+- struct chat_connection *cc;
+-
+- conv = purple_find_chat(gc, id);
+-
+- g_return_if_fail(conv != NULL);
+-
+- purple_debug_info("oscar", "Leaving chat room %s\n",
+- purple_conversation_get_name(conv));
+-
+- cc = find_oscar_chat(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(conv)));
+- flap_connection_schedule_destroy(cc->conn, OSCAR_DISCONNECT_DONE, NULL);
+- oscar_chat_kill(gc, cc);
+-}
+-
+-int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- PurpleConversation *conv = NULL;
+- struct chat_connection *c = NULL;
+- char *buf, *buf2, *buf3;
+- guint16 charset;
+- char *charsetstr;
+- gsize len;
+-
+- if (!(conv = purple_find_chat(gc, id)))
+- return -EINVAL;
+-
+- if (!(c = find_oscar_chat_by_conv(gc, conv)))
+- return -EINVAL;
+-
+- buf = purple_strdup_withhtml(message);
+-
+- if (strstr(buf, "<IMG "))
+- purple_conversation_write(conv, "",
+- _("Your IM Image was not sent. "
+- "You cannot send IM Images in AIM chats."),
+- PURPLE_MESSAGE_ERROR, time(NULL));
+-
+- buf2 = oscar_encode_im(buf, &len, &charset, &charsetstr);
+- /*
+- * Evan S. suggested that maxvis really does mean "number of
+- * 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);
+-
+- buf3 = purple_markup_strip_html(buf);
+- g_free(buf);
+-
+- buf = purple_strdup_withhtml(buf3);
+- g_free(buf3);
+-
+- buf2 = oscar_encode_im(buf, &len, &charset, &charsetstr);
+-
+- if ((len > c->maxlen) || (len > c->maxvis)) {
+- purple_debug_warning("oscar",
+- "Could not send %s because (%" G_GSIZE_FORMAT " > maxlen %i) or (%" G_GSIZE_FORMAT " > maxvis %i)\n",
+- 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.\n",
+- message, buf2);
+- }
+-
+- aim_chat_send_im(od, c->conn, 0, buf2, len, charsetstr, "en");
+- g_free(buf2);
+- g_free(buf);
+-
+- return 0;
+-}
+-
+-PurpleMood* oscar_get_purple_moods(PurpleAccount *account)
+-{
+- return icq_get_purple_moods(account);
+-}
+-
+-const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b)
+-{
+- const char *name = b ? purple_buddy_get_name(b) : NULL;
+- if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
+- return "icq";
+-
+- return "icq";
+-}
+-
+-const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b)
+-{
+- const char *name = b ? purple_buddy_get_name(b) : NULL;
+- if (name && !oscar_util_valid_name_sms(name) && oscar_util_valid_name_icq(name))
+- return "icq";
+-
+- return "aim";
+-}
+-
+-const char *oscar_list_emblem(PurpleBuddy *b)
+-{
+- PurpleConnection *gc = NULL;
+- OscarData *od = NULL;
+- PurpleAccount *account = NULL;
+- PurplePresence *presence;
+- PurpleStatus *status;
+- const char *status_id;
+- aim_userinfo_t *userinfo = NULL;
+- const char *name;
+-
+- account = purple_buddy_get_account(b);
+- name = purple_buddy_get_name(b);
+- if (account != NULL)
+- gc = purple_account_get_connection(account);
+- if (gc != NULL)
+- od = purple_connection_get_protocol_data(gc);
+- if (od != NULL)
+- userinfo = aim_locate_finduserinfo(od, name);
+-
+- presence = purple_buddy_get_presence(b);
+- status = purple_presence_get_active_status(presence);
+- status_id = purple_status_get_id(status);
+-
+- if (purple_presence_is_online(presence) == FALSE) {
+- char *gname;
+- if ((name) && (od) && (od->ssi.received_data) &&
+- (gname = aim_ssi_itemlist_findparentname(od->ssi.local, name)) &&
+- (aim_ssi_waitingforauth(od->ssi.local, gname, name))) {
+- return "not-authorized";
+- }
+- }
+-
+- if (userinfo != NULL ) {
+- if (userinfo->flags & AIM_FLAG_ADMINISTRATOR)
+- return "admin";
+- if (userinfo->flags & AIM_FLAG_ACTIVEBUDDY)
+- return "bot";
+- if (userinfo->capabilities & OSCAR_CAPABILITY_SECUREIM)
+- return "secure";
+- if (userinfo->icqinfo.status & AIM_ICQ_STATE_BIRTHDAY)
+- return "birthday";
+-
+- /* Make the mood icon override anything below this. */
+- if (purple_presence_is_status_primitive_active(presence, PURPLE_STATUS_MOOD))
+- return NULL;
+-
+- if (userinfo->capabilities & OSCAR_CAPABILITY_HIPTOP)
+- return "hiptop";
+- }
+- return NULL;
+-}
+-
+-void oscar_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- OscarData *od;
+- aim_userinfo_t *userinfo;
+-
+- if (!PURPLE_BUDDY_IS_ONLINE(b))
+- return;
+-
+- account = purple_buddy_get_account(b);
+- gc = purple_account_get_connection(account);
+- od = purple_connection_get_protocol_data(gc);
+- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
+-
+- oscar_user_info_append_status(gc, user_info, b, userinfo, /* use_html_status */ FALSE);
+-
+- if (full)
+- oscar_user_info_append_extra_info(gc, user_info, b, userinfo);
+-}
+-
+-char *oscar_status_text(PurpleBuddy *b)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- OscarData *od;
+- const PurplePresence *presence;
+- const PurpleStatus *status;
+- const char *id;
+- const char *message;
+- gchar *ret = NULL;
+-
+- gc = purple_account_get_connection(purple_buddy_get_account(b));
+- account = purple_connection_get_account(gc);
+- od = purple_connection_get_protocol_data(gc);
+- presence = purple_buddy_get_presence(b);
+- status = purple_presence_get_active_status(presence);
+- id = purple_status_get_id(status);
+-
+- if ((od != NULL) && !purple_presence_is_online(presence))
+- {
+- const char *name = purple_buddy_get_name(b);
+- char *gname = aim_ssi_itemlist_findparentname(od->ssi.local, name);
+- if (aim_ssi_waitingforauth(od->ssi.local, gname, name))
+- ret = g_strdup(_("Not Authorized"));
+- else
+- ret = g_strdup(_("Offline"));
+- }
+- else
+- {
+- message = purple_status_get_attr_string(status, "message");
+- if (message != NULL)
+- {
+- gchar *tmp = oscar_util_format_string(message, purple_account_get_username(account));
+- ret = purple_markup_escape_text(tmp, -1);
+- g_free(tmp);
+- }
+- else if (purple_status_is_available(status))
+- {
+- /* Don't show "Available" as status message in case buddy doesn't have a status message */
+- }
+- else
+- {
+- ret = g_strdup(purple_status_get_name(status));
+- }
+- }
+-
+- return ret;
+-}
+-
+-void oscar_set_aim_permdeny(PurpleConnection *gc) {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- /*
+- * Conveniently there is a one-to-one mapping between the
+- * values of libpurple's PurplePrivacyType and the values used
+- * by the oscar protocol.
+- */
+- aim_ssi_setpermdeny(od, account->perm_deny);
+-}
+-
+-void oscar_add_permit(PurpleConnection *gc, const char *who) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- purple_debug_info("oscar", "ssi: About to add a permit\n");
+- aim_ssi_add_to_private_list(od, who, AIM_SSI_TYPE_PERMIT);
+-}
+-
+-void oscar_add_deny(PurpleConnection *gc, const char *who) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- purple_debug_info("oscar", "ssi: About to add a deny\n");
+- aim_ssi_add_to_private_list(od, who, aim_ssi_getdenyentrytype(od));
+-}
+-
+-void oscar_rem_permit(PurpleConnection *gc, const char *who) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- purple_debug_info("oscar", "ssi: About to delete a permit\n");
+- aim_ssi_del_from_private_list(od, who, AIM_SSI_TYPE_PERMIT);
+-}
+-
+-void oscar_rem_deny(PurpleConnection *gc, const char *who) {
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- purple_debug_info("oscar", "ssi: About to delete a deny\n");
+- aim_ssi_del_from_private_list(od, who, aim_ssi_getdenyentrytype(od));
+-}
+-
+-GList *
+-oscar_status_types(PurpleAccount *account)
+-{
+- gboolean is_icq;
+- GList *status_types = NULL;
+- PurpleStatusType *type;
+-
+- g_return_val_if_fail(account != NULL, NULL);
+-
+- /* Used to flag some statuses as "user settable" or not */
+- is_icq = oscar_util_valid_name_icq(purple_account_get_username(account));
+-
+- /* Common status types */
+- /* Really the available message should only be settable for AIM accounts */
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_AVAILABLE,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING),
+- "itmsurl", _("iTunes Music Store Link"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_FREE4CHAT,
+- _("Free For Chat"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+-
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_EVIL,
+- _("Evil"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_DEPRESSION,
+- _("Depression"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_ATHOME,
+- _("At home"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_ATWORK,
+- _("At work"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+-
+- status_types = g_list_prepend(status_types, type);
+-
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- OSCAR_STATUS_ID_LUNCH,
+- _("Lunch"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+-
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
+- OSCAR_STATUS_ID_AWAY,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_INVISIBLE,
+- OSCAR_STATUS_ID_INVISIBLE,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+-
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, OSCAR_STATUS_ID_MOBILE, NULL, FALSE, FALSE, TRUE);
+- status_types = g_list_prepend(status_types, type);
+-
+- /* ICQ-specific status types */
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
+- OSCAR_STATUS_ID_OCCUPIED,
+- _("Occupied"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
+- OSCAR_STATUS_ID_DND,
+- _("Do Not Disturb"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_EXTENDED_AWAY,
+- OSCAR_STATUS_ID_NA,
+- _("Not Available"), TRUE, is_icq, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
+- OSCAR_STATUS_ID_OFFLINE,
+- NULL, TRUE, TRUE, FALSE);
+- status_types = g_list_prepend(status_types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_MOOD,
+- "mood", NULL, TRUE, is_icq, TRUE,
+- PURPLE_MOOD_NAME, _("Mood Name"), purple_value_new(PURPLE_TYPE_STRING),
+- PURPLE_MOOD_COMMENT, _("Mood Comment"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- status_types = g_list_prepend(status_types, type);
+-
+- return g_list_reverse(status_types);
+-}
+-
+-static void oscar_ssi_editcomment(struct name_data *data, const char *text) {
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- OscarData *od;
+- PurpleBuddy *b;
+- PurpleGroup *g;
+-
+- gc = data->gc;
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- b = purple_find_buddy(account, data->name);
+- if (b == NULL) {
+- oscar_free_name_data(data);
+- return;
+- }
+-
+- g = purple_buddy_get_group(b);
+- if (g == NULL) {
+- oscar_free_name_data(data);
+- return;
+- }
+-
+- aim_ssi_editcomment(od, purple_group_get_name(g), data->name, text);
+- oscar_free_name_data(data);
+-}
+-
+-static void oscar_buddycb_edit_comment(PurpleBlistNode *node, gpointer ignore) {
+-
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- OscarData *od;
+- struct name_data *data;
+- PurpleGroup *g;
+- char *comment;
+- gchar *comment_utf8;
+- gchar *title;
+- PurpleAccount *account;
+- const char *name;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- name = purple_buddy_get_name(buddy);
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- od = purple_connection_get_protocol_data(gc);
+-
+- if (!(g = purple_buddy_get_group(buddy)))
+- return;
+-
+- data = g_new(struct name_data, 1);
+-
+- comment = aim_ssi_getcomment(od->ssi.local, purple_group_get_name(g), name);
+- comment_utf8 = comment ? oscar_utf8_try_convert(account, od, comment) : NULL;
+-
+- data->gc = gc;
+- data->name = g_strdup(name);
+- data->nick = g_strdup(purple_buddy_get_alias_only(buddy));
+-
+- title = g_strdup_printf(_("Buddy Comment for %s"), data->name);
+- purple_request_input(gc, title, _("Buddy Comment:"), NULL,
+- comment_utf8, TRUE, FALSE, NULL,
+- _("_OK"), G_CALLBACK(oscar_ssi_editcomment),
+- _("_Cancel"), G_CALLBACK(oscar_free_name_data),
+- account, data->name, NULL,
+- data);
+- g_free(title);
+-
+- g_free(comment);
+- g_free(comment_utf8);
+-}
+-
+-static void
+-oscar_ask_directim_yes_cb(struct oscar_ask_directim_data *data)
+-{
+- peer_connection_propose(data->od, OSCAR_CAPABILITY_DIRECTIM, data->who);
+- g_free(data->who);
+- g_free(data);
+-}
+-
+-static void
+-oscar_ask_directim_no_cb(struct oscar_ask_directim_data *data)
+-{
+- g_free(data->who);
+- g_free(data);
+-}
+-
+-/* This is called from right-click menu on a buddy node. */
+-static void
+-oscar_ask_directim(gpointer object, gpointer ignored)
+-{
+- PurpleBlistNode *node;
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- gchar *buf;
+- struct oscar_ask_directim_data *data;
+- PurpleAccount *account;
+-
+- node = object;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *)node;
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+-
+- data = g_new0(struct oscar_ask_directim_data, 1);
+- data->who = g_strdup(purple_buddy_get_name(buddy));
+- data->od = purple_connection_get_protocol_data(gc);
+- buf = g_strdup_printf(_("You have selected to open a Direct IM connection with %s."),
+- data->who);
+-
+- purple_request_action(gc, NULL, buf,
+- _("Because this reveals your IP address, it "
+- "may be considered a security risk. Do you "
+- "wish to continue?"),
+- 0, /* Default action is "connect" */
+- account, data->who, NULL,
+- data, 2,
+- _("C_onnect"), G_CALLBACK(oscar_ask_directim_yes_cb),
+- _("_Cancel"), G_CALLBACK(oscar_ask_directim_no_cb));
+- g_free(buf);
+-}
+-
+-static void
+-oscar_close_directim(gpointer object, gpointer ignored)
+-{
+- PurpleBlistNode *node;
+- PurpleBuddy *buddy;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- PurpleConversation *conv;
+- OscarData *od;
+- PeerConnection *conn;
+- const char *name;
+-
+- node = object;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy*)node;
+- name = purple_buddy_get_name(buddy);
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- od = gc->proto_data;
+- conn = peer_connection_find_by_type(od, name, OSCAR_CAPABILITY_DIRECTIM);
+-
+- if (conn != NULL)
+- {
+- if (!conn->ready)
+- aim_im_sendch2_cancel(conn);
+-
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+-
+- /* OSCAR_DISCONNECT_LOCAL_CLOSED doesn't write anything to the convo
+- * window. Let the user know that we cancelled the Direct IM. */
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, name);
+- purple_conversation_write(conv, NULL, _("You closed the connection."),
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+-}
+-
+-static void oscar_get_icqxstatusmsg(PurpleBlistNode *node, gpointer ignore)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- OscarData *od;
+- PurpleAccount *account;
+- const char *bname;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *)node;
+- bname = purple_buddy_get_name(buddy);
+-
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- od = purple_connection_get_protocol_data(gc);
+-
+- purple_debug_info("oscar", "Manual X-Status Get From %s to %s:\n", bname, purple_account_get_username(account));
+-
+- icq_im_xstatus_request(od, bname);
+-}
+-
+-static void
+-oscar_get_aim_info_cb(PurpleBlistNode *node, gpointer ignore)
+-{
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *)node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+-
+- aim_locate_getinfoshort(purple_connection_get_protocol_data(gc),
+- purple_buddy_get_name(buddy), 0x00000003);
+-}
+-
+-static GList *
+-oscar_buddy_menu(PurpleBuddy *buddy) {
+- PurpleConnection *gc;
+- OscarData *od;
+- GList *menu;
+- PurpleMenuAction *act;
+- aim_userinfo_t *userinfo;
+- PurpleAccount *account;
+- const char *bname = purple_buddy_get_name(buddy);
+-
+- account = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(account);
+- od = purple_connection_get_protocol_data(gc);
+- userinfo = aim_locate_finduserinfo(od, bname);
+- menu = NULL;
+-
+- if (od->icq && oscar_util_valid_name_icq(bname))
+- {
+- act = purple_menu_action_new(_("Get AIM Info"),
+- PURPLE_CALLBACK(oscar_get_aim_info_cb),
+- NULL, NULL);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- if (purple_buddy_get_group(buddy) != NULL)
+- {
+- /* We only do this if the user is in our buddy list */
+- act = purple_menu_action_new(_("Edit Buddy Comment"),
+- PURPLE_CALLBACK(oscar_buddycb_edit_comment),
+- NULL, NULL);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- if (od->icq)
+- {
+- act = purple_menu_action_new(_("Get X-Status Msg"),
+- PURPLE_CALLBACK(oscar_get_icqxstatusmsg),
+- NULL, NULL);
+- menu = g_list_prepend(menu, act);
+- menu = g_list_prepend(menu, create_visibility_menu_item(od, bname));
+- }
+-
+- if (userinfo &&
+- oscar_util_name_compare(purple_account_get_username(account), bname) &&
+- PURPLE_BUDDY_IS_ONLINE(buddy))
+- {
+- PeerConnection *conn;
+- conn = peer_connection_find_by_type(od, bname, OSCAR_CAPABILITY_DIRECTIM);
+-
+- if (userinfo->capabilities & OSCAR_CAPABILITY_DIRECTIM)
+- {
+- if (conn)
+- {
+- act = purple_menu_action_new(_("End Direct IM Session"),
+- PURPLE_CALLBACK(oscar_close_directim),
+- NULL, NULL);
+- }
+- else
+- {
+- act = purple_menu_action_new(_("Direct IM"),
+- PURPLE_CALLBACK(oscar_ask_directim),
+- NULL, NULL);
+- }
+- menu = g_list_prepend(menu, act);
+- }
+- }
+-
+- if (od->ssi.received_data && purple_buddy_get_group(buddy) != NULL)
+- {
+- /*
+- * We only do this if the user is in our buddy list and we're
+- * waiting for authorization.
+- */
+- char *gname;
+- gname = aim_ssi_itemlist_findparentname(od->ssi.local, bname);
+- if (gname && aim_ssi_waitingforauth(od->ssi.local, gname, bname))
+- {
+- act = purple_menu_action_new(_("Re-request Authorization"),
+- PURPLE_CALLBACK(oscar_auth_sendrequest_menu),
+- NULL, NULL);
+- menu = g_list_prepend(menu, act);
+- }
+- }
+-
+- menu = g_list_reverse(menu);
+-
+- return menu;
+-}
+-
+-
+-GList *oscar_blist_node_menu(PurpleBlistNode *node) {
+- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+- return oscar_buddy_menu((PurpleBuddy *) node);
+- } else {
+- return NULL;
+- }
+-}
+-
+-static void
+-oscar_icq_privacy_opts(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleRequestField *f;
+- gboolean auth, web_aware;
+-
+- f = purple_request_fields_get_field(fields, "authorization");
+- auth = purple_request_field_bool_get_value(f);
+-
+- f = purple_request_fields_get_field(fields, "web_aware");
+- web_aware = purple_request_field_bool_get_value(f);
+-
+- purple_account_set_bool(account, "authorization", auth);
+- purple_account_set_bool(account, "web_aware", web_aware);
+-
+- oscar_set_extended_status(gc);
+- aim_icq_setsecurity(od, auth, web_aware);
+-}
+-
+-static void
+-oscar_show_icq_privacy_opts(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *g;
+- PurpleRequestField *f;
+- gboolean auth, web_aware;
+-
+- auth = purple_account_get_bool(account, "authorization", OSCAR_DEFAULT_AUTHORIZATION);
+- web_aware = purple_account_get_bool(account, "web_aware", OSCAR_DEFAULT_WEB_AWARE);
+-
+- fields = purple_request_fields_new();
+-
+- g = purple_request_field_group_new(NULL);
+-
+- f = purple_request_field_bool_new("authorization", _("Require authorization"), auth);
+- purple_request_field_group_add_field(g, f);
+-
+- f = purple_request_field_bool_new("web_aware", _("Web aware (enabling this will cause you to receive SPAM!)"), web_aware);
+- purple_request_field_group_add_field(g, f);
+-
+- purple_request_fields_add_group(fields, g);
+-
+- purple_request_fields(gc, _("ICQ Privacy Options"), _("ICQ Privacy Options"),
+- NULL, fields,
+- _("OK"), G_CALLBACK(oscar_icq_privacy_opts),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void oscar_confirm_account(PurplePluginAction *action)
+-{
+- PurpleConnection *gc;
+- OscarData *od;
+- FlapConnection *conn;
+-
+- gc = (PurpleConnection *)action->context;
+- od = purple_connection_get_protocol_data(gc);
+-
+- conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
+- if (conn != NULL) {
+- aim_admin_reqconfirm(od, conn);
+- } else {
+- od->conf = TRUE;
+- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
+- }
+-}
+-
+-static void oscar_show_email(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
+-
+- if (conn) {
+- aim_admin_getinfo(od, conn, 0x11);
+- } else {
+- od->reqemail = TRUE;
+- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
+- }
+-}
+-
+-static void oscar_change_email(PurpleConnection *gc, const char *email)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- FlapConnection *conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
+-
+- if (conn) {
+- aim_admin_setemail(od, conn, email);
+- } else {
+- od->setemail = TRUE;
+- od->email = g_strdup(email);
+- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
+- }
+-}
+-
+-static void oscar_show_change_email(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_request_input(gc, NULL, _("Change Address To:"), NULL, NULL,
+- FALSE, FALSE, NULL,
+- _("_OK"), G_CALLBACK(oscar_change_email),
+- _("_Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void oscar_show_awaitingauth(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- PurpleAccount *account = purple_connection_get_account(gc);
+- GSList *buddies, *filtered_buddies, *cur;
+- gchar *text;
+-
+- buddies = purple_find_buddies(account, NULL);
+- filtered_buddies = NULL;
+- for (cur = buddies; cur != NULL; cur = cur->next) {
+- PurpleBuddy *buddy;
+- const gchar *bname, *gname;
+-
+- buddy = cur->data;
+- bname = purple_buddy_get_name(buddy);
+- gname = purple_group_get_name(purple_buddy_get_group(buddy));
+- if (aim_ssi_waitingforauth(od->ssi.local, gname, bname)) {
+- filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
+- }
+- }
+-
+- g_slist_free(buddies);
+-
+- filtered_buddies = g_slist_reverse(filtered_buddies);
+- text = oscar_format_buddies(filtered_buddies, _("you are not waiting for authorization"));
+- g_slist_free(filtered_buddies);
+-
+- purple_notify_formatted(gc, NULL, _("You are awaiting authorization from "
+- "the following buddies"), _("You can re-request "
+- "authorization from these buddies by "
+- "right-clicking on them and selecting "
+- "\"Re-request Authorization.\""), text, NULL, NULL);
+- g_free(text);
+-}
+-
+-static void search_by_email_cb(PurpleConnection *gc, const char *email)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- aim_search_address(od, email);
+-}
+-
+-static void oscar_show_find_email(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_request_input(gc, _("Find Buddy by Email"),
+- _("Search for a buddy by email address"),
+- _("Type the email address of the buddy you are "
+- "searching for."),
+- NULL, FALSE, FALSE, NULL,
+- _("_Search"), G_CALLBACK(search_by_email_cb),
+- _("_Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void oscar_show_set_info(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_account_request_change_user_info(purple_connection_get_account(gc));
+-}
+-
+-static void oscar_show_set_info_icqurl(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_notify_uri(gc, "http://www.icq.com/whitepages/user_details.php");
+-}
+-
+-static void oscar_change_pass(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_account_request_change_password(purple_connection_get_account(gc));
+-}
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-static void oscar_show_chpassurl(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- gchar *substituted = purple_strreplace(od->authinfo->chpassurl, "%s", purple_account_get_username(purple_connection_get_account(gc)));
+- purple_notify_uri(gc, substituted);
+- g_free(substituted);
+-}
+-
+-static void oscar_show_imforwardingurl(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_notify_uri(gc, "http://mymobile.aol.com/dbreg/register?action=imf&clientID=1");
+-}
+-
+-void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (img == NULL) {
+- aim_ssi_delicon(od);
+- } else {
+- PurpleCipherContext *context;
+- guchar md5[16];
+- gconstpointer data = purple_imgstore_get_data(img);
+- size_t len = purple_imgstore_get_size(img);
+-
+- context = purple_cipher_context_new_by_name("md5", NULL);
+- purple_cipher_context_append(context, data, len);
+- purple_cipher_context_digest(context, 16, md5, NULL);
+- purple_cipher_context_destroy(context);
+-
+- aim_ssi_seticon(od, md5, 16);
+- }
+-}
+-
+-/**
+- * Called by the Purple core to determine whether or not we're
+- * allowed to send a file to this user.
+- */
+-gboolean
+-oscar_can_receive_file(PurpleConnection *gc, const char *who)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- if (od != NULL)
+- {
+- aim_userinfo_t *userinfo;
+- userinfo = aim_locate_finduserinfo(od, who);
+-
+- /*
+- * Don't allowing sending a file to a user that does not support
+- * file transfer, and don't allow sending to ourselves.
+- */
+- if (((userinfo == NULL) ||
+- (userinfo->capabilities & OSCAR_CAPABILITY_SENDFILE)) &&
+- oscar_util_name_compare(who, purple_account_get_username(account)))
+- {
+- return TRUE;
+- }
+- }
+-
+- return FALSE;
+-}
+-
+-PurpleXfer *
+-oscar_new_xfer(PurpleConnection *gc, const char *who)
+-{
+- PurpleXfer *xfer;
+- OscarData *od;
+- PurpleAccount *account;
+- PeerConnection *conn;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- xfer = purple_xfer_new(account, PURPLE_XFER_SEND, who);
+- if (xfer)
+- {
+- purple_xfer_ref(xfer);
+- purple_xfer_set_init_fnc(xfer, peer_oft_sendcb_init);
+- purple_xfer_set_cancel_send_fnc(xfer, peer_oft_cb_generic_cancel);
+- purple_xfer_set_request_denied_fnc(xfer, peer_oft_cb_generic_cancel);
+- purple_xfer_set_ack_fnc(xfer, peer_oft_sendcb_ack);
+-
+- conn = peer_connection_new(od, OSCAR_CAPABILITY_SENDFILE, who);
+- conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME;
+- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
+- aim_icbm_makecookie(conn->cookie);
+- conn->xfer = xfer;
+- xfer->data = conn;
+- }
+-
+- return xfer;
+-}
+-
+-/*
+- * Called by the Purple core when the user indicates that a
+- * file is to be sent to a special someone.
+- */
+-void
+-oscar_send_file(PurpleConnection *gc, const char *who, const char *file)
+-{
+- PurpleXfer *xfer;
+-
+- xfer = oscar_new_xfer(gc, who);
+-
+- if (file != NULL)
+- purple_xfer_request_accepted(xfer, file);
+- else
+- purple_xfer_request(xfer);
+-}
+-
+-GList *
+-oscar_actions(PurplePlugin *plugin, gpointer context)
+-{
+- PurpleConnection *gc = (PurpleConnection *) context;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- GList *menu = NULL;
+- PurplePluginAction *act;
+-
+- act = purple_plugin_action_new(_("Set User Info..."),
+- oscar_show_set_info);
+- menu = g_list_prepend(menu, act);
+-
+- if (od->icq)
+- {
+- act = purple_plugin_action_new(_("Set User Info (web)..."),
+- oscar_show_set_info_icqurl);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- act = purple_plugin_action_new(_("Change Password..."),
+- oscar_change_pass);
+- menu = g_list_prepend(menu, act);
+-
+- if (od->authinfo != NULL && od->authinfo->chpassurl != NULL)
+- {
+- /* This only happens when connecting with the old-style BUCP login */
+- act = purple_plugin_action_new(_("Change Password (web)"),
+- oscar_show_chpassurl);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- if (!od->icq)
+- {
+- act = purple_plugin_action_new(_("Configure IM Forwarding (web)"),
+- oscar_show_imforwardingurl);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- menu = g_list_prepend(menu, NULL);
+-
+- if (od->icq)
+- {
+- /* ICQ actions */
+- act = purple_plugin_action_new(_("Set Privacy Options..."),
+- oscar_show_icq_privacy_opts);
+- menu = g_list_prepend(menu, act);
+-
+- act = purple_plugin_action_new(_("Show Visible List"), oscar_show_visible_list);
+- menu = g_list_prepend(menu, act);
+-
+- act = purple_plugin_action_new(_("Show Invisible List"), oscar_show_invisible_list);
+- menu = g_list_prepend(menu, act);
+- }
+- else
+- {
+- /* AIM actions */
+- act = purple_plugin_action_new(_("Confirm Account"),
+- oscar_confirm_account);
+- menu = g_list_prepend(menu, act);
+-
+- act = purple_plugin_action_new(_("Display Currently Registered Email Address"),
+- oscar_show_email);
+- menu = g_list_prepend(menu, act);
+-
+- act = purple_plugin_action_new(_("Change Currently Registered Email Address..."),
+- oscar_show_change_email);
+- menu = g_list_prepend(menu, act);
+- }
+-
+- menu = g_list_prepend(menu, NULL);
+-
+- act = purple_plugin_action_new(_("Show Buddies Awaiting Authorization"),
+- oscar_show_awaitingauth);
+- menu = g_list_prepend(menu, act);
+-
+- menu = g_list_prepend(menu, NULL);
+-
+- act = purple_plugin_action_new(_("Search for Buddy by Email Address..."),
+- oscar_show_find_email);
+- menu = g_list_prepend(menu, act);
+-
+- menu = g_list_reverse(menu);
+-
+- return menu;
+-}
+-
+-void oscar_change_passwd(PurpleConnection *gc, const char *old, const char *new)
+-{
+- OscarData *od = purple_connection_get_protocol_data(gc);
+-
+- if (od->icq) {
+- aim_icq_changepasswd(od, new);
+- } else {
+- FlapConnection *conn;
+- conn = flap_connection_getbytype(od, SNAC_FAMILY_ADMIN);
+- if (conn) {
+- aim_admin_changepasswd(od, conn, new, old);
+- } else {
+- od->chpass = TRUE;
+- od->oldp = g_strdup(old);
+- od->newp = g_strdup(new);
+- aim_srv_requestnew(od, SNAC_FAMILY_ADMIN);
+- }
+- }
+-}
+-
+-void
+-oscar_convo_closed(PurpleConnection *gc, const char *who)
+-{
+- OscarData *od;
+- PeerConnection *conn;
+-
+- od = purple_connection_get_protocol_data(gc);
+- conn = peer_connection_find_by_type(od, who, OSCAR_CAPABILITY_DIRECTIM);
+-
+- if (conn != NULL)
+- {
+- if (!conn->ready)
+- aim_im_sendch2_cancel(conn);
+-
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+- }
+-}
+-
+-const char *
+-oscar_normalize(const PurpleAccount *account, const char *str)
+-{
+- static char buf[BUF_LEN];
+- char *tmp1, *tmp2;
+- int i, j;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+-
+- /* copy str to buf and skip all blanks */
+- i = 0;
+- for (j = 0; str[j]; j++) {
+- if (str[j] != ' ') {
+- buf[i++] = str[j];
+- if (i >= BUF_LEN - 1)
+- break;
+- }
+- }
+- buf[i] = '\0';
+-
+- tmp1 = g_utf8_strdown(buf, -1);
+- tmp2 = g_utf8_normalize(tmp1, -1, G_NORMALIZE_DEFAULT);
+- if (strlen(tmp2) > sizeof(buf) - 1) {
+- purple_debug_error("oscar", "normalized string exceeds buffer length!\n");
+- }
+- g_strlcpy(buf, tmp2, sizeof(buf));
+- g_free(tmp2);
+- g_free(tmp1);
+-
+- return buf;
+-}
+-
+-gboolean
+-oscar_offline_message(const PurpleBuddy *buddy)
+-{
+- return TRUE;
+-}
+-
+-/* TODO: Find somewhere to put this instead of including it in a bunch of places.
+- * Maybe just change purple_accounts_find() to return anything for the prpl if there is no acct_id.
+- */
+-static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
+-{
+- PurpleAccount *acct = NULL;
+-
+- /* If we have a specific acct, use it */
+- if (acct_id) {
+- acct = purple_accounts_find(acct_id, prpl);
+- if (acct && !purple_account_is_connected(acct))
+- acct = NULL;
+- } else { /* Otherwise find an active account for the protocol */
+- GList *l = purple_accounts_get_all();
+- while (l) {
+- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
+- && purple_account_is_connected(l->data)) {
+- acct = l->data;
+- break;
+- }
+- l = l->next;
+- }
+- }
+-
+- return acct;
+-}
+-
+-
+-static gboolean oscar_uri_handler(const char *proto, const char *cmd, GHashTable *params)
+-{
+- char *acct_id = g_hash_table_lookup(params, "account");
+- char prpl[11];
+- PurpleAccount *acct;
+-
+- if (g_ascii_strcasecmp(proto, "aim") && g_ascii_strcasecmp(proto, "icq"))
+- return FALSE;
+-
+- g_snprintf(prpl, sizeof(prpl), "prpl-%s", proto);
+-
+- acct = find_acct(prpl, acct_id);
+-
+- if (!acct)
+- return FALSE;
+-
+- /* aim:GoIM?screenname=SCREENNAME&message=MESSAGE */
+- if (!g_ascii_strcasecmp(cmd, "GoIM")) {
+- char *bname = g_hash_table_lookup(params, "screenname");
+- if (bname) {
+- char *message = g_hash_table_lookup(params, "message");
+-
+- PurpleConversation *conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, bname, acct);
+- if (conv == NULL)
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, bname);
+- purple_conversation_present(conv);
+-
+- if (message) {
+- /* Spaces are encoded as '+' */
+- g_strdelimit(message, "+", ' ');
+- purple_conv_send_confirm(conv, message);
+- }
+- }
+- /*else
+- **If pidgindialogs_im() was in the core, we could use it here.
+- * It is all purple_request_* based, but I'm not sure it really belongs in the core
+- pidgindialogs_im();*/
+-
+- return TRUE;
+- }
+- /* aim:GoChat?roomname=CHATROOMNAME&exchange=4 */
+- else if (!g_ascii_strcasecmp(cmd, "GoChat")) {
+- char *rname = g_hash_table_lookup(params, "roomname");
+- if (rname) {
+- /* This is somewhat hacky, but the params aren't useful after this command */
+- g_hash_table_insert(params, g_strdup("exchange"), g_strdup("4"));
+- g_hash_table_insert(params, g_strdup("room"), g_strdup(rname));
+- serv_join_chat(purple_account_get_connection(acct), params);
+- }
+- /*else
+- ** Same as above (except that this would have to be re-written using purple_request_*)
+- pidgin_blist_joinchat_show(); */
+-
+- return TRUE;
+- }
+- /* aim:AddBuddy?screenname=SCREENNAME&groupname=GROUPNAME*/
+- else if (!g_ascii_strcasecmp(cmd, "AddBuddy")) {
+- char *bname = g_hash_table_lookup(params, "screenname");
+- char *gname = g_hash_table_lookup(params, "groupname");
+- purple_blist_request_add_buddy(acct, bname, gname, NULL);
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-void oscar_init(PurplePlugin *plugin, gboolean is_icq)
+-{
+- PurplePluginProtocolInfo *prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
+- PurpleAccountOption *option;
+- static gboolean init = FALSE;
+- static const gchar *encryption_keys[] = {
+- N_("Use encryption if available"),
+- N_("Require encryption"),
+- N_("Don't use encryption"),
+- NULL
+- };
+- static const gchar *encryption_values[] = {
+- OSCAR_OPPORTUNISTIC_ENCRYPTION,
+- OSCAR_REQUIRE_ENCRYPTION,
+- OSCAR_NO_ENCRYPTION,
+- NULL
+- };
+- GList *encryption_options = NULL;
+- int i;
+-
+- option = purple_account_option_string_new(_("Server"), "server", get_login_server(is_icq, TRUE));
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+-
+- option = purple_account_option_int_new(_("Port"), "port", OSCAR_DEFAULT_LOGIN_PORT);
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+-
+- for (i = 0; encryption_keys[i]; i++) {
+- PurpleKeyValuePair *kvp = g_new0(PurpleKeyValuePair, 1);
+- kvp->key = g_strdup(_(encryption_keys[i]));
+- kvp->value = g_strdup(encryption_values[i]);
+- encryption_options = g_list_append(encryption_options, kvp);
+- }
+- option = purple_account_option_list_new(_("Connection security"), "encryption", encryption_options);
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Use clientLogin"), "use_clientlogin",
+- OSCAR_DEFAULT_USE_CLIENTLOGIN);
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+-
+- option = purple_account_option_bool_new(
+- _("Always use AIM/ICQ proxy server for\nfile transfers and direct IM (slower,\nbut does not reveal your IP address)"), "always_use_rv_proxy",
+- OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY);
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+-
+- if (g_str_equal(purple_plugin_get_id(plugin), "prpl-aim")) {
+- option = purple_account_option_bool_new(_("Allow multiple simultaneous logins"), "allow_multiple_logins",
+- OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS);
+- prpl_info->protocol_options = g_list_append(prpl_info->protocol_options, option);
+- }
+-
+- if (init)
+- return;
+- init = TRUE;
+-
+- /* Preferences */
+- purple_prefs_add_none("/plugins/prpl/oscar");
+- purple_prefs_add_bool("/plugins/prpl/oscar/recent_buddies", FALSE);
+-
+- purple_prefs_remove("/plugins/prpl/oscar/show_idle");
+- purple_prefs_remove("/plugins/prpl/oscar/always_use_rv_proxy");
+-
+- /* protocol handler */
+- /* TODO: figure out a good instance to use here */
+- purple_signal_connect(purple_get_core(), "uri-handler", &init,
+- PURPLE_CALLBACK(oscar_uri_handler), NULL);
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscarcommon.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscarcommon.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/oscarcommon.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscarcommon.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,106 +0,0 @@
+-/* 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/* oscarcommon.h contains prototypes for the prpl functions used by libaim.c
+- * and libicq.c
+- */
+-
+-#include "internal.h"
+-
+-#include "accountopt.h"
+-#include "prpl.h"
+-#include "version.h"
+-#include "notify.h"
+-#include "status.h"
+-
+-#define AIM_DEFAULT_LOGIN_SERVER "login.oscar.aol.com"
+-#define AIM_ALT_LOGIN_SERVER "login.messaging.aol.com"
+-#define AIM_DEFAULT_SSL_LOGIN_SERVER "slogin.oscar.aol.com"
+-#define ICQ_DEFAULT_LOGIN_SERVER "login.icq.com"
+-#define ICQ_DEFAULT_SSL_LOGIN_SERVER "slogin.icq.com"
+-
+-#define OSCAR_DEFAULT_LOGIN_PORT 5190
+-
+-#define OSCAR_OPPORTUNISTIC_ENCRYPTION "opportunistic_encryption"
+-#define OSCAR_REQUIRE_ENCRYPTION "require_encryption"
+-#define OSCAR_NO_ENCRYPTION "no_encryption"
+-
+-#ifndef _WIN32
+-#define OSCAR_DEFAULT_CUSTOM_ENCODING "ISO-8859-1"
+-#else
+-#define OSCAR_DEFAULT_CUSTOM_ENCODING oscar_get_locale_charset()
+-#endif
+-#define OSCAR_DEFAULT_AUTHORIZATION TRUE
+-#define OSCAR_DEFAULT_HIDE_IP TRUE
+-#define OSCAR_DEFAULT_WEB_AWARE FALSE
+-#define OSCAR_DEFAULT_ALWAYS_USE_RV_PROXY FALSE
+-#define OSCAR_DEFAULT_ALLOW_MULTIPLE_LOGINS TRUE
+-#define OSCAR_DEFAULT_USE_CLIENTLOGIN TRUE
+-#define OSCAR_DEFAULT_ENCRYPTION OSCAR_OPPORTUNISTIC_ENCRYPTION
+-
+-#ifdef _WIN32
+-const char *oscar_get_locale_charset(void);
+-#endif
+-PurpleMood* oscar_get_purple_moods(PurpleAccount *account);
+-const char *oscar_list_icon_icq(PurpleAccount *a, PurpleBuddy *b);
+-const char *oscar_list_icon_aim(PurpleAccount *a, PurpleBuddy *b);
+-const char* oscar_list_emblem(PurpleBuddy *b);
+-char *oscar_status_text(PurpleBuddy *b);
+-void oscar_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
+-GList *oscar_status_types(PurpleAccount *account);
+-GList *oscar_blist_node_menu(PurpleBlistNode *node);
+-GList *oscar_chat_info(PurpleConnection *gc);
+-GHashTable *oscar_chat_info_defaults(PurpleConnection *gc, const char *chat_name);
+-void oscar_login(PurpleAccount *account);
+-void oscar_close(PurpleConnection *gc);
+-int oscar_send_im(PurpleConnection *gc, const char *name, const char *message, PurpleMessageFlags imflags);
+-void oscar_set_info(PurpleConnection *gc, const char *rawinfo);
+-unsigned int oscar_send_typing(PurpleConnection *gc, const char *name, PurpleTypingState state);
+-void oscar_get_info(PurpleConnection *gc, const char *name);
+-void oscar_set_status(PurpleAccount *account, PurpleStatus *status);
+-void oscar_set_idle(PurpleConnection *gc, int time);
+-void oscar_change_passwd(PurpleConnection *gc, const char *old, const char *new);
+-void oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group, const char *msg);
+-void oscar_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
+-void oscar_add_permit(PurpleConnection *gc, const char *who);
+-void oscar_add_deny(PurpleConnection *gc, const char *who);
+-void oscar_rem_permit(PurpleConnection *gc, const char *who);
+-void oscar_rem_deny(PurpleConnection *gc, const char *who);
+-void oscar_join_chat(PurpleConnection *gc, GHashTable *data);
+-char *oscar_get_chat_name(GHashTable *data);
+-void oscar_chat_invite(PurpleConnection *gc, int id, const char *message, const char *name);
+-void oscar_chat_leave(PurpleConnection *gc, int id);
+-int oscar_send_chat(PurpleConnection *gc, int id, const char *message, PurpleMessageFlags flags);
+-void oscar_keepalive(PurpleConnection *gc);
+-void oscar_alias_buddy(PurpleConnection *gc, const char *name, const char *alias);
+-void oscar_move_buddy(PurpleConnection *gc, const char *name, const char *old_group, const char *new_group);
+-void oscar_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
+-void oscar_convo_closed(PurpleConnection *gc, const char *who);
+-const char *oscar_normalize(const PurpleAccount *account, const char *str);
+-void oscar_set_icon(PurpleConnection *gc, PurpleStoredImage *img);
+-void oscar_remove_group(PurpleConnection *gc, PurpleGroup *group);
+-gboolean oscar_can_receive_file(PurpleConnection *gc, const char *who);
+-void oscar_send_file(PurpleConnection *gc, const char *who, const char *file);
+-PurpleXfer *oscar_new_xfer(PurpleConnection *gc, const char *who);
+-gboolean oscar_offline_message(const PurpleBuddy *buddy);
+-GList *oscar_actions(PurplePlugin *plugin, gpointer context);
+-void oscar_init(PurplePlugin *plugin, gboolean is_icq);
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar_data.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar_data.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/oscar_data.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar_data.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,157 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "oscar.h"
+-
+-typedef struct _SnacHandler SnacHandler;
+-
+-struct _SnacHandler
+-{
+- guint16 family;
+- guint16 subtype;
+- aim_rxcallback_t handler;
+- guint16 flags;
+-};
+-
+-/**
+- * Allocates a new OscarData and initializes it with default values.
+- */
+-OscarData *
+-oscar_data_new(void)
+-{
+- OscarData *od;
+- aim_module_t *cur;
+- GString *msg;
+-
+- od = g_new0(OscarData, 1);
+-
+- aim_initsnachash(od);
+- od->snacid_next = 0x00000001;
+- od->buddyinfo = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- od->handlerlist = g_hash_table_new_full(g_direct_hash, g_direct_equal, NULL, g_free);
+-
+- /*
+- * Register all the modules for this session...
+- */
+- aim__registermodule(od, misc_modfirst); /* load the catch-all first */
+- aim__registermodule(od, service_modfirst);
+- aim__registermodule(od, locate_modfirst);
+- aim__registermodule(od, buddylist_modfirst);
+- aim__registermodule(od, msg_modfirst);
+- aim__registermodule(od, admin_modfirst);
+- aim__registermodule(od, popups_modfirst);
+- aim__registermodule(od, bos_modfirst);
+- aim__registermodule(od, search_modfirst);
+- aim__registermodule(od, stats_modfirst);
+- aim__registermodule(od, chatnav_modfirst);
+- aim__registermodule(od, chat_modfirst);
+- aim__registermodule(od, bart_modfirst);
+- /* missing 0x11 - 0x12 */
+- aim__registermodule(od, ssi_modfirst);
+- /* missing 0x14 */
+- aim__registermodule(od, icq_modfirst);
+- /* missing 0x16 */
+- /* auth_modfirst is only needed if we're connecting with the old-style BUCP login */
+- aim__registermodule(od, auth_modfirst);
+- aim__registermodule(od, email_modfirst);
+-
+- msg = g_string_new("Registered modules: ");
+- for (cur = od->modlistv; cur; cur = cur->next) {
+- g_string_append_printf(
+- msg,
+- "%s (family=0x%04x, version=0x%04x, toolid=0x%04x, toolversion=0x%04x), ",
+- cur->name,
+- cur->family,
+- cur->version,
+- cur->toolid,
+- cur->toolversion);
+- }
+- purple_debug_misc("oscar", "%s\n", msg->str);
+- g_string_free(msg, TRUE);
+-
+- return od;
+-}
+-
+-/**
+- * Logoff and deallocate a session.
+- *
+- * @param od Session to kill
+- */
+-void
+-oscar_data_destroy(OscarData *od)
+-{
+- aim_cleansnacs(od, -1);
+-
+- /* Only used when connecting with clientLogin */
+- if (od->url_data != NULL)
+- purple_util_fetch_url_cancel(od->url_data);
+-
+- while (od->requesticon)
+- {
+- g_free(od->requesticon->data);
+- od->requesticon = g_slist_delete_link(od->requesticon, od->requesticon);
+- }
+- g_free(od->email);
+- g_free(od->newp);
+- g_free(od->oldp);
+- if (od->getblisttimer > 0)
+- purple_timeout_remove(od->getblisttimer);
+- while (od->oscar_connections != NULL)
+- flap_connection_destroy(od->oscar_connections->data,
+- OSCAR_DISCONNECT_DONE, NULL);
+-
+- while (od->peer_connections != NULL)
+- peer_connection_destroy(od->peer_connections->data,
+- OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+-
+- aim__shutdownmodules(od);
+-
+- g_hash_table_destroy(od->buddyinfo);
+- g_hash_table_destroy(od->handlerlist);
+-
+- g_free(od);
+-}
+-
+-void
+-oscar_data_addhandler(OscarData *od, guint16 family, guint16 subtype, aim_rxcallback_t newhandler, guint16 flags)
+-{
+- SnacHandler *snac_handler;
+-
+- snac_handler = g_new0(SnacHandler, 1);
+-
+- snac_handler->family = family;
+- snac_handler->subtype = subtype;
+- snac_handler->flags = flags;
+- snac_handler->handler = newhandler;
+-
+- g_hash_table_insert(od->handlerlist,
+- GUINT_TO_POINTER((family << 16) + subtype),
+- snac_handler);
+-}
+-
+-aim_rxcallback_t
+-aim_callhandler(OscarData *od, guint16 family, guint16 subtype)
+-{
+- SnacHandler *snac_handler;
+-
+- snac_handler = g_hash_table_lookup(od->handlerlist, GUINT_TO_POINTER((family << 16) + subtype));
+-
+- return snac_handler ? snac_handler->handler : NULL;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/oscar.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/oscar.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/oscar.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1350 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Main libfaim header. Must be included in client for prototypes/macros.
+- *
+- * "come on, i turned a chick lesbian; i think this is the hackish equivalent"
+- * -- Josh Myer
+- *
+- */
+-
+-#ifndef _OSCAR_H_
+-#define _OSCAR_H_
+-
+-#include "internal.h"
+-#include "circbuffer.h"
+-#include "debug.h"
+-#include "eventloop.h"
+-#include "proxy.h"
+-#include "sslconn.h"
+-
+-#include <stdio.h>
+-#include <string.h>
+-#include <fcntl.h>
+-#include <sys/types.h>
+-#include <stdlib.h>
+-#include <stdarg.h>
+-#include <errno.h>
+-#include <time.h>
+-
+-#ifndef _WIN32
+-#include <sys/time.h>
+-#include <unistd.h>
+-#include <netdb.h>
+-#include <netinet/in.h>
+-#include <sys/socket.h>
+-#else
+-#include "libc_interface.h"
+-#endif
+-
+-typedef struct _ByteStream ByteStream;
+-typedef struct _ClientInfo ClientInfo;
+-typedef struct _FlapConnection FlapConnection;
+-typedef struct _FlapFrame FlapFrame;
+-typedef struct _IcbmArgsCh2 IcbmArgsCh2;
+-typedef struct _IcbmCookie IcbmCookie;
+-typedef struct _OscarData OscarData;
+-typedef struct _QueuedSnac QueuedSnac;
+-
+-typedef guint32 aim_snacid_t;
+-
+-#include "snactypes.h"
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif
+-
+-#define FAIM_SNAC_HASH_SIZE 16
+-
+-/*
+- * Current Maximum Length for usernames (not including NULL)
+- *
+- * Currently only names up to 16 characters can be registered
+- * however it is apparently legal for them to be larger.
+- */
+-#define MAXSNLEN 97
+-
+-/*
+- * Current Maximum Length for Instant Messages
+- *
+- * This was found basically by experiment, but not wholly
+- * accurate experiment. It should not be regarded
+- * as completely correct. But its a decent approximation.
+- *
+- * Note that although we can send this much, its impossible
+- * for WinAIM clients (up through the latest (4.0.1957)) to
+- * send any more than 1kb. Amaze all your windows friends
+- * with utterly oversized instant messages!
+- */
+-#define MAXMSGLEN 2544
+-
+-/*
+- * Maximum size of a Buddy Icon.
+- */
+-#define MAXICONLEN 7168
+-#define AIM_ICONIDENT "AVT1picture.id"
+-
+-/*
+- * Found by trial and error.
+- */
+-#define MAXAVAILMSGLEN 251
+-
+-/**
+- * Maximum length for the password of an ICQ account
+- */
+-#define MAXICQPASSLEN 8
+-
+-#define AIM_MD5_STRING "AOL Instant Messenger (SM)"
+-
+-/*
+- * Client info. Filled in by the client and passed in to
+- * aim_send_login(). The information ends up getting passed to OSCAR
+- * through the initial login command.
+- *
+- */
+-struct _ClientInfo
+-{
+- const char *clientstring;
+- guint16 clientid;
+- guint16 major;
+- guint16 minor;
+- guint16 point;
+- guint16 build;
+- guint32 distrib;
+- const char *country; /* two-letter abbrev */
+- const char *lang; /* two-letter abbrev */
+-};
+-
+-/*
+- * We need to use the major-minor-micro versions from the official
+- * AIM and ICQ programs here or AOL won't let us use certain features.
+- *
+- * 0x00000611 is the distid given to us by AOL for use as the default
+- * libpurple distid.
+- */
+-#define CLIENTINFO_PURPLE_AIM { \
+- NULL, \
+- 0x0109, \
+- 0x0005, 0x0001, \
+- 0x0000, 0x0bdc, \
+- 0x00000611, \
+- "us", "en", \
+-}
+-
+-#define CLIENTINFO_PURPLE_ICQ { \
+- NULL, \
+- 0x010a, \
+- 0x0014, 0x0034, \
+- 0x0000, 0x0c18, \
+- 0x00000611, \
+- "us", "en", \
+-}
+-
+-typedef enum
+-{
+- OSCAR_DISCONNECT_DONE, /* not considered an error */
+- OSCAR_DISCONNECT_LOCAL_CLOSED, /* peer connections only, not considered an error */
+- OSCAR_DISCONNECT_REMOTE_CLOSED,
+- OSCAR_DISCONNECT_REMOTE_REFUSED, /* peer connections only */
+- OSCAR_DISCONNECT_LOST_CONNECTION,
+- OSCAR_DISCONNECT_INVALID_DATA,
+- OSCAR_DISCONNECT_COULD_NOT_CONNECT,
+- OSCAR_DISCONNECT_RETRYING /* peer connections only */
+-} OscarDisconnectReason;
+-
+-#define OSCAR_CAPABILITY_BUDDYICON 0x0000000000000001LL
+-#define OSCAR_CAPABILITY_TALK 0x0000000000000002LL
+-#define OSCAR_CAPABILITY_DIRECTIM 0x0000000000000004LL
+-#define OSCAR_CAPABILITY_CHAT 0x0000000000000008LL
+-#define OSCAR_CAPABILITY_GETFILE 0x0000000000000010LL
+-#define OSCAR_CAPABILITY_SENDFILE 0x0000000000000020LL
+-#define OSCAR_CAPABILITY_GAMES 0x0000000000000040LL
+-#define OSCAR_CAPABILITY_ADDINS 0x0000000000000080LL
+-#define OSCAR_CAPABILITY_SENDBUDDYLIST 0x0000000000000100LL
+-#define OSCAR_CAPABILITY_GAMES2 0x0000000000000200LL
+-#define OSCAR_CAPABILITY_ICQ_DIRECT 0x0000000000000400LL
+-#define OSCAR_CAPABILITY_APINFO 0x0000000000000800LL
+-#define OSCAR_CAPABILITY_ICQRTF 0x0000000000001000LL
+-#define OSCAR_CAPABILITY_EMPTY 0x0000000000002000LL
+-#define OSCAR_CAPABILITY_ICQSERVERRELAY 0x0000000000004000LL
+-#define OSCAR_CAPABILITY_UNICODEOLD 0x0000000000008000LL
+-#define OSCAR_CAPABILITY_TRILLIANCRYPT 0x0000000000010000LL
+-#define OSCAR_CAPABILITY_UNICODE 0x0000000000020000LL
+-#define OSCAR_CAPABILITY_INTEROPERATE 0x0000000000040000LL
+-#define OSCAR_CAPABILITY_SHORTCAPS 0x0000000000080000LL
+-#define OSCAR_CAPABILITY_HIPTOP 0x0000000000100000LL
+-#define OSCAR_CAPABILITY_SECUREIM 0x0000000000200000LL
+-#define OSCAR_CAPABILITY_SMS 0x0000000000400000LL
+-#define OSCAR_CAPABILITY_VIDEO 0x0000000000800000LL
+-#define OSCAR_CAPABILITY_ICHATAV 0x0000000001000000LL
+-#define OSCAR_CAPABILITY_LIVEVIDEO 0x0000000002000000LL
+-#define OSCAR_CAPABILITY_CAMERA 0x0000000004000000LL
+-#define OSCAR_CAPABILITY_ICHAT_SCREENSHARE 0x0000000008000000LL
+-#define OSCAR_CAPABILITY_TYPING 0x0000000010000000LL
+-#define OSCAR_CAPABILITY_NEWCAPS 0x0000000020000000LL
+-#define OSCAR_CAPABILITY_XTRAZ 0x0000000040000000LL
+-#define OSCAR_CAPABILITY_GENERICUNKNOWN 0x0000000080000000LL
+-#define OSCAR_CAPABILITY_HTML_MSGS 0x0000000100000000LL
+-#define OSCAR_CAPABILITY_LAST 0x0000000200000000LL
+-
+-#define OSCAR_STATUS_ID_INVISIBLE "invisible"
+-#define OSCAR_STATUS_ID_OFFLINE "offline"
+-#define OSCAR_STATUS_ID_AVAILABLE "available"
+-#define OSCAR_STATUS_ID_AWAY "away"
+-#define OSCAR_STATUS_ID_DND "dnd"
+-#define OSCAR_STATUS_ID_NA "na"
+-#define OSCAR_STATUS_ID_OCCUPIED "occupied"
+-#define OSCAR_STATUS_ID_FREE4CHAT "free4chat"
+-#define OSCAR_STATUS_ID_CUSTOM "custom"
+-#define OSCAR_STATUS_ID_MOBILE "mobile"
+-#define OSCAR_STATUS_ID_EVIL "evil"
+-#define OSCAR_STATUS_ID_DEPRESSION "depression"
+-#define OSCAR_STATUS_ID_ATHOME "athome"
+-#define OSCAR_STATUS_ID_ATWORK "atwork"
+-#define OSCAR_STATUS_ID_LUNCH "lunch"
+-
+-/*
+- * Byte Stream type. Sort of.
+- *
+- * Use of this type serves a couple purposes:
+- * - Buffer/buflen pairs are passed all around everywhere. This turns
+- * that into one value, as well as abstracting it slightly.
+- * - Through the abstraction, it is possible to enable bounds checking
+- * for robustness at the cost of performance. But a clean failure on
+- * weird packets is much better than a segfault.
+- * - I like having variables named "bs".
+- *
+- * Don't touch the insides of this struct. Or I'll have to kill you.
+- *
+- */
+-struct _ByteStream
+-{
+- guint8 *data;
+- size_t len;
+- size_t offset;
+-};
+-
+-struct _QueuedSnac
+-{
+- guint16 family;
+- guint16 subtype;
+- FlapFrame *frame;
+-};
+-
+-struct _FlapFrame
+-{
+- guint8 channel;
+- guint16 seqnum;
+- ByteStream data; /* payload stream */
+-};
+-
+-struct _FlapConnection
+-{
+- OscarData *od; /**< Pointer to parent session. */
+- gboolean connected;
+- time_t lastactivity; /**< Time of last transmit. */
+- guint destroy_timeout;
+- OscarDisconnectReason disconnect_reason;
+- gchar *error_message;
+- guint16 disconnect_code;
+-
+- /* A few variables that are only used when connecting */
+- PurpleProxyConnectData *connect_data;
+- guint16 cookielen;
+- guint8 *cookie;
+- gpointer new_conn_data;
+-
+- int fd;
+- PurpleSslConnection *gsc;
+- guint8 header[6];
+- gssize header_received;
+- FlapFrame buffer_incoming;
+- PurpleCircBuffer *buffer_outgoing;
+- guint watcher_incoming;
+- guint watcher_outgoing;
+-
+- guint16 type;
+- guint16 subtype;
+- guint16 seqnum_out; /**< The sequence number of most recently sent packet. */
+- guint16 seqnum_in; /**< The sequence number of most recently received packet. */
+- GSList *groups;
+- GSList *rateclasses; /* Contains nodes of struct rateclass. */
+- struct rateclass *default_rateclass;
+- GHashTable *rateclass_members; /* Key is family and subtype, value is pointer to the rateclass struct to use. */
+-
+- GQueue *queued_snacs; /**< Contains QueuedSnacs. */
+- GQueue *queued_lowpriority_snacs; /**< Contains QueuedSnacs to send only once queued_snacs is empty */
+- guint queued_timeout;
+-
+- void *internal; /* internal conn-specific libfaim data */
+-};
+-
+-struct _IcbmCookie
+-{
+- guchar cookie[8];
+- int type;
+- void *data;
+- time_t addtime;
+- struct _IcbmCookie *next;
+-};
+-
+-#include "peer.h"
+-
+-/*
+- * AIM Session: The main client-data interface.
+- *
+- */
+-struct _OscarData
+-{
+- /** Only used when connecting with clientLogin */
+- PurpleUtilFetchUrlData *url_data;
+-
+- gboolean iconconnecting;
+- gboolean set_icon;
+-
+- GSList *create_rooms;
+-
+- gboolean conf;
+- gboolean reqemail;
+- gboolean setemail;
+- char *email;
+- gboolean setnick;
+- char *newformatting;
+- gboolean chpass;
+- char *oldp;
+- char *newp;
+-
+- GSList *oscar_chats;
+- GHashTable *buddyinfo;
+- GSList *requesticon;
+-
+- gboolean use_ssl;
+- gboolean icq;
+- guint getblisttimer;
+-
+- struct {
+- guint maxwatchers; /* max users who can watch you */
+- guint maxbuddies; /* max users you can watch */
+- guint maxgroups; /* max groups in server list */
+- guint maxpermits; /* max users on permit list */
+- guint maxdenies; /* max users on deny list */
+- guint maxsiglen; /* max size (bytes) of profile */
+- guint maxawaymsglen; /* max size (bytes) of posted away message */
+- } rights;
+-
+- PurpleConnection *gc;
+-
+- void *modlistv;
+-
+- /*
+- * Outstanding snac handling
+- *
+- * TODO: Should these be per-connection? -mid
+- */
+- void *snac_hash[FAIM_SNAC_HASH_SIZE];
+- aim_snacid_t snacid_next;
+-
+- /*
+- * TODO: Data specific to a certain family should go into a
+- * hashtable and the core parts of libfaim shouldn't
+- * need to know about them.
+- */
+-
+- IcbmCookie *msgcookies;
+- GSList *icq_info;
+-
+- /** Only used when connecting with the old-style BUCP login. */
+- struct aim_authresp_info *authinfo;
+- struct aim_emailinfo *emailinfo;
+-
+- struct {
+- struct aim_userinfo_s *userinfo;
+- } locate;
+-
+- struct {
+- gboolean have_rights;
+- } bos;
+-
+- /* Server-stored information (ssi) */
+- struct {
+- gboolean received_data;
+- guint16 numitems;
+- struct aim_ssi_item *official;
+- struct aim_ssi_item *local;
+- struct aim_ssi_tmp *pending;
+- time_t timestamp;
+- gboolean waiting_for_ack;
+- gboolean in_transaction;
+- } ssi;
+-
+- /** Contains pointers to handler functions for each family/subtype. */
+- GHashTable *handlerlist;
+-
+- /** A linked list containing FlapConnections. */
+- GSList *oscar_connections;
+- guint16 default_port;
+-
+- /** A linked list containing PeerConnections. */
+- GSList *peer_connections;
+-};
+-
+-/* Valid for calling aim_icq_setstatus() and for aim_userinfo_t->icqinfo.status */
+-#define AIM_ICQ_STATE_NORMAL 0x00000000
+-#define AIM_ICQ_STATE_AWAY 0x00000001
+-#define AIM_ICQ_STATE_DND 0x00000002
+-#define AIM_ICQ_STATE_OUT 0x00000004
+-#define AIM_ICQ_STATE_BUSY 0x00000010
+-#define AIM_ICQ_STATE_CHAT 0x00000020
+-#define AIM_ICQ_STATE_INVISIBLE 0x00000100
+-#define AIM_ICQ_STATE_EVIL 0x00003000
+-#define AIM_ICQ_STATE_DEPRESSION 0x00004000
+-#define AIM_ICQ_STATE_ATHOME 0x00005000
+-#define AIM_ICQ_STATE_ATWORK 0x00006000
+-#define AIM_ICQ_STATE_LUNCH 0x00002001
+-#define AIM_ICQ_STATE_EVIL 0x00003000
+-#define AIM_ICQ_STATE_WEBAWARE 0x00010000
+-#define AIM_ICQ_STATE_HIDEIP 0x00020000
+-#define AIM_ICQ_STATE_BIRTHDAY 0x00080000
+-#define AIM_ICQ_STATE_ICQHOMEPAGE 0x00200000
+-#define AIM_ICQ_STATE_DIRECTREQUIREAUTH 0x10000000
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-struct aim_clientrelease
+-{
+- char *name;
+- guint32 build;
+- char *url;
+- char *info;
+-};
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-struct aim_authresp_info
+-{
+- char *bn;
+- guint16 errorcode;
+- char *errorurl;
+- guint16 regstatus;
+- char *email;
+- char *bosip;
+- guint16 cookielen;
+- guint8 *cookie;
+- char *chpassurl;
+- struct aim_clientrelease latestrelease;
+- struct aim_clientrelease latestbeta;
+-};
+-
+-/* Callback data for redirect. */
+-struct aim_redirect_data
+-{
+- guint16 group;
+- const char *ip;
+- guint16 cookielen;
+- const guint8 *cookie;
+- const char *ssl_cert_cn;
+- guint8 use_ssl;
+- struct { /* group == SNAC_FAMILY_CHAT */
+- guint16 exchange;
+- const char *room;
+- guint16 instance;
+- } chat;
+-};
+-
+-int oscar_connect_to_bos(PurpleConnection *gc, OscarData *od, const char *host, guint16 port, guint8 *cookie, guint16 cookielen, const char *tls_certname);
+-
+-/* family_auth.c */
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-int aim_request_login(OscarData *od, FlapConnection *conn, const char *bn);
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-int aim_send_login(OscarData *od, FlapConnection *conn, const char *bn, const char *password, gboolean truncate_pass, ClientInfo *ci, const char *key, gboolean allow_multiple_logins);
+-
+-/**
+- * Only used when connecting with the old-style BUCP login.
+- */
+-/* 0x000b */ int aim_auth_securid_send(OscarData *od, const char *securid);
+-
+-/**
+- * Only used when connecting with clientLogin.
+- */
+-void send_client_login(OscarData *od, const char *username);
+-
+-/* flap_connection.c */
+-FlapConnection *flap_connection_new(OscarData *, int type);
+-void flap_connection_close(OscarData *od, FlapConnection *conn);
+-void flap_connection_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
+-void flap_connection_schedule_destroy(FlapConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
+-FlapConnection *flap_connection_findbygroup(OscarData *od, guint16 group);
+-FlapConnection *flap_connection_getbytype(OscarData *, int type);
+-FlapConnection *flap_connection_getbytype_all(OscarData *, int type);
+-void flap_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond);
+-void flap_connection_recv_cb_ssl(gpointer data, PurpleSslConnection *gsc, PurpleInputCondition cond);
+-
+-void flap_connection_send(FlapConnection *conn, FlapFrame *frame);
+-void flap_connection_send_version(OscarData *od, FlapConnection *conn);
+-void flap_connection_send_version_with_cookie(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy);
+-void flap_connection_send_version_with_cookie_and_clientinfo(OscarData *od, FlapConnection *conn, guint16 length, const guint8 *chipsahoy, ClientInfo *ci, gboolean allow_multiple_login);
+-void flap_connection_send_snac(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data);
+-void flap_connection_send_snac_with_priority(OscarData *od, FlapConnection *conn, guint16 family, const guint16 subtype, aim_snacid_t snacid, ByteStream *data, gboolean high_priority);
+-void flap_connection_send_keepalive(OscarData *od, FlapConnection *conn);
+-FlapFrame *flap_frame_new(OscarData *od, guint16 channel, int datalen);
+-
+-/* oscar_data.c */
+-typedef int (*aim_rxcallback_t)(OscarData *od, FlapConnection *conn, FlapFrame *frame, ...);
+-
+-OscarData *oscar_data_new(void);
+-void oscar_data_destroy(OscarData *);
+-void oscar_data_addhandler(OscarData *od, guint16 family, guint16 subtype, aim_rxcallback_t newhandler, guint16 flags);
+-aim_rxcallback_t aim_callhandler(OscarData *od, guint16 family, guint16 subtype);
+-
+-/* 0x0001 - family_oservice.c */
+-/* 0x0002 */ void aim_srv_clientready(OscarData *od, FlapConnection *conn);
+-/* 0x0004 */ void aim_srv_requestnew(OscarData *od, guint16 serviceid);
+-/* 0x0006 */ void aim_srv_reqrates(OscarData *od, FlapConnection *conn);
+-/* 0x0008 */ void aim_srv_rates_addparam(OscarData *od, FlapConnection *conn);
+-/* 0x000e */ void aim_srv_reqpersonalinfo(OscarData *od, FlapConnection *conn);
+-/* 0x0011 */ void aim_srv_setidle(OscarData *od, guint32 idletime);
+-/* 0x0017 */ void aim_srv_setversions(OscarData *od, FlapConnection *conn);
+-/* 0x001e */ int aim_srv_setextrainfo(OscarData *od, gboolean seticqstatus, guint32 icqstatus, gboolean setstatusmsg, const char *statusmsg, const char *itmsurl);
+-void aim_srv_set_dc_info(OscarData *od);
+-
+-
+-void aim_bos_reqrights(OscarData *od, FlapConnection *conn);
+-
+-#define AIM_RATE_CODE_LIMIT 0x0003
+-
+-/* family_icbm.c */
+-#define AIM_OFT_SUBTYPE_SEND_DIR 0x0002
+-
+-#define AIM_TRANSFER_DENY_DECLINE 0x0001
+-
+-#define AIM_IMPARAM_FLAG_CHANNEL_MSGS_ALLOWED 0x00000001
+-#define AIM_IMPARAM_FLAG_MISSED_CALLS_ENABLED 0x00000002
+-#define AIM_IMPARAM_FLAG_EVENTS_ALLOWED 0x00000008
+-#define AIM_IMPARAM_FLAG_SMS_SUPPORTED 0x00000010
+-#define AIM_IMPARAM_FLAG_OFFLINE_MSGS_ALLOWED 0x00000100
+-
+-/**
+- * This flag tells the server that we always send HTML in messages
+- * sent from an ICQ account to an ICQ account. (If this flag is
+- * not sent then plaintext is sent ICQ<-->ICQ (HTML is sent in all
+- * other cases)).
+- *
+- * If we send an HTML message to an old client that doesn't support
+- * HTML messages, then the oscar servers will merrily strip the HTML
+- * for us.
+- *
+- * All incoming IMs are treated as HTML.
+- */
+-#define AIM_IMPARAM_FLAG_USE_HTML_FOR_ICQ 0x00000400
+-
+-struct aim_icbmparameters
+-{
+- guint16 maxchan;
+- guint32 flags; /* AIM_IMPARAM_FLAG_ */
+- guint16 maxmsglen; /* message size that you will accept */
+- guint16 maxsenderwarn; /* this and below are *10 (999=99.9%) */
+- guint16 maxrecverwarn;
+- guint32 minmsginterval; /* in milliseconds? */
+-};
+-
+-/*
+- * TODO: Should probably combine this with struct chat_connection.
+- */
+-struct aim_chat_roominfo
+-{
+- guint16 exchange;
+- char *name;
+- guint8 namelen;
+- guint16 instance;
+-};
+-
+-struct chat_connection
+-{
+- char *name;
+- char *show; /* AOL did something funny to us */
+- guint16 exchange;
+- guint16 instance;
+- FlapConnection *conn;
+- int id;
+- PurpleConnection *gc;
+- PurpleConversation *conv;
+- int maxlen;
+- int maxvis;
+-};
+-
+-/*
+- * All this chat struct stuff should be in family_chat.c
+- */
+-void oscar_chat_destroy(struct chat_connection *cc);
+-
+-#define AIM_IMFLAGS_AWAY 0x0001 /* mark as an autoreply */
+-#define AIM_IMFLAGS_ACK 0x0002 /* request a receipt notice */
+-#define AIM_IMFLAGS_BUDDYREQ 0x0010 /* buddy icon requested */
+-#define AIM_IMFLAGS_HASICON 0x0020 /* already has icon */
+-#define AIM_IMFLAGS_SUBENC_MACINTOSH 0x0040 /* damn that Steve Jobs! */
+-#define AIM_IMFLAGS_CUSTOMFEATURES 0x0080 /* features field present */
+-#define AIM_IMFLAGS_OFFLINE 0x0800 /* send to offline user */
+-#define AIM_IMFLAGS_TYPINGNOT 0x1000 /* typing notification */
+-
+-#define AIM_CHARSET_ASCII 0x0000 /* ISO 646 */
+-#define AIM_CHARSET_UNICODE 0x0002 /* ISO 10646 (UTF-16/UCS-2BE) */
+-#define AIM_CHARSET_LATIN_1 0x0003 /* ISO 8859-1 */
+-
+-/*
+- * Arguments to aim_send_im_ext().
+- *
+- * This is really complicated. But immensely versatile.
+- *
+- */
+-struct aim_sendimext_args
+-{
+- /* These are _required_ */
+- const char *destbn;
+- guint32 flags; /* often 0 */
+-
+- const char *msg;
+- gsize msglen;
+-
+- /* Only used if AIM_IMFLAGS_HASICON is set */
+- guint32 iconlen;
+- time_t iconstamp;
+- guint32 iconsum;
+-
+- guint16 featureslen;
+- guint8 *features;
+-
+- guint16 charset;
+-};
+-
+-/*
+- * This information is provided in the Incoming ICBM callback for
+- * Channel 1 ICBM's.
+- */
+-struct aim_incomingim_ch1_args
+-{
+- guint32 icbmflags; /* some flags apply only to ->msg, not all mpmsg */
+- time_t timestamp; /* Only set for offline messages */
+-
+- gchar *msg;
+-
+- /* Only provided if AIM_IMFLAGS_HASICON is set */
+- time_t iconstamp;
+- guint32 iconlen;
+- guint16 iconsum;
+-};
+-
+-/* Valid values for channel 2 args->status */
+-#define AIM_RENDEZVOUS_PROPOSE 0x0000
+-#define AIM_RENDEZVOUS_CANCEL 0x0001
+-#define AIM_RENDEZVOUS_CONNECTED 0x0002
+-
+-struct _IcbmArgsCh2
+-{
+- guint16 status;
+- guchar cookie[8];
+- guint64 type; /* One of the OSCAR_CAPABILITY_ constants */
+- const char *proxyip;
+- const char *clientip;
+- const char *verifiedip;
+- guint16 port;
+- gboolean use_proxy;
+- guint16 errorcode;
+- const char *msg; /* invite message or file description */
+- guint16 msglen;
+- const char *encoding;
+- const char *language;
+- guint16 requestnumber;
+- union {
+- struct {
+- guint32 checksum;
+- guint32 length;
+- time_t timestamp;
+- guint8 *icon;
+- } icon;
+- struct {
+- struct aim_chat_roominfo roominfo;
+- } chat;
+- struct {
+- guint8 msgtype;
+- const char *msg;
+- } rtfmsg;
+- struct {
+- guint16 subtype;
+- guint16 totfiles;
+- guint32 totsize;
+- char *filename;
+- } sendfile;
+- } info;
+- void *destructor; /* used internally only */
+-};
+-
+-struct aim_incomingim_ch4_args
+-{
+- guint32 uin; /* Of the sender of the ICBM */
+- guint8 type;
+- guint8 flags;
+- gchar *msg; /* Reason for auth request, deny, or accept */
+- int msglen;
+-};
+-
+-/* SNAC sending functions */
+-/* 0x0002 */ int aim_im_setparams(OscarData *od, struct aim_icbmparameters *params);
+-/* 0x0004 */ int aim_im_reqparams(OscarData *od);
+-/* 0x0006 */ int aim_im_sendch1_ext(OscarData *od, struct aim_sendimext_args *args);
+-/* 0x0006 */ int aim_im_sendch1(OscarData *, const char *destbn, guint16 flags, const char *msg);
+-/* 0x0006 */ int aim_im_sendch2_chatinvite(OscarData *od, const char *bn, const char *msg, guint16 exchange, const char *roomname, guint16 instance);
+-/* 0x0006 */ int aim_im_sendch2_icon(OscarData *od, const char *bn, const guint8 *icon, int iconlen, time_t stamp, guint16 iconsum);
+-
+-/* 0x0006 */ void aim_im_sendch2_cancel(PeerConnection *peer_conn);
+-/* 0x0006 */ void aim_im_sendch2_connected(PeerConnection *peer_conn);
+-/* 0x0006 */ void aim_im_sendch2_odc_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber);
+-/* 0x0006 */ void aim_im_sendch2_odc_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber);
+-/* 0x0006 */ void aim_im_sendch2_sendfile_requestdirect(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 port, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles);
+-/* 0x0006 */ void aim_im_sendch2_sendfile_requestproxy(OscarData *od, guchar *cookie, const char *bn, const guint8 *ip, guint16 pin, guint16 requestnumber, const gchar *filename, guint32 size, guint16 numfiles);
+-
+-/* 0x000b */ int aim_im_denytransfer(OscarData *od, const char *bn, const guchar *cookie, guint16 code);
+-/* 0x0010 */ int aim_im_reqofflinemsgs(OscarData *od);
+-/* 0x0014 */ int aim_im_sendmtn(OscarData *od, guint16 type1, const char *bn, guint16 type2);
+-/* 0x000b */ int icq_relay_xstatus (OscarData *od, const char *sn, const guchar* cookie);
+-void aim_icbm_makecookie(guchar* cookie);
+-void aim_im_send_icq_confirmation(OscarData *od, const char *bn, const guchar *cookie);
+-
+-/* 0x0002 - family_locate.c */
+-/*
+- * AIM User Info, Standard Form.
+- */
+-#define AIM_FLAG_ADMINISTRATOR 0x0002
+-#define AIM_FLAG_AOL 0x0004
+-#define AIM_FLAG_AWAY 0x0020
+-#define AIM_FLAG_WIRELESS 0x0080
+-#define AIM_FLAG_ICQ 0x0040
+-#define AIM_FLAG_ACTIVEBUDDY 0x0400
+-
+-#define AIM_USERINFO_PRESENT_FLAGS 0x00000001
+-#define AIM_USERINFO_PRESENT_MEMBERSINCE 0x00000002
+-#define AIM_USERINFO_PRESENT_ONLINESINCE 0x00000004
+-#define AIM_USERINFO_PRESENT_IDLE 0x00000008
+-#define AIM_USERINFO_PRESENT_ICQEXTSTATUS 0x00000010
+-#define AIM_USERINFO_PRESENT_ICQIPADDR 0x00000020
+-#define AIM_USERINFO_PRESENT_ICQDATA 0x00000040
+-#define AIM_USERINFO_PRESENT_CAPABILITIES 0x00000080
+-#define AIM_USERINFO_PRESENT_SESSIONLEN 0x00000100
+-#define AIM_USERINFO_PRESENT_CREATETIME 0x00000200
+-
+-struct userinfo_node
+-{
+- char *bn;
+- struct userinfo_node *next;
+-};
+-
+-typedef struct aim_userinfo_s
+-{
+- char *bn;
+- guint16 warnlevel; /* evil percent * 10 (999 = 99.9%) */
+- guint16 idletime; /* in seconds */
+- guint16 flags;
+- guint32 createtime; /* time_t */
+- guint32 membersince; /* time_t */
+- guint32 onlinesince; /* time_t */
+- guint32 sessionlen; /* in seconds */
+- guint64 capabilities;
+- struct {
+- guint32 status;
+- guint32 ipaddr;
+- guint8 crap[0x25]; /* until we figure it out... */
+- } icqinfo;
+- guint32 present;
+-
+- guint8 iconcsumtype;
+- guint16 iconcsumlen;
+- guint8 *iconcsum;
+-
+- char *info;
+- char *info_encoding;
+- guint16 info_len;
+-
+- char *status;
+- char *status_encoding;
+- guint16 status_len;
+-
+- char *itmsurl;
+- char *itmsurl_encoding;
+- guint16 itmsurl_len;
+-
+- char *away;
+- char *away_encoding;
+- guint16 away_len;
+-
+- struct aim_userinfo_s *next;
+-} aim_userinfo_t;
+-
+-#define AIM_SENDMEMBLOCK_FLAG_ISREQUEST 0
+-#define AIM_SENDMEMBLOCK_FLAG_ISHASH 1
+-
+-int aim_sendmemblock(OscarData *od, FlapConnection *conn, guint32 offset, guint32 len, const guint8 *buf, guint8 flag);
+-
+-struct aim_invite_priv
+-{
+- char *bn;
+- char *roomname;
+- guint16 exchange;
+- guint16 instance;
+-};
+-
+-#define AIM_COOKIETYPE_CHAT 0x01
+-#define AIM_COOKIETYPE_INVITE 0x02
+-
+-aim_userinfo_t *aim_locate_finduserinfo(OscarData *od, const char *bn);
+-void aim_locate_dorequest(OscarData *od);
+-
+-/* 0x0002 */ int aim_locate_reqrights(OscarData *od);
+-/* 0x0004 */ int aim_locate_setcaps(OscarData *od, guint64 caps);
+-/* 0x0004 */ int aim_locate_setprofile(OscarData *od, const char *profile_encoding, const gchar *profile, const int profile_len, const char *awaymsg_encoding, const gchar *awaymsg, const int awaymsg_len);
+-/* 0x0015 */ int aim_locate_getinfoshort(OscarData *od, const char *bn, guint32 flags);
+-
+-guint64 aim_locate_getcaps(OscarData *od, ByteStream *bs, int len);
+-guint64 aim_locate_getcaps_short(OscarData *od, ByteStream *bs, int len);
+-void aim_info_free(aim_userinfo_t *);
+-int aim_info_extract(OscarData *od, ByteStream *bs, aim_userinfo_t *);
+-int aim_putuserinfo(ByteStream *bs, aim_userinfo_t *info);
+-PurpleMood* icq_get_purple_moods(PurpleAccount *account);
+-const char* icq_get_custom_icon_description(const char *mood);
+-guint8* icq_get_custom_icon_data(const char *mood);
+-int icq_im_xstatus_request(OscarData *od, const char *sn);
+-
+-/* 0x0003 - family_buddy.c */
+-/* 0x0002 */ void aim_buddylist_reqrights(OscarData *, FlapConnection *);
+-
+-
+-/* 0x000a - family_userlookup.c */
+-int aim_search_address(OscarData *, const char *);
+-
+-struct aim_chat_exchangeinfo
+-{
+- guint16 number;
+- guint16 flags;
+- char *name;
+- char *charset1;
+- char *lang1;
+- char *charset2;
+- char *lang2;
+-};
+-
+-#define AIM_CHATFLAGS_NOREFLECT 0x0001
+-#define AIM_CHATFLAGS_AWAY 0x0002
+-int aim_chat_send_im(OscarData *od, FlapConnection *conn, guint16 flags, const gchar *msg, int msglen, const char *encoding, const char *language);
+-int aim_chat_join(OscarData *od, guint16 exchange, const char *roomname, guint16 instance);
+-
+-void aim_chatnav_reqrights(OscarData *od, FlapConnection *conn);
+-
+-int aim_chatnav_createroom(OscarData *od, FlapConnection *conn, const char *name, guint16 exchange);
+-
+-
+-/* 0x0010 - family_bart.c */
+-int aim_bart_upload(OscarData *od, const guint8 *icon, guint16 iconlen);
+-int aim_bart_request(OscarData *od, const char *bn, guint8 iconcsumtype, const guint8 *iconstr, guint16 iconstrlen);
+-
+-
+-
+-/* 0x0013 - family_feedbag.c */
+-#define AIM_SSI_TYPE_BUDDY 0x0000
+-#define AIM_SSI_TYPE_GROUP 0x0001
+-#define AIM_SSI_TYPE_PERMIT 0x0002
+-#define AIM_SSI_TYPE_DENY 0x0003
+-#define AIM_SSI_TYPE_PDINFO 0x0004
+-#define AIM_SSI_TYPE_PRESENCEPREFS 0x0005
+-#define AIM_SSI_TYPE_ICQDENY 0x000e
+-#define AIM_SSI_TYPE_ICONINFO 0x0014
+-
+-/* These flags are set in the 0x00c9 TLV of SSI type 0x0005 */
+-#define AIM_SSI_PRESENCE_FLAG_SHOWIDLE 0x00000400
+-#define AIM_SSI_PRESENCE_FLAG_NORECENTBUDDIES 0x00020000
+-
+-struct aim_ssi_item
+-{
+- char *name;
+- guint16 gid;
+- guint16 bid;
+- guint16 type;
+- GSList *data;
+- struct aim_ssi_item *next;
+-};
+-
+-struct aim_ssi_tmp
+-{
+- guint16 action;
+- guint16 ack;
+- char *name;
+- struct aim_ssi_item *item;
+- struct aim_ssi_tmp *next;
+-};
+-
+-/* These build the actual SNACs and queue them to be sent */
+-/* 0x0002 */ int aim_ssi_reqrights(OscarData *od);
+-/* 0x0004 */ int aim_ssi_reqdata(OscarData *od);
+-/* 0x0007 */ int aim_ssi_enable(OscarData *od);
+-/* 0x0011 */ int aim_ssi_modbegin(OscarData *od);
+-/* 0x0012 */ int aim_ssi_modend(OscarData *od);
+-/* 0x0018 */ int aim_ssi_sendauthrequest(OscarData *od, const char *bn, const char *msg);
+-/* 0x001a */ int aim_ssi_sendauthreply(OscarData *od, const char *bn, guint8 reply, const char *msg);
+-
+-/* Client functions for retrieving SSI data */
+-struct aim_ssi_item *aim_ssi_itemlist_find(struct aim_ssi_item *list, guint16 gid, guint16 bid);
+-struct aim_ssi_item *aim_ssi_itemlist_finditem(struct aim_ssi_item *list, const char *gn, const char *bn, guint16 type);
+-struct aim_ssi_item *aim_ssi_itemlist_exists(struct aim_ssi_item *list, const char *bn);
+-char *aim_ssi_itemlist_findparentname(struct aim_ssi_item *list, const char *bn);
+-int aim_ssi_getpermdeny(struct aim_ssi_item *list);
+-guint32 aim_ssi_getpresence(struct aim_ssi_item *list);
+-char *aim_ssi_getalias(struct aim_ssi_item *list, const char *gn, const char *bn);
+-char *aim_ssi_getcomment(struct aim_ssi_item *list, const char *gn, const char *bn);
+-gboolean aim_ssi_waitingforauth(struct aim_ssi_item *list, const char *gn, const char *bn);
+-
+-/* Client functions for changing SSI data */
+-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_delbuddy(OscarData *od, const char *name, const char *group);
+-int aim_ssi_delgroup(OscarData *od, const char *group);
+-int aim_ssi_movebuddy(OscarData *od, const char *oldgn, const char *newgn, const char *bn);
+-int aim_ssi_aliasbuddy(OscarData *od, const char *gn, const char *bn, const char *alias);
+-int aim_ssi_editcomment(OscarData *od, const char *gn, const char *bn, const char *alias);
+-int aim_ssi_rename_group(OscarData *od, const char *oldgn, const char *newgn);
+-int aim_ssi_cleanlist(OscarData *od);
+-int aim_ssi_deletelist(OscarData *od);
+-int aim_ssi_setpermdeny(OscarData *od, guint8 permdeny);
+-int aim_ssi_setpresence(OscarData *od, guint32 presence);
+-int aim_ssi_seticon(OscarData *od, const guint8 *iconsum, guint8 iconsumlen);
+-int aim_ssi_delicon(OscarData *od);
+-int aim_ssi_add_to_private_list(OscarData *od, const char* name, guint16 list_type);
+-int aim_ssi_del_from_private_list(OscarData* od, const char* name, guint16 list_type);
+-
+-guint16 aim_ssi_getdenyentrytype(OscarData* od);
+-
+-struct aim_icq_info
+-{
+- guint16 reqid;
+-
+- /* simple */
+- guint32 uin;
+-
+- /* general and "home" information (0x00c8) */
+- char *nick;
+- char *first;
+- char *last;
+- char *email;
+- char *homecity;
+- char *homestate;
+- char *homephone;
+- char *homefax;
+- char *homeaddr;
+- char *mobile;
+- char *homezip;
+- guint16 homecountry;
+-/* guint8 timezone;
+- guint8 hideemail; */
+-
+- /* personal (0x00dc) */
+- guint8 age;
+- guint8 unknown;
+- guint8 gender;
+- char *personalwebpage;
+- guint16 birthyear;
+- guint8 birthmonth;
+- guint8 birthday;
+- guint8 language1;
+- guint8 language2;
+- guint8 language3;
+-
+- /* work (0x00d2) */
+- char *workcity;
+- char *workstate;
+- char *workphone;
+- char *workfax;
+- char *workaddr;
+- char *workzip;
+- guint16 workcountry;
+- char *workcompany;
+- char *workdivision;
+- char *workposition;
+- char *workwebpage;
+-
+- /* additional personal information (0x00e6) */
+- char *info;
+-
+- /* email (0x00eb) */
+- guint16 numaddresses;
+- char **email2;
+-
+- /* status note info */
+- guint8 icbm_cookie[8];
+- char *status_note_title;
+-
+- gboolean for_auth_request;
+- char *auth_request_reason;
+-};
+-
+-int aim_icq_setsecurity(OscarData *od, gboolean auth_required, gboolean webaware);
+-int aim_icq_changepasswd(OscarData *od, const char *passwd);
+-int aim_icq_getalias(OscarData *od, const char *uin, gboolean for_auth_request, char *auth_request_reason);
+-int aim_icq_getallinfo(OscarData *od, const char *uin);
+-int aim_icq_sendsms(OscarData *od, const char *name, const char *msg, const char *alias);
+-
+-
+-/* 0x0017 - family_auth.c */
+-void aim_sendcookie(OscarData *, FlapConnection *, const guint16 length, const guint8 *);
+-void aim_admin_changepasswd(OscarData *, FlapConnection *, const char *newpw, const char *curpw);
+-void aim_admin_reqconfirm(OscarData *od, FlapConnection *conn);
+-void aim_admin_getinfo(OscarData *od, FlapConnection *conn, guint16 info);
+-void aim_admin_setemail(OscarData *od, FlapConnection *conn, const char *newemail);
+-void aim_admin_setnick(OscarData *od, FlapConnection *conn, const char *newnick);
+-
+-
+-
+-/* 0x0018 - family_alert.c */
+-struct aim_emailinfo
+-{
+- guint8 *cookie16;
+- guint8 *cookie8;
+- char *url;
+- guint16 nummsgs;
+- guint8 unread;
+- char *domain;
+- guint16 flag;
+- struct aim_emailinfo *next;
+-};
+-
+-int aim_email_sendcookies(OscarData *od);
+-int aim_email_activate(OscarData *od);
+-
+-
+-
+-/* tlv.c - TLV handling */
+-
+-/* TLV structure */
+-typedef struct aim_tlv_s
+-{
+- guint16 type;
+- guint16 length;
+- guint8 *value;
+-} aim_tlv_t;
+-
+-/* TLV handling functions */
+-char *aim_tlv_getvalue_as_string(aim_tlv_t *tlv);
+-
+-aim_tlv_t *aim_tlv_gettlv(GSList *list, const guint16 type, const int nth);
+-int aim_tlv_getlength(GSList *list, const 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 */
+-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(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(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 guint64 caps, const char *mood);
+-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(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(GSList **list, const guint16 type);
+-
+-
+-
+-/* util.c */
+-/* These are really ugly. You'd think this was LISP. I wish it was. */
+-#define aimutil_put8(buf, data) ((*(buf) = (guint8)(data)&0xff),1)
+-#define aimutil_get8(buf) ((*(buf))&0xff)
+-#define aimutil_put16(buf, data) ( \
+- (*(buf) = (guint8)((data)>>8)&0xff), \
+- (*((buf)+1) = (guint8)(data)&0xff), \
+- 2)
+-#define aimutil_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
+-#define aimutil_put32(buf, data) ( \
+- (*((buf)) = (guint8)((data)>>24)&0xff), \
+- (*((buf)+1) = (guint8)((data)>>16)&0xff), \
+- (*((buf)+2) = (guint8)((data)>>8)&0xff), \
+- (*((buf)+3) = (guint8)(data)&0xff), \
+- 4)
+-#define aimutil_get32(buf) ((((*(buf))<<24)&0xff000000) + \
+- (((*((buf)+1))<<16)&0x00ff0000) + \
+- (((*((buf)+2))<< 8)&0x0000ff00) + \
+- (((*((buf)+3) )&0x000000ff)))
+-
+-/* Little-endian versions (damn ICQ) */
+-#define aimutil_putle8(buf, data) ( \
+- (*(buf) = (guint8)(data) & 0xff), \
+- 1)
+-#define aimutil_getle8(buf) ( \
+- (*(buf)) & 0xff \
+- )
+-#define aimutil_putle16(buf, data) ( \
+- (*((buf)+0) = (guint8)((data) >> 0) & 0xff), \
+- (*((buf)+1) = (guint8)((data) >> 8) & 0xff), \
+- 2)
+-#define aimutil_getle16(buf) ( \
+- (((*((buf)+0)) << 0) & 0x00ff) + \
+- (((*((buf)+1)) << 8) & 0xff00) \
+- )
+-#define aimutil_putle32(buf, data) ( \
+- (*((buf)+0) = (guint8)((data) >> 0) & 0xff), \
+- (*((buf)+1) = (guint8)((data) >> 8) & 0xff), \
+- (*((buf)+2) = (guint8)((data) >> 16) & 0xff), \
+- (*((buf)+3) = (guint8)((data) >> 24) & 0xff), \
+- 4)
+-#define aimutil_getle32(buf) ( \
+- (((*((buf)+0)) << 0) & 0x000000ff) + \
+- (((*((buf)+1)) << 8) & 0x0000ff00) + \
+- (((*((buf)+2)) << 16) & 0x00ff0000) + \
+- (((*((buf)+3)) << 24) & 0xff000000))
+-
+-const char *oscar_get_msgerr_reason(size_t reason);
+-int oscar_get_ui_info_int(const char *str, int default_value);
+-const char *oscar_get_ui_info_string(const char *str, const char *default_value);
+-gchar *oscar_get_clientstring(void);
+-
+-guint16 aimutil_iconsum(const guint8 *buf, int buflen);
+-
+-gboolean oscar_util_valid_name(const char *bn);
+-gboolean oscar_util_valid_name_icq(const char *bn);
+-gboolean oscar_util_valid_name_sms(const char *bn);
+-int oscar_util_name_compare(const char *bn1, const char *bn2);
+-gchar *oscar_util_format_string(const char *str, const char *name);
+-gchar *oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message);
+-
+-typedef struct {
+- guint16 family;
+- guint16 subtype;
+- guint16 flags;
+- guint32 id;
+-} aim_modsnac_t;
+-
+-#define AIM_MODULENAME_MAXLEN 16
+-#define AIM_MODFLAG_MULTIFAMILY 0x0001
+-typedef struct aim_module_s
+-{
+- guint16 family;
+- guint16 version;
+- guint16 toolid;
+- guint16 toolversion;
+- guint16 flags;
+- char name[AIM_MODULENAME_MAXLEN+1];
+- int (*snachandler)(OscarData *od, FlapConnection *conn, struct aim_module_s *mod, FlapFrame *rx, aim_modsnac_t *snac, ByteStream *bs);
+- void (*shutdown)(OscarData *od, struct aim_module_s *mod);
+- void *priv;
+- struct aim_module_s *next;
+-} aim_module_t;
+-
+-int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *));
+-void aim__shutdownmodules(OscarData *od);
+-aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group);
+-aim_module_t *aim__findmodule(OscarData *od, const char *name);
+-
+-int admin_modfirst(OscarData *od, aim_module_t *mod);
+-int buddylist_modfirst(OscarData *od, aim_module_t *mod);
+-int bos_modfirst(OscarData *od, aim_module_t *mod);
+-int search_modfirst(OscarData *od, aim_module_t *mod);
+-int stats_modfirst(OscarData *od, aim_module_t *mod);
+-int auth_modfirst(OscarData *od, aim_module_t *mod);
+-int msg_modfirst(OscarData *od, aim_module_t *mod);
+-int misc_modfirst(OscarData *od, aim_module_t *mod);
+-int chatnav_modfirst(OscarData *od, aim_module_t *mod);
+-int chat_modfirst(OscarData *od, aim_module_t *mod);
+-int locate_modfirst(OscarData *od, aim_module_t *mod);
+-int service_modfirst(OscarData *od, aim_module_t *mod);
+-int popups_modfirst(OscarData *od, aim_module_t *mod);
+-int bart_modfirst(OscarData *od, aim_module_t *mod);
+-int ssi_modfirst(OscarData *od, aim_module_t *mod);
+-int icq_modfirst(OscarData *od, aim_module_t *mod);
+-int email_modfirst(OscarData *od, aim_module_t *mod);
+-
+-void aim_genericreq_n(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype);
+-void aim_genericreq_n_snacid(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype);
+-void aim_genericreq_l(OscarData *od, FlapConnection *conn, guint16 family, guint16 subtype, guint32 *);
+-
+-/* bstream.c */
+-int byte_stream_new(ByteStream *bs, size_t len);
+-int byte_stream_init(ByteStream *bs, guint8 *data, size_t len);
+-void byte_stream_destroy(ByteStream *bs);
+-int byte_stream_bytes_left(ByteStream *bs);
+-int byte_stream_curpos(ByteStream *bs);
+-int byte_stream_setpos(ByteStream *bs, size_t off);
+-void byte_stream_rewind(ByteStream *bs);
+-int byte_stream_advance(ByteStream *bs, int n);
+-guint8 byte_stream_get8(ByteStream *bs);
+-guint16 byte_stream_get16(ByteStream *bs);
+-guint32 byte_stream_get32(ByteStream *bs);
+-guint8 byte_stream_getle8(ByteStream *bs);
+-guint16 byte_stream_getle16(ByteStream *bs);
+-guint32 byte_stream_getle32(ByteStream *bs);
+-int byte_stream_getrawbuf(ByteStream *bs, guint8 *buf, size_t len);
+-guint8 *byte_stream_getraw(ByteStream *bs, size_t len);
+-char *byte_stream_getstr(ByteStream *bs, size_t len);
+-int byte_stream_put8(ByteStream *bs, guint8 v);
+-int byte_stream_put16(ByteStream *bs, guint16 v);
+-int byte_stream_put32(ByteStream *bs, guint32 v);
+-int byte_stream_putle8(ByteStream *bs, guint8 v);
+-int byte_stream_putle16(ByteStream *bs, guint16 v);
+-int byte_stream_putle32(ByteStream *bs, guint32 v);
+-int byte_stream_putraw(ByteStream *bs, const guint8 *v, size_t len);
+-int byte_stream_putstr(ByteStream *bs, const char *str);
+-int byte_stream_putbs(ByteStream *bs, ByteStream *srcbs, size_t len);
+-int byte_stream_putuid(ByteStream *bs, OscarData *od);
+-int byte_stream_putcaps(ByteStream *bs, guint64 caps);
+-
+-/**
+- * Inserts a BART asset block into the given byte stream. The flags
+- * and length are set appropriately based on the value of data.
+- */
+-void byte_stream_put_bart_asset(ByteStream *bs, guint16 type, ByteStream *data);
+-
+-/**
+- * A helper function that calls byte_stream_put_bart_asset with the
+- * appropriate data ByteStream given the datastr.
+- */
+-void byte_stream_put_bart_asset_str(ByteStream *bs, guint16 type, const char *datastr);
+-
+-/*
+- * Generic SNAC structure. Rarely if ever used.
+- */
+-typedef struct aim_snac_s {
+- aim_snacid_t id;
+- guint16 family;
+- guint16 type;
+- guint16 flags;
+- void *data;
+- time_t issuetime;
+- struct aim_snac_s *next;
+-} aim_snac_t;
+-
+-/* snac.c */
+-void aim_initsnachash(OscarData *od);
+-aim_snacid_t aim_newsnac(OscarData *, aim_snac_t *newsnac);
+-aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen);
+-aim_snac_t *aim_remsnac(OscarData *, aim_snacid_t id);
+-void aim_cleansnacs(OscarData *, int maxage);
+-int aim_putsnac(ByteStream *, guint16 family, guint16 type, aim_snacid_t id);
+-
+-struct chatsnacinfo {
+- guint16 exchange;
+- char name[128];
+- guint16 instance;
+-};
+-
+-struct rateclass {
+- guint16 classid;
+- guint32 windowsize;
+- guint32 clear;
+- guint32 alert;
+- guint32 limit;
+- guint32 disconnect;
+- guint32 current;
+- guint32 max;
+- guint8 dropping_snacs;
+-
+- struct timeval last; /**< The time when we last sent a SNAC of this rate class. */
+-};
+-
+-int aim_cachecookie(OscarData *od, IcbmCookie *cookie);
+-IcbmCookie *aim_uncachecookie(OscarData *od, guint8 *cookie, int type);
+-IcbmCookie *aim_mkcookie(guint8 *, int, void *);
+-IcbmCookie *aim_checkcookie(OscarData *, const unsigned char *, const int);
+-int aim_freecookie(OscarData *od, IcbmCookie *cookie);
+-int aim_cookie_free(OscarData *od, IcbmCookie *cookie);
+-
+-int aim_chat_readroominfo(ByteStream *bs, struct aim_chat_roominfo *outinfo);
+-
+-void flap_connection_destroy_chat(OscarData *od, FlapConnection *conn);
+-
+-/* userinfo.c - displaying user information */
+-
+-void oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status);
+-void oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo);
+-void oscar_user_info_display_error(OscarData *od, guint16 error_reason, char *buddy);
+-void oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info);
+-void oscar_user_info_display_aim(OscarData *od, aim_userinfo_t *userinfo);
+-
+-/* authorization.c - OSCAR authorization requests */
+-void oscar_auth_sendrequest(PurpleConnection *gc, const char *name, const char *msg);
+-void oscar_auth_sendrequest_menu(PurpleBlistNode *node, gpointer ignored);
+-void oscar_auth_recvrequest(PurpleConnection *gc, gchar *name, gchar *nick, gchar *reason);
+-
+-void oscar_set_aim_permdeny(PurpleConnection *gc);
+-
+-struct buddyinfo
+-{
+- gboolean typingnot;
+- guint32 ipaddr;
+-
+- unsigned long ico_me_len;
+- unsigned long ico_me_csum;
+- time_t ico_me_time;
+- gboolean ico_informed;
+-
+- unsigned long ico_len;
+- unsigned long ico_csum;
+- time_t ico_time;
+- gboolean ico_need;
+- gboolean ico_sent;
+-};
+-
+-struct name_data
+-{
+- PurpleConnection *gc;
+- gchar *name;
+- gchar *nick;
+-};
+-
+-void oscar_free_name_data(struct name_data *data);
+-
+-#ifdef __cplusplus
+-}
+-#endif
+-
+-#endif /* _OSCAR_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/peer.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1136 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Functions dealing with peer connections. This includes the code
+- * used to establish a peer connection for both Oscar File transfer
+- * (OFT) and Oscar Direct Connect (ODC). (ODC is also referred to
+- * as DirectIM and IM Image.)
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-#include <config.h>
+-#endif
+-
+-/* From the oscar PRPL */
+-#include "oscar.h"
+-#include "peer.h"
+-
+-/* From Purple */
+-#include "conversation.h"
+-#include "ft.h"
+-#include "network.h"
+-#include "notify.h"
+-#include "request.h"
+-#include "util.h"
+-
+-#ifndef _WIN32
+-#include <stdio.h>
+-#include <netdb.h>
+-#include <sys/socket.h>
+-#include <netinet/in.h>
+-#include <arpa/inet.h> /* for inet_ntoa */
+-#include <limits.h> /* for UINT_MAX */
+-#endif
+-
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#endif
+-
+-/*
+- * I really want to switch all our networking code to using IPv6 only,
+- * but that really isn't a good idea at all. Evan S. of Adium says
+- * OS X sets all connections as "AF_INET6/PF_INET6," even if there is
+- * nothing inherently IPv6 about them. And I feel like Linux kernel
+- * 2.6.5 is doing the same thing. So we REALLY should accept
+- * connections if they're showing up as IPv6. Old OSes (Solaris?)
+- * that might not have full IPv6 support yet will fail if we try
+- * to use PF_INET6 but it isn't defined. --Mark Doliner
+- */
+-#ifndef PF_INET6
+-#define PF_INET6 PF_INET
+-#endif
+-
+-PeerConnection *
+-peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type)
+-{
+- GSList *cur;
+- PeerConnection *conn;
+-
+- for (cur = od->peer_connections; cur != NULL; cur = cur->next)
+- {
+- conn = cur->data;
+- if ((conn->type == type) && !oscar_util_name_compare(conn->bn, bn))
+- return conn;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * @param cookie This must be exactly 8 characters.
+- */
+-PeerConnection *
+-peer_connection_find_by_cookie(OscarData *od, const char *bn, const guchar *cookie)
+-{
+- GSList *cur;
+- PeerConnection *conn;
+-
+- for (cur = od->peer_connections; cur != NULL; cur = cur->next)
+- {
+- conn = cur->data;
+- if (!memcmp(conn->cookie, cookie, 8) && !oscar_util_name_compare(conn->bn, bn))
+- return conn;
+- }
+-
+- return NULL;
+-}
+-
+-PeerConnection *
+-peer_connection_new(OscarData *od, guint64 type, const char *bn)
+-{
+- PeerConnection *conn;
+- PurpleAccount *account;
+-
+- account = purple_connection_get_account(od->gc);
+-
+- conn = g_new0(PeerConnection, 1);
+- conn->od = od;
+- conn->type = type;
+- conn->bn = g_strdup(bn);
+- conn->buffer_outgoing = purple_circ_buffer_new(0);
+- conn->listenerfd = -1;
+- conn->fd = -1;
+- conn->lastactivity = time(NULL);
+- conn->use_proxy |= purple_account_get_bool(account, "always_use_rv_proxy", FALSE);
+-
+- if (type == OSCAR_CAPABILITY_DIRECTIM)
+- memcpy(conn->magic, "ODC2", 4);
+- else if (type == OSCAR_CAPABILITY_SENDFILE)
+- memcpy(conn->magic, "OFT2", 4);
+-
+- od->peer_connections = g_slist_prepend(od->peer_connections, conn);
+-
+- return conn;
+-}
+-
+-static void
+-peer_connection_close(PeerConnection *conn)
+-{
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- peer_odc_close(conn);
+- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
+- peer_oft_close(conn);
+-
+- if (conn->verified_connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(conn->verified_connect_data);
+- conn->verified_connect_data = NULL;
+- }
+-
+- if (conn->client_connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(conn->client_connect_data);
+- conn->client_connect_data = NULL;
+- }
+-
+- if (conn->listen_data != NULL)
+- {
+- purple_network_listen_cancel(conn->listen_data);
+- conn->listen_data = NULL;
+- }
+-
+- if (conn->connect_timeout_timer != 0)
+- {
+- purple_timeout_remove(conn->connect_timeout_timer);
+- conn->connect_timeout_timer = 0;
+- }
+-
+- if (conn->watcher_incoming != 0)
+- {
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+- }
+- if (conn->watcher_outgoing != 0)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- }
+- if (conn->listenerfd >= 0)
+- {
+- close(conn->listenerfd);
+- conn->listenerfd = -1;
+- }
+- if (conn->fd >= 0)
+- {
+- close(conn->fd);
+- conn->fd = -1;
+- }
+-
+- g_free(conn->buffer_incoming.data);
+- conn->buffer_incoming.data = NULL;
+- conn->buffer_incoming.len = 0;
+- conn->buffer_incoming.offset = 0;
+-
+- purple_circ_buffer_destroy(conn->buffer_outgoing);
+- conn->buffer_outgoing = purple_circ_buffer_new(0);
+-
+- conn->flags &= ~PEER_CONNECTION_FLAG_IS_INCOMING;
+-}
+-
+-static gboolean
+-peer_connection_destroy_cb(gpointer data)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- purple_request_close_with_handle(conn);
+-
+- peer_connection_close(conn);
+-
+- if (conn->checksum_data != NULL)
+- peer_oft_checksum_destroy(conn->checksum_data);
+-
+- if (conn->xfer != NULL)
+- {
+- PurpleXferStatusType status;
+- conn->xfer->data = NULL;
+- status = purple_xfer_get_status(conn->xfer);
+- if ((status != PURPLE_XFER_STATUS_DONE) &&
+- (status != PURPLE_XFER_STATUS_CANCEL_LOCAL) &&
+- (status != PURPLE_XFER_STATUS_CANCEL_REMOTE))
+- {
+- if ((conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_CLOSED) ||
+- (conn->disconnect_reason == OSCAR_DISCONNECT_REMOTE_REFUSED))
+- purple_xfer_cancel_remote(conn->xfer);
+- else
+- purple_xfer_cancel_local(conn->xfer);
+- }
+- purple_xfer_unref(conn->xfer);
+- conn->xfer = NULL;
+- }
+-
+- g_free(conn->bn);
+- g_free(conn->error_message);
+- g_free(conn->proxyip);
+- g_free(conn->clientip);
+- g_free(conn->verifiedip);
+- g_free(conn->xferdata.name);
+- purple_circ_buffer_destroy(conn->buffer_outgoing);
+-
+- conn->od->peer_connections = g_slist_remove(conn->od->peer_connections, conn);
+-
+- g_free(conn);
+-
+- return FALSE;
+-}
+-
+-void
+-peer_connection_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
+-{
+- if (conn->destroy_timeout != 0)
+- purple_timeout_remove(conn->destroy_timeout);
+- conn->disconnect_reason = reason;
+- g_free(conn->error_message);
+- conn->error_message = g_strdup(error_message);
+- peer_connection_destroy_cb(conn);
+-}
+-
+-void
+-peer_connection_schedule_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message)
+-{
+- if (conn->destroy_timeout != 0)
+- /* Already taken care of */
+- return;
+-
+- purple_debug_info("oscar", "Scheduling destruction of peer connection\n");
+- conn->disconnect_reason = reason;
+- g_free(conn->error_message);
+- conn->error_message = g_strdup(error_message);
+- conn->destroy_timeout = purple_timeout_add(0, peer_connection_destroy_cb, conn);
+-}
+-
+-/*******************************************************************/
+-/* Begin code for receiving data on a peer connection */
+-/*******************************************************************/
+-
+-/**
+- * This should be used to read ODC and OFT framing info. It should
+- * NOT be used to read the payload sent across the connection (IMs,
+- * file data, etc), and it should NOT be used to read proxy negotiation
+- * headers.
+- *
+- * Unlike flap_connection_recv_cb(), this only reads one frame at a
+- * time. This is done so that the watcher can be changed during the
+- * handling of the frame. If the watcher is changed then this
+- * function will not read in any more data. This happens when
+- * reading the payload of a direct IM frame, or when we're
+- * receiving a file from the remote user. Once the data has been
+- * read, the watcher will be switched back to this function to
+- * continue reading the next frame.
+- */
+-void
+-peer_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PeerConnection *conn;
+- gssize read;
+-
+- conn = data;
+-
+- /* Start reading a new ODC/OFT frame */
+- if (conn->buffer_incoming.data == NULL)
+- {
+- /* Read the first 6 bytes (magic string and frame length) */
+- read = recv(conn->fd, conn->header + conn->header_received,
+- 6 - conn->header_received, 0);
+-
+- /* Check if the remote user closed the connection */
+- if (read == 0)
+- {
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- return;
+- }
+-
+- /* If there was an error then close the connection */
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- peer_connection_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- return;
+- }
+-
+- conn->lastactivity = time(NULL);
+-
+- /* If we don't even have the first 6 bytes then do nothing */
+- conn->header_received += read;
+- if (conn->header_received < 6)
+- return;
+-
+- /* All ODC/OFT frames must start with a magic string */
+- if (memcmp(conn->magic, conn->header, 4))
+- {
+- purple_debug_warning("oscar", "Expecting magic string to "
+- "be %c%c%c%c but received magic string %c%c%c%c. "
+- "Closing connection.\n",
+- conn->magic[0], conn->magic[1], conn->magic[2],
+- conn->magic[3], conn->header[0], conn->header[1],
+- conn->header[2], conn->header[3]);
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_INVALID_DATA, NULL);
+- return;
+- }
+-
+- /* Initialize a new temporary ByteStream for incoming data */
+- conn->buffer_incoming.len = aimutil_get16(&conn->header[4]) - 6;
+- conn->buffer_incoming.data = g_new(guint8, conn->buffer_incoming.len);
+- conn->buffer_incoming.offset = 0;
+- }
+-
+- /* Read data into the temporary buffer until it is complete */
+- read = recv(conn->fd,
+- &conn->buffer_incoming.data[conn->buffer_incoming.offset],
+- conn->buffer_incoming.len - conn->buffer_incoming.offset,
+- 0);
+-
+- /* Check if the remote user closed the connection */
+- if (read == 0)
+- {
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- return;
+- }
+-
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- peer_connection_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, g_strerror(errno));
+- return;
+- }
+-
+- conn->lastactivity = time(NULL);
+- conn->buffer_incoming.offset += read;
+- if (conn->buffer_incoming.offset < conn->buffer_incoming.len)
+- /* Waiting for more data to arrive */
+- return;
+-
+- /* We have a complete ODC/OFT frame! Handle it and continue reading */
+- byte_stream_rewind(&conn->buffer_incoming);
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- peer_odc_recv_frame(conn, &conn->buffer_incoming);
+- }
+- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- peer_oft_recv_frame(conn, &conn->buffer_incoming);
+- }
+-
+- g_free(conn->buffer_incoming.data);
+- conn->buffer_incoming.data = NULL;
+-
+- conn->header_received = 0;
+-}
+-
+-/*******************************************************************/
+-/* End code for receiving data on a peer connection */
+-/*******************************************************************/
+-
+-/*******************************************************************/
+-/* Begin code for sending data on a peer connection */
+-/*******************************************************************/
+-
+-static void
+-send_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PeerConnection *conn;
+- gsize writelen;
+- gssize wrotelen;
+-
+- conn = data;
+- writelen = purple_circ_buffer_get_max_read(conn->buffer_outgoing);
+-
+- if (writelen == 0)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- /*
+- * The buffer is currently empty, so reset the current input
+- * and output positions to the start of the buffer. We do
+- * this so that the next chunk of data that we put into the
+- * buffer can be read back out of the buffer in one fell swoop.
+- * Otherwise it gets fragmented and we have to read from the
+- * second half of the buffer than go back and read the rest of
+- * the chunk from the first half.
+- *
+- * We're using TCP, which is a stream based protocol, so this
+- * isn't supposed to matter. However, experience has shown
+- * that at least the proxy file transfer code in AIM 6.1.41.2
+- * requires that the entire OFT frame arrive all at once. If
+- * the frame is fragmented then AIM freaks out and aborts the
+- * file transfer. Somebody should teach those guys how to
+- * write good TCP code.
+- */
+- conn->buffer_outgoing->inptr = conn->buffer_outgoing->buffer;
+- conn->buffer_outgoing->outptr = conn->buffer_outgoing->buffer;
+- return;
+- }
+-
+- wrotelen = send(conn->fd, conn->buffer_outgoing->outptr, writelen, 0);
+- if (wrotelen <= 0)
+- {
+- if (wrotelen < 0 && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+- /* No worries */
+- return;
+-
+- if (conn->ready)
+- {
+- purple_input_remove(conn->watcher_outgoing);
+- conn->watcher_outgoing = 0;
+- close(conn->fd);
+- conn->fd = -1;
+- peer_connection_schedule_destroy(conn,
+- OSCAR_DISCONNECT_LOST_CONNECTION, NULL);
+- }
+- else
+- {
+- /*
+- * This could happen when unable to send a negotiation
+- * frame to a peer proxy server.
+- */
+- peer_connection_trynext(conn);
+- }
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(conn->buffer_outgoing, wrotelen);
+- conn->lastactivity = time(NULL);
+-}
+-
+-/**
+- * This should be called by OFT/ODC code to send a standard OFT or ODC
+- * frame across the peer connection along with some payload data. Or
+- * maybe a file. Anything, really.
+- */
+-void
+-peer_connection_send(PeerConnection *conn, ByteStream *bs)
+-{
+- /* Add everything to our outgoing buffer */
+- 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 >= 0))
+- {
+- conn->watcher_outgoing = purple_input_add(conn->fd,
+- PURPLE_INPUT_WRITE, send_cb, conn);
+- send_cb(conn, conn->fd, 0);
+- }
+-}
+-
+-/*******************************************************************/
+-/* End code for sending data on a peer connection */
+-/*******************************************************************/
+-
+-/*******************************************************************/
+-/* Begin code for establishing a peer connection */
+-/*******************************************************************/
+-
+-void
+-peer_connection_finalize_connection(PeerConnection *conn)
+-{
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, peer_connection_recv_cb, conn);
+-
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- /*
+- * If we are connecting to them then send our cookie so they
+- * can verify who we are. Note: This doesn't seem to be
+- * necessary, but it also doesn't seem to hurt.
+- */
+- if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))
+- peer_odc_send_cookie(conn);
+- }
+- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- if (purple_xfer_get_type(conn->xfer) == PURPLE_XFER_SEND)
+- {
+- peer_oft_send_prompt(conn);
+- }
+- }
+-
+- /*
+- * Tell the remote user that we're connected (which may also imply
+- * that we've accepted their request).
+- */
+- if (!(conn->flags & PEER_CONNECTION_FLAG_IS_INCOMING))
+- aim_im_sendch2_connected(conn);
+-}
+-
+-/**
+- * We tried to make an outgoing connection to a remote user. It
+- * either connected or failed to connect.
+- */
+-static void
+-peer_connection_common_established_cb(gpointer data, gint source, const gchar *error_message, gboolean verified)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- if (verified)
+- conn->verified_connect_data = NULL;
+- else
+- conn->client_connect_data = NULL;
+-
+- if (source < 0)
+- {
+- if ((conn->verified_connect_data == NULL) &&
+- (conn->client_connect_data == NULL))
+- {
+- /* Our parallel connection attemps have both failed. */
+- peer_connection_trynext(conn);
+- }
+- return;
+- }
+-
+- purple_timeout_remove(conn->connect_timeout_timer);
+- conn->connect_timeout_timer = 0;
+-
+- if (conn->client_connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(conn->client_connect_data);
+- conn->client_connect_data = NULL;
+- }
+-
+- if (conn->verified_connect_data != NULL)
+- {
+- purple_proxy_connect_cancel(conn->verified_connect_data);
+- conn->verified_connect_data = NULL;
+- }
+-
+- conn->fd = source;
+-
+- peer_connection_finalize_connection(conn);
+-}
+-
+-static void
+-peer_connection_verified_established_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- peer_connection_common_established_cb(data, source, error_message, TRUE);
+-}
+-
+-static void
+-peer_connection_client_established_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- peer_connection_common_established_cb(data, source, error_message, FALSE);
+-}
+-
+-/**
+- * This is the watcher callback for any listening socket that is
+- * waiting for a peer to connect. When a peer connects we set the
+- * input watcher to start reading data from the peer.
+- *
+- * To make sure that the connection is with the intended person and
+- * not with a malicious middle man, we don't send anything until we've
+- * received a peer frame from the remote user and have verified that
+- * the cookie in the peer frame matches the cookie that was exchanged
+- * in the channel 2 ICBM.
+- */
+-void
+-peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PeerConnection *conn;
+- OscarData *od;
+- PurpleConnection *gc;
+- struct sockaddr addr;
+- socklen_t addrlen = sizeof(addr);
+- int flags;
+-
+- conn = data;
+- od = conn->od;
+- gc = od->gc;
+-
+- purple_debug_info("oscar", "Accepting connection on listener socket.\n");
+-
+- conn->fd = accept(conn->listenerfd, &addr, &addrlen);
+- if (conn->fd < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No connection yet--no worries */
+- /* TODO: Hmm, but they SHOULD be connected if we're here, right? */
+- return;
+-
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- if ((addr.sa_family != PF_INET) && (addr.sa_family != PF_INET6))
+- {
+- /* Invalid connection type?! Continue waiting. */
+- close(conn->fd);
+- return;
+- }
+-
+- flags = fcntl(conn->fd, F_GETFL);
+- fcntl(conn->fd, F_SETFL, flags | O_NONBLOCK);
+-#ifndef _WIN32
+- fcntl(conn->fd, F_SETFD, FD_CLOEXEC);
+-#endif
+-
+- purple_input_remove(conn->watcher_incoming);
+-
+- peer_connection_finalize_connection(conn);
+-}
+-
+-/**
+- * We've just opened a listener socket, so we send the remote
+- * user an ICBM and ask them to connect to us.
+- */
+-static void
+-peer_connection_establish_listener_cb(int listenerfd, gpointer data)
+-{
+- PeerConnection *conn;
+- OscarData *od;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PurpleConversation *conv;
+- char *tmp;
+- FlapConnection *bos_conn;
+- const char *listener_ip;
+- const guchar *ip_atoi;
+- unsigned short listener_port;
+-
+- conn = data;
+- conn->listen_data = NULL;
+-
+- if (listenerfd < 0)
+- {
+- /* Could not open listener socket */
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- od = conn->od;
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+- conn->listenerfd = listenerfd;
+-
+- /* Watch for new connections on our listener socket */
+- conn->watcher_incoming = purple_input_add(conn->listenerfd,
+- PURPLE_INPUT_READ, peer_connection_listen_cb, conn);
+-
+- /* Send the "please connect to me!" ICBM */
+- bos_conn = flap_connection_findbygroup(od, SNAC_FAMILY_ICBM);
+- if (bos_conn == NULL)
+- {
+- /* Not good */
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- if (bos_conn->gsc)
+- listener_ip = purple_network_get_my_ip(bos_conn->gsc->fd);
+- else
+- listener_ip = purple_network_get_my_ip(bos_conn->fd);
+-
+- ip_atoi = purple_network_ip_atoi(listener_ip);
+- if (ip_atoi == NULL) {
+- /* Could not convert IP to 4 byte array--weird, but this does
+- happen for some users (#4829, Adium #15839). Maybe they're
+- connecting with IPv6...? Maybe through a proxy? */
+- purple_debug_error("oscar", "Can't ask peer to connect to us "
+- "because purple_network_ip_atoi(%s) returned NULL. "
+- "fd=%d. is_ssl=%d\n",
+- listener_ip ? listener_ip : "(null)",
+- bos_conn->gsc ? bos_conn->gsc->fd : bos_conn->fd,
+- bos_conn->gsc ? 1 : 0);
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- listener_port = purple_network_get_port_from_fd(conn->listenerfd);
+-
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- aim_im_sendch2_odc_requestdirect(od,
+- conn->cookie, conn->bn, ip_atoi,
+- listener_port, ++conn->lastrequestnumber);
+-
+- /* Print a message to a local conversation window */
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- tmp = g_strdup_printf(_("Asking %s to connect to us at %s:%hu for "
+- "Direct IM."), conn->bn, listener_ip, listener_port);
+- purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+- }
+- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- aim_im_sendch2_sendfile_requestdirect(od,
+- conn->cookie, conn->bn,
+- ip_atoi,
+- listener_port, ++conn->lastrequestnumber,
+- (const gchar *)conn->xferdata.name,
+- conn->xferdata.size, conn->xferdata.totfiles);
+- }
+-}
+-
+-/**
+- * This is a callback function used when we're connecting to a peer
+- * using either the client IP or the verified IP and the connection
+- * took longer than 5 seconds to complete. We do this because
+- * waiting for the OS to time out the connection attempt is not
+- * practical--the default timeout on many OSes can be 3 minutes or
+- * more, and users are impatient.
+- *
+- * Worst case scenario: the user is connected to the Internet using
+- * a modem with severe lag. The peer connections fail and Purple falls
+- * back to using a proxied connection. The lower bandwidth
+- * limitations imposed by the proxied connection won't matter because
+- * the user is using a modem.
+- *
+- * I suppose this line of thinking is discriminatory against people
+- * with very high lag but decent throughput who are transferring
+- * large files. But we don't care about those people.
+- *
+- * I (Sean) changed the timeout from 15 to 5 seconds, as 60 seconds is
+- * too long for a user to wait to send a file. I'm also parallelizing
+- * requests when possible. The longest we should have to wait now is 10
+- * seconds. We shouldn't make it shorter than this.
+- */
+-static gboolean
+-peer_connection_tooktoolong(gpointer data)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- purple_debug_info("oscar", "Peer connection timed out after 5 seconds. "
+- "Trying next method...\n");
+-
+- peer_connection_trynext(conn);
+-
+- /* Cancel this timer. It'll be added again, if needed. */
+- return FALSE;
+-}
+-
+-/**
+- * Try to establish the given PeerConnection using a defined
+- * sequence of steps.
+- */
+-void
+-peer_connection_trynext(PeerConnection *conn)
+-{
+- PurpleAccount *account;
+-
+- account = purple_connection_get_account(conn->od->gc);
+-
+- /*
+- * Close any remnants of a previous failed connection attempt.
+- */
+- peer_connection_close(conn);
+-
+- /*
+- * 1. Attempt to connect to the remote user using their verifiedip and clientip.
+- * We try these at the same time and use whichever succeeds first, so we don't
+- * have to wait for a timeout.
+- */
+- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_DIRECT) &&
+- (conn->verifiedip != NULL) && (conn->port != 0) && (!conn->use_proxy))
+- {
+- conn->flags |= PEER_CONNECTION_FLAG_TRIED_DIRECT;
+-
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- gchar *tmp;
+- PurpleConversation *conv;
+- tmp = g_strdup_printf(_("Attempting to connect to %s:%hu."),
+- conn->verifiedip, conn->port);
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- purple_conversation_write(conv, NULL, tmp,
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+- }
+-
+- conn->verified_connect_data = purple_proxy_connect(NULL, account,
+- conn->verifiedip, conn->port,
+- peer_connection_verified_established_cb, conn);
+-
+- if ((conn->verifiedip == NULL) ||
+- strcmp(conn->verifiedip, conn->clientip))
+- {
+- conn->client_connect_data = purple_proxy_connect(NULL, account,
+- conn->clientip, conn->port,
+- peer_connection_client_established_cb, conn);
+- }
+-
+- if ((conn->verified_connect_data != NULL) ||
+- (conn->client_connect_data != NULL))
+- {
+- /* Connecting... */
+- conn->connect_timeout_timer = purple_timeout_add_seconds(5,
+- peer_connection_tooktoolong, conn);
+- return;
+- }
+- }
+-
+- /*
+- * 2. Attempt to have the remote user connect to us (using both
+- * our verifiedip and our clientip).
+- */
+- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_INCOMING) &&
+- (!conn->use_proxy))
+- {
+- conn->flags |= PEER_CONNECTION_FLAG_TRIED_INCOMING;
+-
+- /*
+- * Remote user is connecting to us, so we'll need to verify
+- * that the user who connected is our friend.
+- */
+- conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING;
+-
+- conn->listen_data = purple_network_listen_range(5190, 5290, SOCK_STREAM,
+- peer_connection_establish_listener_cb, conn);
+- if (conn->listen_data != NULL)
+- {
+- /* Opening listener socket... */
+- return;
+- }
+- }
+-
+- /*
+- * 3. Attempt to have both users connect to an intermediate proxy
+- * server.
+- */
+- if (!(conn->flags & PEER_CONNECTION_FLAG_TRIED_PROXY))
+- {
+- conn->flags |= PEER_CONNECTION_FLAG_TRIED_PROXY;
+-
+- /*
+- * If we initiate the proxy connection, then the remote user
+- * could be anyone, so we need to verify that the user who
+- * connected is our friend.
+- */
+- if (!conn->use_proxy)
+- conn->flags |= PEER_CONNECTION_FLAG_IS_INCOMING;
+-
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- gchar *tmp;
+- PurpleConversation *conv;
+- tmp = g_strdup(_("Attempting to connect via proxy server."));
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->bn);
+- purple_conversation_write(conv, NULL, tmp,
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmp);
+- }
+-
+- conn->verified_connect_data = purple_proxy_connect(NULL, account,
+- (conn->proxyip != NULL)
+- ? conn->proxyip
+- : (conn->od->icq ? ICQ_PEER_PROXY_SERVER : AIM_PEER_PROXY_SERVER),
+- PEER_PROXY_PORT,
+- peer_proxy_connection_established_cb, conn);
+- if (conn->verified_connect_data != NULL)
+- {
+- /* Connecting... */
+- return;
+- }
+- }
+-
+- /* Give up! */
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_COULD_NOT_CONNECT, NULL);
+-}
+-
+-/**
+- * Initiate a peer connection with someone.
+- */
+-void
+-peer_connection_propose(OscarData *od, guint64 type, const char *bn)
+-{
+- PeerConnection *conn;
+-
+- if (type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- conn = peer_connection_find_by_type(od, bn, type);
+- if (conn != NULL)
+- {
+- if (conn->ready)
+- {
+- PurpleAccount *account;
+- PurpleConversation *conv;
+-
+- purple_debug_info("oscar", "Already have a direct IM "
+- "session with %s.\n", bn);
+- account = purple_connection_get_account(od->gc);
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- bn, account);
+- if (conv != NULL)
+- purple_conversation_present(conv);
+- return;
+- }
+-
+- /* Cancel the old connection and try again */
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_RETRYING, NULL);
+- }
+- }
+-
+- conn = peer_connection_new(od, type, bn);
+- conn->flags |= PEER_CONNECTION_FLAG_INITIATED_BY_ME;
+- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
+- aim_icbm_makecookie(conn->cookie);
+-
+- peer_connection_trynext(conn);
+-}
+-
+-/**
+- * Someone else wants to establish a peer connection with us,
+- * and we said yes.
+- */
+-static void
+-peer_connection_got_proposition_yes_cb(gpointer data, gint id)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- conn->flags |= PEER_CONNECTION_FLAG_APPROVED;
+- peer_connection_trynext(conn);
+-}
+-
+-/**
+- * Someone else wants to establish a peer connection with us,
+- * and we said no.
+- *
+- * "Well, one time my friend asked me if I wanted to play the
+- * piccolo. But I said no."
+- */
+-static void
+-peer_connection_got_proposition_no_cb(gpointer data, gint id)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- aim_im_denytransfer(conn->od, conn->bn, conn->cookie,
+- AIM_TRANSFER_DENY_DECLINE);
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+-}
+-
+-/**
+- * Someone else wants to establish a peer connection with us.
+- */
+-void
+-peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar *message, IcbmArgsCh2 *args)
+-{
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- PeerConnection *conn;
+- gchar *buf;
+-
+- gc = od->gc;
+- account = purple_connection_get_account(gc);
+-
+- /*
+- * If we have a connection with this same cookie then they are
+- * probably just telling us they weren't able to connect to us
+- * and we should try connecting to them, instead. Or they want
+- * to go through a proxy.
+- */
+- conn = peer_connection_find_by_cookie(od, bn, args->cookie);
+- if ((conn != NULL) && (conn->type == args->type))
+- {
+- purple_debug_info("oscar", "Remote user wants to try a "
+- "different connection method\n");
+- g_free(conn->proxyip);
+- g_free(conn->clientip);
+- g_free(conn->verifiedip);
+- if (args->use_proxy)
+- conn->proxyip = g_strdup(args->proxyip);
+- else
+- conn->proxyip = NULL;
+- conn->verifiedip = g_strdup(args->verifiedip);
+- conn->clientip = g_strdup(args->clientip);
+- conn->port = args->port;
+- conn->use_proxy |= args->use_proxy;
+- conn->lastrequestnumber++;
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- /* If this is a direct IM, then close any existing session */
+- if (args->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- conn = peer_connection_find_by_type(od, bn, args->type);
+- if (conn != NULL)
+- {
+- /* Close the old direct IM and start a new one */
+- purple_debug_info("oscar", "Received new direct IM request "
+- "from %s. Destroying old connection.\n", bn);
+- peer_connection_destroy(conn, OSCAR_DISCONNECT_REMOTE_CLOSED, NULL);
+- }
+- }
+-
+- /* Check for proper arguments */
+- if (args->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- if ((args->info.sendfile.filename == NULL) ||
+- (args->info.sendfile.totsize == 0) ||
+- (args->info.sendfile.totfiles == 0))
+- {
+- purple_debug_warning("oscar",
+- "%s tried to send you a file with incomplete "
+- "information.\n", bn);
+- return;
+- }
+- }
+-
+- conn = peer_connection_new(od, args->type, bn);
+- memcpy(conn->cookie, args->cookie, 8);
+- if (args->use_proxy)
+- conn->proxyip = g_strdup(args->proxyip);
+- conn->clientip = g_strdup(args->clientip);
+- conn->verifiedip = g_strdup(args->verifiedip);
+- conn->port = args->port;
+- conn->use_proxy |= args->use_proxy;
+- conn->lastrequestnumber++;
+-
+- if (args->type == OSCAR_CAPABILITY_DIRECTIM)
+- {
+- buf = g_strdup_printf(_("%s has just asked to directly connect to %s"),
+- bn, purple_account_get_username(account));
+-
+- purple_request_action(conn, NULL, buf,
+- _("This requires a direct connection between "
+- "the two computers and is necessary for IM "
+- "Images. Because your IP address will be "
+- "revealed, this may be considered a privacy "
+- "risk."),
+- PURPLE_DEFAULT_ACTION_NONE,
+- account, bn, NULL,
+- conn, 2,
+- _("C_onnect"), G_CALLBACK(peer_connection_got_proposition_yes_cb),
+- _("Cancel"), G_CALLBACK(peer_connection_got_proposition_no_cb));
+- }
+- else if (args->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- gchar *filename;
+-
+- conn->xfer = purple_xfer_new(account, PURPLE_XFER_RECEIVE, bn);
+- if (conn->xfer)
+- {
+- conn->xfer->data = conn;
+- purple_xfer_ref(conn->xfer);
+- purple_xfer_set_size(conn->xfer, args->info.sendfile.totsize);
+-
+- /* Set the file name */
+- if (g_utf8_validate(args->info.sendfile.filename, -1, NULL))
+- filename = g_strdup(args->info.sendfile.filename);
+- else
+- filename = purple_utf8_salvage(args->info.sendfile.filename);
+-
+- if (args->info.sendfile.subtype == AIM_OFT_SUBTYPE_SEND_DIR)
+- {
+- /*
+- * If they are sending us a directory then the last character
+- * of the file name will be an asterisk. We don't want to
+- * save stuff to a directory named "*" so we remove the
+- * asterisk from the file name.
+- */
+- char *tmp = strrchr(filename, '\\');
+- if ((tmp != NULL) && (tmp[1] == '*'))
+- tmp[0] = '\0';
+- }
+- purple_xfer_set_filename(conn->xfer, filename);
+- g_free(filename);
+-
+- /*
+- * Set the message, unless this is the dummy message from an
+- * ICQ client or an empty message from an AIM client.
+- * TODO: Maybe we should strip HTML and then see if strlen>0?
+- */
+- if ((message != NULL) &&
+- (g_ascii_strncasecmp(message, "<ICQ_COOL_FT>", 13) != 0) &&
+- (g_ascii_strcasecmp(message, "<HTML>") != 0))
+- {
+- purple_xfer_set_message(conn->xfer, message);
+- }
+-
+- /* Setup our I/O op functions */
+- purple_xfer_set_init_fnc(conn->xfer, peer_oft_recvcb_init);
+- purple_xfer_set_end_fnc(conn->xfer, peer_oft_recvcb_end);
+- purple_xfer_set_request_denied_fnc(conn->xfer, peer_oft_cb_generic_cancel);
+- purple_xfer_set_cancel_recv_fnc(conn->xfer, peer_oft_cb_generic_cancel);
+- purple_xfer_set_ack_fnc(conn->xfer, peer_oft_recvcb_ack_recv);
+-
+- /* Now perform the request */
+- purple_xfer_request(conn->xfer);
+- }
+- }
+-}
+-
+-/*******************************************************************/
+-/* End code for establishing a peer connection */
+-/*******************************************************************/
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/peer.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,282 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * OFT and ODC Services
+- */
+-
+-#ifndef _PEER_H_
+-#define _PEER_H_
+-
+-#include "ft.h"
+-#include "network.h"
+-#include "proxy.h"
+-
+-typedef struct _ChecksumData ChecksumData;
+-typedef struct _OdcFrame OdcFrame;
+-typedef struct _OftFrame OftFrame;
+-typedef struct _ProxyFrame ProxyFrame;
+-typedef struct _PeerConnection PeerConnection;
+-
+-#define PEER_CONNECTION_FLAG_INITIATED_BY_ME 0x0001
+-#define PEER_CONNECTION_FLAG_APPROVED 0x0002
+-#define PEER_CONNECTION_FLAG_TRIED_DIRECT 0x0004
+-#define PEER_CONNECTION_FLAG_TRIED_INCOMING 0x0008
+-#define PEER_CONNECTION_FLAG_TRIED_PROXY 0x0010
+-#define PEER_CONNECTION_FLAG_IS_INCOMING 0x0020
+-
+-#define PEER_TYPE_PROMPT 0x0101 /* "I am going to send you this file, is that ok?" */
+-#define PEER_TYPE_RESUMEACCEPT 0x0106 /* We are accepting the resume */
+-#define PEER_TYPE_ACK 0x0202 /* "Yes, it is ok for you to send me that file" */
+-#define PEER_TYPE_DONE 0x0204 /* "I received that file with no problems" or "I already have that file, great!" */
+-#define PEER_TYPE_RESUME 0x0205 /* Resume transferring, sent by whoever receives */
+-#define PEER_TYPE_RESUMEACK 0x0207 /* Our resume accept was ACKed */
+-
+-#define PEER_TYPE_GETFILE_REQUESTLISTING 0x1108 /* "I have a listing.txt file, do you want it?" */
+-#define PEER_TYPE_GETFILE_RECEIVELISTING 0x1209 /* "Yes, please send me your listing.txt file" */
+-#define PEER_TYPE_GETFILE_RECEIVEDLISTING 0x120a /* received corrupt listing.txt file? I'm just guessing about this one... */
+-#define PEER_TYPE_GETFILE_ACKLISTING 0x120b /* "I received the listing.txt file successfully" */
+-#define PEER_TYPE_GETFILE_REQUESTFILE 0x120c /* "Please send me this file" */
+-
+-/*
+- * For peer proxying
+- */
+-#define AIM_PEER_PROXY_SERVER "ars.oscar.aol.com"
+-#define ICQ_PEER_PROXY_SERVER "ars.icq.com"
+-#define PEER_PROXY_PORT 5190 /* The port we should always connect to */
+-#define PEER_PROXY_PACKET_VERSION 0x044a
+-
+-/* Thanks to Keith Lea and the Joust project for documenting these */
+-#define PEER_PROXY_TYPE_ERROR 0x0001
+-#define PEER_PROXY_TYPE_CREATE 0x0002
+-#define PEER_PROXY_TYPE_CREATED 0x0003
+-#define PEER_PROXY_TYPE_JOIN 0x0004
+-#define PEER_PROXY_TYPE_READY 0x0005
+-
+-struct _OdcFrame
+-{
+- /* guchar magic[4]; */ /* 0 */
+- /* guint16 length; */ /* 4 */
+- guint16 type; /* 6 */
+- guint16 subtype; /* 8 */
+- /* Unknown */ /* 10 */
+- guchar cookie[8]; /* 12 */
+- /* Unknown */
+- /* guint32 payloadlength; */ /* 28 */
+- guint16 encoding; /* 32 */
+- /* Unknown */
+- guint16 flags; /* 38 */
+- /* Unknown */
+- guchar bn[32]; /* 44 */
+- /* Unknown */
+- ByteStream payload; /* 76 */
+-};
+-
+-struct _OftFrame
+-{
+- /* guchar magic[4]; */ /* 0 */
+- /* guint16 length; */ /* 4 */
+- guint16 type; /* 6 */
+- guchar cookie[8]; /* 8 */
+- guint16 encrypt; /* 16 */
+- guint16 compress; /* 18 */
+- guint16 totfiles; /* 20 */
+- guint16 filesleft; /* 22 */
+- guint16 totparts; /* 24 */
+- guint16 partsleft; /* 26 */
+- guint32 totsize; /* 28 */
+- guint32 size; /* 32 */
+- guint32 modtime; /* 36 */
+- guint32 checksum; /* 40 */
+- guint32 rfrcsum; /* 44 */
+- guint32 rfsize; /* 48 */
+- guint32 cretime; /* 52 */
+- guint32 rfcsum; /* 56 */
+- guint32 nrecvd; /* 60 */
+- guint32 recvcsum; /* 64 */
+- guchar idstring[32]; /* 68 */
+- guint8 flags; /* 100 */
+- guint8 lnameoffset; /* 101 */
+- guint8 lsizeoffset; /* 102 */
+- guchar dummy[69]; /* 103 */
+- guchar macfileinfo[16]; /* 172 */
+- guint16 nencode; /* 188 */
+- guint16 nlanguage; /* 190 */
+- guchar *name; /* 192 */
+- size_t name_length;
+- /* Payload? */ /* 256 */
+-};
+-
+-struct _ProxyFrame
+-{
+- /* guint16 length; */ /* 0 */
+- guint16 version; /* 2 */
+- guint16 type; /* 4 */
+- guint32 unknown; /* 6 */
+- guint16 flags; /* 10 */
+- ByteStream payload; /* 12 */
+-};
+-
+-struct _PeerConnection
+-{
+- OscarData *od;
+- guint64 type;
+- char *bn;
+- guchar magic[4];
+- guchar cookie[8];
+- guint16 lastrequestnumber;
+-
+- gboolean ready;
+- int flags; /**< Bitmask of PEER_CONNECTION_FLAG_ */
+- time_t lastactivity; /**< Time of last transmit. */
+- guint destroy_timeout;
+- OscarDisconnectReason disconnect_reason;
+- char *error_message;
+-
+- /**
+- * A pointer to either an OdcFrame or an OftFrame.
+- */
+- gpointer frame;
+-
+- /**
+- * This is only used when the peer connection is being established.
+- */
+- PurpleProxyConnectData *client_connect_data;
+- PurpleProxyConnectData *verified_connect_data;
+-
+- /**
+- * This is only used when the peer connection is being established.
+- */
+- PurpleNetworkListenData *listen_data;
+-
+-
+- /**
+- * This is only used when the peer connection is being established.
+- */
+- guint connect_timeout_timer;
+-
+- /**
+- * This is only used while the remote user is attempting to
+- * connect to us.
+- */
+- int listenerfd;
+-
+- int fd;
+- guint8 header[6];
+- gssize header_received;
+- guint8 proxy_header[12];
+- gssize proxy_header_received;
+- ByteStream buffer_incoming;
+- PurpleCircBuffer *buffer_outgoing;
+- guint watcher_incoming;
+- guint watcher_outgoing;
+-
+- /**
+- * IP address of the proxy server, if applicable.
+- */
+- gchar *proxyip;
+-
+- /**
+- * IP address of the remote user from THEIR point of view.
+- */
+- gchar *clientip;
+-
+- /**
+- * IP address of the remote user from the oscar server's
+- * point of view.
+- */
+- gchar *verifiedip;
+-
+- guint16 port;
+- gboolean use_proxy;
+-
+- /**
+- * Checksumming
+- */
+- ChecksumData *checksum_data;
+-
+- /* TODOFT */
+- PurpleXfer *xfer;
+- OftFrame xferdata;
+- guint sending_data_timer;
+-};
+-
+-/*
+- * For all peer connections
+- */
+-
+-/**
+- * Create a new PeerConnection structure and initialize it with some
+- * sane defaults.
+- *
+- * @param type The type of the peer connection. One of
+- * OSCAR_CAPABILITY_DIRECTIM or OSCAR_CAPABILITY_SENDFILE.
+- */
+-PeerConnection *peer_connection_new(OscarData *od, guint64 type, const char *bn);
+-
+-void peer_connection_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
+-void peer_connection_schedule_destroy(PeerConnection *conn, OscarDisconnectReason reason, const gchar *error_message);
+-PeerConnection *peer_connection_find_by_type(OscarData *od, const char *bn, guint64 type);
+-PeerConnection *peer_connection_find_by_cookie(OscarData *od, const char *bn, const guchar *cookie);
+-
+-void peer_connection_listen_cb(gpointer data, gint source, PurpleInputCondition cond);
+-void peer_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond);
+-void peer_connection_send(PeerConnection *conn, ByteStream *bs);
+-
+-void peer_connection_trynext(PeerConnection *conn);
+-void peer_connection_finalize_connection(PeerConnection *conn);
+-void peer_connection_propose(OscarData *od, guint64 type, const char *bn);
+-void peer_connection_got_proposition(OscarData *od, const gchar *bn, const gchar *message, IcbmArgsCh2 *args);
+-
+-/*
+- * For ODC
+- */
+-void peer_odc_close(PeerConnection *conn);
+-void peer_odc_recv_frame(PeerConnection *conn, ByteStream *bs);
+-void peer_odc_send_cookie(PeerConnection *conn);
+-void peer_odc_send_typing(PeerConnection *conn, PurpleTypingState typing);
+-void peer_odc_send_im(PeerConnection *conn, const char *msg, int len, int encoding, gboolean autoreply);
+-
+-/*
+- * For OFT
+- */
+-void peer_oft_close(PeerConnection *conn);
+-void peer_oft_recv_frame(PeerConnection *conn, ByteStream *bs);
+-void peer_oft_send_prompt(PeerConnection *conn);
+-void peer_oft_checksum_destroy(ChecksumData *checksum_data);
+-
+-/* Xfer callbacks for receiving a file */
+-void peer_oft_recvcb_init(PurpleXfer *xfer);
+-void peer_oft_recvcb_end(PurpleXfer *xfer);
+-void peer_oft_recvcb_ack_recv(PurpleXfer *xfer, const guchar *buffer, size_t size);
+-
+-/* Xfer callbacks for sending a file */
+-void peer_oft_sendcb_init(PurpleXfer *xfer);
+-void peer_oft_sendcb_ack(PurpleXfer *xfer, const guchar *buffer, size_t size);
+-
+-/* Xfer callbacks for both sending and receiving */
+-void peer_oft_cb_generic_cancel(PurpleXfer *xfer);
+-
+-/*
+- * For peer proxying
+- */
+-void peer_proxy_connection_established_cb(gpointer data, gint source, const gchar *error_message);
+-
+-#endif /* _PEER_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/peer_proxy.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer_proxy.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/peer_proxy.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/peer_proxy.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,355 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#ifdef HAVE_CONFIG_H
+-#include <config.h>
+-#endif
+-
+-#include "oscar.h"
+-#include "peer.h"
+-
+-static void
+-peer_proxy_send(PeerConnection *conn, ProxyFrame *frame)
+-{
+- size_t length;
+- ByteStream bs;
+-
+- purple_debug_info("oscar", "Outgoing peer proxy frame with "
+- "type=0x%04hx, unknown=0x%08x, flags=0x%04hx, and "
+- "payload length=%" G_GSIZE_FORMAT "\n",
+- frame->type, frame->unknown,
+- frame->flags, frame->payload.len);
+-
+- length = 12 + frame->payload.len;
+- byte_stream_new(&bs, length);
+- byte_stream_put16(&bs, length - 2);
+- byte_stream_put16(&bs, PEER_PROXY_PACKET_VERSION);
+- byte_stream_put16(&bs, frame->type);
+- byte_stream_put32(&bs, frame->unknown);
+- byte_stream_put16(&bs, frame->flags);
+- byte_stream_putraw(&bs, frame->payload.data, frame->payload.len);
+-
+- peer_connection_send(conn, &bs);
+-
+- byte_stream_destroy(&bs);
+-}
+-
+-/**
+- * Create a rendezvous "init send" packet and send it on its merry way.
+- * This is the first packet sent to the proxy server by the first client
+- * to indicate that this will be a proxied connection
+- *
+- * @param conn The peer connection.
+- */
+-static void
+-peer_proxy_send_create_new_conn(PeerConnection *conn)
+-{
+- ProxyFrame frame;
+- PurpleAccount *account;
+- const gchar *bn;
+- guint8 bn_length;
+-
+- memset(&frame, 0, sizeof(ProxyFrame));
+- frame.type = PEER_PROXY_TYPE_CREATE;
+- frame.flags = 0x0000;
+-
+- account = purple_connection_get_account(conn->od->gc);
+- bn = purple_account_get_username(account);
+- bn_length = strlen(bn);
+- byte_stream_new(&frame.payload, 1 + bn_length + 8 + 20);
+- byte_stream_put8(&frame.payload, bn_length);
+- byte_stream_putraw(&frame.payload, (const guint8 *)bn, bn_length);
+- byte_stream_putraw(&frame.payload, conn->cookie, 8);
+-
+- byte_stream_put16(&frame.payload, 0x0001); /* Type */
+- byte_stream_put16(&frame.payload, 16); /* Length */
+- byte_stream_putcaps(&frame.payload, conn->type); /* Value */
+-
+- peer_proxy_send(conn, &frame);
+-
+- byte_stream_destroy(&frame.payload);
+-}
+-
+-/**
+- * Create a rendezvous "init recv" packet and send it on its merry way.
+- * This is the first packet sent to the proxy server by the second client
+- * involved in this rendezvous proxy session.
+- *
+- * @param conn The peer connection.
+- * @param pin The 2 byte PIN sent to us by the other user. This acts
+- * as our passcode when establishing the proxy session.
+- */
+-static void
+-peer_proxy_send_join_existing_conn(PeerConnection *conn, guint16 pin)
+-{
+- ProxyFrame frame;
+- PurpleAccount *account;
+- const gchar *bn;
+- guint8 bn_length;
+-
+- memset(&frame, 0, sizeof(ProxyFrame));
+- frame.type = PEER_PROXY_TYPE_JOIN;
+- frame.flags = 0x0000;
+-
+- account = purple_connection_get_account(conn->od->gc);
+- bn = purple_account_get_username(account);
+- bn_length = strlen(bn);
+- byte_stream_new(&frame.payload, 1 + bn_length + 2 + 8 + 20);
+- byte_stream_put8(&frame.payload, bn_length);
+- byte_stream_putraw(&frame.payload, (const guint8 *)bn, bn_length);
+- byte_stream_put16(&frame.payload, pin);
+- byte_stream_putraw(&frame.payload, conn->cookie, 8);
+-
+- byte_stream_put16(&frame.payload, 0x0001); /* Type */
+- byte_stream_put16(&frame.payload, 16); /* Length */
+- byte_stream_putcaps(&frame.payload, conn->type); /* Value */
+-
+- peer_proxy_send(conn, &frame);
+-
+- byte_stream_destroy(&frame.payload);
+-}
+-
+-/**
+- * Handle an incoming peer proxy negotiation frame.
+- */
+-static void
+-peer_proxy_recv_frame(PeerConnection *conn, ProxyFrame *frame)
+-{
+- purple_debug_info("oscar", "Incoming peer proxy frame with "
+- "type=0x%04hx, unknown=0x%08x, flags=0x%04hx, and "
+- "payload length=%" G_GSIZE_FORMAT "\n", frame->type,
+- frame->unknown, frame->flags, frame->payload.len);
+-
+- if (frame->type == PEER_PROXY_TYPE_CREATED)
+- {
+- /*
+- * Read in 2 byte port then 4 byte IP and tell the
+- * remote user to connect to it by sending an ICBM.
+- */
+- guint16 pin;
+- int i;
+- guint8 ip[4];
+-
+- pin = byte_stream_get16(&frame->payload);
+- for (i = 0; i < 4; i++)
+- ip[i] = byte_stream_get8(&frame->payload);
+- if (conn->type == OSCAR_CAPABILITY_DIRECTIM)
+- aim_im_sendch2_odc_requestproxy(conn->od,
+- conn->cookie,
+- conn->bn, ip, pin, ++conn->lastrequestnumber);
+- else if (conn->type == OSCAR_CAPABILITY_SENDFILE)
+- {
+- aim_im_sendch2_sendfile_requestproxy(conn->od,
+- conn->cookie, conn->bn,
+- ip, pin, ++conn->lastrequestnumber,
+- (const gchar *)conn->xferdata.name,
+- conn->xferdata.size, conn->xferdata.totfiles);
+- }
+- }
+- else if (frame->type == PEER_PROXY_TYPE_READY)
+- {
+- purple_input_remove(conn->watcher_incoming);
+- conn->watcher_incoming = 0;
+-
+- peer_connection_finalize_connection(conn);
+- }
+- else if (frame->type == PEER_PROXY_TYPE_ERROR)
+- {
+- if (byte_stream_bytes_left(&frame->payload) >= 2)
+- {
+- guint16 error;
+- const char *msg;
+- error = byte_stream_get16(&frame->payload);
+- if (error == 0x000d)
+- msg = "bad request";
+- else if (error == 0x0010)
+- msg = "initial request timed out";
+- else if (error == 0x001a)
+- msg ="accept period timed out";
+- else
+- msg = "unknown reason";
+- purple_debug_info("oscar", "Proxy negotiation failed with "
+- "error 0x%04hx: %s\n", error, msg);
+- }
+- else
+- {
+- purple_debug_warning("oscar", "Proxy negotiation failed with "
+- "an unknown error\n");
+- }
+- peer_connection_trynext(conn);
+- }
+- else
+- {
+- purple_debug_warning("oscar", "Unknown peer proxy frame type 0x%04hx.\n",
+- frame->type);
+- }
+-}
+-
+-static void
+-peer_proxy_connection_recv_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PeerConnection *conn;
+- gssize read;
+- ProxyFrame *frame;
+-
+- conn = data;
+- frame = conn->frame;
+-
+- /* Start reading a new proxy frame */
+- if (frame == NULL)
+- {
+- /* Read the first 12 bytes (frame length and header) */
+- read = recv(conn->fd, conn->proxy_header + conn->proxy_header_received,
+- 12 - conn->proxy_header_received, 0);
+-
+- /* Check if the proxy server closed the connection */
+- if (read == 0)
+- {
+- purple_debug_info("oscar", "Peer proxy server closed connection\n");
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- /* If there was an error then close the connection */
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- purple_debug_info("oscar", "Lost connection with peer proxy server\n");
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- conn->lastactivity = time(NULL);
+-
+- /* If we don't even have the first 12 bytes then do nothing */
+- conn->proxy_header_received += read;
+- if (conn->proxy_header_received < 12)
+- return;
+-
+- /* We only support a specific version of the proxy protocol */
+- if (aimutil_get16(&conn->proxy_header[2]) != PEER_PROXY_PACKET_VERSION)
+- {
+- purple_debug_warning("oscar", "Expected peer proxy protocol "
+- "version %u but received version %u. Closing "
+- "connection.\n", PEER_PROXY_PACKET_VERSION,
+- aimutil_get16(&conn->proxy_header[2]));
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- /* Initialize a new temporary ProxyFrame for incoming data */
+- frame = g_new0(ProxyFrame, 1);
+- frame->payload.len = aimutil_get16(&conn->proxy_header[0]) - 10;
+- frame->version = aimutil_get16(&conn->proxy_header[2]);
+- frame->type = aimutil_get16(&conn->proxy_header[4]);
+- frame->unknown = aimutil_get16(&conn->proxy_header[6]);
+- frame->flags = aimutil_get16(&conn->proxy_header[10]);
+- if (frame->payload.len > 0)
+- frame->payload.data = g_new(guint8, frame->payload.len);
+- conn->frame = frame;
+- }
+-
+- /* If this frame has a payload then attempt to read it */
+- if (frame->payload.len - frame->payload.offset > 0)
+- {
+- /* Read data into the temporary buffer until it is complete */
+- read = recv(conn->fd,
+- &frame->payload.data[frame->payload.offset],
+- frame->payload.len - frame->payload.offset,
+- 0);
+-
+- /* Check if the proxy server closed the connection */
+- if (read == 0)
+- {
+- purple_debug_info("oscar", "Peer proxy server closed connection\n");
+- g_free(frame->payload.data);
+- g_free(frame);
+- conn->frame = NULL;
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- /* If there was an error then close the connection */
+- if (read < 0)
+- {
+- if ((errno == EAGAIN) || (errno == EWOULDBLOCK))
+- /* No worries */
+- return;
+-
+- purple_debug_info("oscar", "Lost connection with peer proxy server\n");
+- g_free(frame->payload.data);
+- g_free(frame);
+- conn->frame = NULL;
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- frame->payload.offset += read;
+- }
+-
+- conn->lastactivity = time(NULL);
+- if (frame->payload.offset < frame->payload.len)
+- /* Waiting for more data to arrive */
+- return;
+-
+- /* We have a complete proxy frame! Handle it and continue reading */
+- conn->frame = NULL;
+- byte_stream_rewind(&frame->payload);
+- peer_proxy_recv_frame(conn, frame);
+-
+- g_free(frame->payload.data);
+- g_free(frame);
+-
+- conn->proxy_header_received = 0;
+-}
+-
+-/**
+- * We tried to make an outgoing connection to a proxy server. It
+- * either connected or failed to connect.
+- */
+-void
+-peer_proxy_connection_established_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- PeerConnection *conn;
+-
+- conn = data;
+-
+- conn->verified_connect_data = NULL;
+-
+- if (source < 0)
+- {
+- peer_connection_trynext(conn);
+- return;
+- }
+-
+- conn->fd = source;
+- conn->watcher_incoming = purple_input_add(conn->fd,
+- PURPLE_INPUT_READ, peer_proxy_connection_recv_cb, conn);
+-
+- if (conn->proxyip != NULL)
+- /* Connect to the session created by the remote user */
+- peer_proxy_send_join_existing_conn(conn, conn->port);
+- else
+- /* Create a new session */
+- peer_proxy_send_create_new_conn(conn);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/rxhandlers.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/rxhandlers.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/rxhandlers.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/rxhandlers.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,95 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "oscar.h"
+-#include "peer.h"
+-
+-aim_module_t *aim__findmodulebygroup(OscarData *od, guint16 group)
+-{
+- aim_module_t *cur;
+-
+- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
+- if (cur->family == group)
+- return cur;
+- }
+-
+- return NULL;
+-}
+-
+-aim_module_t *aim__findmodule(OscarData *od, const char *name)
+-{
+- aim_module_t *cur;
+-
+- for (cur = (aim_module_t *)od->modlistv; cur; cur = cur->next) {
+- if (strcmp(name, cur->name) == 0)
+- return cur;
+- }
+-
+- return NULL;
+-}
+-
+-int aim__registermodule(OscarData *od, int (*modfirst)(OscarData *, aim_module_t *))
+-{
+- aim_module_t *mod;
+-
+- if (!od || !modfirst)
+- return -1;
+-
+- mod = g_new0(aim_module_t, 1);
+-
+- if (modfirst(od, mod) == -1) {
+- g_free(mod);
+- return -1;
+- }
+-
+- if (aim__findmodule(od, mod->name)) {
+- if (mod->shutdown)
+- mod->shutdown(od, mod);
+- g_free(mod);
+- return -1;
+- }
+-
+- mod->next = (aim_module_t *)od->modlistv;
+- od->modlistv = mod;
+-
+- return 0;
+-}
+-
+-void aim__shutdownmodules(OscarData *od)
+-{
+- aim_module_t *cur;
+-
+- for (cur = (aim_module_t *)od->modlistv; cur; ) {
+- aim_module_t *tmp;
+-
+- tmp = cur->next;
+-
+- if (cur->shutdown)
+- cur->shutdown(od, cur);
+-
+- g_free(cur);
+-
+- cur = tmp;
+- }
+-
+- od->modlistv = NULL;
+-
+- return;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/snac.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snac.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/snac.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snac.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,163 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- *
+- * Various SNAC-related dodads...
+- *
+- * outstanding_snacs is a list of aim_snac_t structs. A SNAC should be added
+- * whenever a new SNAC is sent and it should remain in the list until the
+- * response for it has been received.
+- *
+- * cleansnacs() should be called periodically by the client in order
+- * to facilitate the aging out of unreplied-to SNACs. This can and does
+- * happen, so it should be handled.
+- *
+- */
+-
+-#include "oscar.h"
+-
+-/*
+- * Called from oscar_session_new() to initialize the hash.
+- */
+-void aim_initsnachash(OscarData *od)
+-{
+- int i;
+-
+- for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++)
+- od->snac_hash[i] = NULL;
+-
+- return;
+-}
+-
+-aim_snacid_t aim_cachesnac(OscarData *od, const guint16 family, const guint16 type, const guint16 flags, const void *data, const int datalen)
+-{
+- aim_snac_t snac;
+-
+- snac.id = od->snacid_next++;
+- snac.family = family;
+- snac.type = type;
+- snac.flags = flags;
+-
+- if (datalen)
+- snac.data = g_memdup(data, datalen);
+- else
+- snac.data = NULL;
+-
+- return aim_newsnac(od, &snac);
+-}
+-
+-/*
+- * Clones the passed snac structure and caches it in the
+- * list/hash.
+- */
+-aim_snacid_t aim_newsnac(OscarData *od, aim_snac_t *newsnac)
+-{
+- aim_snac_t *snac;
+- int index;
+-
+- if (!newsnac)
+- return 0;
+-
+- snac = g_memdup(newsnac, sizeof(aim_snac_t));
+- snac->issuetime = time(NULL);
+-
+- index = snac->id % FAIM_SNAC_HASH_SIZE;
+-
+- snac->next = (aim_snac_t *)od->snac_hash[index];
+- od->snac_hash[index] = (void *)snac;
+-
+- return snac->id;
+-}
+-
+-/*
+- * Finds a snac structure with the passed SNAC ID,
+- * removes it from the list/hash, and returns a pointer to it.
+- *
+- * The returned structure must be freed by the caller.
+- *
+- */
+-aim_snac_t *aim_remsnac(OscarData *od, aim_snacid_t id)
+-{
+- aim_snac_t *cur, **prev;
+- int index;
+-
+- index = id % FAIM_SNAC_HASH_SIZE;
+-
+- for (prev = (aim_snac_t **)&od->snac_hash[index]; (cur = *prev); ) {
+- if (cur->id == id) {
+- *prev = cur->next;
+- if (cur->flags & AIM_SNACFLAGS_DESTRUCTOR) {
+- g_free(cur->data);
+- cur->data = NULL;
+- }
+- return cur;
+- } else
+- prev = &cur->next;
+- }
+-
+- return cur;
+-}
+-
+-/*
+- * This is for cleaning up old SNACs that either don't get replies or
+- * a reply was never received for. Garbage collection. Plain and simple.
+- *
+- * maxage is the _minimum_ age in seconds to keep SNACs.
+- *
+- */
+-void aim_cleansnacs(OscarData *od, int maxage)
+-{
+- int i;
+-
+- for (i = 0; i < FAIM_SNAC_HASH_SIZE; i++) {
+- aim_snac_t *cur, **prev;
+- time_t curtime;
+-
+- if (!od->snac_hash[i])
+- continue;
+-
+- curtime = time(NULL); /* done here in case we waited for the lock */
+-
+- for (prev = (aim_snac_t **)&od->snac_hash[i]; (cur = *prev); ) {
+- if ((curtime - cur->issuetime) > maxage) {
+-
+- *prev = cur->next;
+-
+- g_free(cur->data);
+- g_free(cur);
+- } else
+- prev = &cur->next;
+- }
+- }
+-
+- return;
+-}
+-
+-int aim_putsnac(ByteStream *bs, guint16 family, guint16 subtype, aim_snacid_t snacid)
+-{
+-
+- byte_stream_put16(bs, family);
+- byte_stream_put16(bs, subtype);
+- byte_stream_put16(bs, 0x0000);
+- byte_stream_put32(bs, snacid);
+-
+- return 10;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/snactypes.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snactypes.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/snactypes.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/snactypes.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,287 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * AIM Callback Types
+- *
+- */
+-#ifndef _SNACTYPES_H_
+-#define _SNACTYPES_H_
+-
+-/*
+- * SNAC Families.
+- */
+-#define SNAC_FAMILY_OSERVICE 0x0001
+-#define SNAC_FAMILY_LOCATE 0x0002
+-#define SNAC_FAMILY_BUDDY 0x0003
+-#define SNAC_FAMILY_ICBM 0x0004
+-#define SNAC_FAMILY_ADVERT 0x0005
+-#define SNAC_FAMILY_INVITE 0x0006
+-#define SNAC_FAMILY_ADMIN 0x0007
+-#define SNAC_FAMILY_POPUP 0x0008
+-#define SNAC_FAMILY_BOS 0x0009
+-#define SNAC_FAMILY_USERLOOKUP 0x000a
+-#define SNAC_FAMILY_STATS 0x000b
+-#define SNAC_FAMILY_TRANSLATE 0x000c
+-#define SNAC_FAMILY_CHATNAV 0x000d
+-#define SNAC_FAMILY_CHAT 0x000e
+-#define SNAC_FAMILY_ODIR 0x000f
+-#define SNAC_FAMILY_BART 0x0010
+-#define SNAC_FAMILY_FEEDBAG 0x0013
+-#define SNAC_FAMILY_ICQ 0x0015
+-#define SNAC_FAMILY_AUTH 0x0017
+-#define SNAC_FAMILY_ALERT 0x0018
+-
+-#define AIM_CB_FAM_SPECIAL 0xffff /* Internal libfaim use */
+-
+-/*
+- * SNAC Family: Ack.
+- *
+- * Not really a family, but treating it as one really
+- * helps it fit into the libfaim callback structure better.
+- *
+- */
+-#define AIM_CB_ACK_ACK 0x0001
+-
+-/*
+- * SNAC Family: General.
+- */
+-#define SNAC_SUBTYPE_OSERVICE_ERROR 0x0001
+-#define SNAC_SUBTYPE_OSERVICE_CLIENTREADY 0x0002
+-#define SNAC_SUBTYPE_OSERVICE_SERVERREADY 0x0003
+-#define SNAC_SUBTYPE_OSERVICE_SERVICEREQ 0x0004
+-#define SNAC_SUBTYPE_OSERVICE_REDIRECT 0x0005
+-#define SNAC_SUBTYPE_OSERVICE_RATEINFOREQ 0x0006
+-#define SNAC_SUBTYPE_OSERVICE_RATEINFO 0x0007
+-#define SNAC_SUBTYPE_OSERVICE_RATEINFOACK 0x0008
+-#define SNAC_SUBTYPE_OSERVICE_RATECHANGE 0x000a
+-#define SNAC_SUBTYPE_OSERVICE_SERVERPAUSE 0x000b
+-#define SNAC_SUBTYPE_OSERVICE_SERVERRESUME 0x000d
+-#define SNAC_SUBTYPE_OSERVICE_REQSELFINFO 0x000e
+-#define SNAC_SUBTYPE_OSERVICE_SELFINFO 0x000f
+-#define SNAC_SUBTYPE_OSERVICE_EVIL 0x0010
+-#define SNAC_SUBTYPE_OSERVICE_SETIDLE 0x0011
+-#define SNAC_SUBTYPE_OSERVICE_MIGRATIONREQ 0x0012
+-#define SNAC_SUBTYPE_OSERVICE_MOTD 0x0013
+-#define SNAC_SUBTYPE_OSERVICE_SETPRIVFLAGS 0x0014
+-#define SNAC_SUBTYPE_OSERVICE_WELLKNOWNURL 0x0015
+-#define SNAC_SUBTYPE_OSERVICE_NOP 0x0016
+-#define SNAC_SUBTYPE_OSERVICE_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Location Services.
+- */
+-#define SNAC_SUBTYPE_LOCATE_ERROR 0x0001
+-#define SNAC_SUBTYPE_LOCATE_REQRIGHTS 0x0002
+-#define SNAC_SUBTYPE_LOCATE_RIGHTSINFO 0x0003
+-#define SNAC_SUBTYPE_LOCATE_SETUSERINFO 0x0004
+-#define SNAC_SUBTYPE_LOCATE_REQUSERINFO 0x0005
+-#define SNAC_SUBTYPE_LOCATE_USERINFO 0x0006
+-#define SNAC_SUBTYPE_LOCATE_WATCHERSUBREQ 0x0007
+-#define SNAC_SUBTYPE_LOCATE_WATCHERNOT 0x0008
+-#define SNAC_SUBTYPE_LOCATE_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Buddy List Management Services.
+- */
+-#define SNAC_SUBTYPE_BUDDY_ERROR 0x0001
+-#define SNAC_SUBTYPE_BUDDY_REQRIGHTS 0x0002
+-#define SNAC_SUBTYPE_BUDDY_RIGHTSINFO 0x0003
+-#define SNAC_SUBTYPE_BUDDY_ADDBUDDY 0x0004
+-#define SNAC_SUBTYPE_BUDDY_REMBUDDY 0x0005
+-#define SNAC_SUBTYPE_BUDDY_REJECT 0x000a
+-#define SNAC_SUBTYPE_BUDDY_ONCOMING 0x000b
+-#define SNAC_SUBTYPE_BUDDY_OFFGOING 0x000c
+-#define SNAC_SUBTYPE_BUDDY_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Messaging Services.
+- */
+-#define SNAC_SUBTYPE_ICBM_ERROR 0x0001
+-#define SNAC_SUBTYPE_ICBM_PARAMINFO 0x0005
+-#define SNAC_SUBTYPE_ICBM_INCOMING 0x0007
+-#define SNAC_SUBTYPE_ICBM_EVIL 0x0009
+-#define SNAC_SUBTYPE_ICBM_MISSEDCALL 0x000a
+-#define SNAC_SUBTYPE_ICBM_CLIENTAUTORESP 0x000b
+-#define SNAC_SUBTYPE_ICBM_ACK 0x000c
+-#define SNAC_SUBTYPE_ICBM_MTN 0x0014
+-#define SNAC_SUBTYPE_ICBM_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Advertisement Services
+- */
+-#define SNAC_SUBTYPE_ADVERT_ERROR 0x0001
+-#define SNAC_SUBTYPE_ADVERT_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Invitation Services.
+- */
+-#define SNAC_SUBTYPE_INVITE_ERROR 0x0001
+-#define SNAC_SUBTYPE_INVITE_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Administrative Services.
+- */
+-#define SNAC_SUBTYPE_ADMIN_ERROR 0x0001
+-#define SNAC_SUBTYPE_ADMIN_INFOCHANGE_REPLY 0x0005
+-#define SNAC_SUBTYPE_ADMIN_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Popup Messages
+- */
+-#define SNAC_SUBTYPE_POPUP_ERROR 0x0001
+-#define SNAC_SUBTYPE_POPUP_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Misc BOS Services.
+- */
+-#define SNAC_SUBTYPE_BOS_ERROR 0x0001
+-#define SNAC_SUBTYPE_BOS_RIGHTSQUERY 0x0002
+-#define SNAC_SUBTYPE_BOS_RIGHTS 0x0003
+-#define SNAC_SUBTYPE_BOS_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: User Lookup Services
+- */
+-#define SNAC_SUBTYPE_USERLOOKUP_ERROR 0x0001
+-#define SNAC_SUBTYPE_USERLOOKUP_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: User Status Services
+- */
+-#define SNAC_SUBTYPE_STATS_ERROR 0x0001
+-#define SNAC_SUBTYPE_STATS_SETREPORTINTERVAL 0x0002
+-#define SNAC_SUBTYPE_STATS_REPORTACK 0x0004
+-#define SNAC_SUBTYPE_STATS_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Translation Services
+- */
+-#define SNAC_SUBTYPE_TRANSLATE_ERROR 0x0001
+-#define SNAC_SUBTYPE_TRANSLATE_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Chat Navigation Services
+- */
+-#define SNAC_SUBTYPE_CHATNAV_ERROR 0x0001
+-#define SNAC_SUBTYPE_CHATNAV_CREATE 0x0008
+-#define SNAC_SUBTYPE_CHATNAV_INFO 0x0009
+-#define SNAC_SUBTYPE_CHATNAV_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Chat Services
+- */
+-#define SNAC_SUBTYPE_CHAT_ERROR 0x0001
+-#define SNAC_SUBTYPE_CHAT_ROOMINFOUPDATE 0x0002
+-#define SNAC_SUBTYPE_CHAT_USERJOIN 0x0003
+-#define SNAC_SUBTYPE_CHAT_USERLEAVE 0x0004
+-#define SNAC_SUBTYPE_CHAT_OUTGOINGMSG 0x0005
+-#define SNAC_SUBTYPE_CHAT_INCOMINGMSG 0x0006
+-#define SNAC_SUBTYPE_CHAT_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: "New" Search
+- */
+-#define SNAC_SUBTYPE_ODIR_ERROR 0x0001
+-#define SNAC_SUBTYPE_ODIR_SEARCH 0x0002
+-#define SNAC_SUBTYPE_ODIR_RESULTS 0x0003
+-
+-/*
+- * SNAC Family: Buddy icons
+- */
+-#define SNAC_SUBTYPE_BART_ERROR 0x0001
+-#define SNAC_SUBTYPE_BART_REQUEST 0x0004
+-#define SNAC_SUBTYPE_BART_RESPONSE 0x0005
+-
+-/*
+- * SNAC Family: Server-Stored Buddy Lists
+- */
+-#define SNAC_SUBTYPE_FEEDBAG_ERROR 0x0001
+-#define SNAC_SUBTYPE_FEEDBAG_REQRIGHTS 0x0002
+-#define SNAC_SUBTYPE_FEEDBAG_RIGHTSINFO 0x0003
+-#define SNAC_SUBTYPE_FEEDBAG_REQDATA 0x0004
+-#define SNAC_SUBTYPE_FEEDBAG_REQIFCHANGED 0x0005
+-#define SNAC_SUBTYPE_FEEDBAG_LIST 0x0006
+-#define SNAC_SUBTYPE_FEEDBAG_ACTIVATE 0x0007
+-#define SNAC_SUBTYPE_FEEDBAG_ADD 0x0008
+-#define SNAC_SUBTYPE_FEEDBAG_MOD 0x0009
+-#define SNAC_SUBTYPE_FEEDBAG_DEL 0x000A
+-#define SNAC_SUBTYPE_FEEDBAG_SRVACK 0x000E
+-#define SNAC_SUBTYPE_FEEDBAG_NOLIST 0x000F
+-#define SNAC_SUBTYPE_FEEDBAG_EDITSTART 0x0011
+-#define SNAC_SUBTYPE_FEEDBAG_EDITSTOP 0x0012
+-#define SNAC_SUBTYPE_FEEDBAG_SENDAUTH 0x0014
+-#define SNAC_SUBTYPE_FEEDBAG_RECVAUTH 0x0015
+-#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREQ 0x0018
+-#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREQ 0x0019
+-#define SNAC_SUBTYPE_FEEDBAG_SENDAUTHREP 0x001a
+-#define SNAC_SUBTYPE_FEEDBAG_RECVAUTHREP 0x001b
+-#define SNAC_SUBTYPE_FEEDBAG_ADDED 0x001c
+-
+-/*
+- * SNAC Family: ICQ
+- *
+- * Most of these are actually special.
+- */
+-#define SNAC_SUBTYPE_ICQ_ERROR 0x0001
+-#define SNAC_SUBTYPE_ICQ_OFFLINEMSG 0x00f0
+-#define SNAC_SUBTYPE_ICQ_OFFLINEMSGCOMPLETE 0x00f1
+-#define SNAC_SUBTYPE_ICQ_INFO 0x00f2
+-#define SNAC_SUBTYPE_ICQ_ALIAS 0x00f3
+-#define SNAC_SUBTYPE_ICQ_DEFAULT 0xffff
+-
+-/*
+- * SNAC Family: Authorizer
+- *
+- * Used only in protocol versions three and above.
+- */
+-#define SNAC_SUBTYPE_AUTH_ERROR 0x0001
+-#define SNAC_SUBTYPE_AUTH_LOGINREQEST 0x0002
+-#define SNAC_SUBTYPE_AUTH_LOGINRESPONSE 0x0003
+-#define SNAC_SUBTYPE_AUTH_AUTHREQ 0x0006
+-#define SNAC_SUBTYPE_AUTH_AUTHRESPONSE 0x0007
+-#define SNAC_SUBTYPE_AUTH_SECURID_REQUEST 0x000a
+-#define SNAC_SUBTYPE_AUTH_SECURID_RESPONSE 0x000b
+-
+-/*
+- * SNAC Family: Email
+- *
+- * Used for getting information on the email address
+- * associated with your username.
+- */
+-#define SNAC_SUBTYPE_ALERT_ERROR 0x0001
+-#define SNAC_SUBTYPE_ALERT_SENDCOOKIES 0x0006
+-#define SNAC_SUBTYPE_ALERT_MAILSTATUS 0x0007
+-#define SNAC_SUBTYPE_ALERT_INIT 0x0016
+-
+-/*
+- * SNAC Family: Internal Messages
+- *
+- * This isn't truly a SNAC family either, but using
+- * these, we can integrated non-SNAC services into
+- * the SNAC-centered libfaim callback structure.
+- */
+-#define AIM_CB_SPECIAL_CONNERR 0x0003
+-#define AIM_CB_SPECIAL_CONNINITDONE 0x0006
+-
+-/* SNAC flags */
+-#define AIM_SNACFLAGS_DESTRUCTOR 0x0001
+-
+-#endif /* _SNACTYPES_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/tlv.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/tlv.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/tlv.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/tlv.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,828 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "oscar.h"
+-
+-static aim_tlv_t *
+-createtlv(guint16 type, guint16 length, guint8 *value)
+-{
+- aim_tlv_t *ret;
+-
+- ret = g_new(aim_tlv_t, 1);
+- ret->type = type;
+- ret->length = length;
+- ret->value = value;
+-
+- return ret;
+-}
+-
+-static void
+-freetlv(aim_tlv_t *oldtlv)
+-{
+- g_free(oldtlv->value);
+- g_free(oldtlv);
+-}
+-
+-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);
+-
+- if (length > byte_stream_bytes_left(bs)) {
+- aim_tlvlist_free(list);
+- return NULL;
+- }
+-
+- 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);
+-}
+-
+-/**
+- * Read a TLV chain from a buffer.
+- *
+- * Reads and parses a series of TLV patterns from a data buffer; the
+- * returned structure is manipulatable with the rest of the TLV
+- * routines. When done with a TLV chain, aim_tlvlist_free() should
+- * be called to free the dynamic substructures.
+- *
+- * 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
+- * in libfaim.
+- *
+- * @param bs Input bstream
+- * @return Return the TLV chain read
+- */
+-GSList *aim_tlvlist_read(ByteStream *bs)
+-{
+- GSList *list = NULL;
+-
+- while (byte_stream_bytes_left(bs) > 0) {
+- list = aim_tlv_read(list, bs);
+- if (list == NULL)
+- return NULL;
+- }
+-
+- return g_slist_reverse(list);
+-}
+-
+-/**
+- * Read a TLV chain from a buffer.
+- *
+- * Reads and parses a series of TLV patterns from a data buffer; the
+- * returned structure is manipulatable with the rest of the TLV
+- * routines. When done with a TLV chain, aim_tlvlist_free() should
+- * be called to free the dynamic substructures.
+- *
+- * 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
+- * in libfaim.
+- *
+- * @param bs Input bstream
+- * @param num The max number of TLVs that will be read, or -1 if unlimited.
+- * There are a number of places where you want to read in a tlvchain,
+- * but the chain is not at the end of the SNAC, and the chain is
+- * preceded by the number of TLVs. So you can limit that with this.
+- * @return Return the TLV chain read
+- */
+-GSList *aim_tlvlist_readnum(ByteStream *bs, guint16 num)
+-{
+- GSList *list = NULL;
+-
+- while ((byte_stream_bytes_left(bs) > 0) && (num != 0)) {
+- list = aim_tlv_read(list, bs);
+- if (list == NULL)
+- return NULL;
+- num--;
+- }
+-
+- return g_slist_reverse(list);
+-}
+-
+-/**
+- * Read a TLV chain from a buffer.
+- *
+- * Reads and parses a series of TLV patterns from a data buffer; the
+- * returned structure is manipulatable with the rest of the TLV
+- * routines. When done with a TLV chain, aim_tlvlist_free() should
+- * be called to free the dynamic substructures.
+- *
+- * 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
+- * in libfaim.
+- *
+- * @param bs Input bstream
+- * @param len The max length in bytes that will be read.
+- * There are a number of places where you want to read in a tlvchain,
+- * but the chain is not at the end of the SNAC, and the chain is
+- * preceded by the length of the TLVs. So you can limit that with this.
+- * @return Return the TLV chain read
+- */
+-GSList *aim_tlvlist_readlen(ByteStream *bs, guint16 len)
+-{
+- GSList *list = NULL;
+-
+- while ((byte_stream_bytes_left(bs) > 0) && (len > 0)) {
+- list = aim_tlv_read(list, bs);
+- if (list == NULL)
+- return NULL;
+-
+- len -= 2 + 2 + ((aim_tlv_t *)list->data)->length;
+- }
+-
+- return g_slist_reverse(list);
+-}
+-
+-/**
+- * Duplicate a TLV chain.
+- * This is pretty self explanatory.
+- *
+- * @param orig The TLV chain you want to make a copy of.
+- * @return A newly allocated TLV chain.
+- */
+-GSList *aim_tlvlist_copy(GSList *orig)
+-{
+- GSList *new = NULL;
+- aim_tlv_t *tlv;
+-
+- while (orig != NULL) {
+- tlv = orig->data;
+- aim_tlvlist_add_raw(&new, tlv->type, tlv->length, tlv->value);
+- orig = orig->next;
+- }
+-
+- return new;
+-}
+-
+-/*
+- * Compare two TLV lists for equality. This probably is not the most
+- * efficient way to do this.
+- *
+- * @param one One of the TLV chains to compare.
+- * @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(GSList *one, GSList *two)
+-{
+- ByteStream bs1, bs2;
+-
+- 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));
+-
+- aim_tlvlist_write(&bs1, &one);
+- aim_tlvlist_write(&bs2, &two);
+-
+- if (memcmp(bs1.data, bs2.data, bs1.len)) {
+- byte_stream_destroy(&bs1);
+- byte_stream_destroy(&bs2);
+- return 1;
+- }
+-
+- byte_stream_destroy(&bs1);
+- byte_stream_destroy(&bs2);
+-
+- return 0;
+-}
+-
+-/**
+- * Free a TLV chain structure
+- *
+- * Walks the list of TLVs in the passed TLV chain and
+- * frees each one. Note that any references to this data
+- * should be removed before calling this.
+- *
+- * @param list Chain to be freed
+- */
+-void aim_tlvlist_free(GSList *list)
+-{
+- while (list != NULL)
+- {
+- freetlv(list->data);
+- list = g_slist_delete_link(list, list);
+- }
+-}
+-
+-/**
+- * Count the number of TLVs in a chain.
+- *
+- * @param list Chain to be counted.
+- * @return The number of TLVs stored in the passed chain.
+- */
+-int aim_tlvlist_count(GSList *list)
+-{
+- GSList *cur;
+- int count;
+-
+- if (list == NULL)
+- return 0;
+-
+- for (cur = list, count = 0; cur; cur = cur->next)
+- count++;
+-
+- return count;
+-}
+-
+-/**
+- * Count the number of bytes in a TLV chain.
+- *
+- * @param list Chain to be sized
+- * @return The number of bytes that would be needed to
+- * write the passed TLV chain to a data buffer.
+- */
+-int aim_tlvlist_size(GSList *list)
+-{
+- GSList *cur;
+- int size;
+-
+- if (list == NULL)
+- return 0;
+-
+- for (cur = list, size = 0; cur; cur = cur->next)
+- size += (4 + ((aim_tlv_t *)cur->data)->length);
+-
+- return size;
+-}
+-
+-/**
+- * Adds the passed string as a TLV element of the passed type
+- * to the TLV chain.
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @param length Length of string to add (not including %NULL).
+- * @param value String to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
+-{
+- aim_tlv_t *tlv;
+-
+- if (list == NULL)
+- return 0;
+-
+- tlv = createtlv(type, length, NULL);
+- if (tlv->length > 0)
+- tlv->value = g_memdup(value, length);
+-
+- *list = g_slist_append(*list, tlv);
+-
+- return tlv->length;
+-}
+-
+-/**
+- * Add a one byte integer to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param value Value to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_8(GSList **list, const guint16 type, const guint8 value)
+-{
+- guint8 v8[1];
+-
+- aimutil_put8(v8, value);
+-
+- return aim_tlvlist_add_raw(list, type, 1, v8);
+-}
+-
+-/**
+- * Add a two byte integer to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param value Value to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_16(GSList **list, const guint16 type, const guint16 value)
+-{
+- guint8 v16[2];
+-
+- aimutil_put16(v16, value);
+-
+- return aim_tlvlist_add_raw(list, type, 2, v16);
+-}
+-
+-/**
+- * Add a four byte integer to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param value Value to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_32(GSList **list, const guint16 type, const guint32 value)
+-{
+- guint8 v32[4];
+-
+- aimutil_put32(v32, value);
+-
+- return aim_tlvlist_add_raw(list, type, 4, v32);
+-}
+-
+-/**
+- * Add a string to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param value Value to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_str(GSList **list, const guint16 type, const char *value)
+-{
+- return aim_tlvlist_add_raw(list, type, strlen(value), (guint8 *)value);
+-}
+-
+-static int
+-count_caps(guint64 caps)
+-{
+- int set_bits = 0;
+- while (caps) {
+- set_bits += caps & 1;
+- caps >>= 1;
+- }
+- return set_bits;
+-}
+-
+-/**
+- * Adds a block of capability blocks to a TLV chain. The bitfield
+- * passed in should be a bitwise %OR of any of the %AIM_CAPS constants:
+- *
+- * %OSCAR_CAPABILITY_BUDDYICON Supports Buddy Icons
+- * %OSCAR_CAPABILITY_TALK Supports Voice Chat
+- * %OSCAR_CAPABILITY_IMIMAGE Supports DirectIM/IMImage
+- * %OSCAR_CAPABILITY_CHAT Supports Chat
+- * %OSCAR_CAPABILITY_GETFILE Supports Get File functions
+- * %OSCAR_CAPABILITY_SENDFILE Supports Send File functions
+- *
+- * @param list Destination chain
+- * @param type TLV type to add
+- * @param caps Bitfield of capability flags to send
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_caps(GSList **list, const guint16 type, const guint64 caps, const char *mood)
+-{
+- int len;
+- ByteStream bs;
+- guint32 bs_size;
+- guint8 *data;
+-
+- if (caps == 0)
+- return 0; /* nothing there anyway */
+-
+- data = icq_get_custom_icon_data(mood);
+- bs_size = 16*(count_caps(caps) + (data != NULL ? 1 : 0));
+-
+- byte_stream_new(&bs, bs_size);
+- byte_stream_putcaps(&bs, caps);
+-
+- /* adding of custom icon GUID */
+- if (data != NULL)
+- byte_stream_putraw(&bs, data, 16);
+-
+- len = aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
+-
+- byte_stream_destroy(&bs);
+-
+- return len;
+-}
+-
+-/**
+- * Adds the given chatroom info to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param roomname The name of the chat.
+- * @param instance The instance.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_chatroom(GSList **list, guint16 type, guint16 exchange, const char *roomname, guint16 instance)
+-{
+- int len;
+- ByteStream bs;
+-
+- byte_stream_new(&bs, 2 + 1 + strlen(roomname) + 2);
+-
+- byte_stream_put16(&bs, exchange);
+- byte_stream_put8(&bs, strlen(roomname));
+- byte_stream_putstr(&bs, roomname);
+- byte_stream_put16(&bs, instance);
+-
+- len = aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
+-
+- byte_stream_destroy(&bs);
+-
+- return len;
+-}
+-
+-/**
+- * Adds a TLV with a zero length to a TLV chain.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @return The size of the value added.
+- */
+-int aim_tlvlist_add_noval(GSList **list, const guint16 type)
+-{
+- return aim_tlvlist_add_raw(list, type, 0, NULL);
+-}
+-
+-/*
+- * Note that the inner TLV chain will not be modifiable as a tlvchain once
+- * it is written using this. Or rather, it can be, but updates won't be
+- * made to this.
+- *
+- * TODO: Should probably support sublists for real.
+- *
+- * This is so neat.
+- *
+- * @param list Destination chain.
+- * @param type TLV type to add.
+- * @param t1 The TLV chain you want to write.
+- * @return The number of bytes written to the destination TLV chain.
+- * 0 is returned if there was an error or if the destination
+- * TLV chain has length 0.
+- */
+-int aim_tlvlist_add_frozentlvlist(GSList **list, guint16 type, GSList **tlvlist)
+-{
+- int buflen;
+- ByteStream bs;
+-
+- buflen = aim_tlvlist_size(*tlvlist);
+-
+- if (buflen <= 0)
+- return 0;
+-
+- byte_stream_new(&bs, buflen);
+-
+- aim_tlvlist_write(&bs, tlvlist);
+-
+- aim_tlvlist_add_raw(list, type, byte_stream_curpos(&bs), bs.data);
+-
+- byte_stream_destroy(&bs);
+-
+- return buflen;
+-}
+-
+-/**
+- * Substitute a TLV of a given type with a new TLV of the same type. If
+- * you attempt to replace a TLV that does not exist, this function will
+- * just add a new TLV as if you called aim_tlvlist_add_raw().
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @param length Length of string to add (not including %NULL).
+- * @param value String to add.
+- * @return The length of the TLV.
+- */
+-int aim_tlvlist_replace_raw(GSList **list, const guint16 type, const guint16 length, const guint8 *value)
+-{
+- GSList *cur;
+- aim_tlv_t *tlv;
+-
+- if (list == NULL)
+- return 0;
+-
+- 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(tlv->value);
+- tlv->length = length;
+- if (tlv->length > 0) {
+- tlv->value = g_memdup(value, length);
+- } else
+- tlv->value = NULL;
+-
+- return tlv->length;
+-}
+-
+-/**
+- * Substitute a TLV of a given type with a new TLV of the same type. If
+- * you attempt to replace a TLV that does not exist, this function will
+- * just add a new TLV as if you called aim_tlvlist_add_str().
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @param str String to add.
+- * @return The length of the TLV.
+- */
+-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);
+-}
+-
+-/**
+- * Substitute a TLV of a given type with a new TLV of the same type. If
+- * you attempt to replace a TLV that does not exist, this function will
+- * just add a new TLV as if you called aim_tlvlist_add_raw().
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @return The length of the TLV.
+- */
+-int aim_tlvlist_replace_noval(GSList **list, const guint16 type)
+-{
+- return aim_tlvlist_replace_raw(list, type, 0, NULL);
+-}
+-
+-/**
+- * Substitute a TLV of a given type with a new TLV of the same type. If
+- * you attempt to replace a TLV that does not exist, this function will
+- * just add a new TLV as if you called aim_tlvlist_add_raw().
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @param value 8 bit value to add.
+- * @return The length of the TLV.
+- */
+-int aim_tlvlist_replace_8(GSList **list, const guint16 type, const guint8 value)
+-{
+- guint8 v8[1];
+-
+- aimutil_put8(v8, value);
+-
+- return aim_tlvlist_replace_raw(list, type, 1, v8);
+-}
+-
+-/**
+- * Substitute a TLV of a given type with a new TLV of the same type. If
+- * you attempt to replace a TLV that does not exist, this function will
+- * just add a new TLV as if you called aim_tlvlist_add_raw().
+- *
+- * @param list Desination chain (%NULL pointer if empty).
+- * @param type TLV type.
+- * @param value 32 bit value to add.
+- * @return The length of the TLV.
+- */
+-int aim_tlvlist_replace_32(GSList **list, const guint16 type, const guint32 value)
+-{
+- guint8 v32[4];
+-
+- aimutil_put32(v32, value);
+-
+- return aim_tlvlist_replace_raw(list, type, 4, v32);
+-}
+-
+-/**
+- * 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(GSList **list, const guint16 type)
+-{
+- GSList *cur, *next;
+- aim_tlv_t *tlv;
+-
+- if (list == NULL || *list == NULL)
+- return;
+-
+- 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;
+- }
+-}
+-
+-/**
+- * Write a TLV chain into a data buffer.
+- *
+- * Copies a TLV chain into a raw data buffer, writing only the number
+- * of bytes specified. This operation does not free the chain;
+- * aim_tlvlist_free() must still be called to free up the memory used
+- * by the chain structures.
+- *
+- * 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, GSList **list)
+-{
+- int goodbuflen;
+- GSList *cur;
+- aim_tlv_t *tlv;
+-
+- /* do an initial run to test total length */
+- goodbuflen = aim_tlvlist_size(*list);
+-
+- if (goodbuflen > byte_stream_bytes_left(bs))
+- return 0; /* not enough buffer */
+-
+- /* do the real write-out */
+- for (cur = *list; cur; cur = cur->next) {
+- 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; /* TODO: This is a nonsensical return */
+-}
+-
+-
+-/**
+- * Grab the Nth TLV of type type in the TLV list list.
+- *
+- * Returns a pointer to an aim_tlv_t of the specified type;
+- * %NULL on error. The @nth parameter is specified starting at %1.
+- * In most cases, there will be no more than one TLV of any type
+- * in a chain.
+- *
+- * @param list Source chain.
+- * @param type Requested TLV type.
+- * @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(GSList *list, const guint16 type, const int nth)
+-{
+- GSList *cur;
+- aim_tlv_t *tlv;
+- int i;
+-
+- for (cur = list, i = 0; cur != NULL; cur = cur->next) {
+- tlv = cur->data;
+- if (tlv->type == type)
+- i++;
+- if (i >= nth)
+- return tlv;
+- }
+-
+- return NULL;
+-}
+-
+-/**
+- * Get the length of the data of the nth TLV in the given TLV chain.
+- *
+- * @param list Source chain.
+- * @param type Requested TLV type.
+- * @param nth Index of TLV of type to get.
+- * @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(GSList *list, const guint16 type, const int nth)
+-{
+- aim_tlv_t *tlv;
+-
+- tlv = aim_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return -1;
+-
+- return tlv->length;
+-}
+-
+-char *
+-aim_tlv_getvalue_as_string(aim_tlv_t *tlv)
+-{
+- char *ret;
+-
+- ret = g_malloc(tlv->length + 1);
+- memcpy(ret, tlv->value, tlv->length);
+- ret[tlv->length] = '\0';
+-
+- return ret;
+-}
+-
+-/**
+- * Retrieve the data from the nth TLV in the given TLV chain as a string.
+- *
+- * @param list Source TLV chain.
+- * @param type TLV type to search for.
+- * @param nth Index of TLV to return.
+- * @return The value of the TLV you were looking for, or NULL if one could
+- * not be found. This is a dynamic buffer and must be freed by the
+- * caller.
+- */
+-char *aim_tlv_getstr(GSList *list, const guint16 type, const int nth)
+-{
+- aim_tlv_t *tlv;
+-
+- tlv = aim_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return NULL;
+-
+- return aim_tlv_getvalue_as_string(tlv);
+-}
+-
+-/**
+- * Retrieve the data from the nth TLV in the given TLV chain as an 8bit
+- * integer.
+- *
+- * @param list Source TLV chain.
+- * @param type TLV type to search for.
+- * @param nth Index of TLV to return.
+- * @return The value the TLV you were looking for, or 0 if one could
+- * not be found.
+- */
+-guint8 aim_tlv_get8(GSList *list, const guint16 type, const int nth)
+-{
+- aim_tlv_t *tlv;
+-
+- tlv = aim_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return aimutil_get8(tlv->value);
+-}
+-
+-/**
+- * Retrieve the data from the nth TLV in the given TLV chain as a 16bit
+- * integer.
+- *
+- * @param list Source TLV chain.
+- * @param type TLV type to search for.
+- * @param nth Index of TLV to return.
+- * @return The value the TLV you were looking for, or 0 if one could
+- * not be found.
+- */
+-guint16 aim_tlv_get16(GSList *list, const guint16 type, const int nth)
+-{
+- aim_tlv_t *tlv;
+-
+- tlv = aim_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return aimutil_get16(tlv->value);
+-}
+-
+-/**
+- * Retrieve the data from the nth TLV in the given TLV chain as a 32bit
+- * integer.
+- *
+- * @param list Source TLV chain.
+- * @param type TLV type to search for.
+- * @param nth Index of TLV to return.
+- * @return The value the TLV you were looking for, or 0 if one could
+- * not be found.
+- */
+-guint32 aim_tlv_get32(GSList *list, const guint16 type, const int nth)
+-{
+- aim_tlv_t *tlv;
+-
+- tlv = aim_tlv_gettlv(list, type, nth);
+- if (tlv == NULL)
+- return 0; /* erm */
+-
+- return aimutil_get32(tlv->value);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/userinfo.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/userinfo.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/userinfo.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/userinfo.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,550 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * Displaying various information about buddies.
+- */
+-
+-#include "encoding.h"
+-#include "oscar.h"
+-
+-static gchar *
+-oscar_caps_to_string(guint64 caps)
+-{
+- GString *str;
+- const gchar *tmp;
+- guint64 bit = 1;
+-
+- str = g_string_new("");
+-
+- if (!caps) {
+- return NULL;
+- } else while (bit <= OSCAR_CAPABILITY_LAST) {
+- if (bit & caps) {
+- switch (bit) {
+- case OSCAR_CAPABILITY_BUDDYICON:
+- tmp = _("Buddy Icon");
+- break;
+- case OSCAR_CAPABILITY_TALK:
+- tmp = _("Voice");
+- break;
+- case OSCAR_CAPABILITY_DIRECTIM:
+- tmp = _("AIM Direct IM");
+- break;
+- case OSCAR_CAPABILITY_CHAT:
+- tmp = _("Chat");
+- break;
+- case OSCAR_CAPABILITY_GETFILE:
+- tmp = _("Get File");
+- break;
+- case OSCAR_CAPABILITY_SENDFILE:
+- tmp = _("Send File");
+- break;
+- case OSCAR_CAPABILITY_GAMES:
+- case OSCAR_CAPABILITY_GAMES2:
+- tmp = _("Games");
+- break;
+- case OSCAR_CAPABILITY_XTRAZ:
+- case OSCAR_CAPABILITY_NEWCAPS:
+- tmp = _("ICQ Xtraz");
+- break;
+- case OSCAR_CAPABILITY_ADDINS:
+- tmp = _("Add-Ins");
+- break;
+- case OSCAR_CAPABILITY_SENDBUDDYLIST:
+- tmp = _("Send Buddy List");
+- break;
+- case OSCAR_CAPABILITY_ICQ_DIRECT:
+- tmp = _("ICQ Direct Connect");
+- break;
+- case OSCAR_CAPABILITY_APINFO:
+- tmp = _("AP User");
+- break;
+- case OSCAR_CAPABILITY_ICQRTF:
+- tmp = _("ICQ RTF");
+- break;
+- case OSCAR_CAPABILITY_EMPTY:
+- tmp = _("Nihilist");
+- break;
+- case OSCAR_CAPABILITY_ICQSERVERRELAY:
+- tmp = _("ICQ Server Relay");
+- break;
+- case OSCAR_CAPABILITY_UNICODEOLD:
+- tmp = _("Old ICQ UTF8");
+- break;
+- case OSCAR_CAPABILITY_TRILLIANCRYPT:
+- tmp = _("Trillian Encryption");
+- break;
+- case OSCAR_CAPABILITY_UNICODE:
+- tmp = _("ICQ UTF8");
+- break;
+- case OSCAR_CAPABILITY_HIPTOP:
+- tmp = _("Hiptop");
+- break;
+- case OSCAR_CAPABILITY_SECUREIM:
+- tmp = _("Security Enabled");
+- break;
+- case OSCAR_CAPABILITY_VIDEO:
+- tmp = _("Video Chat");
+- break;
+- /* Not actually sure about this one... WinAIM doesn't show anything */
+- case OSCAR_CAPABILITY_ICHATAV:
+- tmp = _("iChat AV");
+- break;
+- case OSCAR_CAPABILITY_LIVEVIDEO:
+- tmp = _("Live Video");
+- break;
+- case OSCAR_CAPABILITY_CAMERA:
+- tmp = _("Camera");
+- break;
+- case OSCAR_CAPABILITY_ICHAT_SCREENSHARE:
+- tmp = _("Screen Sharing");
+- break;
+- default:
+- tmp = NULL;
+- break;
+- }
+- if (tmp)
+- g_string_append_printf(str, "%s%s", (*(str->str) == '\0' ? "" : ", "), tmp);
+- }
+- bit <<= 1;
+- }
+-
+- return g_string_free(str, FALSE);
+-}
+-
+-static void
+-oscar_user_info_add_pair(PurpleNotifyUserInfo *user_info, const char *name, const char *value)
+-{
+- if (value && value[0]) {
+- purple_notify_user_info_add_pair(user_info, name, value);
+- }
+-}
+-
+-static void
+-oscar_user_info_convert_and_add(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
+- const char *name, const char *value)
+-{
+- gchar *utf8;
+-
+- if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
+- purple_notify_user_info_add_pair(user_info, name, utf8);
+- g_free(utf8);
+- }
+-}
+-
+-static void
+-oscar_user_info_convert_and_add_hyperlink(PurpleAccount *account, OscarData *od, PurpleNotifyUserInfo *user_info,
+- const char *name, const char *value, const char *url_prefix)
+-{
+- gchar *utf8;
+-
+- if (value && value[0] && (utf8 = oscar_utf8_try_convert(account, od, value))) {
+- gchar *tmp = g_strdup_printf("<a href=\"%s%s\">%s</a>", url_prefix, utf8, utf8);
+- purple_notify_user_info_add_pair(user_info, name, tmp);
+- g_free(utf8);
+- g_free(tmp);
+- }
+-}
+-
+-/**
+- * @brief Append the status information to a user_info struct
+- *
+- * The returned information is HTML-ready, appropriately escaped, as all information in a user_info struct should be HTML.
+- *
+- * @param gc The PurpleConnection
+- * @param user_info A PurpleNotifyUserInfo object to which status information will be added
+- * @param b The PurpleBuddy whose status is desired. This or the aim_userinfo_t (or both) must be passed to oscar_user_info_append_status().
+- * @param userinfo The aim_userinfo_t of the buddy whose status is desired. This or the PurpleBuddy (or both) must be passed to oscar_user_info_append_status().
+- * @param use_html_status If TRUE, prefer HTML-formatted away message over plaintext available message.
+- */
+-void
+-oscar_user_info_append_status(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo, gboolean use_html_status)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- OscarData *od;
+- PurplePresence *presence = NULL;
+- PurpleStatus *status = NULL;
+- gchar *message = NULL, *itmsurl = NULL, *tmp;
+- gboolean escaping_needed = TRUE;
+-
+- od = purple_connection_get_protocol_data(gc);
+-
+- if (b == NULL && userinfo == NULL)
+- return;
+-
+- if (b == NULL)
+- b = purple_find_buddy(purple_connection_get_account(gc), userinfo->bn);
+- else
+- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
+-
+- if (b) {
+- presence = purple_buddy_get_presence(b);
+- status = purple_presence_get_active_status(presence);
+- }
+-
+- /* If we have both b and userinfo we favor userinfo, because if we're
+- viewing someone's profile then we want the HTML away message, and
+- the "message" attribute of the status contains only the plaintext
+- message. */
+- if (userinfo) {
+- if ((userinfo->flags & AIM_FLAG_AWAY) && use_html_status && userinfo->away_len > 0 && userinfo->away != NULL && userinfo->away_encoding != NULL) {
+- /* Away message */
+- message = oscar_encoding_to_utf8(userinfo->away_encoding, userinfo->away, userinfo->away_len);
+- escaping_needed = FALSE;
+- } else {
+- /*
+- * Available message or non-HTML away message (because that's
+- * all we have right now.
+- */
+- if ((userinfo->status != NULL) && userinfo->status[0] != '\0') {
+- message = oscar_encoding_to_utf8(userinfo->status_encoding, userinfo->status, userinfo->status_len);
+- }
+-#if defined (_WIN32) || defined (__APPLE__)
+- if (userinfo->itmsurl && (userinfo->itmsurl[0] != '\0')) {
+- itmsurl = oscar_encoding_to_utf8(userinfo->itmsurl_encoding, userinfo->itmsurl, userinfo->itmsurl_len);
+- }
+-#endif
+- }
+- } else {
+- message = g_strdup(purple_status_get_attr_string(status, "message"));
+- itmsurl = g_strdup(purple_status_get_attr_string(status, "itmsurl"));
+- }
+-
+- if (message) {
+- tmp = oscar_util_format_string(message, purple_account_get_username(account));
+- g_free(message);
+- message = tmp;
+- if (escaping_needed) {
+- tmp = purple_markup_escape_text(message, -1);
+- g_free(message);
+- message = tmp;
+- }
+- }
+-
+- if (use_html_status && itmsurl) {
+- tmp = g_strdup_printf("<a href=\"%s\">%s</a>", itmsurl, message);
+- g_free(message);
+- message = tmp;
+- }
+-
+- if (b) {
+- if (purple_presence_is_online(presence)) {
+- gboolean is_away = ((status && !purple_status_is_available(status)) || (userinfo && (userinfo->flags & AIM_FLAG_AWAY)));
+- if (oscar_util_valid_name_icq(purple_buddy_get_name(b)) || is_away || !message || !(*message)) {
+- /* Append the status name for online ICQ statuses, away AIM statuses, and for all buddies with no message.
+- * If the status name and the message are the same, only show one. */
+- const char *status_name = purple_status_get_name(status);
+- if (status_name && message && !strcmp(status_name, message))
+- status_name = NULL;
+-
+- tmp = g_strdup_printf("%s%s%s",
+- status_name ? status_name : "",
+- ((status_name && message) && *message) ? ": " : "",
+- (message && *message) ? message : "");
+- g_free(message);
+- message = tmp;
+- }
+-
+- } else if (aim_ssi_waitingforauth(od->ssi.local,
+- aim_ssi_itemlist_findparentname(od->ssi.local, purple_buddy_get_name(b)),
+- purple_buddy_get_name(b)))
+- {
+- /* Note if an offline buddy is not authorized */
+- tmp = g_strdup_printf("%s%s%s",
+- _("Not Authorized"),
+- (message && *message) ? ": " : "",
+- (message && *message) ? message : "");
+- g_free(message);
+- message = tmp;
+- } else {
+- g_free(message);
+- message = g_strdup(_("Offline"));
+- }
+- }
+-
+- if (presence) {
+- const char *mood;
+- const char *comment;
+- char *description;
+- status = purple_presence_get_status(presence, "mood");
+- mood = icq_get_custom_icon_description(purple_status_get_attr_string(status, PURPLE_MOOD_NAME));
+- if (mood) {
+- comment = purple_status_get_attr_string(status, PURPLE_MOOD_COMMENT);
+- if (comment) {
+- char *escaped_comment = purple_markup_escape_text(comment, -1);
+- description = g_strdup_printf("%s (%s)", _(mood), escaped_comment);
+- g_free(escaped_comment);
+- } else {
+- description = g_strdup(_(mood));
+- }
+- purple_notify_user_info_add_pair(user_info, _("Mood"), description);
+- g_free(description);
+- }
+- }
+-
+- purple_notify_user_info_add_pair(user_info, _("Status"), message);
+- g_free(message);
+-}
+-
+-void
+-oscar_user_info_append_extra_info(PurpleConnection *gc, PurpleNotifyUserInfo *user_info, PurpleBuddy *b, aim_userinfo_t *userinfo)
+-{
+- OscarData *od;
+- PurpleAccount *account;
+- PurplePresence *presence = NULL;
+- PurpleStatus *status = NULL;
+- PurpleGroup *g = NULL;
+- struct buddyinfo *bi = NULL;
+- char *tmp;
+- const char *bname = NULL, *gname = NULL;
+-
+- od = purple_connection_get_protocol_data(gc);
+- account = purple_connection_get_account(gc);
+-
+- if ((user_info == NULL) || ((b == NULL) && (userinfo == NULL)))
+- return;
+-
+- if (userinfo == NULL)
+- userinfo = aim_locate_finduserinfo(od, purple_buddy_get_name(b));
+-
+- if (b == NULL)
+- b = purple_find_buddy(account, userinfo->bn);
+-
+- if (b != NULL) {
+- bname = purple_buddy_get_name(b);
+- g = purple_buddy_get_group(b);
+- gname = purple_group_get_name(g);
+- presence = purple_buddy_get_presence(b);
+- status = purple_presence_get_active_status(presence);
+- }
+-
+- if (userinfo != NULL)
+- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, userinfo->bn));
+-
+- if ((bi != NULL) && (bi->ipaddr != 0)) {
+- tmp = g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
+- (bi->ipaddr & 0xff000000) >> 24,
+- (bi->ipaddr & 0x00ff0000) >> 16,
+- (bi->ipaddr & 0x0000ff00) >> 8,
+- (bi->ipaddr & 0x000000ff));
+- oscar_user_info_add_pair(user_info, _("IP Address"), tmp);
+- g_free(tmp);
+- }
+-
+- if ((userinfo != NULL) && (userinfo->warnlevel != 0)) {
+- tmp = g_strdup_printf("%d", (int)(userinfo->warnlevel/10.0 + .5));
+- oscar_user_info_add_pair(user_info, _("Warning Level"), tmp);
+- g_free(tmp);
+- }
+-
+- if ((b != NULL) && (bname != NULL) && (g != NULL) && (gname != NULL)) {
+- tmp = aim_ssi_getcomment(od->ssi.local, gname, bname);
+- if (tmp != NULL) {
+- char *tmp2 = g_markup_escape_text(tmp, strlen(tmp));
+- g_free(tmp);
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Buddy Comment"), tmp2);
+- g_free(tmp2);
+- }
+- }
+-}
+-
+-void
+-oscar_user_info_display_error(OscarData *od, guint16 error_reason, gchar *buddy)
+-{
+- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
+- gchar *buf = g_strdup_printf(_("User information not available: %s"), oscar_get_msgerr_reason(error_reason));
+- purple_notify_user_info_add_pair(user_info, NULL, buf);
+- purple_notify_userinfo(od->gc, buddy, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+- purple_conv_present_error(buddy, purple_connection_get_account(od->gc), buf);
+- g_free(buf);
+-}
+-
+-void
+-oscar_user_info_display_icq(OscarData *od, struct aim_icq_info *info)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleBuddy *buddy;
+- struct buddyinfo *bi;
+- gchar who[16];
+- PurpleNotifyUserInfo *user_info;
+- const gchar *alias;
+-
+- if (!info->uin)
+- return;
+-
+- user_info = purple_notify_user_info_new();
+-
+- g_snprintf(who, sizeof(who), "%u", info->uin);
+- buddy = purple_find_buddy(account, who);
+- if (buddy != NULL)
+- bi = g_hash_table_lookup(od->buddyinfo, purple_normalize(account, purple_buddy_get_name(buddy)));
+- else
+- bi = NULL;
+-
+- purple_notify_user_info_add_pair(user_info, _("UIN"), who);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Nick"), info->nick);
+- if ((bi != NULL) && (bi->ipaddr != 0)) {
+- char *tstr = g_strdup_printf("%hhu.%hhu.%hhu.%hhu",
+- (bi->ipaddr & 0xff000000) >> 24,
+- (bi->ipaddr & 0x00ff0000) >> 16,
+- (bi->ipaddr & 0x0000ff00) >> 8,
+- (bi->ipaddr & 0x000000ff));
+- purple_notify_user_info_add_pair(user_info, _("IP Address"), tstr);
+- g_free(tstr);
+- }
+- oscar_user_info_convert_and_add(account, od, user_info, _("First Name"), info->first);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Last Name"), info->last);
+- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email, "mailto:");
+- if (info->numaddresses && info->email2) {
+- int i;
+- for (i = 0; i < info->numaddresses; i++) {
+- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Email Address"), info->email2[i], "mailto:");
+- }
+- }
+- oscar_user_info_convert_and_add(account, od, user_info, _("Mobile Phone"), info->mobile);
+-
+- if (info->gender != 0)
+- purple_notify_user_info_add_pair(user_info, _("Gender"), (info->gender == 1 ? _("Female") : _("Male")));
+-
+- if ((info->birthyear > 1900) && (info->birthmonth > 0) && (info->birthday > 0)) {
+- /* Initialize the struct properly or strftime() will crash
+- * under some conditions (e.g. Debian sarge w/ LANG=en_HK). */
+- time_t t = time(NULL);
+- struct tm *tm = localtime(&t);
+-
+- tm->tm_mday = (int)info->birthday;
+- tm->tm_mon = (int)info->birthmonth - 1;
+- tm->tm_year = (int)info->birthyear - 1900;
+-
+- /* Ignore dst setting of today to avoid timezone shift between
+- * dates in summer and winter time. */
+- tm->tm_isdst = -1;
+-
+- /* To be 100% sure that the fields are re-normalized.
+- * If you're sure strftime() ALWAYS does this EVERYWHERE,
+- * feel free to remove it. --rlaager */
+- mktime(tm);
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Birthday"), purple_date_format_short(tm));
+- }
+- if ((info->age > 0) && (info->age < 255)) {
+- char age[5];
+- snprintf(age, sizeof(age), "%hhd", info->age);
+- purple_notify_user_info_add_pair(user_info, _("Age"), age);
+- }
+- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Personal Web Page"), info->email, "");
+- if (buddy != NULL)
+- oscar_user_info_append_status(gc, user_info, buddy, /* aim_userinfo_t */ NULL, /* use_html_status */ TRUE);
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Additional Information"), info->info);
+- purple_notify_user_info_add_section_break(user_info);
+-
+- if ((info->homeaddr && (info->homeaddr[0])) || (info->homecity && info->homecity[0]) || (info->homestate && info->homestate[0]) || (info->homezip && info->homezip[0])) {
+- purple_notify_user_info_add_section_header(user_info, _("Home Address"));
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->homeaddr);
+- oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->homecity);
+- oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->homestate);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->homezip);
+- }
+- if ((info->workaddr && info->workaddr[0]) || (info->workcity && info->workcity[0]) || (info->workstate && info->workstate[0]) || (info->workzip && info->workzip[0])) {
+- purple_notify_user_info_add_section_header(user_info, _("Work Address"));
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Address"), info->workaddr);
+- oscar_user_info_convert_and_add(account, od, user_info, _("City"), info->workcity);
+- oscar_user_info_convert_and_add(account, od, user_info, _("State"), info->workstate);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Zip Code"), info->workzip);
+- }
+- if ((info->workcompany && info->workcompany[0]) || (info->workdivision && info->workdivision[0]) || (info->workposition && info->workposition[0]) || (info->workwebpage && info->workwebpage[0])) {
+- purple_notify_user_info_add_section_header(user_info, _("Work Information"));
+-
+- oscar_user_info_convert_and_add(account, od, user_info, _("Company"), info->workcompany);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Division"), info->workdivision);
+- oscar_user_info_convert_and_add(account, od, user_info, _("Position"), info->workposition);
+- oscar_user_info_convert_and_add_hyperlink(account, od, user_info, _("Web Page"), info->email, "");
+- }
+-
+- if (buddy != NULL)
+- alias = purple_buddy_get_alias(buddy);
+- else
+- alias = who;
+- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-}
+-
+-void
+-oscar_user_info_display_aim(OscarData *od, aim_userinfo_t *userinfo)
+-{
+- PurpleConnection *gc = od->gc;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleNotifyUserInfo *user_info = purple_notify_user_info_new();
+- gchar *tmp = NULL, *info_utf8 = NULL, *base_profile_url = NULL;
+-
+- oscar_user_info_append_status(gc, user_info, /* PurpleBuddy */ NULL, userinfo, /* use_html_status */ TRUE);
+-
+- if ((userinfo->present & AIM_USERINFO_PRESENT_IDLE) && userinfo->idletime != 0) {
+- tmp = purple_str_seconds_to_string(userinfo->idletime*60);
+- oscar_user_info_add_pair(user_info, _("Idle"), tmp);
+- g_free(tmp);
+- }
+-
+- oscar_user_info_append_extra_info(gc, user_info, NULL, userinfo);
+-
+- if ((userinfo->present & AIM_USERINFO_PRESENT_ONLINESINCE) && !oscar_util_valid_name_sms(userinfo->bn)) {
+- /* An SMS contact is always online; its Online Since value is not useful */
+- 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;
+- oscar_user_info_add_pair(user_info, _("Member Since"), purple_date_format_full(localtime(&t)));
+- }
+-
+- if (userinfo->capabilities != 0) {
+- tmp = oscar_caps_to_string(userinfo->capabilities);
+- oscar_user_info_add_pair(user_info, _("Capabilities"), tmp);
+- g_free(tmp);
+- }
+-
+- /* Info */
+- if ((userinfo->info_len > 0) && (userinfo->info != NULL) && (userinfo->info_encoding != NULL)) {
+- info_utf8 = oscar_encoding_to_utf8(userinfo->info_encoding, userinfo->info, userinfo->info_len);
+- tmp = oscar_util_format_string(info_utf8, purple_account_get_username(account));
+- purple_notify_user_info_add_section_break(user_info);
+- oscar_user_info_add_pair(user_info, _("Profile"), tmp);
+- g_free(tmp);
+- g_free(info_utf8);
+- }
+-
+- purple_notify_user_info_add_section_break(user_info);
+- base_profile_url = oscar_util_valid_name_icq(userinfo->bn) ? "http://www.icq.com/people" : "http://profiles.aim.com";
+- tmp = g_strdup_printf("<a href=\"%s/%s\">%s</a>",
+- base_profile_url, purple_normalize(account, userinfo->bn), _("View web profile"));
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+-
+- purple_notify_userinfo(gc, userinfo->bn, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-}
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/util.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/util.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/util.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/util.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,326 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-/*
+- * A little bit of this
+- * A little bit of that
+- * It started with a kiss
+- * Now we're up to bat
+- */
+-
+-#include "oscar.h"
+-
+-#include "core.h"
+-
+-#include <ctype.h>
+-
+-#ifdef _WIN32
+-#include "win32dep.h"
+-#endif
+-
+-static const char * const msgerrreason[] = {
+- N_("Invalid error"),
+- N_("Invalid SNAC"),
+- N_("Server rate limit exceeded"),
+- N_("Client rate limit exceeded"),
+- N_("Not logged in"),
+- N_("Service unavailable"),
+- N_("Service not defined"),
+- N_("Obsolete SNAC"),
+- N_("Not supported by host"),
+- N_("Not supported by client"),
+- N_("Refused by client"),
+- N_("Reply too big"),
+- N_("Responses lost"),
+- N_("Request denied"),
+- N_("Busted SNAC payload"),
+- N_("Insufficient rights"),
+- N_("In local permit/deny"),
+- N_("Warning level too high (sender)"),
+- N_("Warning level too high (receiver)"),
+- N_("User temporarily unavailable"),
+- N_("No match"),
+- N_("List overflow"),
+- N_("Request ambiguous"),
+- N_("Queue full"),
+- N_("Not while on AOL")
+-};
+-static const int msgerrreasonlen = G_N_ELEMENTS(msgerrreason);
+-
+-const char *oscar_get_msgerr_reason(size_t reason)
+-{
+- return (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason");
+-}
+-
+-int oscar_get_ui_info_int(const char *str, int default_value)
+-{
+- GHashTable *ui_info;
+-
+- ui_info = purple_core_get_ui_info();
+- if (ui_info != NULL) {
+- gpointer value;
+- if (g_hash_table_lookup_extended(ui_info, str, NULL, &value))
+- return GPOINTER_TO_INT(value);
+- }
+-
+- return default_value;
+-}
+-
+-const char *oscar_get_ui_info_string(const char *str, const char *default_value)
+-{
+- GHashTable *ui_info;
+- const char *value = NULL;
+-
+- ui_info = purple_core_get_ui_info();
+- if (ui_info != NULL)
+- value = g_hash_table_lookup(ui_info, str);
+- if (value == NULL)
+- value = default_value;
+-
+- return value;
+-}
+-
+-gchar *oscar_get_clientstring(void)
+-{
+- const char *name, *version;
+-
+- name = oscar_get_ui_info_string("name", "Purple");
+- version = oscar_get_ui_info_string("version", VERSION);
+-
+- return g_strdup_printf("%s/%s", name, version);;
+-}
+-
+-/**
+- * Calculate the checksum of a given icon.
+- */
+-guint16
+-aimutil_iconsum(const guint8 *buf, int buflen)
+-{
+- guint32 sum;
+- int i;
+-
+- for (i=0, sum=0; i+1<buflen; i+=2)
+- sum += (buf[i+1] << 8) + buf[i];
+- if (i < buflen)
+- sum += buf[i];
+- sum = ((sum & 0xffff0000) >> 16) + (sum & 0x0000ffff);
+-
+- return sum;
+-}
+-
+-/**
+- * Check if the given name is a valid AIM username.
+- * Example: BobDole
+- * Example: Henry_Ford@mac.com
+- * Example: 1KrazyKat@example.com
+- *
+- * @return TRUE if the name is valid, FALSE if not.
+- */
+-static gboolean
+-oscar_util_valid_name_aim(const char *name)
+-{
+- int i;
+-
+- if (purple_email_is_valid(name))
+- return TRUE;
+-
+- /* Normal AIM usernames can't start with a number, period or underscore */
+- if (isalnum(name[0]) == 0)
+- return FALSE;
+-
+- for (i = 0; name[i] != '\0'; i++) {
+- if (!isalnum(name[i]) && name[i] != ' ' && name[i] != '.' && name[i] != '_')
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-/**
+- * Check if the given name is a valid ICQ username.
+- * Example: 1234567
+- *
+- * @return TRUE if the name is valid, FALSE if not.
+- */
+-gboolean
+-oscar_util_valid_name_icq(const char *name)
+-{
+- int i;
+-
+- for (i = 0; name[i] != '\0'; i++) {
+- if (!isdigit(name[i]))
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-/**
+- * Check if the given name is a valid SMS username.
+- * Example: +19195551234
+- *
+- * @return TRUE if the name is valid, FALSE if not.
+- */
+-gboolean
+-oscar_util_valid_name_sms(const char *name)
+-{
+- int i;
+-
+- if (name[0] != '+')
+- return FALSE;
+-
+- for (i = 1; name[i] != '\0'; i++) {
+- if (!isdigit(name[i]))
+- return FALSE;
+- }
+-
+- return TRUE;
+-}
+-
+-/**
+- * Check if the given name is a valid oscar username.
+- *
+- * @return TRUE if the name is valid, FALSE if not.
+- */
+-gboolean
+-oscar_util_valid_name(const char *name)
+-{
+- if ((name == NULL) || (*name == '\0'))
+- return FALSE;
+-
+- return oscar_util_valid_name_icq(name)
+- || oscar_util_valid_name_sms(name)
+- || oscar_util_valid_name_aim(name);
+-}
+-
+-/**
+- * This takes two names and compares them using the rules
+- * on usernames for AIM/AOL. Mainly, this means case and space
+- * insensitivity (all case differences and spacing differences are
+- * ignored, with the exception that usernames can not start with
+- * a space).
+- *
+- * @return 0 if equal, non-0 if different
+- */
+-/* TODO: Do something different for email addresses. */
+-int
+-oscar_util_name_compare(const char *name1, const char *name2)
+-{
+-
+- if ((name1 == NULL) || (name2 == NULL))
+- return -1;
+-
+- do {
+- while (*name2 == ' ')
+- name2++;
+- while (*name1 == ' ')
+- name1++;
+- if (toupper(*name1) != toupper(*name2))
+- return 1;
+- } while ((*name1 != '\0') && name1++ && name2++);
+-
+- return 0;
+-}
+-
+-/**
+- * Looks for %n, %d, or %t in a string, and replaces them with the
+- * specified name, date, and time, respectively.
+- *
+- * @param str The string that may contain the special variables.
+- * @param name The sender name.
+- *
+- * @return A newly allocated string where the special variables are
+- * expanded. This should be g_free'd by the caller.
+- */
+-gchar *
+-oscar_util_format_string(const char *str, const char *name)
+-{
+- char *c;
+- GString *cpy;
+- time_t t;
+- struct tm *tme;
+-
+- g_return_val_if_fail(str != NULL, NULL);
+- g_return_val_if_fail(name != NULL, NULL);
+-
+- /* Create an empty GString that is hopefully big enough for most messages */
+- cpy = g_string_sized_new(1024);
+-
+- t = time(NULL);
+- tme = localtime(&t);
+-
+- c = (char *)str;
+- while (*c) {
+- switch (*c) {
+- case '%':
+- if (*(c + 1)) {
+- switch (*(c + 1)) {
+- case 'n':
+- /* append name */
+- g_string_append(cpy, name);
+- c++;
+- break;
+- case 'd':
+- /* append date */
+- g_string_append(cpy, purple_date_format_short(tme));
+- c++;
+- break;
+- case 't':
+- /* append time */
+- g_string_append(cpy, purple_time_format(tme));
+- c++;
+- break;
+- default:
+- g_string_append_c(cpy, *c);
+- }
+- } else {
+- g_string_append_c(cpy, *c);
+- }
+- break;
+- default:
+- g_string_append_c(cpy, *c);
+- }
+- c++;
+- }
+-
+- return g_string_free(cpy, FALSE);
+-}
+-
+-gchar *
+-oscar_format_buddies(GSList *buddies, const gchar *no_buddies_message)
+-{
+- GSList *cur;
+- GString *result;
+- if (!buddies) {
+- return g_strdup_printf("<i>%s</i>", no_buddies_message);
+- }
+- result = g_string_new("");
+- for (cur = buddies; cur != NULL; cur = cur->next) {
+- PurpleBuddy *buddy = cur->data;
+- const gchar *bname = purple_buddy_get_name(buddy);
+- const gchar *alias = purple_buddy_get_alias_only(buddy);
+- g_string_append(result, bname);
+- if (alias) {
+- g_string_append_printf(result, " (%s)", alias);
+- }
+- g_string_append(result, "<br>");
+- }
+- return g_string_free(result, FALSE);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/visibility.c pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.c
+--- pidgin-2.10.7/libpurple/protocols/oscar/visibility.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,140 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#include "visibility.h"
+-
+-/* Translators: This string is a menu option that, if selected, will cause
+- you to appear online to the chosen user even when your status is set to
+- Invisible. */
+-#define APPEAR_ONLINE N_("Appear Online")
+-
+-/* Translators: This string is a menu option that, if selected, will cause
+- you to appear offline to the chosen user when your status is set to
+- Invisible (this is the default). */
+-#define DONT_APPEAR_ONLINE N_("Don't Appear Online")
+-
+-/* Translators: This string is a menu option that, if selected, will cause
+- you to always appear offline to the chosen user (even when your status
+- isn't Invisible). */
+-#define APPEAR_OFFLINE N_("Appear Offline")
+-
+-/* Translators: This string is a menu option that, if selected, will cause
+- you to appear offline to the chosen user if you are invisible, and
+- appear online to the chosen user if you are not invisible (this is the
+- default). */
+-#define DONT_APPEAR_OFFLINE N_("Don't Appear Offline")
+-
+-static guint16
+-get_buddy_list_type(OscarData *od)
+-{
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- return purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE) ? AIM_SSI_TYPE_PERMIT : AIM_SSI_TYPE_DENY;
+-}
+-
+-static gboolean
+-is_buddy_on_list(OscarData *od, const char *bname)
+-{
+- return aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, get_buddy_list_type(od)) != NULL;
+-}
+-
+-static void
+-visibility_cb(PurpleBlistNode *node, gpointer whatever)
+-{
+- PurpleBuddy *buddy = PURPLE_BUDDY(node);
+- const char* bname = purple_buddy_get_name(buddy);
+- OscarData *od = purple_connection_get_protocol_data(purple_account_get_connection(purple_buddy_get_account(buddy)));
+- guint16 list_type = get_buddy_list_type(od);
+-
+- if (!is_buddy_on_list(od, bname)) {
+- aim_ssi_add_to_private_list(od, bname, list_type);
+- } else {
+- aim_ssi_del_from_private_list(od, bname, list_type);
+- }
+-}
+-
+-PurpleMenuAction *
+-create_visibility_menu_item(OscarData *od, const char *bname)
+-{
+- PurpleAccount *account = purple_connection_get_account(od->gc);
+- gboolean invisible = purple_account_is_status_active(account, OSCAR_STATUS_ID_INVISIBLE);
+- gboolean on_list = is_buddy_on_list(od, bname);
+- const gchar *label;
+-
+- if (invisible) {
+- label = on_list ? _(DONT_APPEAR_ONLINE) : _(APPEAR_ONLINE);
+- } else {
+- label = on_list ? _(DONT_APPEAR_OFFLINE) : _(APPEAR_OFFLINE);
+- }
+- return purple_menu_action_new(label, PURPLE_CALLBACK(visibility_cb), NULL, NULL);
+-}
+-
+-static void
+-show_private_list(PurplePluginAction *action, guint16 list_type, const gchar *title, const gchar *list_description, const gchar *menu_action_name)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- OscarData *od = purple_connection_get_protocol_data(gc);
+- PurpleAccount *account = purple_connection_get_account(gc);
+- GSList *buddies, *filtered_buddies, *cur;
+- gchar *text, *secondary;
+-
+- buddies = purple_find_buddies(account, NULL);
+- filtered_buddies = NULL;
+- for (cur = buddies; cur != NULL; cur = cur->next) {
+- PurpleBuddy *buddy;
+- const gchar *bname;
+-
+- buddy = cur->data;
+- bname = purple_buddy_get_name(buddy);
+- if (aim_ssi_itemlist_finditem(od->ssi.local, NULL, bname, list_type)) {
+- filtered_buddies = g_slist_prepend(filtered_buddies, buddy);
+- }
+- }
+-
+- g_slist_free(buddies);
+-
+- filtered_buddies = g_slist_reverse(filtered_buddies);
+- text = oscar_format_buddies(filtered_buddies, _("you have no buddies on this list"));
+- g_slist_free(filtered_buddies);
+-
+- secondary = g_strdup_printf(_("You can add a buddy to this list "
+- "by right-clicking on them and "
+- "selecting \"%s\""), menu_action_name);
+- purple_notify_formatted(gc, title, list_description, secondary, text, NULL, NULL);
+- g_free(secondary);
+- g_free(text);
+-}
+-
+-void
+-oscar_show_visible_list(PurplePluginAction *action)
+-{
+- show_private_list(action, AIM_SSI_TYPE_PERMIT, _("Visible List"),
+- _("These buddies will see "
+- "your status when you switch "
+- "to \"Invisible\""),
+- _(APPEAR_ONLINE));
+-}
+-
+-void
+-oscar_show_invisible_list(PurplePluginAction *action)
+-{
+- show_private_list(action, AIM_SSI_TYPE_DENY, _("Invisible List"),
+- _("These buddies will always see you as offline"),
+- _(APPEAR_OFFLINE));
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/oscar/visibility.h pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.h
+--- pidgin-2.10.7/libpurple/protocols/oscar/visibility.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/oscar/visibility.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,32 +0,0 @@
+-/*
+- * Purple's oscar protocol plugin
+- * This file is the legal property of its developers.
+- * Please see the AUTHORS file distributed alongside this file.
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+-*/
+-
+-#ifndef _VISIBILITY_H_
+-#define _VISIBILITY_H_
+-
+-#include "oscar.h"
+-#include "plugin.h"
+-#include "util.h"
+-
+-PurpleMenuAction * create_visibility_menu_item(OscarData *od, const char *bname);
+-void oscar_show_visible_list(PurplePluginAction *action);
+-void oscar_show_invisible_list(PurplePluginAction *action);
+-
+-#endif
+\ No newline at end of file
+diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,37 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-noinst_HEADERS = sametime.h
+-
+-SAMETIMESOURCES = sametime.c
+-
+-AM_CFLAGS = \
+- $(st)
+-
+-if STATIC_SAMETIME
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libsametime.la
+-libsametime_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libsametime.la
+-
+-endif
+-
+-libsametime_la_SOURCES = $(SAMETIMESOURCES)
+-libsametime_la_LDFLAGS = -module -avoid-version
+-libsametime_la_LIBADD = $(GLIB_LIBS) $(MEANWHILE_LIBS)
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(DEBUG_CFLAGS) \
+- $(GLIB_CFLAGS) \
+- $(MEANWHILE_CFLAGS) \
+- -DG_LOG_DOMAIN=\"sametime\"
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.in 2013-02-11 07:17:21.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,752 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/sametime
+-DIST_COMMON = $(noinst_HEADERS) $(srcdir)/Makefile.am \
+- $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-am__DEPENDENCIES_1 =
+-libsametime_la_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+- $(am__DEPENDENCIES_1)
+-am__objects_1 = libsametime_la-sametime.lo
+-am_libsametime_la_OBJECTS = $(am__objects_1)
+-libsametime_la_OBJECTS = $(am_libsametime_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libsametime_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC \
+- $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=link $(CCLD) \
+- $(libsametime_la_CFLAGS) $(CFLAGS) $(libsametime_la_LDFLAGS) \
+- $(LDFLAGS) -o $@
+-@STATIC_SAMETIME_FALSE@am_libsametime_la_rpath = -rpath $(pkgdir)
+-@STATIC_SAMETIME_TRUE@am_libsametime_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libsametime_la_SOURCES)
+-DIST_SOURCES = $(libsametime_la_SOURCES)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-HEADERS = $(noinst_HEADERS)
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-noinst_HEADERS = sametime.h
+-SAMETIMESOURCES = sametime.c
+-AM_CFLAGS = \
+- $(st)
+-
+-@STATIC_SAMETIME_FALSE@st =
+-@STATIC_SAMETIME_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_SAMETIME_TRUE@noinst_LTLIBRARIES = libsametime.la
+-@STATIC_SAMETIME_TRUE@libsametime_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_SAMETIME_FALSE@pkg_LTLIBRARIES = libsametime.la
+-libsametime_la_SOURCES = $(SAMETIMESOURCES)
+-libsametime_la_LDFLAGS = -module -avoid-version
+-libsametime_la_LIBADD = $(GLIB_LIBS) $(MEANWHILE_LIBS)
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(DEBUG_CFLAGS) \
+- $(GLIB_CFLAGS) \
+- $(MEANWHILE_CFLAGS) \
+- -DG_LOG_DOMAIN=\"sametime\"
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/sametime/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/sametime/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libsametime.la: $(libsametime_la_OBJECTS) $(libsametime_la_DEPENDENCIES) $(EXTRA_libsametime_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libsametime_la_LINK) $(am_libsametime_la_rpath) $(libsametime_la_OBJECTS) $(libsametime_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libsametime_la-sametime.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libsametime_la-sametime.lo: sametime.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsametime_la_CFLAGS) $(CFLAGS) -MT libsametime_la-sametime.lo -MD -MP -MF $(DEPDIR)/libsametime_la-sametime.Tpo -c -o libsametime_la-sametime.lo `test -f 'sametime.c' || echo '$(srcdir)/'`sametime.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libsametime_la-sametime.Tpo $(DEPDIR)/libsametime_la-sametime.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='sametime.c' object='libsametime_la-sametime.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libsametime_la_CFLAGS) $(CFLAGS) -c -o libsametime_la-sametime.lo `test -f 'sametime.c' || echo '$(srcdir)/'`sametime.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES) $(HEADERS)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/sametime/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,85 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libsametime
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libsametime
+-NEEDED_DLLS = $(MEANWHILE_TOP)/bin/libmeanwhile-1.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
+-
+-CFLAGS += -DG_LOG_DOMAIN=\"sametime\"
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(MEANWHILE_TOP)/include/meanwhile \
+- -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$(MEANWHILE_TOP)/lib \
+- -L$(PURPLE_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = sametime.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lintl \
+- -lws2_32 \
+- -lmeanwhile \
+- -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)
+- 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) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-
+-clean:
+- rm -f $(OBJECTS)
+- rm -f $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/sametime.c pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.c
+--- pidgin-2.10.7/libpurple/protocols/sametime/sametime.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,5832 +0,0 @@
+-
+-/*
+- Meanwhile Protocol Plugin for Purple
+- Adds Lotus Sametime support to Purple using the Meanwhile library
+-
+- Copyright (C) 2004 Christopher (siege) O'Brien <siege@preoccupied.net>
+-
+- This program is free software; you can redistribute it and/or modify
+- it under the terms of the GNU General Public License as published by
+- the Free Software Foundation; either version 2 of the License, or (at
+- your option) any later version.
+-
+- This program is distributed in the hope that it will be useful, but
+- WITHOUT ANY WARRANTY; without even the implied warranty of
+- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- General Public License for more details.
+-
+- You should have received a copy of the GNU General Public License
+- along with this program; if not, write to the Free Software
+- Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301,
+- USA.
+-*/
+-
+-#include "internal.h"
+-
+-/* system includes */
+-#include <stdlib.h>
+-#include <time.h>
+-
+-/* glib includes */
+-#include <glib.h>
+-
+-/* purple includes */
+-#include "account.h"
+-#include "accountopt.h"
+-#include "circbuffer.h"
+-#include "conversation.h"
+-#include "debug.h"
+-#include "ft.h"
+-#include "imgstore.h"
+-#include "mime.h"
+-#include "notify.h"
+-#include "plugin.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-#include "request.h"
+-#include "util.h"
+-#include "version.h"
+-
+-/* meanwhile includes */
+-#include <mw_cipher.h>
+-#include <mw_common.h>
+-#include <mw_error.h>
+-#include <mw_service.h>
+-#include <mw_session.h>
+-#include <mw_srvc_aware.h>
+-#include <mw_srvc_conf.h>
+-#include <mw_srvc_ft.h>
+-#include <mw_srvc_im.h>
+-#include <mw_srvc_place.h>
+-#include <mw_srvc_resolve.h>
+-#include <mw_srvc_store.h>
+-#include <mw_st_list.h>
+-
+-/* plugin includes */
+-#include "sametime.h"
+-
+-
+-/* considering that there's no display of this information for prpls,
+- I don't know why I even bother providing these. Oh valiant reader,
+- I do it all for you. */
+-/* scratch that, I just added it to the prpl options panel */
+-#define PLUGIN_ID "prpl-meanwhile"
+-#define PLUGIN_NAME "Sametime"
+-#define PLUGIN_SUMMARY "Sametime Protocol Plugin"
+-#define PLUGIN_DESC "Open implementation of a Lotus Sametime client"
+-#define PLUGIN_AUTHOR "Christopher (siege) O'Brien <siege@preoccupied.net>"
+-#define PLUGIN_HOMEPAGE "http://meanwhile.sourceforge.net/"
+-
+-
+-/* plugin preference names */
+-#define MW_PRPL_OPT_BASE "/plugins/prpl/meanwhile"
+-#define MW_PRPL_OPT_BLIST_ACTION MW_PRPL_OPT_BASE "/blist_action"
+-#define MW_PRPL_OPT_PSYCHIC MW_PRPL_OPT_BASE "/psychic"
+-#define MW_PRPL_OPT_FORCE_LOGIN MW_PRPL_OPT_BASE "/force_login"
+-#define MW_PRPL_OPT_SAVE_DYNAMIC MW_PRPL_OPT_BASE "/save_dynamic"
+-
+-
+-/* stages of connecting-ness */
+-#define MW_CONNECT_STEPS 11
+-
+-
+-/* stages of conciousness */
+-#define MW_STATE_OFFLINE "offline"
+-#define MW_STATE_ACTIVE "active"
+-#define MW_STATE_AWAY "away"
+-#define MW_STATE_BUSY "dnd"
+-#define MW_STATE_MESSAGE "message"
+-#define MW_STATE_ENLIGHTENED "buddha"
+-
+-
+-/* keys to get/set chat information */
+-#define CHAT_KEY_CREATOR "chat.creator"
+-#define CHAT_KEY_NAME "chat.name"
+-#define CHAT_KEY_TOPIC "chat.topic"
+-#define CHAT_KEY_INVITE "chat.invite"
+-#define CHAT_KEY_IS_PLACE "chat.is_place"
+-
+-
+-/* key for associating a mwLoginType with a buddy */
+-#define BUDDY_KEY_CLIENT "meanwhile.client"
+-
+-/* store the remote alias so that we can re-create it easily */
+-#define BUDDY_KEY_NAME "meanwhile.shortname"
+-
+-/* enum mwSametimeUserType */
+-#define BUDDY_KEY_TYPE "meanwhile.type"
+-
+-
+-/* key for the real group name for a meanwhile group */
+-#define GROUP_KEY_NAME "meanwhile.group"
+-
+-/* enum mwSametimeGroupType */
+-#define GROUP_KEY_TYPE "meanwhile.type"
+-
+-/* NAB group owning account */
+-#define GROUP_KEY_OWNER "meanwhile.account"
+-
+-/* key gtk blist uses to indicate a collapsed group */
+-#define GROUP_KEY_COLLAPSED "collapsed"
+-
+-
+-/* verification replacement */
+-#define mwSession_NO_SECRET "meanwhile.no_secret"
+-
+-
+-/* keys to get/set purple plugin information */
+-#define MW_KEY_HOST "server"
+-#define MW_KEY_PORT "port"
+-#define MW_KEY_FORCE "force_login"
+-#define MW_KEY_FAKE_IT "fake_client_id"
+-#define MW_KEY_CLIENT "client_id_val"
+-#define MW_KEY_MAJOR "client_major"
+-#define MW_KEY_MINOR "client_minor"
+-
+-
+-/** number of seconds from the first blist change before a save to the
+- storage service occurs. */
+-#define BLIST_SAVE_SECONDS 15
+-
+-
+-/** the possible buddy list storage settings */
+-enum blist_choice {
+- blist_choice_LOCAL = 1, /**< local only */
+- blist_choice_MERGE = 2, /**< merge from server */
+- blist_choice_STORE = 3, /**< merge from and save to server */
+- blist_choice_SYNCH = 4 /**< sync with server */
+-};
+-
+-
+-/** the default blist storage option */
+-#define BLIST_CHOICE_DEFAULT blist_choice_SYNCH
+-
+-
+-/* testing for the above */
+-#define BLIST_PREF_IS(n) (purple_prefs_get_int(MW_PRPL_OPT_BLIST_ACTION)==(n))
+-#define BLIST_PREF_IS_LOCAL() BLIST_PREF_IS(blist_choice_LOCAL)
+-#define BLIST_PREF_IS_MERGE() BLIST_PREF_IS(blist_choice_MERGE)
+-#define BLIST_PREF_IS_STORE() BLIST_PREF_IS(blist_choice_STORE)
+-#define BLIST_PREF_IS_SYNCH() BLIST_PREF_IS(blist_choice_SYNCH)
+-
+-
+-/* debugging output */
+-#define DEBUG_ERROR(...) purple_debug_error(G_LOG_DOMAIN, __VA_ARGS__)
+-#define DEBUG_INFO(...) purple_debug_info(G_LOG_DOMAIN, __VA_ARGS__)
+-#define DEBUG_MISC(...) purple_debug_misc(G_LOG_DOMAIN, __VA_ARGS__)
+-#define DEBUG_WARN(...) purple_debug_warning(G_LOG_DOMAIN, __VA_ARGS__)
+-
+-
+-/** ensure non-null strings */
+-#ifndef NSTR
+-# define NSTR(str) ((str)? (str): "(null)")
+-#endif
+-
+-
+-/** calibrates distinct secure channel nomenclature */
+-static const unsigned char no_secret[] = {
+- 0x2d, 0x2d, 0x20, 0x73, 0x69, 0x65, 0x67, 0x65,
+- 0x20, 0x6c, 0x6f, 0x76, 0x65, 0x73, 0x20, 0x6a,
+- 0x65, 0x6e, 0x6e, 0x69, 0x20, 0x61, 0x6e, 0x64,
+- 0x20, 0x7a, 0x6f, 0x65, 0x20, 0x2d, 0x2d, 0x00,
+-};
+-
+-
+-/** handler IDs from g_log_set_handler in mw_plugin_init */
+-static guint log_handler[2] = { 0, 0 };
+-
+-
+-/** the purple plugin data.
+- available as gc->proto_data and mwSession_getClientData */
+-struct mwPurplePluginData {
+- struct mwSession *session;
+-
+- struct mwServiceAware *srvc_aware;
+- struct mwServiceConference *srvc_conf;
+- struct mwServiceFileTransfer *srvc_ft;
+- struct mwServiceIm *srvc_im;
+- struct mwServicePlace *srvc_place;
+- struct mwServiceResolve *srvc_resolve;
+- struct mwServiceStorage *srvc_store;
+-
+- /** map of PurpleGroup:mwAwareList and mwAwareList:PurpleGroup */
+- GHashTable *group_list_map;
+-
+- /** event id for the buddy list save callback */
+- guint save_event;
+-
+- /** socket fd */
+- int socket;
+- gint outpa; /* like inpa, but the other way */
+-
+- /** circular buffer for outgoing data */
+- PurpleCircBuffer *sock_buf;
+-
+- PurpleConnection *gc;
+-};
+-
+-
+-typedef struct {
+- PurpleBuddy *buddy;
+- PurpleGroup *group;
+-} BuddyAddData;
+-
+-
+-/* blist and aware functions */
+-
+-static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist);
+-
+-static void blist_store(struct mwPurplePluginData *pd);
+-
+-static void blist_schedule(struct mwPurplePluginData *pd);
+-
+-static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist);
+-
+-static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist);
+-
+-static gboolean buddy_is_external(PurpleBuddy *b);
+-
+-static void buddy_add(struct mwPurplePluginData *pd, PurpleBuddy *buddy);
+-
+-static PurpleBuddy *
+-buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
+- struct mwSametimeUser *stuser);
+-
+-static void group_add(struct mwPurplePluginData *pd, PurpleGroup *group);
+-
+-static PurpleGroup *
+-group_ensure(PurpleConnection *gc, struct mwSametimeGroup *stgroup);
+-
+-static struct mwAwareList *
+-list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group);
+-
+-
+-/* session functions */
+-
+-static struct mwSession *
+-gc_to_session(PurpleConnection *gc);
+-
+-static PurpleConnection *session_to_gc(struct mwSession *session);
+-
+-
+-/* conference functions */
+-
+-static struct mwConference *
+-conf_find_by_id(struct mwPurplePluginData *pd, int id);
+-
+-
+-/* conversation functions */
+-
+-struct convo_msg {
+- enum mwImSendType type;
+- gpointer data;
+- GDestroyNotify clear;
+-};
+-
+-
+-struct convo_data {
+- struct mwConversation *conv;
+- GList *queue; /**< outgoing message queue, list of convo_msg */
+-};
+-
+-static void convo_data_new(struct mwConversation *conv);
+-
+-static void convo_data_free(struct convo_data *conv);
+-
+-static void convo_features(struct mwConversation *conv);
+-
+-static PurpleConversation *convo_get_gconv(struct mwConversation *conv);
+-
+-
+-/* name and id */
+-
+-struct named_id {
+- char *id;
+- char *name;
+-};
+-
+-
+-/* connection functions */
+-
+-static void connect_cb(gpointer data, gint source, const gchar *error_message);
+-
+-
+-/* ----- session ------ */
+-
+-
+-/** resolves a mwSession from a PurpleConnection */
+-static struct mwSession *gc_to_session(PurpleConnection *gc) {
+- struct mwPurplePluginData *pd;
+-
+- g_return_val_if_fail(gc != NULL, NULL);
+-
+- pd = gc->proto_data;
+- g_return_val_if_fail(pd != NULL, NULL);
+-
+- return pd->session;
+-}
+-
+-
+-/** resolves a PurpleConnection from a mwSession */
+-static PurpleConnection *session_to_gc(struct mwSession *session) {
+- struct mwPurplePluginData *pd;
+-
+- g_return_val_if_fail(session != NULL, NULL);
+-
+- pd = mwSession_getClientData(session);
+- g_return_val_if_fail(pd != NULL, NULL);
+-
+- return pd->gc;
+-}
+-
+-
+-static void write_cb(gpointer data, gint source, PurpleInputCondition cond) {
+- struct mwPurplePluginData *pd = data;
+- PurpleCircBuffer *circ = pd->sock_buf;
+- gsize avail;
+- int ret;
+-
+- DEBUG_INFO("write_cb\n");
+-
+- g_return_if_fail(circ != NULL);
+-
+- avail = purple_circ_buffer_get_max_read(circ);
+- if(BUF_LONG < avail) avail = BUF_LONG;
+-
+- while(avail) {
+- ret = write(pd->socket, circ->outptr, avail);
+-
+- if(ret <= 0)
+- break;
+-
+- purple_circ_buffer_mark_read(circ, ret);
+- avail = purple_circ_buffer_get_max_read(circ);
+- if(BUF_LONG < avail) avail = BUF_LONG;
+- }
+-
+- if(! avail) {
+- purple_input_remove(pd->outpa);
+- pd->outpa = 0;
+- }
+-}
+-
+-
+-static int mw_session_io_write(struct mwSession *session,
+- const guchar *buf, gsize len) {
+- struct mwPurplePluginData *pd;
+- gssize ret = 0;
+- int err = 0;
+-
+- pd = mwSession_getClientData(session);
+-
+- /* socket was already closed. */
+- if(pd->socket == 0)
+- return 1;
+-
+- if(pd->outpa) {
+- DEBUG_INFO("already pending INPUT_WRITE, buffering\n");
+- purple_circ_buffer_append(pd->sock_buf, buf, len);
+- return 0;
+- }
+-
+- while(len) {
+- ret = write(pd->socket, buf, (len > BUF_LEN)? BUF_LEN: len);
+-
+- if(ret <= 0)
+- break;
+-
+- len -= ret;
+- buf += ret;
+- }
+-
+- if(ret <= 0)
+- err = errno;
+-
+- if(err == EAGAIN) {
+- /* append remainder to circular buffer */
+- DEBUG_INFO("EAGAIN\n");
+- purple_circ_buffer_append(pd->sock_buf, buf, len);
+- pd->outpa = purple_input_add(pd->socket, PURPLE_INPUT_WRITE, write_cb, pd);
+-
+- } else if(len > 0) {
+- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- DEBUG_ERROR("write returned %" G_GSSIZE_FORMAT ", %" G_GSIZE_FORMAT
+- " bytes left unwritten\n", ret, len);
+- purple_connection_error_reason(pd->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- tmp);
+- g_free(tmp);
+-
+-#if 0
+- close(pd->socket);
+- pd->socket = 0;
+-#endif
+-
+- return -1;
+- }
+-
+- return 0;
+-}
+-
+-
+-static void mw_session_io_close(struct mwSession *session) {
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+-
+- pd = mwSession_getClientData(session);
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+-
+- if(pd->outpa) {
+- purple_input_remove(pd->outpa);
+- pd->outpa = 0;
+- }
+-
+- if(pd->socket) {
+- close(pd->socket);
+- pd->socket = 0;
+- }
+-
+- if(gc->inpa) {
+- purple_input_remove(gc->inpa);
+- gc->inpa = 0;
+- }
+-}
+-
+-
+-static void mw_session_clear(struct mwSession *session) {
+- ; /* nothing for now */
+-}
+-
+-
+-/* ----- aware list ----- */
+-
+-
+-static void blist_resolve_alias_cb(struct mwServiceResolve *srvc,
+- guint32 id, guint32 code, GList *results,
+- gpointer data) {
+- struct mwResolveResult *result;
+- struct mwResolveMatch *match;
+-
+- g_return_if_fail(results != NULL);
+-
+- result = results->data;
+- g_return_if_fail(result != NULL);
+- g_return_if_fail(result->matches != NULL);
+-
+- match = result->matches->data;
+- g_return_if_fail(match != NULL);
+-
+- purple_blist_server_alias_buddy(data, match->name);
+- purple_blist_node_set_string(data, BUDDY_KEY_NAME, match->name);
+-}
+-
+-
+-static void mw_aware_list_on_aware(struct mwAwareList *list,
+- struct mwAwareSnapshot *aware) {
+-
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+-
+- struct mwPurplePluginData *pd;
+- guint32 idle;
+- guint stat;
+- const char *id;
+- const char *status = MW_STATE_ACTIVE;
+-
+- gc = mwAwareList_getClientData(list);
+- acct = purple_connection_get_account(gc);
+-
+- pd = gc->proto_data;
+- idle = aware->status.time;
+- stat = aware->status.status;
+- id = aware->id.user;
+-
+- if(idle) {
+- guint32 idle_len; /*< how long a client has been idle */
+- guint32 ugly_idle_len; /*< how long a broken client has been idle */
+-
+- DEBUG_INFO("%s has idle value 0x%x\n", NSTR(id), idle);
+-
+- idle_len = time(NULL) - idle;
+- ugly_idle_len = ((time(NULL) * 1000) - idle) / 1000;
+-
+- if(idle > ugly_idle_len)
+- ugly_idle_len = 0;
+- else
+- ugly_idle_len = (ugly_idle_len - idle) / 1000;
+-
+- /*
+- what's the deal here? Well, good clients are smart enough to
+- publish their idle time by using an attribute to indicate that
+- they went idle at some time UTC, in seconds since epoch. Bad
+- clients use milliseconds since epoch. So we're going to compute
+- the idle time for either method, then figure out the lower of
+- the two and use that. Blame the ST 7.5 development team for
+- this.
+- */
+-
+- DEBUG_INFO("idle time: %u, ugly idle time: %u\n", idle_len, ugly_idle_len);
+-
+-#if 1
+- if(idle_len <= ugly_idle_len) {
+- ; /* DEBUG_INFO("sane idle value, let's use it\n"); */
+- } else {
+- idle = time(NULL) - ugly_idle_len;
+- }
+-
+-#else
+- if(idle < 0 || idle > time(NULL)) {
+- DEBUG_INFO("hiding a messy idle value 0x%x\n", NSTR(id), idle);
+- idle = -1;
+- }
+-#endif
+- }
+-
+- switch(stat) {
+- case mwStatus_ACTIVE:
+- status = MW_STATE_ACTIVE;
+- idle = 0;
+- break;
+-
+- case mwStatus_IDLE:
+- if(! idle) idle = -1;
+- break;
+-
+- case mwStatus_AWAY:
+- status = MW_STATE_AWAY;
+- break;
+-
+- case mwStatus_BUSY:
+- status = MW_STATE_BUSY;
+- break;
+- }
+-
+- /* NAB group members */
+- if(aware->group) {
+- PurpleGroup *group;
+- PurpleBuddy *buddy;
+- PurpleBlistNode *bnode;
+-
+- group = g_hash_table_lookup(pd->group_list_map, list);
+- buddy = purple_find_buddy_in_group(acct, id, group);
+- bnode = (PurpleBlistNode *) buddy;
+-
+- if(! buddy) {
+- struct mwServiceResolve *srvc;
+- GList *query;
+-
+- buddy = purple_buddy_new(acct, id, NULL);
+- purple_blist_add_buddy(buddy, NULL, group, NULL);
+-
+- bnode = (PurpleBlistNode *) buddy;
+-
+- srvc = pd->srvc_resolve;
+- query = g_list_append(NULL, (char *) id);
+-
+- mwServiceResolve_resolve(srvc, query, mwResolveFlag_USERS,
+- blist_resolve_alias_cb, buddy, NULL);
+- g_list_free(query);
+- }
+-
+- purple_blist_node_set_int(bnode, BUDDY_KEY_TYPE, mwSametimeUser_NORMAL);
+- }
+-
+- if(aware->online) {
+- purple_prpl_got_user_status(acct, id, status, NULL);
+- purple_prpl_got_user_idle(acct, id, !!idle, (time_t) idle);
+-
+- } else {
+- purple_prpl_got_user_status(acct, id, MW_STATE_OFFLINE, NULL);
+- }
+-}
+-
+-
+-static void mw_aware_list_on_attrib(struct mwAwareList *list,
+- struct mwAwareIdBlock *id,
+- struct mwAwareAttribute *attrib) {
+-
+- ; /* nothing. We'll get attribute data as we need it */
+-}
+-
+-
+-static void mw_aware_list_clear(struct mwAwareList *list) {
+- ; /* nothing for now */
+-}
+-
+-
+-static struct mwAwareListHandler mw_aware_list_handler = {
+- mw_aware_list_on_aware,
+- mw_aware_list_on_attrib,
+- mw_aware_list_clear,
+-};
+-
+-
+-/** Ensures that an Aware List is associated with the given group, and
+- returns that list. */
+-static struct mwAwareList *
+-list_ensure(struct mwPurplePluginData *pd, PurpleGroup *group) {
+-
+- struct mwAwareList *list;
+-
+- g_return_val_if_fail(pd != NULL, NULL);
+- g_return_val_if_fail(group != NULL, NULL);
+-
+- list = g_hash_table_lookup(pd->group_list_map, group);
+- if(! list) {
+- list = mwAwareList_new(pd->srvc_aware, &mw_aware_list_handler);
+- mwAwareList_setClientData(list, pd->gc, NULL);
+-
+- mwAwareList_watchAttributes(list,
+- mwAttribute_AV_PREFS_SET,
+- mwAttribute_MICROPHONE,
+- mwAttribute_SPEAKERS,
+- mwAttribute_VIDEO_CAMERA,
+- mwAttribute_FILE_TRANSFER,
+- NULL);
+-
+- g_hash_table_replace(pd->group_list_map, group, list);
+- g_hash_table_insert(pd->group_list_map, list, group);
+- }
+-
+- return list;
+-}
+-
+-
+-static void blist_export(PurpleConnection *gc, struct mwSametimeList *stlist) {
+- /* - find the account for this connection
+- - iterate through the buddy list
+- - add each buddy matching this account to the stlist
+- */
+-
+- PurpleAccount *acct;
+- PurpleBlistNode *gn, *cn, *bn;
+- PurpleGroup *grp;
+- PurpleBuddy *bdy;
+-
+- struct mwSametimeGroup *stg = NULL;
+- struct mwIdBlock idb = { NULL, NULL };
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- for(gn = purple_blist_get_root(); gn;
+- gn = purple_blist_node_get_sibling_next(gn)) {
+- const char *owner;
+- const char *gname;
+- enum mwSametimeGroupType gtype;
+- gboolean gopen;
+-
+- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
+- grp = (PurpleGroup *) gn;
+-
+- /* the group's type (normal or dynamic) */
+- gtype = purple_blist_node_get_int(gn, GROUP_KEY_TYPE);
+- if(! gtype) gtype = mwSametimeGroup_NORMAL;
+-
+- /* if it's a normal group with none of our people in it, skip it */
+- if(gtype == mwSametimeGroup_NORMAL && !purple_group_on_account(grp, acct))
+- continue;
+-
+- /* if the group has an owner and we're not it, skip it */
+- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
+- if(owner && strcmp(owner, purple_account_get_username(acct)))
+- continue;
+-
+- /* the group's actual name may be different from the purple group's
+- name. Find whichever is there */
+- gname = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
+- if(! gname) gname = purple_group_get_name(grp);
+-
+- /* we save this, but never actually honor it */
+- gopen = ! purple_blist_node_get_bool(gn, GROUP_KEY_COLLAPSED);
+-
+- stg = mwSametimeGroup_new(stlist, gtype, gname);
+- mwSametimeGroup_setAlias(stg, purple_group_get_name(grp));
+- mwSametimeGroup_setOpen(stg, gopen);
+-
+- /* don't attempt to put buddies in a dynamic group, it breaks
+- other clients */
+- if(gtype == mwSametimeGroup_DYNAMIC)
+- continue;
+-
+- for(cn = purple_blist_node_get_first_child(gn);
+- cn;
+- cn = purple_blist_node_get_sibling_next(cn)) {
+- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
+-
+- for(bn = purple_blist_node_get_first_child(cn);
+- bn;
+- bn = purple_blist_node_get_sibling_next(bn)) {
+- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
+- if(! PURPLE_BLIST_NODE_SHOULD_SAVE(bn)) continue;
+-
+- bdy = (PurpleBuddy *) bn;
+-
+- if(purple_buddy_get_account(bdy) == acct) {
+- struct mwSametimeUser *stu;
+- enum mwSametimeUserType utype;
+-
+- idb.user = (char *)purple_buddy_get_name(bdy);
+-
+- utype = purple_blist_node_get_int(bn, BUDDY_KEY_TYPE);
+- if(! utype) utype = mwSametimeUser_NORMAL;
+-
+- stu = mwSametimeUser_new(stg, utype, &idb);
+- mwSametimeUser_setShortName(stu, purple_buddy_get_server_alias(bdy));
+- mwSametimeUser_setAlias(stu, purple_buddy_get_local_buddy_alias(bdy));
+- }
+- }
+- }
+- }
+-}
+-
+-
+-static void blist_store(struct mwPurplePluginData *pd) {
+-
+- struct mwSametimeList *stlist;
+- struct mwServiceStorage *srvc;
+- struct mwStorageUnit *unit;
+-
+- PurpleConnection *gc;
+-
+- struct mwPutBuffer *b;
+- struct mwOpaque *o;
+-
+- g_return_if_fail(pd != NULL);
+-
+- srvc = pd->srvc_store;
+- g_return_if_fail(srvc != NULL);
+-
+- gc = pd->gc;
+-
+- if(BLIST_PREF_IS_LOCAL() || BLIST_PREF_IS_MERGE()) {
+- DEBUG_INFO("preferences indicate not to save remote blist\n");
+- return;
+-
+- } else if(MW_SERVICE_IS_DEAD(srvc)) {
+- DEBUG_INFO("aborting save of blist: storage service is not alive\n");
+- return;
+-
+- } else if(BLIST_PREF_IS_STORE() || BLIST_PREF_IS_SYNCH()) {
+- DEBUG_INFO("saving remote blist\n");
+-
+- } else {
+- g_return_if_reached();
+- }
+-
+- /* create and export to a list object */
+- stlist = mwSametimeList_new();
+- blist_export(gc, stlist);
+-
+- /* write it to a buffer */
+- b = mwPutBuffer_new();
+- mwSametimeList_put(b, stlist);
+- mwSametimeList_free(stlist);
+-
+- /* put the buffer contents into a storage unit */
+- unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+- o = mwStorageUnit_asOpaque(unit);
+- mwPutBuffer_finalize(o, b);
+-
+- /* save the storage unit to the service */
+- mwServiceStorage_save(srvc, unit, NULL, NULL, NULL);
+-}
+-
+-
+-static gboolean blist_save_cb(gpointer data) {
+- struct mwPurplePluginData *pd = data;
+-
+- blist_store(pd);
+- pd->save_event = 0;
+- return FALSE;
+-}
+-
+-
+-/** schedules the buddy list to be saved to the server */
+-static void blist_schedule(struct mwPurplePluginData *pd) {
+- if(pd->save_event) return;
+-
+- pd->save_event = purple_timeout_add_seconds(BLIST_SAVE_SECONDS,
+- blist_save_cb, pd);
+-}
+-
+-
+-static gboolean buddy_is_external(PurpleBuddy *b) {
+- g_return_val_if_fail(b != NULL, FALSE);
+- return purple_str_has_prefix(purple_buddy_get_name(b), "@E ");
+-}
+-
+-
+-/** Actually add a buddy to the aware service, and schedule the buddy
+- list to be saved to the server */
+-static void buddy_add(struct mwPurplePluginData *pd,
+- PurpleBuddy *buddy) {
+-
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *) purple_buddy_get_name(buddy), NULL };
+- struct mwAwareList *list;
+-
+- PurpleGroup *group;
+- GList *add;
+-
+- add = g_list_prepend(NULL, &idb);
+-
+- group = purple_buddy_get_group(buddy);
+- list = list_ensure(pd, group);
+-
+- if(mwAwareList_addAware(list, add)) {
+- purple_blist_remove_buddy(buddy);
+- }
+-
+- blist_schedule(pd);
+-
+- g_list_free(add);
+-}
+-
+-
+-/** ensure that a PurpleBuddy exists in the group with data
+- appropriately matching the st user entry from the st list */
+-static PurpleBuddy *buddy_ensure(PurpleConnection *gc, PurpleGroup *group,
+- struct mwSametimeUser *stuser) {
+-
+- struct mwPurplePluginData *pd = gc->proto_data;
+- PurpleBuddy *buddy;
+- PurpleAccount *acct = purple_connection_get_account(gc);
+-
+- const char *id = mwSametimeUser_getUser(stuser);
+- const char *name = mwSametimeUser_getShortName(stuser);
+- const char *alias = mwSametimeUser_getAlias(stuser);
+- enum mwSametimeUserType type = mwSametimeUser_getType(stuser);
+-
+- g_return_val_if_fail(id != NULL, NULL);
+- g_return_val_if_fail(strlen(id) > 0, NULL);
+-
+- buddy = purple_find_buddy_in_group(acct, id, group);
+- if(! buddy) {
+- buddy = purple_buddy_new(acct, id, alias);
+-
+- purple_blist_add_buddy(buddy, NULL, group, NULL);
+- buddy_add(pd, buddy);
+- }
+-
+- purple_blist_alias_buddy(buddy, alias);
+- purple_blist_server_alias_buddy(buddy, name);
+- purple_blist_node_set_string((PurpleBlistNode *) buddy, BUDDY_KEY_NAME, name);
+- purple_blist_node_set_int((PurpleBlistNode *) buddy, BUDDY_KEY_TYPE, type);
+-
+- return buddy;
+-}
+-
+-
+-/** add aware watch for a dynamic group */
+-static void group_add(struct mwPurplePluginData *pd,
+- PurpleGroup *group) {
+-
+- struct mwAwareIdBlock idb = { mwAware_GROUP, NULL, NULL };
+- struct mwAwareList *list;
+- const char *n;
+- GList *add;
+-
+- n = purple_blist_node_get_string((PurpleBlistNode *) group, GROUP_KEY_NAME);
+- if(! n) n = purple_group_get_name(group);
+-
+- idb.user = (char *) n;
+- add = g_list_prepend(NULL, &idb);
+-
+- list = list_ensure(pd, group);
+- mwAwareList_addAware(list, add);
+- g_list_free(add);
+-}
+-
+-
+-/** ensure that a PurpleGroup exists in the blist with data
+- appropriately matching the st group entry from the st list */
+-static PurpleGroup *group_ensure(PurpleConnection *gc,
+- struct mwSametimeGroup *stgroup) {
+- PurpleAccount *acct;
+- PurpleGroup *group = NULL;
+- PurpleBuddyList *blist;
+- PurpleBlistNode *gn;
+- const char *name, *alias, *owner;
+- enum mwSametimeGroupType type;
+-
+- acct = purple_connection_get_account(gc);
+- owner = purple_account_get_username(acct);
+-
+- blist = purple_get_blist();
+- g_return_val_if_fail(blist != NULL, NULL);
+-
+- name = mwSametimeGroup_getName(stgroup);
+- alias = mwSametimeGroup_getAlias(stgroup);
+- type = mwSametimeGroup_getType(stgroup);
+-
+- if (!name) {
+- DEBUG_WARN("Can't ensure a null group\n");
+- return NULL;
+- }
+-
+- if (!name) {
+- DEBUG_WARN("Can't ensure a null group\n");
+- return NULL;
+- }
+-
+- DEBUG_INFO("attempting to ensure group %s, called %s\n",
+- NSTR(name), NSTR(alias));
+-
+- /* first attempt at finding the group, by the name key */
+- for(gn = purple_blist_get_root(); gn;
+- gn = purple_blist_node_get_sibling_next(gn)) {
+- const char *n, *o;
+- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
+- n = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
+- o = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
+-
+- DEBUG_INFO("found group named %s, owned by %s\n", NSTR(n), NSTR(o));
+-
+- if(n && !strcmp(n, name)) {
+- if(!o || !strcmp(o, owner)) {
+- DEBUG_INFO("that'll work\n");
+- group = (PurpleGroup *) gn;
+- break;
+- }
+- }
+- }
+-
+- /* try again, by alias */
+- if(! group) {
+- DEBUG_INFO("searching for group by alias %s\n", NSTR(alias));
+- group = purple_find_group(alias);
+- }
+-
+- /* oh well, no such group. Let's create it! */
+- if(! group) {
+- DEBUG_INFO("creating group\n");
+- group = purple_group_new(alias);
+- purple_blist_add_group(group, NULL);
+- }
+-
+- gn = (PurpleBlistNode *) group;
+- purple_blist_node_set_string(gn, GROUP_KEY_NAME, name);
+- purple_blist_node_set_int(gn, GROUP_KEY_TYPE, type);
+-
+- if(type == mwSametimeGroup_DYNAMIC) {
+- purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner);
+- group_add(gc->proto_data, group);
+- }
+-
+- return group;
+-}
+-
+-
+-/** merge the entries from a st list into the purple blist */
+-static void blist_merge(PurpleConnection *gc, struct mwSametimeList *stlist) {
+- struct mwSametimeGroup *stgroup;
+- struct mwSametimeUser *stuser;
+-
+- PurpleGroup *group;
+- PurpleBuddy *buddy;
+-
+- GList *gl, *gtl, *ul, *utl;
+-
+- gl = gtl = mwSametimeList_getGroups(stlist);
+- for(; gl; gl = gl->next) {
+-
+- stgroup = (struct mwSametimeGroup *) gl->data;
+- group = group_ensure(gc, stgroup);
+-
+- ul = utl = mwSametimeGroup_getUsers(stgroup);
+- for(; ul; ul = ul->next) {
+-
+- stuser = (struct mwSametimeUser *) ul->data;
+- buddy = buddy_ensure(gc, group, stuser);
+- }
+- g_list_free(utl);
+- }
+- g_list_free(gtl);
+-}
+-
+-
+-/** remove all buddies on account from group. If del is TRUE and group
+- is left empty, remove group as well */
+-static void group_clear(PurpleGroup *group, PurpleAccount *acct, gboolean del) {
+- PurpleConnection *gc;
+- GList *prune = NULL;
+- PurpleBlistNode *gn, *cn, *bn;
+-
+- g_return_if_fail(group != NULL);
+-
+- DEBUG_INFO("clearing members from pruned group %s\n", NSTR(purple_group_get_name(group)));
+-
+- gc = purple_account_get_connection(acct);
+- g_return_if_fail(gc != NULL);
+-
+- gn = (PurpleBlistNode *) group;
+-
+- for(cn = purple_blist_node_get_first_child(gn);
+- cn;
+- cn = purple_blist_node_get_sibling_next(cn)) {
+- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
+-
+- for(bn = purple_blist_node_get_first_child(cn);
+- bn;
+- bn = purple_blist_node_get_sibling_next(bn)) {
+- PurpleBuddy *gb = (PurpleBuddy *) bn;
+-
+- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
+-
+- if(purple_buddy_get_account(gb) == acct) {
+- DEBUG_INFO("clearing %s from group\n", NSTR(purple_buddy_get_name(gb)));
+- prune = g_list_prepend(prune, gb);
+- }
+- }
+- }
+-
+- /* quickly unsubscribe from presence for the entire group */
+- purple_account_remove_group(acct, group);
+-
+- /* remove blist entries that need to go */
+- while(prune) {
+- purple_blist_remove_buddy(prune->data);
+- prune = g_list_delete_link(prune, prune);
+- }
+- DEBUG_INFO("cleared buddies\n");
+-
+- /* optionally remove group from blist */
+- if(del && !purple_blist_get_group_size(group, TRUE)) {
+- DEBUG_INFO("removing empty group\n");
+- purple_blist_remove_group(group);
+- }
+-}
+-
+-
+-/** prune out group members that shouldn't be there */
+-static void group_prune(PurpleConnection *gc, PurpleGroup *group,
+- struct mwSametimeGroup *stgroup) {
+-
+- PurpleAccount *acct;
+- PurpleBlistNode *gn, *cn, *bn;
+-
+- GHashTable *stusers;
+- GList *prune = NULL;
+- GList *ul, *utl;
+-
+- g_return_if_fail(group != NULL);
+-
+- DEBUG_INFO("pruning membership of group %s\n", NSTR(purple_group_get_name(group)));
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- stusers = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- /* build a hash table for quick lookup while pruning the group
+- contents */
+- utl = mwSametimeGroup_getUsers(stgroup);
+- for(ul = utl; ul; ul = ul->next) {
+- const char *id = mwSametimeUser_getUser(ul->data);
+- g_hash_table_insert(stusers, (char *) id, ul->data);
+- DEBUG_INFO("server copy has %s\n", NSTR(id));
+- }
+- g_list_free(utl);
+-
+- gn = (PurpleBlistNode *) group;
+-
+- for(cn = purple_blist_node_get_first_child(gn);
+- cn;
+- cn = purple_blist_node_get_sibling_next(cn)) {
+- if(! PURPLE_BLIST_NODE_IS_CONTACT(cn)) continue;
+-
+- for(bn = purple_blist_node_get_first_child(cn);
+- bn;
+- bn = purple_blist_node_get_sibling_next(bn)) {
+- PurpleBuddy *gb = (PurpleBuddy *) bn;
+-
+- if(! PURPLE_BLIST_NODE_IS_BUDDY(bn)) continue;
+-
+- /* if the account is correct and they're not in our table, mark
+- them for pruning */
+- if(purple_buddy_get_account(gb) == acct && !g_hash_table_lookup(stusers, purple_buddy_get_name(gb))) {
+- DEBUG_INFO("marking %s for pruning\n", NSTR(purple_buddy_get_name(gb)));
+- prune = g_list_prepend(prune, gb);
+- }
+- }
+- }
+- DEBUG_INFO("done marking\n");
+-
+- g_hash_table_destroy(stusers);
+-
+- if(prune) {
+- purple_account_remove_buddies(acct, prune, NULL);
+- while(prune) {
+- purple_blist_remove_buddy(prune->data);
+- prune = g_list_delete_link(prune, prune);
+- }
+- }
+-}
+-
+-
+-/** synch the entries from a st list into the purple blist, removing any
+- existing buddies that aren't in the st list */
+-static void blist_sync(PurpleConnection *gc, struct mwSametimeList *stlist) {
+-
+- PurpleAccount *acct;
+- PurpleBuddyList *blist;
+- PurpleBlistNode *gn;
+-
+- GHashTable *stgroups;
+- GList *g_prune = NULL;
+-
+- GList *gl, *gtl;
+-
+- const char *acct_n;
+-
+- DEBUG_INFO("synchronizing local buddy list from server list\n");
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- acct_n = purple_account_get_username(acct);
+-
+- blist = purple_get_blist();
+- g_return_if_fail(blist != NULL);
+-
+- /* build a hash table for quick lookup while pruning the local
+- list, mapping group name to group structure */
+- stgroups = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- gtl = mwSametimeList_getGroups(stlist);
+- for(gl = gtl; gl; gl = gl->next) {
+- const char *name = mwSametimeGroup_getName(gl->data);
+- g_hash_table_insert(stgroups, (char *) name, gl->data);
+- }
+- g_list_free(gtl);
+-
+- /* find all groups which should be pruned from the local list */
+- for(gn = purple_blist_get_root(); gn;
+- gn = purple_blist_node_get_sibling_next(gn)) {
+- PurpleGroup *grp = (PurpleGroup *) gn;
+- const char *gname, *owner;
+- struct mwSametimeGroup *stgrp;
+-
+- if(! PURPLE_BLIST_NODE_IS_GROUP(gn)) continue;
+-
+- /* group not belonging to this account */
+- if(! purple_group_on_account(grp, acct))
+- continue;
+-
+- /* dynamic group belonging to this account. don't prune contents */
+- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
+- if(owner && !strcmp(owner, acct_n))
+- continue;
+-
+- /* we actually are synching by this key as opposed to the group
+- title, which can be different things in the st list */
+- gname = purple_blist_node_get_string(gn, GROUP_KEY_NAME);
+- if(! gname) gname = purple_group_get_name(grp);
+-
+- stgrp = g_hash_table_lookup(stgroups, gname);
+- if(! stgrp) {
+- /* remove the whole group */
+- DEBUG_INFO("marking group %s for pruning\n", purple_group_get_name(grp));
+- g_prune = g_list_prepend(g_prune, grp);
+-
+- } else {
+- /* synch the group contents */
+- group_prune(gc, grp, stgrp);
+- }
+- }
+- DEBUG_INFO("done marking groups\n");
+-
+- /* don't need this anymore */
+- g_hash_table_destroy(stgroups);
+-
+- /* prune all marked groups */
+- while(g_prune) {
+- PurpleGroup *grp = g_prune->data;
+- PurpleBlistNode *gn = (PurpleBlistNode *) grp;
+- const char *owner;
+- gboolean del = TRUE;
+-
+- owner = purple_blist_node_get_string(gn, GROUP_KEY_OWNER);
+- if(owner && strcmp(owner, acct_n)) {
+- /* it's a specialty group belonging to another account with some
+- of our members in it, so don't fully delete it */
+- del = FALSE;
+- }
+-
+- group_clear(g_prune->data, acct, del);
+- g_prune = g_list_delete_link(g_prune, g_prune);
+- }
+-
+- /* done with the pruning, let's merge in the additions */
+- blist_merge(gc, stlist);
+-}
+-
+-
+-/** callback passed to the storage service when it's told to load the
+- st list */
+-static void fetch_blist_cb(struct mwServiceStorage *srvc,
+- guint32 result, struct mwStorageUnit *item,
+- gpointer data) {
+-
+- struct mwPurplePluginData *pd = data;
+- struct mwSametimeList *stlist;
+-
+- struct mwGetBuffer *b;
+-
+- g_return_if_fail(result == ERR_SUCCESS);
+-
+- /* check our preferences for loading */
+- if(BLIST_PREF_IS_LOCAL()) {
+- DEBUG_INFO("preferences indicate not to load remote buddy list\n");
+- return;
+- }
+-
+- b = mwGetBuffer_wrap(mwStorageUnit_asOpaque(item));
+-
+- stlist = mwSametimeList_new();
+- mwSametimeList_get(b, stlist);
+-
+- /* merge or synch depending on preferences */
+- if(BLIST_PREF_IS_MERGE() || BLIST_PREF_IS_STORE()) {
+- blist_merge(pd->gc, stlist);
+-
+- } else if(BLIST_PREF_IS_SYNCH()) {
+- blist_sync(pd->gc, stlist);
+- }
+-
+- mwSametimeList_free(stlist);
+- mwGetBuffer_free(b);
+-}
+-
+-
+-/** signal triggered when a conversation is opened in Purple */
+-static void conversation_created_cb(PurpleConversation *g_conv,
+- struct mwPurplePluginData *pd) {
+-
+- /* we need to tell the IM service to negotiate features for the
+- conversation right away, otherwise it'll wait until the first
+- message is sent before offering NotesBuddy features. Therefore
+- whenever Purple creates a conversation, we'll immediately open the
+- channel to the other side and figure out what the target can
+- handle. Unfortunately, this makes us vulnerable to Psychic Mode,
+- whereas a more lazy negotiation based on the first message
+- would not */
+-
+- PurpleConnection *gc;
+- struct mwIdBlock who = { 0, 0 };
+- struct mwConversation *conv;
+-
+- gc = purple_conversation_get_gc(g_conv);
+- if(pd->gc != gc)
+- return; /* not ours */
+-
+- if(purple_conversation_get_type(g_conv) != PURPLE_CONV_TYPE_IM)
+- return; /* wrong type */
+-
+- who.user = (char *) purple_conversation_get_name(g_conv);
+- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
+-
+- convo_features(conv);
+-
+- if(mwConversation_isClosed(conv))
+- mwConversation_open(conv);
+-}
+-
+-
+-static void blist_menu_nab(PurpleBlistNode *node, gpointer data) {
+- struct mwPurplePluginData *pd = data;
+- PurpleConnection *gc;
+-
+- PurpleGroup *group = (PurpleGroup *) node;
+-
+- GString *str;
+- char *tmp;
+- const char *gname;
+-
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+- g_return_if_fail(gc != NULL);
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_GROUP(node));
+-
+- str = g_string_new(NULL);
+-
+- tmp = (char *) purple_blist_node_get_string(node, GROUP_KEY_NAME);
+- gname = purple_group_get_name(group);
+-
+- g_string_append_printf(str, _("<b>Group Title:</b> %s<br>"), gname);
+- g_string_append_printf(str, _("<b>Notes Group ID:</b> %s<br>"), tmp);
+-
+- tmp = g_strdup_printf(_("Info for Group %s"), gname);
+-
+- purple_notify_formatted(gc, tmp, _("Notes Address Book Information"),
+- NULL, str->str, NULL, NULL);
+-
+- g_free(tmp);
+- g_string_free(str, TRUE);
+-}
+-
+-
+-/** The normal blist menu prpl function doesn't get called for groups,
+- so we use the blist-node-extended-menu signal to trigger this
+- handler */
+-static void blist_node_menu_cb(PurpleBlistNode *node,
+- GList **menu, struct mwPurplePluginData *pd) {
+- const char *owner;
+- PurpleGroup *group;
+- PurpleAccount *acct;
+- PurpleMenuAction *act;
+-
+- /* we only want groups */
+- if(! PURPLE_BLIST_NODE_IS_GROUP(node)) return;
+- group = (PurpleGroup *) node;
+-
+- acct = purple_connection_get_account(pd->gc);
+- g_return_if_fail(acct != NULL);
+-
+- /* better make sure we're connected */
+- if(! purple_account_is_connected(acct)) return;
+-
+-#if 0
+- /* if there's anyone in the group for this acct, offer to invite
+- them all to a conference */
+- if(purple_group_on_account(group, acct)) {
+- act = purple_menu_action_new(_("Invite Group to Conference..."),
+- PURPLE_CALLBACK(blist_menu_group_invite),
+- pd, NULL);
+- *menu = g_list_append(*menu, NULL);
+- }
+-#endif
+-
+- /* check if it's a NAB group for this account */
+- owner = purple_blist_node_get_string(node, GROUP_KEY_OWNER);
+- if(owner && !strcmp(owner, purple_account_get_username(acct))) {
+- act = purple_menu_action_new(_("Get Notes Address Book Info"),
+- PURPLE_CALLBACK(blist_menu_nab), pd, NULL);
+- *menu = g_list_append(*menu, act);
+- }
+-}
+-
+-
+-/* lifted this from oldstatus, since HEAD doesn't do this at login
+- anymore. */
+-static void blist_init(PurpleAccount *acct) {
+- PurpleBlistNode *gnode, *cnode, *bnode;
+- GList *add_buds = NULL;
+-
+- for(gnode = purple_blist_get_root(); gnode;
+- gnode = purple_blist_node_get_sibling_next(gnode)) {
+- if(! PURPLE_BLIST_NODE_IS_GROUP(gnode)) continue;
+-
+- for(cnode = purple_blist_node_get_first_child(gnode);
+- cnode;
+- cnode = purple_blist_node_get_sibling_next(cnode)) {
+- if(! PURPLE_BLIST_NODE_IS_CONTACT(cnode))
+- continue;
+- for(bnode = purple_blist_node_get_first_child(cnode);
+- bnode;
+- bnode = purple_blist_node_get_sibling_next(bnode)) {
+- PurpleBuddy *b;
+- if(!PURPLE_BLIST_NODE_IS_BUDDY(bnode))
+- continue;
+-
+- b = (PurpleBuddy *)bnode;
+- if(purple_buddy_get_account(b) == acct) {
+- add_buds = g_list_append(add_buds, b);
+- }
+- }
+- }
+- }
+-
+- if(add_buds) {
+- purple_account_add_buddies(acct, add_buds);
+- g_list_free(add_buds);
+- }
+-}
+-
+-
+-/** Last thing to happen from a started session */
+-static void services_starting(struct mwPurplePluginData *pd) {
+-
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+- struct mwStorageUnit *unit;
+- PurpleBlistNode *l;
+-
+- gc = pd->gc;
+- acct = purple_connection_get_account(gc);
+-
+- /* grab the buddy list from the server */
+- unit = mwStorageUnit_new(mwStore_AWARE_LIST);
+- mwServiceStorage_load(pd->srvc_store, unit, fetch_blist_cb, pd, NULL);
+-
+- /* find all the NAB groups and subscribe to them */
+- for(l = purple_blist_get_root(); l;
+- l = purple_blist_node_get_sibling_next(l)) {
+- PurpleGroup *group = (PurpleGroup *) l;
+- enum mwSametimeGroupType gt;
+- const char *owner;
+-
+- if(! PURPLE_BLIST_NODE_IS_GROUP(l)) continue;
+-
+- /* if the group is ownerless, or has an owner and we're not it,
+- skip it */
+- owner = purple_blist_node_get_string(l, GROUP_KEY_OWNER);
+- if(!owner || strcmp(owner, purple_account_get_username(acct)))
+- continue;
+-
+- gt = purple_blist_node_get_int(l, GROUP_KEY_TYPE);
+- if(gt == mwSametimeGroup_DYNAMIC)
+- group_add(pd, group);
+- }
+-
+- /* set the aware attributes */
+- /* indicate we understand what AV prefs are, but don't support any */
+- mwServiceAware_setAttributeBoolean(pd->srvc_aware,
+- mwAttribute_AV_PREFS_SET, TRUE);
+- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_MICROPHONE);
+- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_SPEAKERS);
+- mwServiceAware_unsetAttribute(pd->srvc_aware, mwAttribute_VIDEO_CAMERA);
+-
+- /* ... but we can do file transfers! */
+- mwServiceAware_setAttributeBoolean(pd->srvc_aware,
+- mwAttribute_FILE_TRANSFER, TRUE);
+-
+- blist_init(acct);
+-}
+-
+-
+-static void session_loginRedirect(struct mwSession *session,
+- const char *host) {
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- guint port;
+- const char *current_host;
+-
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+- account = purple_connection_get_account(gc);
+- port = purple_account_get_int(account, MW_KEY_PORT, MW_PLUGIN_DEFAULT_PORT);
+- current_host = purple_account_get_string(account, MW_KEY_HOST,
+- MW_PLUGIN_DEFAULT_HOST);
+-
+- if(purple_account_get_bool(account, MW_KEY_FORCE, FALSE) ||
+- !host || (! strcmp(current_host, host)) ||
+- (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL)) {
+-
+- /* if we're configured to force logins, or if we're being
+- redirected to the already configured host, or if we couldn't
+- connect to the new host, we'll force the login instead */
+-
+- mwSession_forceLogin(session);
+- }
+-}
+-
+-
+-static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status);
+-
+-
+-/** called from mw_session_stateChange when the session's state is
+- mwSession_STARTED. Any finalizing of start-up stuff should go
+- here */
+-static void session_started(struct mwPurplePluginData *pd) {
+- PurpleStatus *status;
+- PurpleAccount *acct;
+-
+- /* set out initial status */
+- acct = purple_connection_get_account(pd->gc);
+- status = purple_account_get_active_status(acct);
+- mw_prpl_set_status(acct, status);
+-
+- /* start watching for new conversations */
+- purple_signal_connect(purple_conversations_get_handle(),
+- "conversation-created", pd,
+- PURPLE_CALLBACK(conversation_created_cb), pd);
+-
+- /* watch for group extended menu items */
+- purple_signal_connect(purple_blist_get_handle(),
+- "blist-node-extended-menu", pd,
+- PURPLE_CALLBACK(blist_node_menu_cb), pd);
+-
+- /* use our services to do neat things */
+- services_starting(pd);
+-}
+-
+-
+-static void session_stopping(struct mwPurplePluginData *pd) {
+- /* stop watching the signals from session_started */
+- purple_signals_disconnect_by_handle(pd);
+-}
+-
+-
+-static void mw_session_stateChange(struct mwSession *session,
+- enum mwSessionState state,
+- gpointer info) {
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- const char *msg = NULL;
+-
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- switch(state) {
+- case mwSession_STARTING:
+- msg = _("Sending Handshake");
+- purple_connection_update_progress(gc, msg, 2, MW_CONNECT_STEPS);
+- break;
+-
+- case mwSession_HANDSHAKE:
+- msg = _("Waiting for Handshake Acknowledgement");
+- purple_connection_update_progress(gc, msg, 3, MW_CONNECT_STEPS);
+- break;
+-
+- case mwSession_HANDSHAKE_ACK:
+- msg = _("Handshake Acknowledged, Sending Login");
+- purple_connection_update_progress(gc, msg, 4, MW_CONNECT_STEPS);
+- break;
+-
+- case mwSession_LOGIN:
+- msg = _("Waiting for Login Acknowledgement");
+- purple_connection_update_progress(gc, msg, 5, MW_CONNECT_STEPS);
+- break;
+-
+- case mwSession_LOGIN_REDIR:
+- msg = _("Login Redirected");
+- purple_connection_update_progress(gc, msg, 6, MW_CONNECT_STEPS);
+- session_loginRedirect(session, info);
+- break;
+-
+- case mwSession_LOGIN_CONT:
+- msg = _("Forcing Login");
+- purple_connection_update_progress(gc, msg, 7, MW_CONNECT_STEPS);
+-
+- case mwSession_LOGIN_ACK:
+- msg = _("Login Acknowledged");
+- purple_connection_update_progress(gc, msg, 8, MW_CONNECT_STEPS);
+- break;
+-
+- case mwSession_STARTED:
+- msg = _("Starting Services");
+- purple_connection_update_progress(gc, msg, 9, MW_CONNECT_STEPS);
+-
+- session_started(pd);
+-
+- msg = _("Connected");
+- purple_connection_update_progress(gc, msg, 10, MW_CONNECT_STEPS);
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+- break;
+-
+- case mwSession_STOPPING:
+-
+- session_stopping(pd);
+-
+- if(GPOINTER_TO_UINT(info) & ERR_FAILURE) {
+- char *err = mwError(GPOINTER_TO_UINT(info));
+- PurpleConnectionError reason;
+- switch (GPOINTER_TO_UINT(info)) {
+- case VERSION_MISMATCH:
+- reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+-
+- case USER_RESTRICTED:
+- case INCORRECT_LOGIN:
+- case USER_UNREGISTERED:
+- case GUEST_IN_USE:
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+-
+- case ENCRYPT_MISMATCH:
+- case ERR_ENCRYPT_NO_SUPPORT:
+- case ERR_NO_COMMON_ENCRYPT:
+- reason = PURPLE_CONNECTION_ERROR_ENCRYPTION_ERROR;
+- break;
+-
+- case VERIFICATION_DOWN:
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_IMPOSSIBLE;
+- break;
+-
+- case MULTI_SERVER_LOGIN:
+- case MULTI_SERVER_LOGIN2:
+- reason = PURPLE_CONNECTION_ERROR_NAME_IN_USE;
+- break;
+-
+- default:
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- }
+- purple_connection_error_reason(gc, reason, err);
+- g_free(err);
+- }
+- break;
+-
+- case mwSession_STOPPED:
+- break;
+-
+- case mwSession_UNKNOWN:
+- default:
+- DEBUG_WARN("session in unknown state\n");
+- }
+-}
+-
+-
+-static void mw_session_setPrivacyInfo(struct mwSession *session) {
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+- struct mwPrivacyInfo *privacy;
+- GSList *l, **ll;
+- guint count;
+-
+- DEBUG_INFO("privacy information set from server\n");
+-
+- g_return_if_fail(session != NULL);
+-
+- pd = mwSession_getClientData(session);
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+- g_return_if_fail(gc != NULL);
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- privacy = mwSession_getPrivacyInfo(session);
+- count = privacy->count;
+-
+- ll = (privacy->deny)? &acct->deny: &acct->permit;
+- for(l = *ll; l; l = l->next) g_free(l->data);
+- g_slist_free(*ll);
+- l = *ll = NULL;
+-
+- while(count--) {
+- struct mwUserItem *u = privacy->users + count;
+- l = g_slist_prepend(l, g_strdup(u->id));
+- }
+- *ll = l;
+-}
+-
+-
+-static void mw_session_setUserStatus(struct mwSession *session) {
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- struct mwAwareIdBlock idb = { mwAware_USER, NULL, NULL };
+- struct mwUserStatus *stat;
+-
+- g_return_if_fail(session != NULL);
+-
+- pd = mwSession_getClientData(session);
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+- g_return_if_fail(gc != NULL);
+-
+- idb.user = mwSession_getProperty(session, mwSession_AUTH_USER_ID);
+- stat = mwSession_getUserStatus(session);
+-
+- /* trigger an update of our own status if we're in the buddy list */
+- mwServiceAware_setStatus(pd->srvc_aware, &idb, stat);
+-}
+-
+-
+-static void mw_session_admin(struct mwSession *session,
+- const char *text) {
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+- const char *host;
+- const char *msg;
+- char *prim;
+-
+- gc = session_to_gc(session);
+- g_return_if_fail(gc != NULL);
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- host = purple_account_get_string(acct, MW_KEY_HOST, NULL);
+-
+- msg = _("A Sametime administrator has issued the following announcement"
+- " on server %s");
+- prim = g_strdup_printf(msg, NSTR(host));
+-
+- purple_notify_message(gc, PURPLE_NOTIFY_MSG_INFO,
+- _("Sametime Administrator Announcement"),
+- prim, text, NULL, NULL);
+-
+- g_free(prim);
+-}
+-
+-
+-/** called from read_cb, attempts to read available data from sock and
+- pass it to the session, passing back the return code from the read
+- call for handling in read_cb */
+-static int read_recv(struct mwSession *session, int sock) {
+- guchar buf[BUF_LEN];
+- int len;
+-
+- len = read(sock, buf, BUF_LEN);
+- if(len > 0) {
+- mwSession_recv(session, buf, len);
+- }
+-
+- return len;
+-}
+-
+-
+-/** callback triggered from purple_input_add, watches the socked for
+- available data to be processed by the session */
+-static void read_cb(gpointer data, gint source, PurpleInputCondition cond) {
+- struct mwPurplePluginData *pd = data;
+- int ret = 0, err = 0;
+-
+- g_return_if_fail(pd != NULL);
+-
+- ret = read_recv(pd->session, pd->socket);
+-
+- /* normal operation ends here */
+- if(ret > 0) return;
+-
+- /* fetch the global error value */
+- err = errno;
+-
+- /* read problem occurred if we're here, so we'll need to take care of
+- it and clean up internal state */
+-
+- if(pd->socket) {
+- close(pd->socket);
+- pd->socket = 0;
+- }
+-
+- if(pd->gc->inpa) {
+- purple_input_remove(pd->gc->inpa);
+- pd->gc->inpa = 0;
+- }
+-
+- if(! ret) {
+- DEBUG_INFO("connection reset\n");
+- purple_connection_error_reason(pd->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Server closed the connection"));
+-
+- } else if(ret < 0) {
+- const gchar *err_str = g_strerror(err);
+- char *msg = NULL;
+-
+- DEBUG_INFO("error in read callback: %s\n", err_str);
+-
+- msg = g_strdup_printf(_("Lost connection with server: %s"), err_str);
+- purple_connection_error_reason(pd->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- msg);
+- g_free(msg);
+- }
+-}
+-
+-
+-/** Callback passed to purple_proxy_connect when an account is logged
+- in, and if the session logging in receives a redirect message */
+-static void connect_cb(gpointer data, gint source, const gchar *error_message) {
+-
+- struct mwPurplePluginData *pd = data;
+- PurpleConnection *gc = pd->gc;
+-
+- if(source < 0) {
+- /* connection failed */
+-
+- if(pd->socket) {
+- /* this is a redirect connect, force login on existing socket */
+- mwSession_forceLogin(pd->session);
+-
+- } else {
+- /* this is a regular connect, error out */
+- gchar *tmp = g_strdup_printf(_("Unable to connect: %s"),
+- error_message);
+- purple_connection_error_reason(pd->gc,
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- tmp);
+- g_free(tmp);
+- }
+-
+- return;
+- }
+-
+- if(pd->socket) {
+- /* stop any existing login attempt */
+- mwSession_stop(pd->session, ERR_SUCCESS);
+- }
+-
+- pd->socket = source;
+- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ,
+- read_cb, pd);
+-
+- mwSession_start(pd->session);
+-}
+-
+-
+-static void mw_session_announce(struct mwSession *s,
+- struct mwLoginInfo *from,
+- gboolean may_reply,
+- const char *text) {
+- struct mwPurplePluginData *pd;
+- PurpleAccount *acct;
+- PurpleConversation *conv;
+- PurpleBuddy *buddy;
+- char *who = from->user_id;
+- char *msg;
+-
+- pd = mwSession_getClientData(s);
+- acct = purple_connection_get_account(pd->gc);
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, acct);
+- if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, who);
+-
+- buddy = purple_find_buddy(acct, who);
+- if(buddy) who = (char *) purple_buddy_get_contact_alias(buddy);
+-
+- who = g_strdup_printf(_("Announcement from %s"), who);
+- msg = purple_markup_linkify(text);
+-
+- purple_conversation_write(conv, who, msg ? msg : "", PURPLE_MESSAGE_RECV, time(NULL));
+- g_free(who);
+- g_free(msg);
+-}
+-
+-
+-static struct mwSessionHandler mw_session_handler = {
+- mw_session_io_write,
+- mw_session_io_close,
+- mw_session_clear,
+- mw_session_stateChange,
+- mw_session_setPrivacyInfo,
+- mw_session_setUserStatus,
+- mw_session_admin,
+- mw_session_announce,
+-};
+-
+-
+-static void mw_aware_on_attrib(struct mwServiceAware *srvc,
+- struct mwAwareAttribute *attrib) {
+-
+- ; /** @todo handle server attributes. There may be some stuff we
+- actually want to look for, but I'm not aware of anything right
+- now.*/
+-}
+-
+-
+-static void mw_aware_clear(struct mwServiceAware *srvc) {
+- ; /* nothing for now */
+-}
+-
+-
+-static struct mwAwareHandler mw_aware_handler = {
+- mw_aware_on_attrib,
+- mw_aware_clear,
+-};
+-
+-
+-static struct mwServiceAware *mw_srvc_aware_new(struct mwSession *s) {
+- struct mwServiceAware *srvc;
+- srvc = mwServiceAware_new(s, &mw_aware_handler);
+- return srvc;
+-};
+-
+-
+-static void mw_conf_invited(struct mwConference *conf,
+- struct mwLoginInfo *inviter,
+- const char *invitation) {
+-
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+-
+- char *c_inviter, *c_name, *c_topic, *c_invitation;
+- GHashTable *ht;
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+-
+- c_inviter = g_strdup(inviter->user_id);
+- g_hash_table_insert(ht, CHAT_KEY_CREATOR, c_inviter);
+-
+- c_name = g_strdup(mwConference_getName(conf));
+- g_hash_table_insert(ht, CHAT_KEY_NAME, c_name);
+-
+- c_topic = g_strdup(mwConference_getTitle(conf));
+- g_hash_table_insert(ht, CHAT_KEY_TOPIC, c_topic);
+-
+- c_invitation = g_strdup(invitation);
+- g_hash_table_insert(ht, CHAT_KEY_INVITE, c_invitation);
+-
+- DEBUG_INFO("received invitation from '%s' to join ('%s','%s'): '%s'\n",
+- NSTR(c_inviter), NSTR(c_name),
+- NSTR(c_topic), NSTR(c_invitation));
+-
+- if(! c_topic) c_topic = "(no title)";
+- if(! c_invitation) c_invitation = "(no message)";
+- serv_got_chat_invite(gc, c_topic, c_inviter, c_invitation, ht);
+-}
+-
+-
+-/* The following mess helps us relate a mwConference to a PurpleConvChat
+- in the various forms by which either may be indicated */
+-
+-#define CONF_TO_ID(conf) (GPOINTER_TO_INT(conf))
+-#define ID_TO_CONF(pd, id) (conf_find_by_id((pd), (id)))
+-
+-#define CHAT_TO_ID(chat) (purple_conv_chat_get_id(chat))
+-#define ID_TO_CHAT(id) (purple_find_chat(id))
+-
+-#define CHAT_TO_CONF(pd, chat) (ID_TO_CONF((pd), CHAT_TO_ID(chat)))
+-#define CONF_TO_CHAT(conf) (ID_TO_CHAT(CONF_TO_ID(conf)))
+-
+-
+-static struct mwConference *
+-conf_find_by_id(struct mwPurplePluginData *pd, int id) {
+-
+- struct mwServiceConference *srvc = pd->srvc_conf;
+- struct mwConference *conf = NULL;
+- GList *l, *ll;
+-
+- ll = mwServiceConference_getConferences(srvc);
+- for(l = ll; l; l = l->next) {
+- struct mwConference *c = l->data;
+- PurpleConvChat *h = mwConference_getClientData(c);
+-
+- if(CHAT_TO_ID(h) == id) {
+- conf = c;
+- break;
+- }
+- }
+- g_list_free(ll);
+-
+- return conf;
+-}
+-
+-
+-static void mw_conf_opened(struct mwConference *conf, GList *members) {
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConversation *g_conf;
+-
+- const char *n = mwConference_getName(conf);
+- const char *t = mwConference_getTitle(conf);
+-
+- DEBUG_INFO("conf %s opened, %u initial members\n",
+- NSTR(n), g_list_length(members));
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- if(! t) t = "(no title)";
+- g_conf = serv_got_joined_chat(gc, CONF_TO_ID(conf), t);
+-
+- mwConference_setClientData(conf, PURPLE_CONV_CHAT(g_conf), NULL);
+-
+- for(; members; members = members->next) {
+- struct mwLoginInfo *peer = members->data;
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(g_conf), peer->user_id,
+- NULL, PURPLE_CBFLAGS_NONE, FALSE);
+- }
+-}
+-
+-
+-static void mw_conf_closed(struct mwConference *conf, guint32 reason) {
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+-
+- const char *n = mwConference_getName(conf);
+- char *msg = mwError(reason);
+-
+- DEBUG_INFO("conf %s closed, 0x%08x\n", NSTR(n), reason);
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- serv_got_chat_left(gc, CONF_TO_ID(conf));
+-
+- purple_notify_error(gc, _("Conference Closed"), NULL, msg);
+- g_free(msg);
+-}
+-
+-
+-static void mw_conf_peer_joined(struct mwConference *conf,
+- struct mwLoginInfo *peer) {
+-
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConvChat *g_conf;
+-
+- const char *n = mwConference_getName(conf);
+-
+- DEBUG_INFO("%s joined conf %s\n", NSTR(peer->user_id), NSTR(n));
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- g_conf = mwConference_getClientData(conf);
+- g_return_if_fail(g_conf != NULL);
+-
+- purple_conv_chat_add_user(g_conf, peer->user_id,
+- NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-
+-static void mw_conf_peer_parted(struct mwConference *conf,
+- struct mwLoginInfo *peer) {
+-
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConvChat *g_conf;
+-
+- const char *n = mwConference_getName(conf);
+-
+- DEBUG_INFO("%s left conf %s\n", NSTR(peer->user_id), NSTR(n));
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- g_conf = mwConference_getClientData(conf);
+- g_return_if_fail(g_conf != NULL);
+-
+- purple_conv_chat_remove_user(g_conf, peer->user_id, NULL);
+-}
+-
+-
+-static void mw_conf_text(struct mwConference *conf,
+- struct mwLoginInfo *who, const char *text) {
+-
+- struct mwServiceConference *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- char *esc;
+-
+- if(! text) return;
+-
+- srvc = mwConference_getService(conf);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- esc = g_markup_escape_text(text, -1);
+- serv_got_chat_in(gc, CONF_TO_ID(conf), who->user_id, 0, esc, time(NULL));
+- g_free(esc);
+-}
+-
+-
+-static void mw_conf_typing(struct mwConference *conf,
+- struct mwLoginInfo *who, gboolean typing) {
+-
+- /* purple really has no good way to expose this to the user. */
+-
+- const char *n = mwConference_getName(conf);
+- const char *w = who->user_id;
+-
+- if(typing) {
+- DEBUG_INFO("%s in conf %s: <typing>\n", NSTR(w), NSTR(n));
+-
+- } else {
+- DEBUG_INFO("%s in conf %s: <stopped typing>\n", NSTR(w), NSTR(n));
+- }
+-}
+-
+-
+-static void mw_conf_clear(struct mwServiceConference *srvc) {
+- ;
+-}
+-
+-
+-static struct mwConferenceHandler mw_conference_handler = {
+- mw_conf_invited,
+- mw_conf_opened,
+- mw_conf_closed,
+- mw_conf_peer_joined,
+- mw_conf_peer_parted,
+- mw_conf_text,
+- mw_conf_typing,
+- mw_conf_clear,
+-};
+-
+-
+-static struct mwServiceConference *mw_srvc_conf_new(struct mwSession *s) {
+- struct mwServiceConference *srvc;
+- srvc = mwServiceConference_new(s, &mw_conference_handler);
+- return srvc;
+-}
+-
+-
+-/** size of an outgoing file transfer chunk */
+-#define MW_FT_LEN (BUF_LONG * 2)
+-
+-
+-static void ft_incoming_cancel(PurpleXfer *xfer) {
+- /* incoming transfer rejected or cancelled in-progress */
+- struct mwFileTransfer *ft = xfer->data;
+- if(ft) mwFileTransfer_reject(ft);
+-}
+-
+-
+-static void ft_incoming_init(PurpleXfer *xfer) {
+- /* incoming transfer accepted */
+-
+- /* - accept the mwFileTransfer
+- - open/create the local FILE "wb"
+- - stick the FILE's fp in xfer->dest_fp
+- */
+-
+- struct mwFileTransfer *ft;
+- FILE *fp;
+-
+- ft = xfer->data;
+-
+- fp = g_fopen(xfer->local_filename, "wb");
+- if(! fp) {
+- mwFileTransfer_cancel(ft);
+- return;
+- }
+-
+- xfer->dest_fp = fp;
+- mwFileTransfer_accept(ft);
+-}
+-
+-
+-static void mw_ft_offered(struct mwFileTransfer *ft) {
+- /*
+- - create a purple ft object
+- - offer it
+- */
+-
+- struct mwServiceFileTransfer *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+- const char *who;
+- PurpleXfer *xfer;
+-
+- /* @todo add some safety checks */
+- srvc = mwFileTransfer_getService(ft);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+- acct = purple_connection_get_account(gc);
+-
+- who = mwFileTransfer_getUser(ft)->user;
+-
+- DEBUG_INFO("file transfer %p offered\n", ft);
+- DEBUG_INFO(" from: %s\n", NSTR(who));
+- DEBUG_INFO(" file: %s\n", NSTR(mwFileTransfer_getFileName(ft)));
+- DEBUG_INFO(" size: %u\n", mwFileTransfer_getFileSize(ft));
+- DEBUG_INFO(" text: %s\n", NSTR(mwFileTransfer_getMessage(ft)));
+-
+- xfer = purple_xfer_new(acct, PURPLE_XFER_RECEIVE, who);
+- if (xfer)
+- {
+- purple_xfer_ref(xfer);
+- mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
+- xfer->data = ft;
+-
+- purple_xfer_set_init_fnc(xfer, ft_incoming_init);
+- purple_xfer_set_cancel_recv_fnc(xfer, ft_incoming_cancel);
+- purple_xfer_set_request_denied_fnc(xfer, ft_incoming_cancel);
+-
+- purple_xfer_set_filename(xfer, mwFileTransfer_getFileName(ft));
+- purple_xfer_set_size(xfer, mwFileTransfer_getFileSize(ft));
+- purple_xfer_set_message(xfer, mwFileTransfer_getMessage(ft));
+-
+- purple_xfer_request(xfer);
+- }
+-}
+-
+-
+-static void ft_send(struct mwFileTransfer *ft, FILE *fp) {
+- guchar buf[MW_FT_LEN];
+- struct mwOpaque o = { MW_FT_LEN, buf };
+- guint32 rem;
+- PurpleXfer *xfer;
+-
+- xfer = mwFileTransfer_getClientData(ft);
+-
+- rem = mwFileTransfer_getRemaining(ft);
+- if(rem < MW_FT_LEN) o.len = rem;
+-
+- if(fread(buf, (size_t) o.len, 1, fp)) {
+-
+- /* calculate progress and display it */
+- xfer->bytes_sent += o.len;
+- xfer->bytes_remaining -= o.len;
+- purple_xfer_update_progress(xfer);
+-
+- mwFileTransfer_send(ft, &o);
+-
+- } else {
+- int err = errno;
+- DEBUG_WARN("problem reading from file %s: %s\n",
+- NSTR(mwFileTransfer_getFileName(ft)), g_strerror(err));
+-
+- mwFileTransfer_cancel(ft);
+- }
+-}
+-
+-
+-static void mw_ft_opened(struct mwFileTransfer *ft) {
+- /*
+- - get purple ft from client data in ft
+- - set the state to active
+- */
+-
+- PurpleXfer *xfer;
+-
+- xfer = mwFileTransfer_getClientData(ft);
+-
+- if(! xfer) {
+- mwFileTransfer_cancel(ft);
+- mwFileTransfer_free(ft);
+- g_return_if_reached();
+- }
+-
+- if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
+- xfer->dest_fp = g_fopen(xfer->local_filename, "rb");
+- ft_send(ft, xfer->dest_fp);
+- }
+-}
+-
+-
+-static void mw_ft_closed(struct mwFileTransfer *ft, guint32 code) {
+- /*
+- - get purple ft from client data in ft
+- - indicate rejection/cancelation/completion
+- - free the file transfer itself
+- */
+-
+- PurpleXfer *xfer;
+-
+- xfer = mwFileTransfer_getClientData(ft);
+- if(xfer) {
+- xfer->data = NULL;
+-
+- if(! mwFileTransfer_getRemaining(ft)) {
+- purple_xfer_set_completed(xfer, TRUE);
+- purple_xfer_end(xfer);
+-
+- } else if(mwFileTransfer_isCancelLocal(ft)) {
+- /* calling purple_xfer_cancel_local is redundant, since that's
+- probably what triggered this function to be called */
+- ;
+-
+- } else if(mwFileTransfer_isCancelRemote(ft)) {
+- /* steal the reference for the xfer */
+- mwFileTransfer_setClientData(ft, NULL, NULL);
+- purple_xfer_cancel_remote(xfer);
+-
+- /* drop the stolen reference */
+- purple_xfer_unref(xfer);
+- return;
+- }
+- }
+-
+- mwFileTransfer_free(ft);
+-}
+-
+-
+-static void mw_ft_recv(struct mwFileTransfer *ft,
+- struct mwOpaque *data) {
+- /*
+- - get purple ft from client data in ft
+- - update transfered percentage
+- - if done, destroy the ft, disassociate from purple ft
+- */
+-
+- PurpleXfer *xfer;
+- FILE *fp;
+- size_t wc;
+-
+- xfer = mwFileTransfer_getClientData(ft);
+- g_return_if_fail(xfer != NULL);
+-
+- fp = xfer->dest_fp;
+- g_return_if_fail(fp != NULL);
+-
+- /* we must collect and save our precious data */
+- wc = fwrite(data->data, 1, data->len, fp);
+- if (wc != data->len) {
+- DEBUG_ERROR("failed to write data\n");
+- purple_xfer_cancel_local(xfer);
+- return;
+- }
+-
+- /* update the progress */
+- xfer->bytes_sent += data->len;
+- xfer->bytes_remaining -= data->len;
+- purple_xfer_update_progress(xfer);
+-
+- /* let the other side know we got it, and to send some more */
+- mwFileTransfer_ack(ft);
+-}
+-
+-
+-static void mw_ft_ack(struct mwFileTransfer *ft) {
+- PurpleXfer *xfer;
+-
+- xfer = mwFileTransfer_getClientData(ft);
+- g_return_if_fail(xfer != NULL);
+- g_return_if_fail(xfer->watcher == 0);
+-
+- if(! mwFileTransfer_getRemaining(ft)) {
+- purple_xfer_set_completed(xfer, TRUE);
+- purple_xfer_end(xfer);
+-
+- } else if(mwFileTransfer_isOpen(ft)) {
+- ft_send(ft, xfer->dest_fp);
+- }
+-}
+-
+-
+-static void mw_ft_clear(struct mwServiceFileTransfer *srvc) {
+- ;
+-}
+-
+-
+-static struct mwFileTransferHandler mw_ft_handler = {
+- mw_ft_offered,
+- mw_ft_opened,
+- mw_ft_closed,
+- mw_ft_recv,
+- mw_ft_ack,
+- mw_ft_clear,
+-};
+-
+-
+-static struct mwServiceFileTransfer *mw_srvc_ft_new(struct mwSession *s) {
+- struct mwServiceFileTransfer *srvc;
+- GHashTable *ft_map;
+-
+- ft_map = g_hash_table_new(g_direct_hash, g_direct_equal);
+-
+- srvc = mwServiceFileTransfer_new(s, &mw_ft_handler);
+- mwService_setClientData(MW_SERVICE(srvc), ft_map,
+- (GDestroyNotify) g_hash_table_destroy);
+-
+- return srvc;
+-}
+-
+-
+-static void convo_data_free(struct convo_data *cd) {
+- GList *l;
+-
+- /* clean the queue */
+- for(l = cd->queue; l; l = g_list_delete_link(l, l)) {
+- struct convo_msg *m = l->data;
+- if(m->clear) m->clear(m->data);
+- g_free(m);
+- }
+-
+- g_free(cd);
+-}
+-
+-
+-/** allocates a convo_data structure and associates it with the
+- conversation in the client data slot */
+-static void convo_data_new(struct mwConversation *conv) {
+- struct convo_data *cd;
+-
+- g_return_if_fail(conv != NULL);
+-
+- if(mwConversation_getClientData(conv))
+- return;
+-
+- cd = g_new0(struct convo_data, 1);
+- cd->conv = conv;
+-
+- mwConversation_setClientData(conv, cd, (GDestroyNotify) convo_data_free);
+-}
+-
+-
+-static PurpleConversation *convo_get_gconv(struct mwConversation *conv) {
+- struct mwServiceIm *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+-
+- struct mwIdBlock *idb;
+-
+- srvc = mwConversation_getService(conv);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+- acct = purple_connection_get_account(gc);
+-
+- idb = mwConversation_getTarget(conv);
+-
+- return purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- idb->user, acct);
+-}
+-
+-
+-static void convo_queue(struct mwConversation *conv,
+- enum mwImSendType type, gconstpointer data) {
+-
+- struct convo_data *cd;
+- struct convo_msg *m;
+-
+- convo_data_new(conv);
+- cd = mwConversation_getClientData(conv);
+-
+- m = g_new0(struct convo_msg, 1);
+- m->type = type;
+-
+- switch(type) {
+- case mwImSend_PLAIN:
+- m->data = g_strdup(data);
+- m->clear = g_free;
+- break;
+-
+- case mwImSend_TYPING:
+- default:
+- m->data = (gpointer) data;
+- m->clear = NULL;
+- }
+-
+- cd->queue = g_list_append(cd->queue, m);
+-}
+-
+-
+-/* Does what it takes to get an error displayed for a conversation */
+-static void convo_error(struct mwConversation *conv, guint32 err) {
+- PurpleConversation *gconv;
+- char *tmp, *text;
+- struct mwIdBlock *idb;
+-
+- idb = mwConversation_getTarget(conv);
+-
+- tmp = mwError(err);
+- text = g_strconcat(_("Unable to send message: "), tmp, NULL);
+-
+- gconv = convo_get_gconv(conv);
+- if(gconv && !purple_conv_present_error(idb->user, gconv->account, text)) {
+-
+- g_free(text);
+- text = g_strdup_printf(_("Unable to send message to %s:"),
+- (idb->user)? idb->user: "(unknown)");
+- purple_notify_error(purple_account_get_connection(gconv->account),
+- NULL, text, tmp);
+- }
+-
+- g_free(tmp);
+- g_free(text);
+-}
+-
+-
+-static void convo_queue_send(struct mwConversation *conv) {
+- struct convo_data *cd;
+- GList *l;
+-
+- cd = mwConversation_getClientData(conv);
+-
+- for(l = cd->queue; l; l = g_list_delete_link(l, l)) {
+- struct convo_msg *m = l->data;
+-
+- mwConversation_send(conv, m->type, m->data);
+-
+- if(m->clear) m->clear(m->data);
+- g_free(m);
+- }
+-
+- cd->queue = NULL;
+-}
+-
+-
+-/** called when a mw conversation leaves a purple conversation to
+- inform the purple conversation that it's unsafe to offer any *cool*
+- features. */
+-static void convo_nofeatures(struct mwConversation *conv) {
+- PurpleConversation *gconv;
+- PurpleConnection *gc;
+-
+- gconv = convo_get_gconv(conv);
+- if(! gconv) return;
+-
+- gc = purple_conversation_get_gc(gconv);
+- if(! gc) return;
+-
+- purple_conversation_set_features(gconv, gc->flags);
+-}
+-
+-
+-/** called when a mw conversation and purple conversation come together,
+- to inform the purple conversation of what features to offer the
+- user */
+-static void convo_features(struct mwConversation *conv) {
+- PurpleConversation *gconv;
+- PurpleConnectionFlags feat;
+-
+- gconv = convo_get_gconv(conv);
+- if(! gconv) return;
+-
+- feat = purple_conversation_get_features(gconv);
+-
+- if(mwConversation_isOpen(conv)) {
+- if(mwConversation_supports(conv, mwImSend_HTML)) {
+- feat |= PURPLE_CONNECTION_HTML;
+- } else {
+- feat &= ~PURPLE_CONNECTION_HTML;
+- }
+-
+- if(mwConversation_supports(conv, mwImSend_MIME)) {
+- feat &= ~PURPLE_CONNECTION_NO_IMAGES;
+- } else {
+- feat |= PURPLE_CONNECTION_NO_IMAGES;
+- }
+-
+- DEBUG_INFO("conversation features set to 0x%04x\n", feat);
+- purple_conversation_set_features(gconv, feat);
+-
+- } else {
+- convo_nofeatures(conv);
+- }
+-}
+-
+-
+-static void mw_conversation_opened(struct mwConversation *conv) {
+- struct mwServiceIm *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+-
+- struct convo_dat *cd;
+-
+- srvc = mwConversation_getService(conv);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+- acct = purple_connection_get_account(gc);
+-
+- /* set up the queue */
+- cd = mwConversation_getClientData(conv);
+- if(cd) {
+- convo_queue_send(conv);
+-
+- if(! convo_get_gconv(conv)) {
+- mwConversation_free(conv);
+- return;
+- }
+-
+- } else {
+- convo_data_new(conv);
+- }
+-
+- { /* record the client key for the buddy */
+- PurpleBuddy *buddy;
+- struct mwLoginInfo *info;
+- info = mwConversation_getTargetInfo(conv);
+-
+- buddy = purple_find_buddy(acct, info->user_id);
+- if(buddy) {
+- purple_blist_node_set_int((PurpleBlistNode *) buddy,
+- BUDDY_KEY_CLIENT, info->type);
+- }
+- }
+-
+- convo_features(conv);
+-}
+-
+-
+-static void mw_conversation_closed(struct mwConversation *conv,
+- guint32 reason) {
+-
+- struct convo_data *cd;
+-
+- g_return_if_fail(conv != NULL);
+-
+- /* if there's an error code and a non-typing message in the queue,
+- print an error message to the conversation */
+- cd = mwConversation_getClientData(conv);
+- if(reason && cd && cd->queue) {
+- GList *l;
+- for(l = cd->queue; l; l = l->next) {
+- struct convo_msg *m = l->data;
+- if(m->type != mwImSend_TYPING) {
+- convo_error(conv, reason);
+- break;
+- }
+- }
+- }
+-
+-#if 0
+- /* don't do this, to prevent the occasional weird sending of
+- formatted messages as plaintext when the other end closes the
+- conversation after we've begun composing the message */
+- convo_nofeatures(conv);
+-#endif
+-
+- mwConversation_removeClientData(conv);
+-}
+-
+-
+-static void im_recv_text(struct mwConversation *conv,
+- struct mwPurplePluginData *pd,
+- const char *msg) {
+-
+- struct mwIdBlock *idb;
+- char *txt, *esc;
+- const char *t;
+-
+- idb = mwConversation_getTarget(conv);
+-
+- txt = purple_utf8_try_convert(msg);
+- t = txt? txt: msg;
+-
+- esc = g_markup_escape_text(t, -1);
+- serv_got_im(pd->gc, idb->user, esc, 0, time(NULL));
+- g_free(esc);
+-
+- g_free(txt);
+-}
+-
+-
+-static void im_recv_typing(struct mwConversation *conv,
+- struct mwPurplePluginData *pd,
+- gboolean typing) {
+-
+- struct mwIdBlock *idb;
+- idb = mwConversation_getTarget(conv);
+-
+- serv_got_typing(pd->gc, idb->user, 0,
+- typing? PURPLE_TYPING: PURPLE_NOT_TYPING);
+-}
+-
+-
+-static void im_recv_html(struct mwConversation *conv,
+- struct mwPurplePluginData *pd,
+- const char *msg) {
+- struct mwIdBlock *idb;
+- char *t1, *t2;
+- const char *t;
+-
+- idb = mwConversation_getTarget(conv);
+-
+- /* ensure we're receiving UTF8 */
+- t1 = purple_utf8_try_convert(msg);
+- t = t1? t1: msg;
+-
+- /* convert entities to UTF8 so they'll log correctly */
+- t2 = purple_utf8_ncr_decode(t);
+- t = t2? t2: t;
+-
+- serv_got_im(pd->gc, idb->user, t, 0, time(NULL));
+-
+- g_free(t1);
+- g_free(t2);
+-}
+-
+-
+-static void im_recv_subj(struct mwConversation *conv,
+- struct mwPurplePluginData *pd,
+- const char *subj) {
+-
+- /** @todo somehow indicate receipt of a conversation subject. It
+- would also be nice if we added a /topic command for the
+- protocol */
+- ;
+-}
+-
+-
+-/** generate "cid:908@20582notesbuddy" from "<908@20582notesbuddy>" */
+-static char *make_cid(const char *cid) {
+- gsize n;
+- char *c, *d;
+-
+- g_return_val_if_fail(cid != NULL, NULL);
+-
+- n = strlen(cid);
+- g_return_val_if_fail(n > 2, NULL);
+-
+- c = g_strndup(cid+1, n-2);
+- d = g_strdup_printf("cid:%s", c);
+-
+- g_free(c);
+- return d;
+-}
+-
+-
+-static void im_recv_mime(struct mwConversation *conv,
+- struct mwPurplePluginData *pd,
+- const char *data) {
+-
+- GHashTable *img_by_cid;
+- GList *images;
+-
+- GString *str;
+-
+- PurpleMimeDocument *doc;
+- GList *parts;
+-
+- img_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+- images = NULL;
+-
+- /* don't want the contained string to ever be NULL */
+- str = g_string_new("");
+-
+- doc = purple_mime_document_parse(data);
+-
+- /* handle all the MIME parts */
+- parts = purple_mime_document_get_parts(doc);
+- for(; parts; parts = parts->next) {
+- PurpleMimePart *part = parts->data;
+- const char *type;
+-
+- type = purple_mime_part_get_field(part, "content-type");
+- DEBUG_INFO("MIME part Content-Type: %s\n", NSTR(type));
+-
+- if(! type) {
+- ; /* feh */
+-
+- } else if(purple_str_has_prefix(type, "image")) {
+- /* put images into the image store */
+-
+- guchar *d_dat;
+- gsize d_len;
+- char *cid;
+- int img;
+-
+- /* obtain and unencode the data */
+- purple_mime_part_get_data_decoded(part, &d_dat, &d_len);
+-
+- /* look up the content id */
+- cid = (char *) purple_mime_part_get_field(part, "Content-ID");
+- cid = make_cid(cid);
+-
+- /* add image to the purple image store */
+- img = purple_imgstore_add_with_id(d_dat, d_len, cid);
+-
+- /* map the cid to the image store identifier */
+- g_hash_table_insert(img_by_cid, cid, GINT_TO_POINTER(img));
+-
+- /* recall the image for dereferencing later */
+- images = g_list_append(images, GINT_TO_POINTER(img));
+-
+- } else if(purple_str_has_prefix(type, "text")) {
+-
+- /* concatenate all the text parts together */
+- guchar *data;
+- gsize len;
+-
+- purple_mime_part_get_data_decoded(part, &data, &len);
+- g_string_append(str, (const char *)data);
+- g_free(data);
+- }
+- }
+-
+- purple_mime_document_free(doc);
+-
+- /* @todo should put this in its own function */
+- { /* replace each IMG tag's SRC attribute with an ID attribute. This
+- actually modifies the contents of str */
+- GData *attribs;
+- char *start, *end;
+- char *tmp = str->str;
+-
+- while(*tmp && purple_markup_find_tag("img", tmp, (const char **) &start,
+- (const char **) &end, &attribs)) {
+-
+- char *alt, *align, *border, *src;
+- int img = 0;
+-
+- alt = g_datalist_get_data(&attribs, "alt");
+- align = g_datalist_get_data(&attribs, "align");
+- border = g_datalist_get_data(&attribs, "border");
+- src = g_datalist_get_data(&attribs, "src");
+-
+- if(src)
+- img = GPOINTER_TO_INT(g_hash_table_lookup(img_by_cid, src));
+-
+- if(img) {
+- GString *atstr;
+- gsize len = (end - start);
+- gsize mov;
+-
+- atstr = g_string_new("");
+- if(alt) g_string_append_printf(atstr, " alt=\"%s\"", alt);
+- if(align) g_string_append_printf(atstr, " align=\"%s\"", align);
+- if(border) g_string_append_printf(atstr, " border=\"%s\"", border);
+-
+- mov = g_snprintf(start, len, "<img%s id=\"%i\"", atstr->str, img);
+- while(mov < len) start[mov++] = ' ';
+-
+- g_string_free(atstr, TRUE);
+- }
+-
+- g_datalist_clear(&attribs);
+- tmp = end + 1;
+- }
+- }
+-
+- im_recv_html(conv, pd, str->str);
+-
+- g_string_free(str, TRUE);
+-
+- /* clean up the cid table */
+- g_hash_table_destroy(img_by_cid);
+-
+- /* dereference all the imgages */
+- while(images) {
+- purple_imgstore_unref_by_id(GPOINTER_TO_INT(images->data));
+- images = g_list_delete_link(images, images);
+- }
+-}
+-
+-
+-static void mw_conversation_recv(struct mwConversation *conv,
+- enum mwImSendType type,
+- gconstpointer msg) {
+- struct mwServiceIm *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+-
+- srvc = mwConversation_getService(conv);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+-
+- switch(type) {
+- case mwImSend_PLAIN:
+- im_recv_text(conv, pd, msg);
+- break;
+-
+- case mwImSend_TYPING:
+- im_recv_typing(conv, pd, !! msg);
+- break;
+-
+- case mwImSend_HTML:
+- im_recv_html(conv, pd, msg);
+- break;
+-
+- case mwImSend_SUBJECT:
+- im_recv_subj(conv, pd, msg);
+- break;
+-
+- case mwImSend_MIME:
+- im_recv_mime(conv, pd, msg);
+- break;
+-
+- default:
+- DEBUG_INFO("conversation received strange type, 0x%04x\n", type);
+- ; /* erm... */
+- }
+-}
+-
+-
+-static void mw_place_invite(struct mwConversation *conv,
+- const char *message,
+- const char *title, const char *name) {
+- struct mwServiceIm *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+-
+- struct mwIdBlock *idb;
+- GHashTable *ht;
+-
+- srvc = mwConversation_getService(conv);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+-
+- idb = mwConversation_getTarget(conv);
+-
+- ht = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, g_free);
+- g_hash_table_insert(ht, CHAT_KEY_CREATOR, g_strdup(idb->user));
+- g_hash_table_insert(ht, CHAT_KEY_NAME, g_strdup(name));
+- g_hash_table_insert(ht, CHAT_KEY_TOPIC, g_strdup(title));
+- g_hash_table_insert(ht, CHAT_KEY_INVITE, g_strdup(message));
+- g_hash_table_insert(ht, CHAT_KEY_IS_PLACE, g_strdup("")); /* ugh */
+-
+- if(! title) title = "(no title)";
+- if(! message) message = "(no message)";
+- serv_got_chat_invite(pd->gc, title, idb->user, message, ht);
+-
+- mwConversation_close(conv, ERR_SUCCESS);
+- mwConversation_free(conv);
+-}
+-
+-
+-static void mw_im_clear(struct mwServiceIm *srvc) {
+- ;
+-}
+-
+-
+-static struct mwImHandler mw_im_handler = {
+- mw_conversation_opened,
+- mw_conversation_closed,
+- mw_conversation_recv,
+- mw_place_invite,
+- mw_im_clear,
+-};
+-
+-
+-static struct mwServiceIm *mw_srvc_im_new(struct mwSession *s) {
+- struct mwServiceIm *srvc;
+- srvc = mwServiceIm_new(s, &mw_im_handler);
+- mwServiceIm_setClientType(srvc, mwImClient_NOTESBUDDY);
+- return srvc;
+-}
+-
+-
+-/* The following helps us relate a mwPlace to a PurpleConvChat in the
+- various forms by which either may be indicated. Uses some of
+- the similar macros from the conference service above */
+-
+-#define PLACE_TO_ID(place) (GPOINTER_TO_INT(place))
+-#define ID_TO_PLACE(pd, id) (place_find_by_id((pd), (id)))
+-
+-#define CHAT_TO_PLACE(pd, chat) (ID_TO_PLACE((pd), CHAT_TO_ID(chat)))
+-#define PLACE_TO_CHAT(place) (ID_TO_CHAT(PLACE_TO_ID(place)))
+-
+-
+-static struct mwPlace *
+-place_find_by_id(struct mwPurplePluginData *pd, int id) {
+- struct mwServicePlace *srvc = pd->srvc_place;
+- struct mwPlace *place = NULL;
+- GList *l;
+-
+- l = (GList *) mwServicePlace_getPlaces(srvc);
+- for(; l; l = l->next) {
+- struct mwPlace *p = l->data;
+- PurpleConvChat *h = PURPLE_CONV_CHAT(mwPlace_getClientData(p));
+-
+- if(CHAT_TO_ID(h) == id) {
+- place = p;
+- break;
+- }
+- }
+-
+- return place;
+-}
+-
+-
+-static void mw_place_opened(struct mwPlace *place) {
+- struct mwServicePlace *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConversation *gconf;
+-
+- GList *members, *l;
+-
+- const char *n = mwPlace_getName(place);
+- const char *t = mwPlace_getTitle(place);
+-
+- srvc = mwPlace_getService(place);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- members = mwPlace_getMembers(place);
+-
+- DEBUG_INFO("place %s opened, %u initial members\n",
+- NSTR(n), g_list_length(members));
+-
+- if(! t) t = "(no title)";
+- gconf = serv_got_joined_chat(gc, PLACE_TO_ID(place), t);
+-
+- mwPlace_setClientData(place, gconf, NULL);
+-
+- for(l = members; l; l = l->next) {
+- struct mwIdBlock *idb = l->data;
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), idb->user,
+- NULL, PURPLE_CBFLAGS_NONE, FALSE);
+- }
+- g_list_free(members);
+-}
+-
+-
+-static void mw_place_closed(struct mwPlace *place, guint32 code) {
+- struct mwServicePlace *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+-
+- const char *n = mwPlace_getName(place);
+- char *msg = mwError(code);
+-
+- DEBUG_INFO("place %s closed, 0x%08x\n", NSTR(n), code);
+-
+- srvc = mwPlace_getService(place);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- serv_got_chat_left(gc, PLACE_TO_ID(place));
+-
+- purple_notify_error(gc, _("Place Closed"), NULL, msg);
+- g_free(msg);
+-}
+-
+-
+-static void mw_place_peerJoined(struct mwPlace *place,
+- const struct mwIdBlock *peer) {
+- struct mwServicePlace *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConversation *gconf;
+-
+- const char *n = mwPlace_getName(place);
+-
+- DEBUG_INFO("%s joined place %s\n", NSTR(peer->user), NSTR(n));
+-
+- srvc = mwPlace_getService(place);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- gconf = mwPlace_getClientData(place);
+- g_return_if_fail(gconf != NULL);
+-
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(gconf), peer->user,
+- NULL, PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-
+-static void mw_place_peerParted(struct mwPlace *place,
+- const struct mwIdBlock *peer) {
+- struct mwServicePlace *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- PurpleConversation *gconf;
+-
+- const char *n = mwPlace_getName(place);
+-
+- DEBUG_INFO("%s left place %s\n", NSTR(peer->user), NSTR(n));
+-
+- srvc = mwPlace_getService(place);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- gconf = mwPlace_getClientData(place);
+- g_return_if_fail(gconf != NULL);
+-
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(gconf), peer->user, NULL);
+-}
+-
+-
+-static void mw_place_peerSetAttribute(struct mwPlace *place,
+- const struct mwIdBlock *peer,
+- guint32 attr, struct mwOpaque *o) {
+- ;
+-}
+-
+-
+-static void mw_place_peerUnsetAttribute(struct mwPlace *place,
+- const struct mwIdBlock *peer,
+- guint32 attr) {
+- ;
+-}
+-
+-
+-static void mw_place_message(struct mwPlace *place,
+- const struct mwIdBlock *who,
+- const char *msg) {
+- struct mwServicePlace *srvc;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+- char *esc;
+-
+- if(! msg) return;
+-
+- srvc = mwPlace_getService(place);
+- session = mwService_getSession(MW_SERVICE(srvc));
+- pd = mwSession_getClientData(session);
+- gc = pd->gc;
+-
+- esc = g_markup_escape_text(msg, -1);
+- serv_got_chat_in(gc, PLACE_TO_ID(place), who->user, 0, esc, time(NULL));
+- g_free(esc);
+-}
+-
+-
+-static void mw_place_clear(struct mwServicePlace *srvc) {
+- ;
+-}
+-
+-
+-static struct mwPlaceHandler mw_place_handler = {
+- mw_place_opened,
+- mw_place_closed,
+- mw_place_peerJoined,
+- mw_place_peerParted,
+- mw_place_peerSetAttribute,
+- mw_place_peerUnsetAttribute,
+- mw_place_message,
+- mw_place_clear,
+-};
+-
+-
+-static struct mwServicePlace *mw_srvc_place_new(struct mwSession *s) {
+- struct mwServicePlace *srvc;
+- srvc = mwServicePlace_new(s, &mw_place_handler);
+- return srvc;
+-}
+-
+-
+-static struct mwServiceResolve *mw_srvc_resolve_new(struct mwSession *s) {
+- struct mwServiceResolve *srvc;
+- srvc = mwServiceResolve_new(s);
+- return srvc;
+-}
+-
+-
+-static struct mwServiceStorage *mw_srvc_store_new(struct mwSession *s) {
+- struct mwServiceStorage *srvc;
+- srvc = mwServiceStorage_new(s);
+- return srvc;
+-}
+-
+-
+-/** allocate and associate a mwPurplePluginData with a PurpleConnection */
+-static struct mwPurplePluginData *mwPurplePluginData_new(PurpleConnection *gc) {
+- struct mwPurplePluginData *pd;
+-
+- g_return_val_if_fail(gc != NULL, NULL);
+-
+- pd = g_new0(struct mwPurplePluginData, 1);
+- pd->gc = gc;
+- pd->session = mwSession_new(&mw_session_handler);
+- pd->srvc_aware = mw_srvc_aware_new(pd->session);
+- pd->srvc_conf = mw_srvc_conf_new(pd->session);
+- pd->srvc_ft = mw_srvc_ft_new(pd->session);
+- pd->srvc_im = mw_srvc_im_new(pd->session);
+- pd->srvc_place = mw_srvc_place_new(pd->session);
+- pd->srvc_resolve = mw_srvc_resolve_new(pd->session);
+- pd->srvc_store = mw_srvc_store_new(pd->session);
+- pd->group_list_map = g_hash_table_new(g_direct_hash, g_direct_equal);
+- pd->sock_buf = purple_circ_buffer_new(0);
+-
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_aware));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_conf));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_ft));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_im));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_place));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_resolve));
+- mwSession_addService(pd->session, MW_SERVICE(pd->srvc_store));
+-
+- mwSession_addCipher(pd->session, mwCipher_new_RC2_40(pd->session));
+- mwSession_addCipher(pd->session, mwCipher_new_RC2_128(pd->session));
+-
+- mwSession_setClientData(pd->session, pd, NULL);
+- gc->proto_data = pd;
+-
+- return pd;
+-}
+-
+-
+-static void mwPurplePluginData_free(struct mwPurplePluginData *pd) {
+- g_return_if_fail(pd != NULL);
+-
+- pd->gc->proto_data = NULL;
+-
+- mwSession_removeService(pd->session, mwService_AWARE);
+- mwSession_removeService(pd->session, mwService_CONFERENCE);
+- mwSession_removeService(pd->session, mwService_FILE_TRANSFER);
+- mwSession_removeService(pd->session, mwService_IM);
+- mwSession_removeService(pd->session, mwService_PLACE);
+- mwSession_removeService(pd->session, mwService_RESOLVE);
+- mwSession_removeService(pd->session, mwService_STORAGE);
+-
+- mwService_free(MW_SERVICE(pd->srvc_aware));
+- mwService_free(MW_SERVICE(pd->srvc_conf));
+- mwService_free(MW_SERVICE(pd->srvc_ft));
+- mwService_free(MW_SERVICE(pd->srvc_im));
+- mwService_free(MW_SERVICE(pd->srvc_place));
+- mwService_free(MW_SERVICE(pd->srvc_resolve));
+- mwService_free(MW_SERVICE(pd->srvc_store));
+-
+- mwCipher_free(mwSession_getCipher(pd->session, mwCipher_RC2_40));
+- mwCipher_free(mwSession_getCipher(pd->session, mwCipher_RC2_128));
+-
+- mwSession_free(pd->session);
+-
+- g_hash_table_destroy(pd->group_list_map);
+- purple_circ_buffer_destroy(pd->sock_buf);
+-
+- g_free(pd);
+-}
+-
+-
+-static const char *mw_prpl_list_icon(PurpleAccount *a, PurpleBuddy *b) {
+- /* my little green dude is a chopped up version of the aim running
+- guy. First, cut off the head and store someplace safe. Then,
+- take the left-half side of the body and throw it away. Make a
+- copy of the remaining body, and flip it horizontally. Now attach
+- the two pieces into an X shape, and drop the head back on the
+- top, being careful to center it. Then, just change the color
+- saturation to bring the red down a bit, and voila! */
+-
+- /* then, throw all of that away and use sodipodi to make a new
+- icon. You know, LIKE A REAL MAN. */
+-
+- return "meanwhile";
+-}
+-
+-
+-static const char* mw_prpl_list_emblem(PurpleBuddy *b)
+-{
+- if(buddy_is_external(b))
+- return "external";
+-
+- return NULL;
+-}
+-
+-
+-static char *mw_prpl_status_text(PurpleBuddy *b) {
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+- struct mwAwareIdBlock t = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
+- const char *ret = NULL;
+-
+- if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
+- && (pd = gc->proto_data))
+- ret = mwServiceAware_getText(pd->srvc_aware, &t);
+-
+- return (ret && g_utf8_validate(ret, -1, NULL)) ? g_markup_escape_text(ret, -1): NULL;
+-}
+-
+-
+-static const char *status_text(PurpleBuddy *b) {
+- PurplePresence *presence;
+- PurpleStatus *status;
+-
+- presence = purple_buddy_get_presence(b);
+- status = purple_presence_get_active_status(presence);
+-
+- return purple_status_get_name(status);
+-}
+-
+-
+-static gboolean user_supports(struct mwServiceAware *srvc,
+- const char *who, guint32 feature) {
+-
+- const struct mwAwareAttribute *attr;
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
+-
+- attr = mwServiceAware_getAttribute(srvc, &idb, feature);
+- return (attr != NULL) && mwAwareAttribute_asBoolean(attr);
+-}
+-
+-
+-static char *user_supports_text(struct mwServiceAware *srvc, const char *who) {
+- const char *feat[] = {NULL, NULL, NULL, NULL, NULL};
+- const char **f = feat;
+-
+- if(user_supports(srvc, who, mwAttribute_AV_PREFS_SET)) {
+- gboolean mic, speak, video;
+-
+- mic = user_supports(srvc, who, mwAttribute_MICROPHONE);
+- speak = user_supports(srvc, who, mwAttribute_SPEAKERS);
+- video = user_supports(srvc, who, mwAttribute_VIDEO_CAMERA);
+-
+- if(mic) *f++ = _("Microphone");
+- if(speak) *f++ = _("Speakers");
+- if(video) *f++ = _("Video Camera");
+- }
+-
+- if(user_supports(srvc, who, mwAttribute_FILE_TRANSFER))
+- *f++ = _("File Transfer");
+-
+- return (*feat)? g_strjoinv(", ", (char **)feat): NULL;
+- /* jenni loves siege */
+-}
+-
+-
+-static void mw_prpl_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full) {
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd = NULL;
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(b), NULL };
+-
+- const char *message = NULL;
+- const char *status;
+- char *tmp;
+-
+- if ((gc = purple_account_get_connection(purple_buddy_get_account(b)))
+- && (pd = gc->proto_data))
+- message = mwServiceAware_getText(pd->srvc_aware, &idb);
+-
+- status = status_text(b);
+-
+- if(message != NULL && g_utf8_validate(message, -1, NULL) && purple_utf8_strcasecmp(status, message)) {
+- tmp = g_markup_escape_text(message, -1);
+- purple_notify_user_info_add_pair(user_info, status, tmp);
+- g_free(tmp);
+-
+- } else {
+- purple_notify_user_info_add_pair(user_info, _("Status"), status);
+- }
+-
+- if(full && pd != NULL) {
+- tmp = user_supports_text(pd->srvc_aware, purple_buddy_get_name(b));
+- if(tmp) {
+- purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
+- g_free(tmp);
+- }
+-
+- if(buddy_is_external(b)) {
+- purple_notify_user_info_add_pair(user_info, NULL, _("External User"));
+- }
+- }
+-}
+-
+-static GList *mw_prpl_status_types(PurpleAccount *acct)
+-{
+- GList *types = NULL;
+- PurpleStatusType *type;
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE,
+- MW_STATE_ACTIVE, NULL, TRUE, TRUE, FALSE,
+- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY,
+- MW_STATE_AWAY, NULL, TRUE, TRUE, FALSE,
+- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE,
+- MW_STATE_BUSY, _("Do Not Disturb"), TRUE, TRUE, FALSE,
+- MW_STATE_MESSAGE, _("Message"), purple_value_new(PURPLE_TYPE_STRING),
+- NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
+- MW_STATE_OFFLINE, NULL, TRUE, TRUE, FALSE);
+- types = g_list_append(types, type);
+-
+- return types;
+-}
+-
+-
+-static void conf_create_prompt_cancel(PurpleBuddy *buddy,
+- PurpleRequestFields *fields) {
+- ; /* nothing to do */
+-}
+-
+-
+-static void conf_create_prompt_join(PurpleBuddy *buddy,
+- PurpleRequestFields *fields) {
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+- struct mwServiceConference *srvc;
+-
+- PurpleRequestField *f;
+-
+- const char *topic, *invite;
+- struct mwConference *conf;
+- struct mwIdBlock idb = { NULL, NULL };
+-
+- acct = purple_buddy_get_account(buddy);
+- gc = purple_account_get_connection(acct);
+- pd = gc->proto_data;
+- srvc = pd->srvc_conf;
+-
+- f = purple_request_fields_get_field(fields, CHAT_KEY_TOPIC);
+- topic = purple_request_field_string_get_value(f);
+-
+- f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
+- invite = purple_request_field_string_get_value(f);
+-
+- conf = mwConference_new(srvc, topic);
+- mwConference_open(conf);
+-
+- idb.user = (char *)purple_buddy_get_name(buddy);
+- mwConference_invite(conf, &idb, invite);
+-}
+-
+-
+-static void blist_menu_conf_create(PurpleBuddy *buddy, const char *msg) {
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *g;
+- PurpleRequestField *f;
+-
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+-
+- const char *msgA;
+- const char *msgB;
+- char *msg1;
+-
+- g_return_if_fail(buddy != NULL);
+-
+- acct = purple_buddy_get_account(buddy);
+- g_return_if_fail(acct != NULL);
+-
+- gc = purple_account_get_connection(acct);
+- g_return_if_fail(gc != NULL);
+-
+- fields = purple_request_fields_new();
+-
+- g = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, g);
+-
+- f = purple_request_field_string_new(CHAT_KEY_TOPIC, _("Topic"), NULL, FALSE);
+- purple_request_field_group_add_field(g, f);
+-
+- f = purple_request_field_string_new(CHAT_KEY_INVITE, _("Message"), msg, FALSE);
+- purple_request_field_group_add_field(g, f);
+-
+- msgA = _("Create conference with user");
+- msgB = _("Please enter a topic for the new conference, and an invitation"
+- " message to be sent to %s");
+- msg1 = g_strdup_printf(msgB, purple_buddy_get_name(buddy));
+-
+- purple_request_fields(gc, _("New Conference"),
+- msgA, msg1, fields,
+- _("Create"), G_CALLBACK(conf_create_prompt_join),
+- _("Cancel"), G_CALLBACK(conf_create_prompt_cancel),
+- acct, purple_buddy_get_name(buddy), NULL,
+- buddy);
+- g_free(msg1);
+-}
+-
+-
+-static void conf_select_prompt_cancel(PurpleBuddy *buddy,
+- PurpleRequestFields *fields) {
+- ;
+-}
+-
+-
+-static void conf_select_prompt_invite(PurpleBuddy *buddy,
+- PurpleRequestFields *fields) {
+- PurpleRequestField *f;
+- GList *l;
+- const char *msg;
+-
+- f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
+- msg = purple_request_field_string_get_value(f);
+-
+- f = purple_request_fields_get_field(fields, "conf");
+- l = purple_request_field_list_get_selected(f);
+-
+- if(l) {
+- gpointer d = purple_request_field_list_get_data(f, l->data);
+-
+- if(GPOINTER_TO_INT(d) == 0x01) {
+- blist_menu_conf_create(buddy, msg);
+-
+- } else {
+- struct mwIdBlock idb = { (char *)purple_buddy_get_name(buddy), NULL };
+- mwConference_invite(d, &idb, msg);
+- }
+- }
+-}
+-
+-
+-static void blist_menu_conf_list(PurpleBuddy *buddy,
+- GList *confs) {
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *g;
+- PurpleRequestField *f;
+-
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+-
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- acct = purple_buddy_get_account(buddy);
+- g_return_if_fail(acct != NULL);
+-
+- gc = purple_account_get_connection(acct);
+- g_return_if_fail(gc != NULL);
+-
+- fields = purple_request_fields_new();
+-
+- g = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, g);
+-
+- f = purple_request_field_list_new("conf", _("Available Conferences"));
+- purple_request_field_list_set_multi_select(f, FALSE);
+- for(; confs; confs = confs->next) {
+- struct mwConference *c = confs->data;
+- purple_request_field_list_add_icon(f, mwConference_getTitle(c), NULL, c);
+- }
+- purple_request_field_list_add_icon(f, _("Create New Conference..."),
+- NULL, GINT_TO_POINTER(0x01));
+- purple_request_field_group_add_field(g, f);
+-
+- f = purple_request_field_string_new(CHAT_KEY_INVITE, "Message", NULL, FALSE);
+- purple_request_field_group_add_field(g, f);
+-
+- msgA = _("Invite user to a conference");
+- msgB = _("Select a conference from the list below to send an invite to"
+- " user %s. Select \"Create New Conference\" if you'd like to"
+- " create a new conference to invite this user to.");
+- msg = g_strdup_printf(msgB, purple_buddy_get_name(buddy));
+-
+- purple_request_fields(gc, _("Invite to Conference"),
+- msgA, msg, fields,
+- _("Invite"), G_CALLBACK(conf_select_prompt_invite),
+- _("Cancel"), G_CALLBACK(conf_select_prompt_cancel),
+- acct, purple_buddy_get_name(buddy), NULL,
+- buddy);
+- g_free(msg);
+-}
+-
+-
+-static void blist_menu_conf(PurpleBlistNode *node, gpointer data) {
+- PurpleBuddy *buddy = (PurpleBuddy *) node;
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+- GList *l;
+-
+- g_return_if_fail(node != NULL);
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- acct = purple_buddy_get_account(buddy);
+- g_return_if_fail(acct != NULL);
+-
+- gc = purple_account_get_connection(acct);
+- g_return_if_fail(gc != NULL);
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- /*
+- - get a list of all conferences on this session
+- - if none, prompt to create one, and invite buddy to it
+- - else, prompt to select a conference or create one
+- */
+-
+- l = mwServiceConference_getConferences(pd->srvc_conf);
+- if(l) {
+- blist_menu_conf_list(buddy, l);
+- g_list_free(l);
+-
+- } else {
+- blist_menu_conf_create(buddy, NULL);
+- }
+-}
+-
+-
+-#if 0
+-static void blist_menu_announce(PurpleBlistNode *node, gpointer data) {
+- PurpleBuddy *buddy = (PurpleBuddy *) node;
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+- struct mwSession *session;
+- char *rcpt_name;
+- GList *rcpt;
+-
+- g_return_if_fail(node != NULL);
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- acct = buddy->account;
+- g_return_if_fail(acct != NULL);
+-
+- gc = purple_account_get_connection(acct);
+- g_return_if_fail(gc != NULL);
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- rcpt_name = g_strdup_printf("@U %s", buddy->name);
+- rcpt = g_list_prepend(NULL, rcpt_name);
+-
+- session = pd->session;
+- mwSession_sendAnnounce(session, FALSE,
+- "This is a TEST announcement. Please ignore.",
+- rcpt);
+-
+- g_list_free(rcpt);
+- g_free(rcpt_name);
+-}
+-#endif
+-
+-
+-static GList *mw_prpl_blist_node_menu(PurpleBlistNode *node) {
+- GList *l = NULL;
+- PurpleMenuAction *act;
+-
+- if(! PURPLE_BLIST_NODE_IS_BUDDY(node))
+- return l;
+-
+- l = g_list_append(l, NULL);
+-
+- act = purple_menu_action_new(_("Invite to Conference..."),
+- PURPLE_CALLBACK(blist_menu_conf), NULL, NULL);
+- l = g_list_append(l, act);
+-
+-#if 0
+- act = purple_menu_action_new(_("Send TEST Announcement"),
+- PURPLE_CALLBACK(blist_menu_announce), NULL, NULL);
+- l = g_list_append(l, act);
+-#endif
+-
+- /** note: this never gets called for a PurpleGroup, have to use the
+- blist-node-extended-menu signal for that. The function
+- blist_node_menu_cb is assigned to this signal in the function
+- services_starting */
+-
+- return l;
+-}
+-
+-
+-static GList *mw_prpl_chat_info(PurpleConnection *gc) {
+- GList *l = NULL;
+- struct proto_chat_entry *pce;
+-
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _("Topic:");
+- pce->identifier = CHAT_KEY_TOPIC;
+- l = g_list_append(l, pce);
+-
+- return l;
+-}
+-
+-
+-static GHashTable *mw_prpl_chat_info_defaults(PurpleConnection *gc,
+- const char *name) {
+- GHashTable *table;
+-
+- g_return_val_if_fail(gc != NULL, NULL);
+-
+- table = g_hash_table_new_full(g_str_hash, g_str_equal,
+- NULL, g_free);
+-
+- g_hash_table_insert(table, CHAT_KEY_NAME, g_strdup(name));
+- g_hash_table_insert(table, CHAT_KEY_INVITE, NULL);
+-
+- return table;
+-}
+-
+-
+-static void mw_prpl_login(PurpleAccount *acct);
+-
+-
+-static void mw_prpl_login(PurpleAccount *account) {
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+-
+- char *user, *pass, *host;
+- guint port;
+-
+- gc = purple_account_get_connection(account);
+- pd = mwPurplePluginData_new(gc);
+-
+- /* while we do support images, the default is to not offer it */
+- gc->flags |= PURPLE_CONNECTION_NO_IMAGES;
+-
+- user = g_strdup(purple_account_get_username(account));
+-
+- host = strrchr(user, ':');
+- if(host) {
+- /* annoying user split from 1.2.0, need to undo it */
+- *host++ = '\0';
+- purple_account_set_string(account, MW_KEY_HOST, host);
+- purple_account_set_username(account, user);
+-
+- } else {
+- host = (char *) purple_account_get_string(account, MW_KEY_HOST,
+- MW_PLUGIN_DEFAULT_HOST);
+- }
+-
+- if(! host || ! *host) {
+- /* somehow, we don't have a host to connect to. Well, we need one
+- to actually continue, so let's ask the user directly. */
+- g_free(user);
+- purple_connection_error_reason(gc,
+- PURPLE_CONNECTION_ERROR_INVALID_SETTINGS,
+- _("A server is required to connect this account"));
+- return;
+- }
+-
+- pass = g_strdup(purple_account_get_password(account));
+- port = purple_account_get_int(account, MW_KEY_PORT, MW_PLUGIN_DEFAULT_PORT);
+-
+- DEBUG_INFO("user: '%s'\n", user);
+- DEBUG_INFO("host: '%s'\n", host);
+- DEBUG_INFO("port: %u\n", port);
+-
+- mwSession_setProperty(pd->session, mwSession_NO_SECRET,
+- (char *) no_secret, NULL);
+- mwSession_setProperty(pd->session, mwSession_AUTH_USER_ID, user, g_free);
+- mwSession_setProperty(pd->session, mwSession_AUTH_PASSWORD, pass, g_free);
+-
+- if(purple_account_get_bool(account, MW_KEY_FAKE_IT, FALSE)) {
+- guint client, major, minor;
+-
+- /* if we're faking the login, let's also fake the version we're
+- reporting. Let's also allow the actual values to be specified */
+-
+- client = purple_account_get_int(account, MW_KEY_CLIENT, mwLogin_BINARY);
+- major = purple_account_get_int(account, MW_KEY_MAJOR, 0x001e);
+- minor = purple_account_get_int(account, MW_KEY_MINOR, 0x196f);
+-
+- DEBUG_INFO("client id: 0x%04x\n", client);
+- DEBUG_INFO("client major: 0x%04x\n", major);
+- DEBUG_INFO("client minor: 0x%04x\n", minor);
+-
+- mwSession_setProperty(pd->session, mwSession_CLIENT_TYPE_ID,
+- GUINT_TO_POINTER(client), NULL);
+-
+- mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MAJOR,
+- GUINT_TO_POINTER(major), NULL);
+-
+- mwSession_setProperty(pd->session, mwSession_CLIENT_VER_MINOR,
+- GUINT_TO_POINTER(minor), NULL);
+- }
+-
+- purple_connection_update_progress(gc, _("Connecting"), 1, MW_CONNECT_STEPS);
+-
+- if (purple_proxy_connect(gc, account, host, port, connect_cb, pd) == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- }
+-}
+-
+-
+-static void mw_prpl_close(PurpleConnection *gc) {
+- struct mwPurplePluginData *pd;
+-
+- g_return_if_fail(gc != NULL);
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- /* get rid of the blist save timeout */
+- if(pd->save_event) {
+- purple_timeout_remove(pd->save_event);
+- pd->save_event = 0;
+- blist_store(pd);
+- }
+-
+- /* stop the session */
+- mwSession_stop(pd->session, 0x00);
+-
+- /* no longer necessary */
+- gc->proto_data = NULL;
+-
+- /* stop watching the socket */
+- if(gc->inpa) {
+- purple_input_remove(gc->inpa);
+- gc->inpa = 0;
+- }
+-
+- /* clean up the rest */
+- mwPurplePluginData_free(pd);
+-}
+-
+-
+-static int mw_rand(void) {
+- static int seed = 0;
+-
+- /* for diversity, not security. don't touch */
+- srand(time(NULL) ^ seed);
+- seed = rand();
+-
+- return seed;
+-}
+-
+-
+-/** generates a random-ish content id string */
+-static char *im_mime_content_id(void) {
+- return g_strdup_printf("%03x@%05xmeanwhile",
+- mw_rand() & 0xfff, mw_rand() & 0xfffff);
+-}
+-
+-
+-/** generates a multipart/related content type with a random-ish
+- boundary value */
+-static char *im_mime_content_type(void) {
+- return g_strdup_printf("multipart/related; boundary=related_MW%03x_%04x",
+- mw_rand() & 0xfff, mw_rand() & 0xffff);
+-}
+-
+-
+-/** determine content type from extension. Not so happy about this,
+- but I don't want to actually write image type detection */
+-static char *im_mime_img_content_type(PurpleStoredImage *img) {
+- const char *fn = purple_imgstore_get_filename(img);
+- const char *ct = NULL;
+-
+- ct = strrchr(fn, '.');
+- if(! ct) {
+- ct = "image";
+-
+- } else if(! strcmp(".png", ct)) {
+- ct = "image/png";
+-
+- } else if(! strcmp(".jpg", ct)) {
+- ct = "image/jpeg";
+-
+- } else if(! strcmp(".jpeg", ct)) {
+- ct = "image/jpeg";
+-
+- } else if(! strcmp(".gif", ct)) {
+- ct = "image/gif";
+-
+- } else {
+- ct = "image";
+- }
+-
+- return g_strdup_printf("%s; name=\"%s\"", ct, fn);
+-}
+-
+-
+-static char *im_mime_img_content_disp(PurpleStoredImage *img) {
+- const char *fn = purple_imgstore_get_filename(img);
+- return g_strdup_printf("attachment; filename=\"%s\"", fn);
+-}
+-
+-
+-/** turn an IM with embedded images into a multi-part mime document */
+-static char *im_mime_convert(PurpleConnection *gc,
+- struct mwConversation *conv,
+- const char *message) {
+- GString *str;
+- PurpleMimeDocument *doc;
+- PurpleMimePart *part;
+-
+- GData *attr;
+- char *tmp, *start, *end;
+-
+- str = g_string_new(NULL);
+-
+- doc = purple_mime_document_new();
+-
+- purple_mime_document_set_field(doc, "Mime-Version", "1.0");
+- purple_mime_document_set_field(doc, "Content-Disposition", "inline");
+-
+- tmp = im_mime_content_type();
+- purple_mime_document_set_field(doc, "Content-Type", tmp);
+- g_free(tmp);
+-
+- tmp = (char *) message;
+- while(*tmp && purple_markup_find_tag("img", tmp, (const char **) &start,
+- (const char **) &end, &attr)) {
+- char *id;
+- PurpleStoredImage *img = NULL;
+-
+- gsize len = (start - tmp);
+-
+- /* append the in-between-tags text */
+- if(len) g_string_append_len(str, tmp, len);
+-
+- /* find the imgstore data by the id tag */
+- id = g_datalist_get_data(&attr, "id");
+- if(id && *id)
+- img = purple_imgstore_find_by_id(atoi(id));
+-
+- if(img) {
+- char *cid;
+- gpointer data;
+- size_t size;
+-
+- part = purple_mime_part_new(doc);
+-
+- data = im_mime_img_content_disp(img);
+- purple_mime_part_set_field(part, "Content-Disposition", data);
+- g_free(data);
+-
+- data = im_mime_img_content_type(img);
+- purple_mime_part_set_field(part, "Content-Type", data);
+- g_free(data);
+-
+- cid = im_mime_content_id();
+- data = g_strdup_printf("<%s>", cid);
+- purple_mime_part_set_field(part, "Content-ID", data);
+- g_free(data);
+-
+- purple_mime_part_set_field(part, "Content-transfer-encoding", "base64");
+-
+- /* obtain and base64 encode the image data, and put it in the
+- mime part */
+- size = purple_imgstore_get_size(img);
+- data = purple_base64_encode(purple_imgstore_get_data(img), (gsize) size);
+- purple_mime_part_set_data(part, data);
+- g_free(data);
+-
+- /* append the modified tag */
+- g_string_append_printf(str, "<img src=\"cid:%s\">", cid);
+- g_free(cid);
+-
+- } else {
+- /* append the literal image tag, since we couldn't find a
+- relative imgstore object */
+- gsize len = (end - start) + 1;
+- g_string_append_len(str, start, len);
+- }
+-
+- g_datalist_clear(&attr);
+- tmp = end + 1;
+- }
+-
+- /* append left-overs */
+- g_string_append(str, tmp);
+-
+- /* add the text/html part */
+- part = purple_mime_part_new(doc);
+- purple_mime_part_set_field(part, "Content-Disposition", "inline");
+-
+- tmp = purple_utf8_ncr_encode(str->str);
+- purple_mime_part_set_field(part, "Content-Type", "text/html");
+- purple_mime_part_set_field(part, "Content-Transfer-Encoding", "7bit");
+- purple_mime_part_set_data(part, tmp);
+- g_free(tmp);
+-
+- g_string_free(str, TRUE);
+-
+- str = g_string_new(NULL);
+- purple_mime_document_write(doc, str);
+- tmp = str->str;
+- g_string_free(str, FALSE);
+-
+- return tmp;
+-}
+-
+-
+-static int mw_prpl_send_im(PurpleConnection *gc,
+- const char *name,
+- const char *message,
+- PurpleMessageFlags flags) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwIdBlock who = { (char *) name, NULL };
+- struct mwConversation *conv;
+-
+- g_return_val_if_fail(gc != NULL, 0);
+- pd = gc->proto_data;
+-
+- g_return_val_if_fail(pd != NULL, 0);
+-
+- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
+-
+- /* this detection of features to determine how to send the message
+- (plain, html, or mime) is flawed because the other end of the
+- conversation could close their channel at any time, rendering any
+- existing formatting in an outgoing message innapropriate. The end
+- result is that it may be possible that the other side of the
+- conversation will receive a plaintext message with html contents,
+- which is bad. I'm not sure how to fix this correctly. */
+-
+- if(strstr(message, "<img ") || strstr(message, "<IMG "))
+- flags |= PURPLE_MESSAGE_IMAGES;
+-
+- if(mwConversation_isOpen(conv)) {
+- char *tmp;
+- int ret;
+-
+- if((flags & PURPLE_MESSAGE_IMAGES) &&
+- mwConversation_supports(conv, mwImSend_MIME)) {
+- /* send a MIME message */
+-
+- tmp = im_mime_convert(gc, conv, message);
+- ret = mwConversation_send(conv, mwImSend_MIME, tmp);
+- g_free(tmp);
+-
+- } else if(mwConversation_supports(conv, mwImSend_HTML)) {
+- /* send an HTML message */
+-
+- char *ncr;
+- ncr = purple_utf8_ncr_encode(message);
+- tmp = purple_strdup_withhtml(ncr);
+- g_free(ncr);
+-
+- ret = mwConversation_send(conv, mwImSend_HTML, tmp);
+- g_free(tmp);
+-
+- } else {
+- /* default to text */
+- tmp = purple_markup_strip_html(message);
+- ret = mwConversation_send(conv, mwImSend_PLAIN, tmp);
+- g_free(tmp);
+- }
+-
+- return !ret;
+-
+- } else {
+-
+- /* queue up the message safely as plain text */
+- char *tmp = purple_markup_strip_html(message);
+- convo_queue(conv, mwImSend_PLAIN, tmp);
+- g_free(tmp);
+-
+- if(! mwConversation_isPending(conv))
+- mwConversation_open(conv);
+-
+- return 1;
+- }
+-}
+-
+-
+-static unsigned int mw_prpl_send_typing(PurpleConnection *gc,
+- const char *name,
+- PurpleTypingState state) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwIdBlock who = { (char *) name, NULL };
+- struct mwConversation *conv;
+-
+- gpointer t = GINT_TO_POINTER(!! state);
+-
+- g_return_val_if_fail(gc != NULL, 0);
+- pd = gc->proto_data;
+-
+- g_return_val_if_fail(pd != NULL, 0);
+-
+- conv = mwServiceIm_getConversation(pd->srvc_im, &who);
+-
+- if(mwConversation_isOpen(conv)) {
+- mwConversation_send(conv, mwImSend_TYPING, t);
+-
+- } else if((state == PURPLE_TYPING) || (state == PURPLE_TYPED)) {
+- /* only open a channel for sending typing notification, not for
+- when typing has stopped. There's no point in re-opening a
+- channel just to tell someone that this side isn't typing. */
+-
+- convo_queue(conv, mwImSend_TYPING, t);
+-
+- if(! mwConversation_isPending(conv)) {
+- mwConversation_open(conv);
+- }
+- }
+-
+- return 0;
+-}
+-
+-
+-static const char *mw_client_name(guint16 type) {
+- switch(type) {
+- case mwLogin_LIB:
+- return "Lotus Binary Library";
+-
+- case mwLogin_JAVA_WEB:
+- return "Lotus Java Client Applet";
+-
+- case mwLogin_BINARY:
+- return "Lotus Sametime Connect";
+-
+- case mwLogin_JAVA_APP:
+- return "Lotus Java Client Application";
+-
+- case mwLogin_LINKS:
+- return "Lotus Sametime Links";
+-
+- case mwLogin_NOTES_6_5:
+- case mwLogin_NOTES_6_5_3:
+- case mwLogin_NOTES_7_0_beta:
+- case mwLogin_NOTES_7_0:
+- return "Lotus Notes Client";
+-
+- case mwLogin_ICT:
+- case mwLogin_ICT_1_7_8_2:
+- case mwLogin_ICT_SIP:
+- return "IBM Community Tools";
+-
+- case mwLogin_NOTESBUDDY_4_14:
+- case mwLogin_NOTESBUDDY_4_15:
+- case mwLogin_NOTESBUDDY_4_16:
+- return "Alphaworks NotesBuddy";
+-
+- case 0x1305:
+- case 0x1306:
+- case 0x1307:
+- return "Lotus Sametime Connect 7.5";
+-
+- case mwLogin_SANITY:
+- return "Sanity";
+-
+- case mwLogin_ST_PERL:
+- return "ST-Send-Message";
+-
+- case mwLogin_TRILLIAN:
+- case mwLogin_TRILLIAN_IBM:
+- return "Trillian";
+-
+- case mwLogin_MEANWHILE:
+- return "Meanwhile";
+-
+- default:
+- return NULL;
+- }
+-}
+-
+-
+-static void mw_prpl_get_info(PurpleConnection *gc, const char *who) {
+-
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
+-
+- struct mwPurplePluginData *pd;
+- PurpleAccount *acct;
+- PurpleBuddy *b;
+- PurpleNotifyUserInfo *user_info;
+- char *tmp;
+- const char *tmp2;
+-
+- g_return_if_fail(who != NULL);
+- g_return_if_fail(*who != '\0');
+-
+- pd = gc->proto_data;
+-
+- acct = purple_connection_get_account(gc);
+- b = purple_find_buddy(acct, who);
+- user_info = purple_notify_user_info_new();
+-
+- if(purple_str_has_prefix(who, "@E ")) {
+- purple_notify_user_info_add_pair(user_info, _("External User"), NULL);
+- }
+-
+- purple_notify_user_info_add_pair(user_info, _("User ID"), who);
+-
+- if(b) {
+- guint32 type;
+-
+- if(purple_buddy_get_server_alias(b)) {
+- purple_notify_user_info_add_pair(user_info, _("Full Name"), purple_buddy_get_server_alias(b));
+- }
+-
+- type = purple_blist_node_get_int((PurpleBlistNode *) b, BUDDY_KEY_CLIENT);
+- if(type) {
+- tmp = g_strdup(mw_client_name(type));
+- if (!tmp)
+- tmp = g_strdup_printf(_("Unknown (0x%04x)<br>"), type);
+-
+- purple_notify_user_info_add_pair(user_info, _("Last Known Client"), tmp);
+-
+- g_free(tmp);
+- }
+- }
+-
+- tmp = user_supports_text(pd->srvc_aware, who);
+- if(tmp) {
+- purple_notify_user_info_add_pair(user_info, _("Supports"), tmp);
+- g_free(tmp);
+- }
+-
+- if(b) {
+- purple_notify_user_info_add_pair(user_info, _("Status"), status_text(b));
+-
+- /* XXX Is this adding a status message in its own section rather than with the "Status" label? */
+- tmp2 = mwServiceAware_getText(pd->srvc_aware, &idb);
+- if(tmp2 && g_utf8_validate(tmp2, -1, NULL)) {
+- tmp = g_markup_escape_text(tmp2, -1);
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+- }
+- }
+-
+- /* @todo emit a signal to allow a plugin to override the display of
+- this notification, so that it can create its own */
+-
+- purple_notify_userinfo(gc, who, user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-}
+-
+-
+-static void mw_prpl_set_status(PurpleAccount *acct, PurpleStatus *status) {
+- PurpleConnection *gc;
+- const char *state;
+- char *message = NULL;
+- struct mwSession *session;
+- struct mwUserStatus stat;
+-
+- g_return_if_fail(acct != NULL);
+- gc = purple_account_get_connection(acct);
+-
+- state = purple_status_get_id(status);
+-
+- DEBUG_INFO("Set status to %s\n", purple_status_get_name(status));
+-
+- g_return_if_fail(gc != NULL);
+-
+- session = gc_to_session(gc);
+- g_return_if_fail(session != NULL);
+-
+- /* get a working copy of the current status */
+- mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
+-
+- /* determine the state */
+- if(! strcmp(state, MW_STATE_ACTIVE)) {
+- stat.status = mwStatus_ACTIVE;
+-
+- } else if(! strcmp(state, MW_STATE_AWAY)) {
+- stat.status = mwStatus_AWAY;
+-
+- } else if(! strcmp(state, MW_STATE_BUSY)) {
+- stat.status = mwStatus_BUSY;
+- }
+-
+- /* determine the message */
+- message = (char *) purple_status_get_attr_string(status, MW_STATE_MESSAGE);
+-
+- if(message) {
+- /* all the possible non-NULL values of message up to this point
+- are const, so we don't need to free them */
+- message = purple_markup_strip_html(message);
+- }
+-
+- /* out with the old */
+- g_free(stat.desc);
+-
+- /* in with the new */
+- stat.desc = (char *) message;
+-
+- mwSession_setUserStatus(session, &stat);
+- mwUserStatus_clear(&stat);
+-}
+-
+-
+-static void mw_prpl_set_idle(PurpleConnection *gc, int t) {
+- struct mwSession *session;
+- struct mwUserStatus stat;
+-
+-
+- session = gc_to_session(gc);
+- g_return_if_fail(session != NULL);
+-
+- mwUserStatus_clone(&stat, mwSession_getUserStatus(session));
+-
+- if(t) {
+- time_t now = time(NULL);
+- stat.time = now - t;
+-
+- } else {
+- stat.time = 0;
+- }
+-
+- if(t > 0 && stat.status == mwStatus_ACTIVE) {
+- /* we were active and went idle, so change the status to IDLE. */
+- stat.status = mwStatus_IDLE;
+-
+- } else if(t == 0 && stat.status == mwStatus_IDLE) {
+- /* we only become idle automatically, so change back to ACTIVE */
+- stat.status = mwStatus_ACTIVE;
+- }
+-
+- mwSession_setUserStatus(session, &stat);
+- mwUserStatus_clear(&stat);
+-}
+-
+-
+-static void notify_im(PurpleConnection *gc, GList *row, void *user_data) {
+- PurpleAccount *acct;
+- PurpleConversation *conv;
+- char *id;
+-
+- acct = purple_connection_get_account(gc);
+- id = g_list_nth_data(row, 1);
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, id, acct);
+- if(! conv) conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, id);
+- purple_conversation_present(conv);
+-}
+-
+-
+-static void notify_add(PurpleConnection *gc, GList *row, void *user_data) {
+- BuddyAddData *data = user_data;
+- const char *group_name = NULL;
+-
+- if (data && data->group) {
+- group_name = purple_group_get_name(data->group);
+- }
+-
+- purple_blist_request_add_buddy(purple_connection_get_account(gc),
+- g_list_nth_data(row, 1), group_name,
+- g_list_nth_data(row, 0));
+-}
+-
+-
+-static void notify_close(gpointer data) {
+- if (data) {
+- g_free(data);
+- }
+-}
+-
+-
+-static void multi_resolved_query(struct mwResolveResult *result,
+- PurpleConnection *gc, gpointer data) {
+- GList *l;
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- PurpleNotifySearchResults *sres;
+- PurpleNotifySearchColumn *scol;
+-
+- sres = purple_notify_searchresults_new();
+-
+- scol = purple_notify_searchresults_column_new(_("User Name"));
+- purple_notify_searchresults_column_add(sres, scol);
+-
+- scol = purple_notify_searchresults_column_new(_("Sametime ID"));
+- purple_notify_searchresults_column_add(sres, scol);
+-
+- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM,
+- notify_im);
+-
+- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD,
+- notify_add);
+-
+- for(l = result->matches; l; l = l->next) {
+- struct mwResolveMatch *match = l->data;
+- GList *row = NULL;
+-
+- DEBUG_INFO("multi resolve: %s, %s\n",
+- NSTR(match->id), NSTR(match->name));
+-
+- if(!match->id || !match->name)
+- continue;
+-
+- row = g_list_append(row, g_strdup(match->name));
+- row = g_list_append(row, g_strdup(match->id));
+- purple_notify_searchresults_row_add(sres, row);
+- }
+-
+- msgA = _("An ambiguous user ID was entered");
+- msgB = _("The identifier '%s' may possibly refer to any of the following"
+- " users. Please select the correct user from the list below to"
+- " add them to your buddy list.");
+- msg = g_strdup_printf(msgB, result->name);
+-
+- purple_notify_searchresults(gc, _("Select User"),
+- msgA, msg, sres, notify_close, data);
+-
+- g_free(msg);
+-}
+-
+-
+-static void add_buddy_resolved(struct mwServiceResolve *srvc,
+- guint32 id, guint32 code, GList *results,
+- gpointer b) {
+-
+- struct mwResolveResult *res = NULL;
+- BuddyAddData *data = b;
+- PurpleBuddy *buddy = NULL;
+- PurpleConnection *gc;
+- struct mwPurplePluginData *pd;
+-
+- g_return_if_fail(data != NULL);
+-
+- buddy = data->buddy;
+-
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- pd = gc->proto_data;
+-
+- if(results)
+- res = results->data;
+-
+- if(!code && res && res->matches) {
+- if(!res->matches->next) {
+- struct mwResolveMatch *match = res->matches->data;
+-
+- /* only one? that might be the right one! */
+- if(strcmp(res->name, match->id)) {
+- /* uh oh, the single result isn't identical to the search
+- term, better safe then sorry, so let's make sure it's who
+- the user meant to add */
+- purple_blist_remove_buddy(buddy);
+- multi_resolved_query(res, gc, data);
+-
+- } else {
+-
+- /* same person, set the server alias */
+- purple_blist_server_alias_buddy(buddy, match->name);
+- purple_blist_node_set_string((PurpleBlistNode *) buddy,
+- BUDDY_KEY_NAME, match->name);
+-
+- /* subscribe to awareness */
+- buddy_add(pd, buddy);
+-
+- blist_schedule(pd);
+-
+- g_free(data);
+- }
+-
+- } else {
+- /* prompt user if more than one match was returned */
+- purple_blist_remove_buddy(buddy);
+- multi_resolved_query(res, gc, data);
+- }
+-
+- return;
+- }
+-
+-#if 0
+- /* fall-through indicates that we couldn't find a matching user in
+- the resolve service (ether error or zero results), so we remove
+- this buddy */
+-
+- /* note: I can't really think of a good reason to alter the buddy
+- list in any way. There has been at least one report where the
+- resolve service isn't returning correct results anyway, so let's
+- just leave them in the list. I'm just going to if0 this section
+- out unless I can think of a very good reason to do this. -siege */
+-
+- DEBUG_INFO("no such buddy in community\n");
+- purple_blist_remove_buddy(buddy);
+- blist_schedule(pd);
+-
+- if(res && res->name) {
+- /* compose and display an error message */
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- msgA = _("Unable to add user: user not found");
+-
+- msgB = _("The identifier '%s' did not match any users in your"
+- " Sametime community. This entry has been removed from"
+- " your buddy list.");
+- msg = g_strdup_printf(msgB, NSTR(res->name));
+-
+- purple_notify_error(gc, _("Unable to add user"), msgA, msg);
+-
+- g_free(msg);
+- }
+-#endif
+-}
+-
+-
+-static void mw_prpl_add_buddy(PurpleConnection *gc,
+- PurpleBuddy *buddy,
+- PurpleGroup *group) {
+-
+- struct mwPurplePluginData *pd = gc->proto_data;
+- struct mwServiceResolve *srvc;
+- GList *query;
+- enum mwResolveFlag flags;
+- guint32 req;
+- BuddyAddData *data;
+-
+- /* catch external buddies. They won't be in the resolve service */
+- if(buddy_is_external(buddy)) {
+- buddy_add(pd, buddy);
+- return;
+- }
+-
+- data = g_new0(BuddyAddData, 1);
+- data->buddy = buddy;
+- data->group = group;
+-
+- srvc = pd->srvc_resolve;
+-
+- query = g_list_prepend(NULL, (char *)purple_buddy_get_name(buddy));
+- flags = mwResolveFlag_FIRST | mwResolveFlag_USERS;
+-
+- req = mwServiceResolve_resolve(srvc, query, flags, add_buddy_resolved,
+- data, NULL);
+- g_list_free(query);
+-
+- if(req == SEARCH_ERROR) {
+- purple_blist_remove_buddy(buddy);
+- blist_schedule(pd);
+- }
+-}
+-
+-
+-static void foreach_add_buddies(PurpleGroup *group, GList *buddies,
+- struct mwPurplePluginData *pd) {
+- struct mwAwareList *list;
+-
+- list = list_ensure(pd, group);
+- mwAwareList_addAware(list, buddies);
+- g_list_free(buddies);
+-}
+-
+-
+-static void mw_prpl_add_buddies(PurpleConnection *gc,
+- GList *buddies,
+- GList *groups) {
+-
+- struct mwPurplePluginData *pd;
+- GHashTable *group_sets;
+- struct mwAwareIdBlock *idbs, *idb;
+-
+- pd = gc->proto_data;
+-
+- /* map PurpleGroup:GList of mwAwareIdBlock */
+- group_sets = g_hash_table_new(g_direct_hash, g_direct_equal);
+-
+- /* bunch of mwAwareIdBlock allocated at once, free'd at once */
+- idb = idbs = g_new(struct mwAwareIdBlock, g_list_length(buddies));
+-
+- /* first pass collects mwAwareIdBlock lists for each group */
+- for(; buddies; buddies = buddies->next) {
+- PurpleBuddy *b = buddies->data;
+- PurpleGroup *g;
+- const char *fn;
+- GList *l;
+-
+- /* nab the saved server alias and stick it on the buddy */
+- fn = purple_blist_node_get_string((PurpleBlistNode *) b, BUDDY_KEY_NAME);
+- purple_blist_server_alias_buddy(b, fn);
+-
+- /* convert PurpleBuddy into a mwAwareIdBlock */
+- idb->type = mwAware_USER;
+- idb->user = (char *) purple_buddy_get_name(b);
+- idb->community = NULL;
+-
+- /* put idb into the list associated with the buddy's group */
+- g = purple_buddy_get_group(b);
+- l = g_hash_table_lookup(group_sets, g);
+- l = g_list_prepend(l, idb++);
+- g_hash_table_insert(group_sets, g, l);
+- }
+-
+- /* each group's buddies get added in one shot, and schedule the blist
+- for saving */
+- g_hash_table_foreach(group_sets, (GHFunc) foreach_add_buddies, pd);
+- blist_schedule(pd);
+-
+- /* cleanup */
+- g_hash_table_destroy(group_sets);
+- g_free(idbs);
+-}
+-
+-
+-static void mw_prpl_remove_buddy(PurpleConnection *gc,
+- PurpleBuddy *buddy, PurpleGroup *group) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *)purple_buddy_get_name(buddy), NULL };
+- struct mwAwareList *list;
+-
+- GList *rem = g_list_prepend(NULL, &idb);
+-
+- pd = gc->proto_data;
+- group = purple_buddy_get_group(buddy);
+- list = list_ensure(pd, group);
+-
+- mwAwareList_removeAware(list, rem);
+- blist_schedule(pd);
+-
+- g_list_free(rem);
+-}
+-
+-
+-static void privacy_fill(struct mwPrivacyInfo *priv,
+- GSList *members) {
+-
+- struct mwUserItem *u;
+- guint count;
+-
+- count = g_slist_length(members);
+- DEBUG_INFO("privacy_fill: %u members\n", count);
+-
+- priv->count = count;
+- priv->users = g_new0(struct mwUserItem, count);
+-
+- while(count--) {
+- u = priv->users + count;
+- u->id = members->data;
+- members = members->next;
+- }
+-}
+-
+-
+-static void mw_prpl_set_permit_deny(PurpleConnection *gc) {
+- PurpleAccount *acct;
+- struct mwPurplePluginData *pd;
+- struct mwSession *session;
+-
+- struct mwPrivacyInfo privacy = {
+- FALSE, /* deny */
+- 0, /* count */
+- NULL, /* users */
+- };
+-
+- g_return_if_fail(gc != NULL);
+-
+- acct = purple_connection_get_account(gc);
+- g_return_if_fail(acct != NULL);
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- session = pd->session;
+- g_return_if_fail(session != NULL);
+-
+- switch(acct->perm_deny) {
+- case PURPLE_PRIVACY_DENY_USERS:
+- DEBUG_INFO("PURPLE_PRIVACY_DENY_USERS\n");
+- privacy_fill(&privacy, acct->deny);
+- privacy.deny = TRUE;
+- break;
+-
+- case PURPLE_PRIVACY_ALLOW_ALL:
+- DEBUG_INFO("PURPLE_PRIVACY_ALLOW_ALL\n");
+- privacy.deny = TRUE;
+- break;
+-
+- case PURPLE_PRIVACY_ALLOW_USERS:
+- DEBUG_INFO("PURPLE_PRIVACY_ALLOW_USERS\n");
+- privacy_fill(&privacy, acct->permit);
+- privacy.deny = FALSE;
+- break;
+-
+- case PURPLE_PRIVACY_DENY_ALL:
+- DEBUG_INFO("PURPLE_PRIVACY_DENY_ALL\n");
+- privacy.deny = FALSE;
+- break;
+-
+- default:
+- DEBUG_INFO("acct->perm_deny is 0x%x\n", acct->perm_deny);
+- return;
+- }
+-
+- mwSession_setPrivacyInfo(session, &privacy);
+- g_free(privacy.users);
+-}
+-
+-
+-static void mw_prpl_add_permit(PurpleConnection *gc, const char *name) {
+- mw_prpl_set_permit_deny(gc);
+-}
+-
+-
+-static void mw_prpl_add_deny(PurpleConnection *gc, const char *name) {
+- mw_prpl_set_permit_deny(gc);
+-}
+-
+-
+-static void mw_prpl_rem_permit(PurpleConnection *gc, const char *name) {
+- mw_prpl_set_permit_deny(gc);
+-}
+-
+-
+-static void mw_prpl_rem_deny(PurpleConnection *gc, const char *name) {
+- mw_prpl_set_permit_deny(gc);
+-}
+-
+-
+-static struct mwConference *conf_find(struct mwServiceConference *srvc,
+- const char *name) {
+- GList *l, *ll;
+- struct mwConference *conf = NULL;
+-
+- ll = mwServiceConference_getConferences(srvc);
+- for(l = ll; l; l = l->next) {
+- struct mwConference *c = l->data;
+- if(! strcmp(name, mwConference_getName(c))) {
+- conf = c;
+- break;
+- }
+- }
+- g_list_free(ll);
+-
+- return conf;
+-}
+-
+-
+-static void mw_prpl_join_chat(PurpleConnection *gc,
+- GHashTable *components) {
+-
+- struct mwPurplePluginData *pd;
+- char *c, *t;
+-
+- pd = gc->proto_data;
+-
+- c = g_hash_table_lookup(components, CHAT_KEY_NAME);
+- t = g_hash_table_lookup(components, CHAT_KEY_TOPIC);
+-
+- if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) {
+- /* use place service */
+- struct mwServicePlace *srvc;
+- struct mwPlace *place = NULL;
+-
+- srvc = pd->srvc_place;
+- place = mwPlace_new(srvc, c, t);
+- mwPlace_open(place);
+-
+- } else {
+- /* use conference service */
+- struct mwServiceConference *srvc;
+- struct mwConference *conf = NULL;
+-
+- srvc = pd->srvc_conf;
+- if(c) conf = conf_find(srvc, c);
+-
+- if(conf) {
+- DEBUG_INFO("accepting conference invitation\n");
+- mwConference_accept(conf);
+-
+- } else {
+- DEBUG_INFO("creating new conference\n");
+- conf = mwConference_new(srvc, t);
+- mwConference_open(conf);
+- }
+- }
+-}
+-
+-
+-static void mw_prpl_reject_chat(PurpleConnection *gc,
+- GHashTable *components) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwServiceConference *srvc;
+- char *c;
+-
+- pd = gc->proto_data;
+- srvc = pd->srvc_conf;
+-
+- if(g_hash_table_lookup(components, CHAT_KEY_IS_PLACE)) {
+- ; /* nothing needs doing */
+-
+- } else {
+- /* reject conference */
+- c = g_hash_table_lookup(components, CHAT_KEY_NAME);
+- if(c) {
+- struct mwConference *conf = conf_find(srvc, c);
+- if(conf) mwConference_reject(conf, ERR_SUCCESS, "Declined");
+- }
+- }
+-}
+-
+-
+-static char *mw_prpl_get_chat_name(GHashTable *components) {
+- return g_hash_table_lookup(components, CHAT_KEY_NAME);
+-}
+-
+-
+-static void mw_prpl_chat_invite(PurpleConnection *gc,
+- int id,
+- const char *invitation,
+- const char *who) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwConference *conf;
+- struct mwPlace *place;
+- struct mwIdBlock idb = { (char *) who, NULL };
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- conf = ID_TO_CONF(pd, id);
+-
+- if(conf) {
+- mwConference_invite(conf, &idb, invitation);
+- return;
+- }
+-
+- place = ID_TO_PLACE(pd, id);
+- g_return_if_fail(place != NULL);
+-
+- /* @todo: use the IM service for invitation */
+- mwPlace_legacyInvite(place, &idb, invitation);
+-}
+-
+-
+-static void mw_prpl_chat_leave(PurpleConnection *gc,
+- int id) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwConference *conf;
+-
+- pd = gc->proto_data;
+-
+- g_return_if_fail(pd != NULL);
+- conf = ID_TO_CONF(pd, id);
+-
+- if(conf) {
+- mwConference_destroy(conf, ERR_SUCCESS, "Leaving");
+-
+- } else {
+- struct mwPlace *place = ID_TO_PLACE(pd, id);
+- g_return_if_fail(place != NULL);
+-
+- mwPlace_destroy(place, ERR_SUCCESS);
+- }
+-}
+-
+-
+-static void mw_prpl_chat_whisper(PurpleConnection *gc,
+- int id,
+- const char *who,
+- const char *message) {
+-
+- mw_prpl_send_im(gc, who, message, 0);
+-}
+-
+-
+-static int mw_prpl_chat_send(PurpleConnection *gc,
+- int id,
+- const char *message,
+- PurpleMessageFlags flags) {
+-
+- struct mwPurplePluginData *pd;
+- struct mwConference *conf;
+- char *msg;
+- int ret;
+-
+- pd = gc->proto_data;
+-
+- g_return_val_if_fail(pd != NULL, 0);
+- conf = ID_TO_CONF(pd, id);
+-
+- msg = purple_markup_strip_html(message);
+-
+- if(conf) {
+- ret = ! mwConference_sendText(conf, msg);
+-
+- } else {
+- struct mwPlace *place = ID_TO_PLACE(pd, id);
+- g_return_val_if_fail(place != NULL, 0);
+-
+- ret = ! mwPlace_sendText(place, msg);
+- }
+-
+- g_free(msg);
+- return ret;
+-}
+-
+-
+-static void mw_prpl_keepalive(PurpleConnection *gc) {
+- struct mwSession *session;
+-
+- g_return_if_fail(gc != NULL);
+-
+- session = gc_to_session(gc);
+- g_return_if_fail(session != NULL);
+-
+- mwSession_sendKeepalive(session);
+-}
+-
+-
+-static void mw_prpl_alias_buddy(PurpleConnection *gc,
+- const char *who,
+- const char *alias) {
+-
+- struct mwPurplePluginData *pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- /* it's a change to the buddy list, so we've gotta reflect that in
+- the server copy */
+-
+- blist_schedule(pd);
+-}
+-
+-
+-static void mw_prpl_group_buddy(PurpleConnection *gc,
+- const char *who,
+- const char *old_group,
+- const char *new_group) {
+-
+- struct mwAwareIdBlock idb = { mwAware_USER, (char *) who, NULL };
+- GList *gl = g_list_prepend(NULL, &idb);
+-
+- struct mwPurplePluginData *pd = gc->proto_data;
+- PurpleGroup *group;
+- struct mwAwareList *list;
+-
+- /* add who to new_group's aware list */
+- group = purple_find_group(new_group);
+- list = list_ensure(pd, group);
+- mwAwareList_addAware(list, gl);
+-
+- /* remove who from old_group's aware list */
+- group = purple_find_group(old_group);
+- list = list_ensure(pd, group);
+- mwAwareList_removeAware(list, gl);
+-
+- g_list_free(gl);
+-
+- /* schedule the changes to be saved */
+- blist_schedule(pd);
+-}
+-
+-
+-static void mw_prpl_rename_group(PurpleConnection *gc,
+- const char *old,
+- PurpleGroup *group,
+- GList *buddies) {
+-
+- struct mwPurplePluginData *pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+-
+- /* it's a change in the buddy list, so we've gotta reflect that in
+- the server copy. Also, having this function should prevent all
+- those buddies from being removed and re-added. We don't really
+- give a crap what the group is named in Purple other than to record
+- that as the group name/alias */
+-
+- blist_schedule(pd);
+-}
+-
+-
+-static void mw_prpl_buddy_free(PurpleBuddy *buddy) {
+- /* I don't think we have any cleanup for buddies yet */
+- ;
+-}
+-
+-
+-static void mw_prpl_convo_closed(PurpleConnection *gc, const char *who) {
+- struct mwPurplePluginData *pd = gc->proto_data;
+- struct mwServiceIm *srvc;
+- struct mwConversation *conv;
+- struct mwIdBlock idb = { (char *) who, NULL };
+-
+- g_return_if_fail(pd != NULL);
+-
+- srvc = pd->srvc_im;
+- g_return_if_fail(srvc != NULL);
+-
+- conv = mwServiceIm_findConversation(srvc, &idb);
+- if(! conv) return;
+-
+- if(mwConversation_isOpen(conv))
+- mwConversation_free(conv);
+-}
+-
+-
+-static const char *mw_prpl_normalize(const PurpleAccount *account,
+- const char *id) {
+-
+- /* code elsewhere assumes that the return value points to different
+- memory than the passed value, but it won't free the normalized
+- data. wtf? */
+-
+- static char buf[BUF_LEN];
+- g_strlcpy(buf, id, sizeof(buf));
+- return buf;
+-}
+-
+-
+-static void mw_prpl_remove_group(PurpleConnection *gc, PurpleGroup *group) {
+- struct mwPurplePluginData *pd;
+- struct mwAwareList *list;
+-
+- pd = gc->proto_data;
+- g_return_if_fail(pd != NULL);
+- g_return_if_fail(pd->group_list_map != NULL);
+-
+- list = g_hash_table_lookup(pd->group_list_map, group);
+-
+- if(list) {
+- g_hash_table_remove(pd->group_list_map, list);
+- g_hash_table_remove(pd->group_list_map, group);
+- mwAwareList_free(list);
+-
+- blist_schedule(pd);
+- }
+-}
+-
+-
+-static gboolean mw_prpl_can_receive_file(PurpleConnection *gc,
+- const char *who) {
+- struct mwPurplePluginData *pd;
+- struct mwServiceAware *srvc;
+- PurpleAccount *acct;
+-
+- g_return_val_if_fail(gc != NULL, FALSE);
+-
+- pd = gc->proto_data;
+- g_return_val_if_fail(pd != NULL, FALSE);
+-
+- srvc = pd->srvc_aware;
+- g_return_val_if_fail(srvc != NULL, FALSE);
+-
+- acct = purple_connection_get_account(gc);
+- g_return_val_if_fail(acct != NULL, FALSE);
+-
+- return purple_find_buddy(acct, who) &&
+- user_supports(srvc, who, mwAttribute_FILE_TRANSFER);
+-}
+-
+-
+-static void ft_outgoing_init(PurpleXfer *xfer) {
+- PurpleAccount *acct;
+- PurpleConnection *gc;
+-
+- struct mwPurplePluginData *pd;
+- struct mwServiceFileTransfer *srvc;
+- struct mwFileTransfer *ft;
+-
+- const char *filename;
+- gsize filesize;
+- FILE *fp;
+-
+- struct mwIdBlock idb = { NULL, NULL };
+-
+- DEBUG_INFO("ft_outgoing_init\n");
+-
+- acct = purple_xfer_get_account(xfer);
+- gc = purple_account_get_connection(acct);
+- pd = gc->proto_data;
+- srvc = pd->srvc_ft;
+-
+- filename = purple_xfer_get_local_filename(xfer);
+- filesize = purple_xfer_get_size(xfer);
+- idb.user = xfer->who;
+-
+- purple_xfer_update_progress(xfer);
+-
+- /* test that we can actually send the file */
+- fp = g_fopen(filename, "rb");
+- if(! fp) {
+- char *msg = g_strdup_printf(_("Error reading file %s: \n%s\n"),
+- filename, g_strerror(errno));
+- purple_xfer_error(purple_xfer_get_type(xfer), acct, xfer->who, msg);
+- g_free(msg);
+- return;
+- }
+- fclose(fp);
+-
+- {
+- char *tmp = strrchr(filename, G_DIR_SEPARATOR);
+- if(tmp++) filename = tmp;
+- }
+-
+- ft = mwFileTransfer_new(srvc, &idb, NULL, filename, filesize);
+-
+- purple_xfer_ref(xfer);
+- mwFileTransfer_setClientData(ft, xfer, (GDestroyNotify) purple_xfer_unref);
+- xfer->data = ft;
+-
+- mwFileTransfer_offer(ft);
+-}
+-
+-
+-static void ft_outgoing_cancel(PurpleXfer *xfer) {
+- struct mwFileTransfer *ft = xfer->data;
+-
+- DEBUG_INFO("ft_outgoing_cancel called\n");
+-
+- if(ft) mwFileTransfer_cancel(ft);
+-}
+-
+-
+-static PurpleXfer *mw_prpl_new_xfer(PurpleConnection *gc, const char *who) {
+- PurpleAccount *acct;
+- PurpleXfer *xfer;
+-
+- acct = purple_connection_get_account(gc);
+-
+- xfer = purple_xfer_new(acct, PURPLE_XFER_SEND, who);
+- if (xfer)
+- {
+- purple_xfer_set_init_fnc(xfer, ft_outgoing_init);
+- purple_xfer_set_cancel_send_fnc(xfer, ft_outgoing_cancel);
+- }
+-
+- return xfer;
+-}
+-
+-static void mw_prpl_send_file(PurpleConnection *gc,
+- const char *who, const char *file) {
+-
+- PurpleXfer *xfer = mw_prpl_new_xfer(gc, who);
+-
+- if(file) {
+- DEBUG_INFO("file != NULL\n");
+- purple_xfer_request_accepted(xfer, file);
+-
+- } else {
+- DEBUG_INFO("file == NULL\n");
+- purple_xfer_request(xfer);
+- }
+-}
+-
+-
+-static PurplePluginProtocolInfo mw_prpl_info = {
+- OPT_PROTO_IM_IMAGE,
+- NULL, /*< set in mw_plugin_init */
+- NULL, /*< set in mw_plugin_init */
+- NO_BUDDY_ICONS,
+- mw_prpl_list_icon,
+- mw_prpl_list_emblem,
+- mw_prpl_status_text,
+- mw_prpl_tooltip_text,
+- mw_prpl_status_types,
+- mw_prpl_blist_node_menu,
+- mw_prpl_chat_info,
+- mw_prpl_chat_info_defaults,
+- mw_prpl_login,
+- mw_prpl_close,
+- mw_prpl_send_im,
+- NULL,
+- mw_prpl_send_typing,
+- mw_prpl_get_info,
+- mw_prpl_set_status,
+- mw_prpl_set_idle,
+- NULL,
+- mw_prpl_add_buddy,
+- mw_prpl_add_buddies,
+- mw_prpl_remove_buddy,
+- NULL,
+- mw_prpl_add_permit,
+- mw_prpl_add_deny,
+- mw_prpl_rem_permit,
+- mw_prpl_rem_deny,
+- mw_prpl_set_permit_deny,
+- mw_prpl_join_chat,
+- mw_prpl_reject_chat,
+- mw_prpl_get_chat_name,
+- mw_prpl_chat_invite,
+- mw_prpl_chat_leave,
+- mw_prpl_chat_whisper,
+- mw_prpl_chat_send,
+- mw_prpl_keepalive,
+- NULL,
+- NULL,
+- NULL,
+- mw_prpl_alias_buddy,
+- mw_prpl_group_buddy,
+- mw_prpl_rename_group,
+- mw_prpl_buddy_free,
+- mw_prpl_convo_closed,
+- mw_prpl_normalize,
+- NULL,
+- mw_prpl_remove_group,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- mw_prpl_can_receive_file,
+- mw_prpl_send_file,
+- mw_prpl_new_xfer,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- sizeof(PurplePluginProtocolInfo),
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-
+-static PurplePluginPrefFrame *
+-mw_plugin_get_plugin_pref_frame(PurplePlugin *plugin) {
+- PurplePluginPrefFrame *frame;
+- PurplePluginPref *pref;
+-
+- frame = purple_plugin_pref_frame_new();
+-
+- pref = purple_plugin_pref_new_with_label(_("Remotely Stored Buddy List"));
+- purple_plugin_pref_frame_add(frame, pref);
+-
+-
+- pref = purple_plugin_pref_new_with_name(MW_PRPL_OPT_BLIST_ACTION);
+- purple_plugin_pref_set_label(pref, _("Buddy List Storage Mode"));
+-
+- purple_plugin_pref_set_type(pref, PURPLE_PLUGIN_PREF_CHOICE);
+- purple_plugin_pref_add_choice(pref, _("Local Buddy List Only"),
+- GINT_TO_POINTER(blist_choice_LOCAL));
+- purple_plugin_pref_add_choice(pref, _("Merge List from Server"),
+- GINT_TO_POINTER(blist_choice_MERGE));
+- purple_plugin_pref_add_choice(pref, _("Merge and Save List to Server"),
+- GINT_TO_POINTER(blist_choice_STORE));
+- purple_plugin_pref_add_choice(pref, _("Synchronize List with Server"),
+- GINT_TO_POINTER(blist_choice_SYNCH));
+-
+- purple_plugin_pref_frame_add(frame, pref);
+-
+- return frame;
+-}
+-
+-
+-static PurplePluginUiInfo mw_plugin_ui_info = {
+- mw_plugin_get_plugin_pref_frame,
+- 0, /* page_num */
+- NULL, /* frame */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-
+-static void st_import_action_cb(PurpleConnection *gc, char *filename) {
+- struct mwSametimeList *l;
+-
+- FILE *file;
+- char buf[BUF_LEN];
+- size_t len;
+-
+- GString *str;
+-
+- file = g_fopen(filename, "r");
+- g_return_if_fail(file != NULL);
+-
+- str = g_string_new(NULL);
+- while( (len = fread(buf, 1, BUF_LEN, file)) ) {
+- g_string_append_len(str, buf, len);
+- }
+-
+- fclose(file);
+-
+- l = mwSametimeList_load(str->str);
+- g_string_free(str, TRUE);
+-
+- blist_merge(gc, l);
+- mwSametimeList_free(l);
+-}
+-
+-
+-/** prompts for a file to import blist from */
+-static void st_import_action(PurplePluginAction *act) {
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- char *title;
+-
+- gc = act->context;
+- account = purple_connection_get_account(gc);
+- title = g_strdup_printf(_("Import Sametime List for Account %s"),
+- purple_account_get_username(account));
+-
+- purple_request_file(gc, title, NULL, FALSE,
+- G_CALLBACK(st_import_action_cb), NULL,
+- account, NULL, NULL,
+- gc);
+-
+- g_free(title);
+-}
+-
+-
+-static void st_export_action_cb(PurpleConnection *gc, char *filename) {
+- struct mwSametimeList *l;
+- char *str;
+- FILE *file;
+-
+- file = g_fopen(filename, "w");
+- g_return_if_fail(file != NULL);
+-
+- l = mwSametimeList_new();
+- blist_export(gc, l);
+- str = mwSametimeList_store(l);
+- mwSametimeList_free(l);
+-
+- fprintf(file, "%s", str);
+- fclose(file);
+-
+- g_free(str);
+-}
+-
+-
+-/** prompts for a file to export blist to */
+-static void st_export_action(PurplePluginAction *act) {
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- char *title;
+-
+- gc = act->context;
+- account = purple_connection_get_account(gc);
+- title = g_strdup_printf(_("Export Sametime List for Account %s"),
+- purple_account_get_username(account));
+-
+- purple_request_file(gc, title, NULL, TRUE,
+- G_CALLBACK(st_export_action_cb), NULL,
+- account, NULL, NULL,
+- gc);
+-
+- g_free(title);
+-}
+-
+-
+-static void remote_group_multi_cleanup(gpointer ignore,
+- PurpleRequestFields *fields) {
+-
+- PurpleRequestField *f;
+- GList *l;
+-
+- f = purple_request_fields_get_field(fields, "group");
+- l = purple_request_field_list_get_items(f);
+-
+- for(; l; l = l->next) {
+- const char *i = l->data;
+- struct named_id *res;
+-
+- res = purple_request_field_list_get_data(f, i);
+-
+- g_free(res->id);
+- g_free(res->name);
+- g_free(res);
+- }
+-}
+-
+-
+-static void remote_group_done(struct mwPurplePluginData *pd,
+- const char *id, const char *name) {
+- PurpleConnection *gc;
+- PurpleAccount *acct;
+- PurpleGroup *group;
+- PurpleBlistNode *gn;
+- const char *owner;
+-
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+- acct = purple_connection_get_account(gc);
+-
+- /* collision checking */
+- group = purple_find_group(name);
+- if(group) {
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- msgA = _("Unable to add group: group exists");
+- msgB = _("A group named '%s' already exists in your buddy list.");
+- msg = g_strdup_printf(msgB, name);
+-
+- purple_notify_error(gc, _("Unable to add group"), msgA, msg);
+-
+- g_free(msg);
+- return;
+- }
+-
+- group = purple_group_new(name);
+- gn = (PurpleBlistNode *) group;
+-
+- owner = purple_account_get_username(acct);
+-
+- purple_blist_node_set_string(gn, GROUP_KEY_NAME, id);
+- purple_blist_node_set_int(gn, GROUP_KEY_TYPE, mwSametimeGroup_DYNAMIC);
+- purple_blist_node_set_string(gn, GROUP_KEY_OWNER, owner);
+- purple_blist_add_group(group, NULL);
+-
+- group_add(pd, group);
+- blist_schedule(pd);
+-}
+-
+-
+-static void remote_group_multi_cb(struct mwPurplePluginData *pd,
+- PurpleRequestFields *fields) {
+- PurpleRequestField *f;
+- GList *l;
+-
+- f = purple_request_fields_get_field(fields, "group");
+- l = purple_request_field_list_get_selected(f);
+-
+- if(l) {
+- const char *i = l->data;
+- struct named_id *res;
+-
+- res = purple_request_field_list_get_data(f, i);
+- remote_group_done(pd, res->id, res->name);
+- }
+-
+- remote_group_multi_cleanup(NULL, fields);
+-}
+-
+-
+-static void remote_group_multi(struct mwResolveResult *result,
+- struct mwPurplePluginData *pd) {
+-
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *g;
+- PurpleRequestField *f;
+- GList *l;
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- PurpleConnection *gc = pd->gc;
+-
+- fields = purple_request_fields_new();
+-
+- g = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, g);
+-
+- f = purple_request_field_list_new("group", _("Possible Matches"));
+- purple_request_field_list_set_multi_select(f, FALSE);
+- purple_request_field_set_required(f, TRUE);
+-
+- for(l = result->matches; l; l = l->next) {
+- struct mwResolveMatch *match = l->data;
+- struct named_id *res = g_new0(struct named_id, 1);
+-
+- res->id = g_strdup(match->id);
+- res->name = g_strdup(match->name);
+-
+- purple_request_field_list_add_icon(f, res->name, NULL, res);
+- }
+-
+- purple_request_field_group_add_field(g, f);
+-
+- msgA = _("Notes Address Book group results");
+- msgB = _("The identifier '%s' may possibly refer to any of the following"
+- " Notes Address Book groups. Please select the correct group from"
+- " the list below to add it to your buddy list.");
+- msg = g_strdup_printf(msgB, result->name);
+-
+- purple_request_fields(gc, _("Select Notes Address Book"),
+- msgA, msg, fields,
+- _("Add Group"), G_CALLBACK(remote_group_multi_cb),
+- _("Cancel"), G_CALLBACK(remote_group_multi_cleanup),
+- purple_connection_get_account(gc), result->name, NULL,
+- pd);
+-
+- g_free(msg);
+-}
+-
+-
+-static void remote_group_resolved(struct mwServiceResolve *srvc,
+- guint32 id, guint32 code, GList *results,
+- gpointer b) {
+-
+- struct mwResolveResult *res = NULL;
+- struct mwSession *session;
+- struct mwPurplePluginData *pd;
+- PurpleConnection *gc;
+-
+- session = mwService_getSession(MW_SERVICE(srvc));
+- g_return_if_fail(session != NULL);
+-
+- pd = mwSession_getClientData(session);
+- g_return_if_fail(pd != NULL);
+-
+- gc = pd->gc;
+- g_return_if_fail(gc != NULL);
+-
+- if(!code && results) {
+- res = results->data;
+-
+- if(res->matches) {
+- remote_group_multi(res, pd);
+- return;
+- }
+- }
+-
+- if(res && res->name) {
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- msgA = _("Unable to add group: group not found");
+-
+- msgB = _("The identifier '%s' did not match any Notes Address Book"
+- " groups in your Sametime community.");
+- msg = g_strdup_printf(msgB, res->name);
+-
+- purple_notify_error(gc, _("Unable to add group"), msgA, msg);
+-
+- g_free(msg);
+- }
+-}
+-
+-
+-static void remote_group_action_cb(PurpleConnection *gc, const char *name) {
+- struct mwPurplePluginData *pd;
+- struct mwServiceResolve *srvc;
+- GList *query;
+- enum mwResolveFlag flags;
+- guint32 req;
+-
+- pd = gc->proto_data;
+- srvc = pd->srvc_resolve;
+-
+- query = g_list_prepend(NULL, (char *) name);
+- flags = mwResolveFlag_FIRST | mwResolveFlag_GROUPS;
+-
+- req = mwServiceResolve_resolve(srvc, query, flags, remote_group_resolved,
+- NULL, NULL);
+- g_list_free(query);
+-
+- if(req == SEARCH_ERROR) {
+- /** @todo display error */
+- }
+-}
+-
+-
+-static void remote_group_action(PurplePluginAction *act) {
+- PurpleConnection *gc;
+- const char *msgA;
+- const char *msgB;
+-
+- gc = act->context;
+-
+- msgA = _("Notes Address Book Group");
+- msgB = _("Enter the name of a Notes Address Book group in the field below"
+- " to add the group and its members to your buddy list.");
+-
+- purple_request_input(gc, _("Add Group"), msgA, msgB, NULL,
+- FALSE, FALSE, NULL,
+- _("Add"), G_CALLBACK(remote_group_action_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-
+-static void search_notify(struct mwResolveResult *result,
+- PurpleConnection *gc) {
+- GList *l;
+- const char *msgA;
+- const char *msgB;
+- char *msg1;
+- char *msg2;
+-
+- PurpleNotifySearchResults *sres;
+- PurpleNotifySearchColumn *scol;
+-
+- sres = purple_notify_searchresults_new();
+-
+- scol = purple_notify_searchresults_column_new(_("User Name"));
+- purple_notify_searchresults_column_add(sres, scol);
+-
+- scol = purple_notify_searchresults_column_new(_("Sametime ID"));
+- purple_notify_searchresults_column_add(sres, scol);
+-
+- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_IM,
+- notify_im);
+-
+- purple_notify_searchresults_button_add(sres, PURPLE_NOTIFY_BUTTON_ADD,
+- notify_add);
+-
+- for(l = result->matches; l; l = l->next) {
+- struct mwResolveMatch *match = l->data;
+- GList *row = NULL;
+-
+- if(!match->id || !match->name)
+- continue;
+-
+- row = g_list_append(row, g_strdup(match->name));
+- row = g_list_append(row, g_strdup(match->id));
+- purple_notify_searchresults_row_add(sres, row);
+- }
+-
+- msgA = _("Search results for '%s'");
+- msgB = _("The identifier '%s' may possibly refer to any of the following"
+- " users. You may add these users to your buddy list or send them"
+- " messages with the action buttons below.");
+-
+- msg1 = g_strdup_printf(msgA, result->name);
+- msg2 = g_strdup_printf(msgB, result->name);
+-
+- purple_notify_searchresults(gc, _("Search Results"),
+- msg1, msg2, sres, notify_close, NULL);
+-
+- g_free(msg1);
+- g_free(msg2);
+-}
+-
+-
+-static void search_resolved(struct mwServiceResolve *srvc,
+- guint32 id, guint32 code, GList *results,
+- gpointer b) {
+-
+- PurpleConnection *gc = b;
+- struct mwResolveResult *res = NULL;
+-
+- if(results) res = results->data;
+-
+- if(!code && res && res->matches) {
+- search_notify(res, gc);
+-
+- } else {
+- const char *msgA;
+- const char *msgB;
+- char *msg;
+-
+- msgA = _("No matches");
+- msgB = _("The identifier '%s' did not match any users in your"
+- " Sametime community.");
+- msg = g_strdup_printf(msgB, (res && res->name) ? NSTR(res->name) : "");
+-
+- purple_notify_error(gc, _("No Matches"), msgA, msg);
+-
+- g_free(msg);
+- }
+-}
+-
+-
+-static void search_action_cb(PurpleConnection *gc, const char *name) {
+- struct mwPurplePluginData *pd;
+- struct mwServiceResolve *srvc;
+- GList *query;
+- enum mwResolveFlag flags;
+- guint32 req;
+-
+- pd = gc->proto_data;
+- srvc = pd->srvc_resolve;
+-
+- query = g_list_prepend(NULL, (char *) name);
+- flags = mwResolveFlag_FIRST | mwResolveFlag_USERS;
+-
+- req = mwServiceResolve_resolve(srvc, query, flags, search_resolved,
+- gc, NULL);
+- g_list_free(query);
+-
+- if(req == SEARCH_ERROR) {
+- /** @todo display error */
+- }
+-}
+-
+-
+-static void search_action(PurplePluginAction *act) {
+- PurpleConnection *gc;
+- const char *msgA;
+- const char *msgB;
+-
+- gc = act->context;
+-
+- msgA = _("Search for a user");
+- msgB = _("Enter a name or partial ID in the field below to search"
+- " for matching users in your Sametime community.");
+-
+- purple_request_input(gc, _("User Search"), msgA, msgB, NULL,
+- FALSE, FALSE, NULL,
+- _("Search"), G_CALLBACK(search_action_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-
+-static GList *mw_plugin_actions(PurplePlugin *plugin, gpointer context) {
+- PurplePluginAction *act;
+- GList *l = NULL;
+-
+- act = purple_plugin_action_new(_("Import Sametime List..."),
+- st_import_action);
+- l = g_list_append(l, act);
+-
+- act = purple_plugin_action_new(_("Export Sametime List..."),
+- st_export_action);
+- l = g_list_append(l, act);
+-
+- act = purple_plugin_action_new(_("Add Notes Address Book Group..."),
+- remote_group_action);
+- l = g_list_append(l, act);
+-
+- act = purple_plugin_action_new(_("User Search..."),
+- search_action);
+- l = g_list_append(l, act);
+-
+- return l;
+-}
+-
+-
+-static gboolean mw_plugin_load(PurplePlugin *plugin) {
+- return TRUE;
+-}
+-
+-
+-static gboolean mw_plugin_unload(PurplePlugin *plugin) {
+- return TRUE;
+-}
+-
+-
+-static void mw_plugin_destroy(PurplePlugin *plugin) {
+- g_log_remove_handler(G_LOG_DOMAIN, log_handler[0]);
+- g_log_remove_handler("meanwhile", log_handler[1]);
+-}
+-
+-static PurplePluginInfo mw_plugin_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 */
+-
+- PLUGIN_ID, /**< id */
+- PLUGIN_NAME, /**< name */
+- DISPLAY_VERSION, /**< version */
+- PLUGIN_SUMMARY, /**< summary */
+- PLUGIN_DESC, /**< description */
+- PLUGIN_AUTHOR, /**< author */
+- PLUGIN_HOMEPAGE, /**< homepage */
+-
+- mw_plugin_load, /**< load */
+- mw_plugin_unload, /**< unload */
+- mw_plugin_destroy, /**< destroy */
+-
+- NULL, /**< ui_info */
+- &mw_prpl_info, /**< extra_info */
+- &mw_plugin_ui_info, /**< prefs_info */
+- mw_plugin_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-
+-static void mw_log_handler(const gchar *domain, GLogLevelFlags flags,
+- const gchar *msg, gpointer data) {
+-
+- if(! (msg && *msg)) return;
+-
+- /* handle g_log requests via purple's built-in debug logging */
+- if(flags & G_LOG_LEVEL_ERROR) {
+- purple_debug_error(domain, "%s\n", msg);
+-
+- } else if(flags & G_LOG_LEVEL_WARNING) {
+- purple_debug_warning(domain, "%s\n", msg);
+-
+- } else {
+- purple_debug_info(domain, "%s\n", msg);
+- }
+-}
+-
+-
+-static void mw_plugin_init(PurplePlugin *plugin) {
+- PurpleAccountUserSplit *split;
+- PurpleAccountOption *opt;
+- GList *l = NULL;
+-
+- GLogLevelFlags logflags =
+- G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION;
+-
+- /* set up the preferences */
+- purple_prefs_add_none(MW_PRPL_OPT_BASE);
+- purple_prefs_add_int(MW_PRPL_OPT_BLIST_ACTION, BLIST_CHOICE_DEFAULT);
+-
+- /* set up account ID as user:server */
+- split = purple_account_user_split_new(_("Server"),
+- MW_PLUGIN_DEFAULT_HOST, ':');
+- mw_prpl_info.user_splits = g_list_append(mw_prpl_info.user_splits, split);
+-
+- /* remove dead preferences */
+- purple_prefs_remove(MW_PRPL_OPT_PSYCHIC);
+- purple_prefs_remove(MW_PRPL_OPT_SAVE_DYNAMIC);
+-
+- /* port to connect to */
+- opt = purple_account_option_int_new(_("Port"), MW_KEY_PORT,
+- MW_PLUGIN_DEFAULT_PORT);
+- l = g_list_append(l, opt);
+-
+- { /* copy the old force login setting from prefs if it's
+- there. Don't delete the preference, since there may be more
+- than one account that wants to check for it. */
+- gboolean b = FALSE;
+- const char *label = _("Force login (ignore server redirects)");
+-
+- if(purple_prefs_exists(MW_PRPL_OPT_FORCE_LOGIN))
+- b = purple_prefs_get_bool(MW_PRPL_OPT_FORCE_LOGIN);
+-
+- opt = purple_account_option_bool_new(label, MW_KEY_FORCE, b);
+- l = g_list_append(l, opt);
+- }
+-
+- /* pretend to be Sametime Connect */
+- opt = purple_account_option_bool_new(_("Hide client identity"),
+- MW_KEY_FAKE_IT, FALSE);
+- l = g_list_append(l, opt);
+-
+- mw_prpl_info.protocol_options = l;
+- l = NULL;
+-
+- /* forward all our g_log messages to purple. Generally all the logging
+- calls are using purple_log directly, but the g_return macros will
+- get caught here */
+- log_handler[0] = g_log_set_handler(G_LOG_DOMAIN, logflags,
+- mw_log_handler, NULL);
+-
+- /* redirect meanwhile's logging to purple's */
+- log_handler[1] = g_log_set_handler("meanwhile", logflags,
+- mw_log_handler, NULL);
+-}
+-
+-
+-PURPLE_INIT_PLUGIN(sametime, mw_plugin_init, mw_plugin_info);
+-/* The End. */
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/sametime/sametime.h pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.h
+--- pidgin-2.10.7/libpurple/protocols/sametime/sametime.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/sametime/sametime.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,26 +0,0 @@
+-
+-
+-/* CFLAGS trumps configure values */
+-
+-
+-/** default host for the purple plugin. You can specialize a build to
+- default to your server by supplying this at compile time */
+-#ifndef MW_PLUGIN_DEFAULT_HOST
+-#define MW_PLUGIN_DEFAULT_HOST ""
+-#endif
+-/* "" */
+-
+-
+-/** default port for the purple plugin. You can specialize a build to
+- default to your server by supplying this at compile time */
+-#ifndef MW_PLUGIN_DEFAULT_PORT
+-#define MW_PLUGIN_DEFAULT_PORT 1533
+-#endif
+-/* 1533 */
+-
+-
+-/** default encoding for the purple plugin.*/
+-#ifndef MW_PLUGIN_DEFAULT_ENCODING
+-#define MW_PLUGIN_DEFAULT_ENCODING "ISO-8859-1"
+-#endif
+-/* ISO-8859-1 */
+diff -Nur pidgin-2.10.7/libpurple/protocols/silc/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/silc/Makefile.in 2013-02-11 07:17:22.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.in 2013-08-16 23:50:52.621915468 -0300
+@@ -196,8 +196,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -259,8 +257,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/silc/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/silc/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/silc/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libsilc protocol plugin
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-TARGET = libsilc
+-NEEDED_DLLS = $(SILC_TOOLKIT)/bin/libsilc-1-1-2.dll \
+- $(SILC_TOOLKIT)/bin/libsilcclient-1-1-3.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,0x74000000 -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS)
+- rm -f $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/silc10/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/silc10/Makefile.in 2013-02-11 07:17:22.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.in 2013-08-16 23:51:39.120015095 -0300
+@@ -196,8 +196,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -259,8 +257,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/silc10/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/silc10/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/silc10/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libsilc protocol plugin
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/simple/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/simple/Makefile.in 2013-02-11 07:17:22.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.in 2013-08-16 23:51:48.486970456 -0300
+@@ -189,8 +189,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -252,8 +250,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/protocols/simple/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/simple/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/simple/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,78 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libsimple
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libsimple
+-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 = simple.c \
+- sipmsg.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(DLL_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)
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libyahoo.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoo.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/libyahoo.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoo.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,348 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#include <account.h>
+-#include <core.h>
+-
+-#include "libymsg.h"
+-#include "yahoochat.h"
+-#include "yahoo_aliases.h"
+-#include "yahoo_doodle.h"
+-#include "yahoo_filexfer.h"
+-#include "yahoo_picture.h"
+-
+-static PurplePlugin *my_protocol = NULL;
+-
+-static void yahoo_register_commands(void)
+-{
+- purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+- PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoo", yahoopurple_cmd_chat_join,
+- _("join &lt;room&gt;: Join a chat room on the Yahoo network"), NULL);
+- purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+- PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoo", yahoopurple_cmd_chat_list,
+- _("list: List rooms on the Yahoo network"), NULL);
+- purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoo", yahoopurple_cmd_buzz,
+- _("buzz: Buzz a user to get their attention"), NULL);
+- purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoo", yahoo_doodle_purple_cmd_start,
+- _("doodle: Request user to start a Doodle session"), NULL);
+-}
+-
+-static PurpleAccount *find_acct(const char *prpl, const char *acct_id)
+-{
+- PurpleAccount *acct = NULL;
+-
+- /* If we have a specific acct, use it */
+- if (acct_id) {
+- acct = purple_accounts_find(acct_id, prpl);
+- if (acct && !purple_account_is_connected(acct))
+- acct = NULL;
+- } else { /* Otherwise find an active account for the protocol */
+- GList *l = purple_accounts_get_all();
+- while (l) {
+- if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
+- && purple_account_is_connected(l->data)) {
+- acct = l->data;
+- break;
+- }
+- l = l->next;
+- }
+- }
+-
+- return acct;
+-}
+-
+-/* This may not be the best way to do this, but we find the first key w/o a value
+- * and assume it is the buddy name */
+-static void yahoo_find_uri_novalue_param(gpointer key, gpointer value, gpointer user_data)
+-{
+- char **retval = user_data;
+-
+- if (value == NULL && *retval == NULL) {
+- *retval = key;
+- }
+-}
+-
+-static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable *params)
+-{
+- char *acct_id = g_hash_table_lookup(params, "account");
+- PurpleAccount *acct;
+-
+- if (g_ascii_strcasecmp(proto, "ymsgr"))
+- return FALSE;
+-
+- acct = find_acct(purple_plugin_get_id(my_protocol), acct_id);
+-
+- if (!acct)
+- return FALSE;
+-
+- /* ymsgr:SendIM?screename&m=The+Message */
+- if (!g_ascii_strcasecmp(cmd, "SendIM")) {
+- char *sname = NULL;
+- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &sname);
+- if (sname) {
+- char *message = g_hash_table_lookup(params, "m");
+-
+- PurpleConversation *conv = purple_find_conversation_with_account(
+- PURPLE_CONV_TYPE_IM, sname, acct);
+- if (conv == NULL)
+- conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, acct, sname);
+- purple_conversation_present(conv);
+-
+- if (message) {
+- /* Spaces are encoded as '+' */
+- g_strdelimit(message, "+", ' ');
+- purple_conv_send_confirm(conv, message);
+- }
+- }
+- /* else
+- **If pidgindialogs_im() was in the core, we could use it here.
+- * It is all purple_request_* based, but I'm not sure it really belongs in the core
+- pidgindialogs_im(); */
+-
+- return TRUE;
+- }
+- /* ymsgr:Chat?roomname */
+- else if (!g_ascii_strcasecmp(cmd, "Chat")) {
+- char *rname = NULL;
+- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &rname);
+- if (rname) {
+- /* This is somewhat hacky, but the params aren't useful after this command */
+- g_hash_table_insert(params, g_strdup("room"), g_strdup(rname));
+- g_hash_table_insert(params, g_strdup("type"), g_strdup("Chat"));
+- serv_join_chat(purple_account_get_connection(acct), params);
+- }
+- /* else
+- ** Same as above (except that this would have to be re-written using purple_request_*)
+- pidgin_blist_joinchat_show(); */
+-
+- return TRUE;
+- }
+- /* ymsgr:AddFriend?name */
+- else if (!g_ascii_strcasecmp(cmd, "AddFriend")) {
+- char *name = NULL;
+- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &name);
+- purple_blist_request_add_buddy(acct, name, NULL, NULL);
+- return TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-static GHashTable *
+-yahoo_get_account_text_table(PurpleAccount *account)
+-{
+- GHashTable *table;
+- table = g_hash_table_new(g_str_hash, g_str_equal);
+- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo ID..."));
+- return table;
+-}
+-
+-static gboolean yahoo_unload_plugin(PurplePlugin *plugin)
+-{
+- yahoo_dest_colorht();
+-
+- return TRUE;
+-}
+-
+-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
+-{
+- yahoo_doodle_start,
+- yahoo_doodle_end,
+- yahoo_doodle_get_dimensions,
+- NULL,
+- yahoo_doodle_get_brush,
+- yahoo_doodle_set_brush,
+- yahoo_doodle_send_draw_list,
+- yahoo_doodle_clear,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+- yahoo_list_icon,
+- yahoo_list_emblem,
+- yahoo_status_text,
+- yahoo_tooltip_text,
+- yahoo_status_types,
+- yahoo_blist_node_menu,
+- yahoo_c_info,
+- yahoo_c_info_defaults,
+- yahoo_login,
+- yahoo_close,
+- yahoo_send_im,
+- NULL, /* set info */
+- yahoo_send_typing,
+- yahoo_get_info,
+- yahoo_set_status,
+- yahoo_set_idle,
+- NULL, /* change_passwd*/
+- yahoo_add_buddy,
+- NULL, /* add_buddies */
+- yahoo_remove_buddy,
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- yahoo_add_deny,
+- NULL, /* rem_permit */
+- yahoo_rem_deny,
+- yahoo_set_permit_deny,
+- yahoo_c_join,
+- NULL, /* reject chat invite */
+- yahoo_get_chat_name,
+- yahoo_c_invite,
+- yahoo_c_leave,
+- NULL, /* chat whisper */
+- yahoo_c_send,
+- yahoo_keepalive,
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- yahoo_update_alias, /* alias_buddy */
+- yahoo_change_buddys_group,
+- yahoo_rename_group,
+- NULL, /* buddy_free */
+- NULL, /* convo_closed */
+- purple_normalize_nocase, /* normalize */
+- yahoo_set_buddy_icon,
+- NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
+- NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- yahoo_roomlist_get_list,
+- yahoo_roomlist_cancel,
+- yahoo_roomlist_expand_category,
+- yahoo_can_receive_file, /* can_receive_file */
+- yahoo_send_file,
+- yahoo_new_xfer,
+- yahoo_offline_message, /* offline_message */
+- &yahoo_whiteboard_prpl_ops,
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+-
+- yahoo_send_attention,
+- yahoo_attention_types,
+-
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- yahoo_get_account_text_table, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- NULL, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-yahoo", /**< id */
+- "Yahoo", /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("Yahoo! Protocol Plugin"),
+- /** description */
+- N_("Yahoo! Protocol Plugin"),
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+- NULL, /**< load */
+- yahoo_unload_plugin, /**< unload */
+- NULL, /**< destroy */
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL,
+- yahoo_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- PurpleAccountOption *option;
+-
+- option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+-#if 0
+- option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-#endif
+-
+- my_protocol = plugin;
+- yahoo_register_commands();
+- yahoo_init_colorht();
+-
+- purple_signal_connect(purple_get_core(), "uri-handler", plugin,
+- PURPLE_CALLBACK(yahoo_uri_handler), NULL);
+-}
+-
+-PURPLE_INIT_PLUGIN(yahoo, init_plugin, info);
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libyahoojp.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoojp.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/libyahoojp.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libyahoojp.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,241 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#include <account.h>
+-
+-#include "libymsg.h"
+-#include "yahoochat.h"
+-#include "yahoo_aliases.h"
+-#include "yahoo_doodle.h"
+-#include "yahoo_filexfer.h"
+-#include "yahoo_picture.h"
+-
+-static void yahoojp_register_commands(void)
+-{
+- purple_cmd_register("join", "s", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+- PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoojp", yahoopurple_cmd_chat_join,
+- _("join &lt;room&gt;: Join a chat room on the Yahoo network"), NULL);
+- purple_cmd_register("list", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT |
+- PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoojp", yahoopurple_cmd_chat_list,
+- _("list: List rooms on the Yahoo network"), NULL);
+- purple_cmd_register("buzz", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoojp", yahoopurple_cmd_buzz,
+- _("buzz: Buzz a user to get their attention"), NULL);
+- purple_cmd_register("doodle", "", PURPLE_CMD_P_PRPL,
+- PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PRPL_ONLY,
+- "prpl-yahoojp", yahoo_doodle_purple_cmd_start,
+- _("doodle: Request user to start a Doodle session"), NULL);
+-}
+-
+-static GHashTable *
+-yahoojp_get_account_text_table(PurpleAccount *account)
+-{
+- GHashTable *table;
+- table = g_hash_table_new(g_str_hash, g_str_equal);
+- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo JAPAN ID..."));
+- return table;
+-}
+-
+-static gboolean yahoojp_unload_plugin(PurplePlugin *plugin)
+-{
+- yahoo_dest_colorht();
+-
+- return TRUE;
+-}
+-
+-static PurpleWhiteboardPrplOps yahoo_whiteboard_prpl_ops =
+-{
+- yahoo_doodle_start,
+- yahoo_doodle_end,
+- yahoo_doodle_get_dimensions,
+- NULL,
+- yahoo_doodle_get_brush,
+- yahoo_doodle_set_brush,
+- yahoo_doodle_send_draw_list,
+- yahoo_doodle_clear,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static PurplePluginProtocolInfo prpl_info =
+-{
+- OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC,
+- NULL, /* user_splits */
+- NULL, /* protocol_options */
+- {"png,gif,jpeg", 96, 96, 96, 96, 0, PURPLE_ICON_SCALE_SEND},
+- yahoo_list_icon,
+- yahoo_list_emblem,
+- yahoo_status_text,
+- yahoo_tooltip_text,
+- yahoo_status_types,
+- yahoo_blist_node_menu,
+- yahoo_c_info,
+- yahoo_c_info_defaults,
+- yahoo_login,
+- yahoo_close,
+- yahoo_send_im,
+- NULL, /* set info */
+- yahoo_send_typing,
+- yahoo_get_info,
+- yahoo_set_status,
+- yahoo_set_idle,
+- NULL, /* change_passwd*/
+- yahoo_add_buddy,
+- NULL, /* add_buddies */
+- yahoo_remove_buddy,
+- NULL, /* remove_buddies */
+- NULL, /* add_permit */
+- yahoo_add_deny,
+- NULL, /* rem_permit */
+- yahoo_rem_deny,
+- yahoo_set_permit_deny,
+- yahoo_c_join,
+- NULL, /* reject chat invite */
+- yahoo_get_chat_name,
+- yahoo_c_invite,
+- yahoo_c_leave,
+- NULL, /* chat whisper */
+- yahoo_c_send,
+- yahoo_keepalive,
+- NULL, /* register_user */
+- NULL, /* get_cb_info */
+- NULL, /* get_cb_away */
+- yahoo_update_alias, /* alias_buddy */
+- yahoo_change_buddys_group,
+- yahoo_rename_group,
+- NULL, /* buddy_free */
+- NULL, /* convo_closed */
+- purple_normalize_nocase, /* normalize */
+- yahoo_set_buddy_icon,
+- NULL, /* void (*remove_group)(PurpleConnection *gc, const char *group);*/
+- NULL, /* char *(*get_cb_real_name)(PurpleConnection *gc, int id, const char *who); */
+- NULL, /* set_chat_topic */
+- NULL, /* find_blist_chat */
+- yahoo_roomlist_get_list,
+- yahoo_roomlist_cancel,
+- yahoo_roomlist_expand_category,
+- NULL, /* can_receive_file */
+- yahoo_send_file,
+- yahoo_new_xfer,
+- yahoo_offline_message, /* offline_message */
+- &yahoo_whiteboard_prpl_ops,
+- NULL, /* send_raw */
+- NULL, /* roomlist_room_serialize */
+- NULL, /* unregister_user */
+-
+- yahoo_send_attention,
+- yahoo_attention_types,
+-
+- sizeof(PurplePluginProtocolInfo), /* struct_size */
+- yahoojp_get_account_text_table, /* get_account_text_table */
+- NULL, /* initiate_media */
+- NULL, /* get_media_caps */
+- NULL, /* get_moods */
+- NULL, /* set_public_alias */
+- NULL, /* get_public_alias */
+- NULL, /* add_buddy_with_invite */
+- NULL /* add_buddies_with_invite */
+-};
+-
+-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-yahoojp", /**< id */
+- "Yahoo JAPAN", /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("Yahoo! JAPAN Protocol Plugin"),
+- /** description */
+- N_("Yahoo! JAPAN Protocol Plugin"),
+- NULL, /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+- NULL, /**< load */
+- yahoojp_unload_plugin, /**< unload */
+- NULL, /**< destroy */
+- NULL, /**< ui_info */
+- &prpl_info, /**< extra_info */
+- NULL,
+- yahoo_actions,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- PurpleAccountOption *option;
+-
+- option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_int_new(_("File transfer port"), "xfer_port", YAHOO_XFER_PORT);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8");
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+- option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-
+-#if 0
+- option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL);
+- prpl_info.protocol_options = g_list_append(prpl_info.protocol_options, option);
+-#endif
+-
+- yahoojp_register_commands();
+- yahoo_init_colorht();
+-}
+-
+-PURPLE_INIT_PLUGIN(yahoojp, init_plugin, info);
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,5298 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "blist.h"
+-#include "cipher.h"
+-#include "cmds.h"
+-#include "core.h"
+-#include "debug.h"
+-#include "network.h"
+-#include "notify.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-#include "proxy.h"
+-#include "request.h"
+-#include "server.h"
+-#include "util.h"
+-#include "version.h"
+-#include "xmlnode.h"
+-
+-#include "libymsg.h"
+-#include "yahoochat.h"
+-#include "yahoo_aliases.h"
+-#include "yahoo_doodle.h"
+-#include "yahoo_filexfer.h"
+-#include "yahoo_friend.h"
+-#include "yahoo_packet.h"
+-#include "yahoo_picture.h"
+-#include "ycht.h"
+-
+-/* #define YAHOO_DEBUG */
+-
+-/* #define TRY_WEBMESSENGER_LOGIN 0 */
+-
+-/* One hour */
+-#define PING_TIMEOUT 3600
+-
+-/* One minute */
+-#define KEEPALIVE_TIMEOUT 60
+-
+-#ifdef TRY_WEBMESSENGER_LOGIN
+-static void yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message);
+-#endif /* TRY_WEBMESSENGER_LOGIN */
+-
+-static gboolean yahoo_is_japan(PurpleAccount *account)
+-{
+- return purple_strequal(purple_account_get_protocol_id(account), "prpl-yahoojp");
+-}
+-
+-static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f)
+-{
+- char *status = NULL;
+-
+- if (!gc || !name || !f || !purple_find_buddy(purple_connection_get_account(gc), name))
+- return;
+-
+- switch (f->status) {
+- case YAHOO_STATUS_OFFLINE:
+- status = YAHOO_STATUS_TYPE_OFFLINE;
+- break;
+- case YAHOO_STATUS_AVAILABLE:
+- status = YAHOO_STATUS_TYPE_AVAILABLE;
+- break;
+- case YAHOO_STATUS_BRB:
+- status = YAHOO_STATUS_TYPE_BRB;
+- break;
+- case YAHOO_STATUS_BUSY:
+- status = YAHOO_STATUS_TYPE_BUSY;
+- break;
+- case YAHOO_STATUS_NOTATHOME:
+- status = YAHOO_STATUS_TYPE_NOTATHOME;
+- break;
+- case YAHOO_STATUS_NOTATDESK:
+- status = YAHOO_STATUS_TYPE_NOTATDESK;
+- break;
+- case YAHOO_STATUS_NOTINOFFICE:
+- status = YAHOO_STATUS_TYPE_NOTINOFFICE;
+- break;
+- case YAHOO_STATUS_ONPHONE:
+- status = YAHOO_STATUS_TYPE_ONPHONE;
+- break;
+- case YAHOO_STATUS_ONVACATION:
+- status = YAHOO_STATUS_TYPE_ONVACATION;
+- break;
+- case YAHOO_STATUS_OUTTOLUNCH:
+- status = YAHOO_STATUS_TYPE_OUTTOLUNCH;
+- break;
+- case YAHOO_STATUS_STEPPEDOUT:
+- status = YAHOO_STATUS_TYPE_STEPPEDOUT;
+- break;
+- case YAHOO_STATUS_INVISIBLE: /* this should never happen? */
+- status = YAHOO_STATUS_TYPE_INVISIBLE;
+- break;
+- case YAHOO_STATUS_CUSTOM:
+- case YAHOO_STATUS_IDLE:
+- if (!f->away)
+- status = YAHOO_STATUS_TYPE_AVAILABLE;
+- else
+- status = YAHOO_STATUS_TYPE_AWAY;
+- break;
+- default:
+- purple_debug_warning("yahoo", "Warning, unknown status %d\n", f->status);
+- break;
+- }
+-
+- if (status) {
+- if (f->status == YAHOO_STATUS_CUSTOM)
+- purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, "message",
+- yahoo_friend_get_status_message(f), NULL);
+- else
+- purple_prpl_got_user_status(purple_connection_get_account(gc), name, status, NULL);
+- }
+-
+- if (f->idle != 0)
+- purple_prpl_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
+- else
+- purple_prpl_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
+-
+- if (f->sms)
+- purple_prpl_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
+- else
+- purple_prpl_got_user_status_deactive(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE);
+-}
+-
+-static void yahoo_process_status(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- GSList *l = pkt->hash;
+- YahooFriend *f = NULL;
+- char *name = NULL;
+- gboolean unicode = FALSE;
+- char *message = NULL;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+- char *fedname = NULL;
+-
+- if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) {
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NAME_IN_USE,
+- _("You have signed on from another location"));
+- return;
+- }
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 0: /* we won't actually do anything with this */
+- case 1: /* we won't actually do anything with this */
+- break;
+- case 8: /* how many online buddies we have */
+- break;
+- case 7: /* the current buddy */
+- /* update the previous buddy before changing the variables */
+- if (f) {
+- if (message)
+- yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
+- if (name)
+- yahoo_update_status(gc, name, f);
+- }
+- name = message = NULL;
+- f = NULL;
+- if (pair->value && g_utf8_validate(pair->value, -1, NULL)) {
+- GSList *tmplist;
+-
+- name = pair->value;
+-
+- /* Look ahead to see if we have the federation info about the buddy */
+- for (tmplist = l->next; tmplist; tmplist = tmplist->next) {
+- struct yahoo_pair *p = tmplist->data;
+- if (p->key == 7)
+- break;
+- if (p->key == 241) {
+- fed = strtol(p->value, NULL, 10);
+- g_free(fedname);
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- name = fedname = g_strconcat("msn/", name, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- name = fedname = g_strconcat("ocs/", name, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- name = fedname = g_strconcat("ibm/", name, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- fedname = NULL;
+- break;
+- }
+- break;
+- }
+- }
+- f = yahoo_friend_find_or_new(gc, name);
+- f->fed = fed;
+- }
+- break;
+- case 10: /* state */
+- if (!f)
+- break;
+-
+- f->status = strtol(pair->value, NULL, 10);
+- if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT))
+- f->away = 1;
+- else
+- f->away = 0;
+-
+- if (f->status == YAHOO_STATUS_IDLE) {
+- /* Idle may have already been set in a more precise way in case 137 */
+- if (f->idle == 0)
+- {
+- if(pkt->service == YAHOO_SERVICE_STATUS_15)
+- f->idle = -1;
+- else
+- f->idle = time(NULL);
+- }
+- } else
+- f->idle = 0;
+-
+- if (f->status != YAHOO_STATUS_CUSTOM)
+- yahoo_friend_set_status_message(f, NULL);
+-
+- f->sms = 0;
+- break;
+- case 19: /* custom message */
+- if (f)
+- message = pair->value;
+- break;
+- case 11: /* this is the buddy's session id */
+- if (f)
+- f->session_id = strtol(pair->value, NULL, 10);
+- break;
+- case 17: /* in chat? */
+- break;
+- case 47: /* is custom status away or not? 2=idle*/
+- if (!f)
+- break;
+-
+- /* I have no idea what it means when this is
+- * set when someone's available, but it doesn't
+- * mean idle. */
+- if (f->status == YAHOO_STATUS_AVAILABLE)
+- break;
+-
+- f->away = strtol(pair->value, NULL, 10);
+- if (f->away == 2) {
+- /* Idle may have already been set in a more precise way in case 137 */
+- if (f->idle == 0)
+- {
+- if(pkt->service == YAHOO_SERVICE_STATUS_15)
+- f->idle = -1;
+- else
+- f->idle = time(NULL);
+- }
+- }
+-
+- break;
+- case 138: /* when value is 1, either we're not idle, or we are but won't say how long */
+- if (!f)
+- break;
+-
+- if( (strtol(pair->value, NULL, 10) == 1) && (f->idle) )
+- f->idle = -1;
+- break;
+- case 137: /* usually idle time in seconds, sometimes login time */
+- if (!f)
+- break;
+-
+- if (f->status != YAHOO_STATUS_AVAILABLE)
+- f->idle = time(NULL) - strtol(pair->value, NULL, 10);
+- break;
+- case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
+- if (strtol(pair->value, NULL, 10) == 0) {
+- if (f)
+- f->status = YAHOO_STATUS_OFFLINE;
+- if (name) {
+- purple_prpl_got_user_status(account, name, "offline", NULL);
+- purple_prpl_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
+- }
+- break;
+- }
+- break;
+- case 60: /* SMS */
+- if (f) {
+- f->sms = strtol(pair->value, NULL, 10);
+- yahoo_update_status(gc, name, f);
+- }
+- break;
+- case 197: /* Avatars */
+- {
+- guchar *decoded;
+- char *tmp;
+- gsize len;
+-
+- if (pair->value) {
+- decoded = purple_base64_decode(pair->value, &len);
+- if (decoded && len > 0) {
+- tmp = purple_str_binary_to_ascii(decoded, len);
+- purple_debug_info("yahoo", "Got key 197, value = %s\n", tmp);
+- g_free(tmp);
+- }
+- g_free(decoded);
+- }
+- break;
+- }
+- case 192: /* Pictures, aka Buddy Icons, checksum */
+- {
+- /* FIXME: Please, if you know this protocol,
+- * FIXME: fix up the strtol() stuff if possible. */
+- int cksum = strtol(pair->value, NULL, 10);
+- const char *locksum = NULL;
+- PurpleBuddy *b;
+-
+- if (!name)
+- break;
+-
+- b = purple_find_buddy(gc->account, name);
+-
+- if (!cksum || (cksum == -1)) {
+- if (f)
+- yahoo_friend_set_buddy_icon_need_request(f, TRUE);
+- purple_buddy_icons_set_for_user(gc->account, name, NULL, 0, NULL);
+- break;
+- }
+-
+- if (!f)
+- break;
+-
+- yahoo_friend_set_buddy_icon_need_request(f, FALSE);
+- if (b) {
+- locksum = purple_buddy_icons_get_checksum_for_user(b);
+- if (!locksum || (cksum != strtol(locksum, NULL, 10)))
+- yahoo_send_picture_request(gc, name);
+- }
+-
+- break;
+- }
+- case 16: /* Custom error message */
+- {
+- char *tmp = yahoo_string_decode(gc, pair->value, TRUE);
+- purple_notify_error(gc, NULL, tmp, NULL);
+- g_free(tmp);
+- }
+- break;
+- case 97: /* Unicode status message */
+- unicode = !strcmp(pair->value, "1");
+- break;
+- case 244: /* client version number. Yahoo Client Detection */
+- if(f && strtol(pair->value, NULL, 10))
+- f->version_id = strtol(pair->value, NULL, 10);
+- break;
+- case 241: /* Federated network buddy belongs to */
+- break; /* We process this when get '7' */
+- default:
+- purple_debug_warning("yahoo",
+- "Unknown status key %d\n", pair->key);
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- if (f) {
+- if (pkt->service == YAHOO_SERVICE_LOGOFF)
+- f->status = YAHOO_STATUS_OFFLINE;
+- if (message)
+- yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
+-
+- if (name) /* update the last buddy */
+- yahoo_update_status(gc, name, f);
+- }
+-
+- g_free(fedname);
+-}
+-
+-static void yahoo_do_group_check(PurpleAccount *account, GHashTable *ht, const char *name, const char *group)
+-{
+- PurpleBuddy *b;
+- PurpleGroup *g;
+- GSList *list, *i;
+- gboolean onlist = FALSE;
+- char *oname = NULL;
+-
+- if (g_hash_table_lookup_extended(ht, name, (gpointer *)&oname, (gpointer *)&list))
+- g_hash_table_steal(ht, oname);
+- else
+- list = purple_find_buddies(account, name);
+-
+- for (i = list; i; i = i->next) {
+- b = i->data;
+- g = purple_buddy_get_group(b);
+- if (!purple_utf8_strcasecmp(group, purple_group_get_name(g))) {
+- purple_debug_misc("yahoo",
+- "Oh good, %s is in the right group (%s).\n", name, group);
+- list = g_slist_delete_link(list, i);
+- onlist = TRUE;
+- break;
+- }
+- }
+-
+- if (!onlist) {
+- purple_debug_misc("yahoo",
+- "Uhoh, %s isn't on the list (or not in this group), adding him to group %s.\n", name, group);
+- if (!(g = purple_find_group(group))) {
+- g = purple_group_new(group);
+- purple_blist_add_group(g, NULL);
+- }
+- b = purple_buddy_new(account, name, NULL);
+- purple_blist_add_buddy(b, NULL, g, NULL);
+- }
+-
+- if (list) {
+- if (!oname)
+- oname = g_strdup(name);
+- g_hash_table_insert(ht, oname, list);
+- } else
+- g_free(oname);
+-}
+-
+-static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data)
+-{
+- char *name = key;
+- GSList *list = value, *i;
+- PurpleBuddy *b;
+- PurpleGroup *g;
+-
+- for (i = list; i; i = i->next) {
+- b = i->data;
+- g = purple_buddy_get_group(b);
+- purple_debug_misc("yahoo", "Deleting Buddy %s from group %s.\n", name,
+- purple_group_get_name(g));
+- purple_blist_remove_buddy(b);
+- }
+-}
+-
+-static char *_getcookie(char *rawcookie)
+-{
+- char *cookie = NULL;
+- char *tmpcookie;
+- char *cookieend;
+-
+- if (strlen(rawcookie) < 2)
+- return NULL;
+- tmpcookie = g_strdup(rawcookie+2);
+- cookieend = strchr(tmpcookie, ';');
+-
+- if (cookieend)
+- *cookieend = '\0';
+-
+- cookie = g_strdup(tmpcookie);
+- g_free(tmpcookie);
+-
+- return cookie;
+-}
+-
+-static void yahoo_process_cookie(YahooData *yd, char *c)
+-{
+- if (c[0] == 'Y') {
+- if (yd->cookie_y)
+- g_free(yd->cookie_y);
+- yd->cookie_y = _getcookie(c);
+- } else if (c[0] == 'T') {
+- if (yd->cookie_t)
+- g_free(yd->cookie_t);
+- yd->cookie_t = _getcookie(c);
+- } else
+- purple_debug_info("yahoo", "Unrecognized cookie '%c'\n", c[0]);
+- yd->cookies = g_slist_prepend(yd->cookies, g_strdup(c));
+-}
+-
+-static void yahoo_process_list_15(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+-
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- GHashTable *ht;
+- char *norm_bud = NULL;
+- char *temp = NULL;
+- YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */
+- /* But what if you had no friends? */
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+- int stealth = 0;
+-
+- ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- l = l->next;
+-
+- switch (pair->key) {
+- case 302:
+- /* This is always 318 before a group, 319 before the first s/n in a group, 320 before any ignored s/n.
+- * It is not sent for s/n's in a group after the first.
+- * All ignored s/n's are listed last, so when we see a 320 we clear the group and begin marking the
+- * s/n's as ignored. It is always followed by an identical 300 key.
+- */
+- if (pair->value && !strcmp(pair->value, "320")) {
+- /* No longer in any group; this indicates the start of the ignore list. */
+- g_free(yd->current_list15_grp);
+- yd->current_list15_grp = NULL;
+- }
+-
+- break;
+- case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */
+- if(temp != NULL) {
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- norm_bud = g_strconcat("msn/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- norm_bud = g_strconcat("ocs/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- norm_bud = g_strconcat("ibm/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_PBX:
+- norm_bud = g_strconcat("pbx/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- norm_bud = g_strdup(temp);
+- break;
+- }
+- if (yd->current_list15_grp) {
+- /* This buddy is in a group */
+- f = yahoo_friend_find_or_new(gc, norm_bud);
+- if (!purple_find_buddy(account, norm_bud)) {
+- PurpleBuddy *b;
+- PurpleGroup *g;
+- if (!(g = purple_find_group(yd->current_list15_grp))) {
+- g = purple_group_new(yd->current_list15_grp);
+- purple_blist_add_group(g, NULL);
+- }
+- b = purple_buddy_new(account, norm_bud, NULL);
+- purple_blist_add_buddy(b, NULL, g, NULL);
+- }
+- yahoo_do_group_check(account, ht, norm_bud, yd->current_list15_grp);
+- if(fed) {
+- f->fed = fed;
+- purple_debug_info("yahoo", "Setting federation to %d\n", f->fed);
+- }
+- if(stealth == 2)
+- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
+-
+- /* set p2p status not connected and no p2p packet sent */
+- if(fed == YAHOO_FEDERATION_NONE) {
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
+- f->p2p_packet_sent = 0;
+- } else
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
+- } else {
+- /* This buddy is on the ignore list (and therefore in no group) */
+- purple_debug_info("yahoo", "%s adding %s to the deny list because of the ignore list / no group was found\n",account->username, norm_bud);
+- purple_privacy_deny_add(account, norm_bud, 1);
+- }
+-
+- g_free(norm_bud);
+- norm_bud=NULL;
+- fed = YAHOO_FEDERATION_NONE;
+- stealth = 0;
+- g_free(temp);
+- temp = NULL;
+- }
+- break;
+- case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */
+- break;
+- case 65: /* This is the group */
+- g_free(yd->current_list15_grp);
+- yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 7: /* buddy's s/n */
+- g_free(temp);
+- temp = g_strdup(purple_normalize(account, pair->value));
+- break;
+- case 241: /* user on federated network */
+- fed = strtol(pair->value, NULL, 10);
+- break;
+- case 59: /* somebody told cookies come here too, but im not sure */
+- yahoo_process_cookie(yd, pair->value);
+- break;
+- case 317: /* Stealth Setting */
+- stealth = strtol(pair->value, NULL, 10);
+- break;
+- /* case 242: */ /* this seems related to 241 */
+- /* break; */
+- }
+- }
+-
+- g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
+-
+- /* The reporter of ticket #9745 determined that we weren't retrieving the
+- * aliases during buddy list retrieval, so we never updated aliases that
+- * changed while we were signed off. */
+- yahoo_fetch_aliases(gc);
+-
+- /* Now that we have processed the buddy list, we can say yahoo has connected */
+- purple_connection_set_display_name(gc, purple_normalize(account, purple_account_get_username(account)));
+- yd->logged_in = TRUE;
+- purple_debug_info("yahoo","Authentication: Connection established\n");
+- purple_connection_set_state(gc, PURPLE_CONNECTED);
+- if (yd->picture_upload_todo) {
+- yahoo_buddy_icon_upload(gc, yd->picture_upload_todo);
+- yd->picture_upload_todo = NULL;
+- }
+- yahoo_set_status(account, purple_account_get_active_status(account));
+-
+- g_hash_table_destroy(ht);
+- g_free(temp);
+-}
+-
+-static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- gboolean export = FALSE;
+- gboolean got_serv_list = FALSE;
+- YahooFriend *f = NULL;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- GHashTable *ht;
+-
+- char **lines;
+- char **split;
+- char **buddies;
+- char **tmp, **bud, *norm_bud;
+- char *grp = NULL;
+-
+- if (pkt->id)
+- yd->session_id = pkt->id;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- l = l->next;
+-
+- switch (pair->key) {
+- case 87:
+- if (!yd->tmp_serv_blist)
+- yd->tmp_serv_blist = g_string_new(pair->value);
+- else
+- g_string_append(yd->tmp_serv_blist, pair->value);
+- break;
+- case 88:
+- if (!yd->tmp_serv_ilist)
+- yd->tmp_serv_ilist = g_string_new(pair->value);
+- else
+- g_string_append(yd->tmp_serv_ilist, pair->value);
+- break;
+- case 89:
+- yd->profiles = g_strsplit(pair->value, ",", -1);
+- break;
+- case 59: /* cookies, yum */
+- yahoo_process_cookie(yd, pair->value);
+- break;
+- case YAHOO_SERVICE_PRESENCE_PERM:
+- if (!yd->tmp_serv_plist)
+- yd->tmp_serv_plist = g_string_new(pair->value);
+- else
+- g_string_append(yd->tmp_serv_plist, pair->value);
+- break;
+- }
+- }
+-
+- if (pkt->status != 0)
+- return;
+-
+- if (yd->tmp_serv_blist) {
+- ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
+-
+- lines = g_strsplit(yd->tmp_serv_blist->str, "\n", -1);
+- for (tmp = lines; *tmp; tmp++) {
+- split = g_strsplit(*tmp, ":", 2);
+- if (!split)
+- continue;
+- if (!split[0] || !split[1]) {
+- g_strfreev(split);
+- continue;
+- }
+- grp = yahoo_string_decode(gc, split[0], FALSE);
+- buddies = g_strsplit(split[1], ",", -1);
+- for (bud = buddies; bud && *bud; bud++) {
+- norm_bud = g_strdup(purple_normalize(account, *bud));
+- f = yahoo_friend_find_or_new(gc, norm_bud);
+-
+- if (!purple_find_buddy(account, norm_bud)) {
+- PurpleBuddy *b;
+- PurpleGroup *g;
+- if (!(g = purple_find_group(grp))) {
+- g = purple_group_new(grp);
+- purple_blist_add_group(g, NULL);
+- }
+- b = purple_buddy_new(account, norm_bud, NULL);
+- purple_blist_add_buddy(b, NULL, g, NULL);
+- export = TRUE;
+- }
+-
+- yahoo_do_group_check(account, ht, norm_bud, grp);
+- /* set p2p status not connected and no p2p packet sent */
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
+- f->p2p_packet_sent = 0;
+-
+- g_free(norm_bud);
+- }
+- g_strfreev(buddies);
+- g_strfreev(split);
+- g_free(grp);
+- }
+- g_strfreev(lines);
+-
+- g_string_free(yd->tmp_serv_blist, TRUE);
+- yd->tmp_serv_blist = NULL;
+- g_hash_table_foreach(ht, yahoo_do_group_cleanup, NULL);
+- g_hash_table_destroy(ht);
+- }
+-
+- if (yd->tmp_serv_ilist) {
+- buddies = g_strsplit(yd->tmp_serv_ilist->str, ",", -1);
+- for (bud = buddies; bud && *bud; bud++) {
+- /* The server is already ignoring the user */
+- got_serv_list = TRUE;
+- purple_privacy_deny_add(account, *bud, 1);
+- }
+- g_strfreev(buddies);
+-
+- g_string_free(yd->tmp_serv_ilist, TRUE);
+- yd->tmp_serv_ilist = NULL;
+- }
+-
+- if (got_serv_list &&
+- ((account->perm_deny != PURPLE_PRIVACY_ALLOW_BUDDYLIST) &&
+- (account->perm_deny != PURPLE_PRIVACY_DENY_ALL) &&
+- (account->perm_deny != PURPLE_PRIVACY_ALLOW_USERS)))
+- {
+- account->perm_deny = PURPLE_PRIVACY_DENY_USERS;
+- purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_PRIVACY_DENY_USERS.\n",
+- account->username);
+- }
+-
+- if (yd->tmp_serv_plist) {
+- buddies = g_strsplit(yd->tmp_serv_plist->str, ",", -1);
+- for (bud = buddies; bud && *bud; bud++) {
+- f = yahoo_friend_find(gc, *bud);
+- if (f) {
+- purple_debug_info("yahoo", "%s setting presence for %s to PERM_OFFLINE\n",
+- account->username, *bud);
+- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
+- }
+- }
+- g_strfreev(buddies);
+- g_string_free(yd->tmp_serv_plist, TRUE);
+- yd->tmp_serv_plist = NULL;
+-
+- }
+- /* Now that we've got the list, request aliases */
+- yahoo_fetch_aliases(gc);
+-}
+-
+-/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
+-static void yahoo_process_notify(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
+-{
+- PurpleAccount *account;
+- char *msg = NULL;
+- char *from = NULL;
+- char *stat = NULL;
+- char *game = NULL;
+- YahooFriend *f = NULL;
+- GSList *l = pkt->hash;
+- gint val_11 = 0;
+- YahooData *yd = gc->proto_data;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- account = purple_connection_get_account(gc);
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 4 || pair->key == 1)
+- from = pair->value;
+- if (pair->key == 49)
+- msg = pair->value;
+- if (pair->key == 13)
+- stat = pair->value;
+- if (pair->key == 14)
+- game = pair->value;
+- if (pair->key == 11)
+- val_11 = strtol(pair->value, NULL, 10);
+- if (pair->key == 241)
+- fed = strtol(pair->value, NULL, 10);
+- l = l->next;
+- }
+-
+- if (!from || !msg)
+- return;
+-
+- /* disconnect the peer if connected through p2p and sends wrong value for session id */
+- if( (pkt_type == YAHOO_PKT_TYPE_P2P) && (val_11 != yd->session_id) ) {
+- purple_debug_warning("yahoo","p2p: %s sent us notify with wrong session id. Disconnecting p2p connection to peer\n", from);
+- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+- g_hash_table_remove(yd->peers, from);
+- return;
+- }
+-
+- if (!g_ascii_strncasecmp(msg, "TYPING", strlen("TYPING"))
+- && (purple_privacy_check(account, from)))
+- {
+- char *fed_from = from;
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- fed_from = g_strconcat("msn/", from, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- fed_from = g_strconcat("ocs/", from, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- fed_from = g_strconcat("ibm/", from, NULL);
+- break;
+- case YAHOO_FEDERATION_PBX:
+- fed_from = g_strconcat("pbx/", from, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- break;
+- }
+-
+- if (stat && *stat == '1')
+- serv_got_typing(gc, fed_from, 0, PURPLE_TYPING);
+- else
+- serv_got_typing_stopped(gc, fed_from);
+-
+- if (fed_from != from)
+- g_free(fed_from);
+-
+- } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
+- PurpleBuddy *bud = purple_find_buddy(account, from);
+-
+- if (!bud) {
+- purple_debug_warning("yahoo",
+- "%s is playing a game, and doesn't want you to know.\n", from);
+- }
+-
+- f = yahoo_friend_find(gc, from);
+- if (!f)
+- return; /* if they're not on the list, don't bother */
+-
+- yahoo_friend_set_game(f, NULL);
+-
+- if (stat && *stat == '1') {
+- yahoo_friend_set_game(f, game);
+- if (bud)
+- yahoo_update_status(gc, from, f);
+- }
+- } else if (!g_ascii_strncasecmp(msg, "WEBCAMINVITE", strlen("WEBCAMINVITE"))) {
+- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, from, account);
+- char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from);
+- purple_conversation_write(conv, NULL, buf, PURPLE_MESSAGE_SYSTEM|PURPLE_MESSAGE_NOTIFY, time(NULL));
+- g_free(buf);
+- }
+-}
+-
+-
+-struct _yahoo_im {
+- char *from;
+- char *active_id;
+- int time;
+- int utf8;
+- int buddy_icon;
+- char *id;
+- char *msg;
+- YahooFederation fed;
+- char *fed_from;
+-};
+-
+-static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account;
+- GSList *l = pkt->hash;
+- struct _yahoo_im *sms = NULL;
+- YahooData *yd;
+- char *server_msg = NULL;
+- char *m;
+-
+- yd = gc->proto_data;
+- account = purple_connection_get_account(gc);
+-
+- while (l != NULL) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 4) {
+- sms = g_new0(struct _yahoo_im, 1);
+- sms->from = g_strdup_printf("+%s", pair->value);
+- sms->time = time(NULL);
+- sms->utf8 = TRUE;
+- }
+- if (pair->key == 14) {
+- if (sms)
+- sms->msg = pair->value;
+- }
+- if (pair->key == 68)
+- if(sms)
+- g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value));
+- if (pair->key == 16)
+- server_msg = pair->value;
+- l = l->next;
+- }
+-
+- if(!sms) {
+- purple_debug_info("yahoo", "Received a malformed SMS packet!\n");
+- return;
+- }
+-
+- if( (pkt->status == -1) || (pkt->status == YAHOO_STATUS_DISCONNECTED) ) {
+- if (server_msg) {
+- PurpleConversation *c;
+- c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms->from, account);
+- if (c == NULL)
+- c = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, sms->from);
+- purple_conversation_write(c, NULL, server_msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+- else
+- purple_notify_error(gc, NULL, _("Your SMS was not delivered"), NULL);
+-
+- g_free(sms->from);
+- g_free(sms);
+- return ;
+- }
+-
+- if (!sms->from || !sms->msg) {
+- g_free(sms);
+- return;
+- }
+-
+- m = yahoo_string_decode(gc, sms->msg, sms->utf8);
+- serv_got_im(gc, sms->from, m, 0, sms->time);
+-
+- g_free(m);
+- g_free(sms->from);
+- g_free(sms);
+-}
+-
+-/* pkt_type is YAHOO_PKT_TYPE_SERVER if pkt arrives from yahoo server, YAHOO_PKT_TYPE_P2P if pkt arrives through p2p */
+-static void yahoo_process_message(PurpleConnection *gc, struct yahoo_packet *pkt, yahoo_pkt_type pkt_type)
+-{
+- PurpleAccount *account;
+- YahooData *yd = gc->proto_data;
+- GSList *l = pkt->hash;
+- GSList *list = NULL;
+- struct _yahoo_im *im = NULL;
+-
+- account = purple_connection_get_account(gc);
+-
+- if (pkt->status <= 1 || pkt->status == 5 || pkt->status == YAHOO_STATUS_OFFLINE) {
+- /* messages are received with status YAHOO_STATUS_OFFLINE in case of p2p */
+- while (l != NULL) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 4 || pair->key == 1) {
+- im = g_new0(struct _yahoo_im, 1);
+- list = g_slist_append(list, im);
+- im->from = pair->value;
+- im->time = time(NULL);
+- im->utf8 = TRUE;
+- im->fed = YAHOO_FEDERATION_NONE;
+- im->fed_from = g_strdup(im->from);
+- }
+- if (im && pair->key == 5)
+- im->active_id = pair->value;
+- if (pair->key == 97)
+- if (im)
+- im->utf8 = strtol(pair->value, NULL, 10);
+- if (pair->key == 15)
+- if (im)
+- im->time = strtol(pair->value, NULL, 10);
+- if (pair->key == 206)
+- if (im)
+- im->buddy_icon = strtol(pair->value, NULL, 10);
+- if (pair->key == 14) {
+- if (im)
+- im->msg = pair->value;
+- }
+- if (im && pair->key == 241) {
+- im->fed = strtol(pair->value, NULL, 10);
+- g_free(im->fed_from);
+- switch (im->fed) {
+- case YAHOO_FEDERATION_MSN:
+- im->fed_from = g_strconcat("msn/",im->from, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- im->fed_from = g_strconcat("ocs/",im->from, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- im->fed_from = g_strconcat("ibm/",im->from, NULL);
+- break;
+- case YAHOO_FEDERATION_PBX:
+- im->fed_from = g_strconcat("pbx/",im->from, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- im->fed_from = g_strdup(im->from);
+- break;
+- }
+- purple_debug_info("yahoo", "Message from federated (%d) buddy %s.\n", im->fed, im->fed_from);
+-
+- }
+- /* peer session id */
+- if (im && (pair->key == 11)) {
+- /* disconnect the peer if connected through p2p and sends wrong value for session id */
+- if( (im->fed == YAHOO_FEDERATION_NONE) && (pkt_type == YAHOO_PKT_TYPE_P2P)
+- && (yd->session_id != strtol(pair->value, NULL, 10)) )
+- {
+- purple_debug_warning("yahoo","p2p: %s sent us message with wrong session id. Disconnecting p2p connection to peer\n", im->fed_from);
+- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+- g_hash_table_remove(yd->peers, im->fed_from);
+- g_free(im->fed_from);
+- g_free(im);
+- return; /* Not sure whether we should process remaining IMs in this packet */
+- }
+- }
+- /* IMV key */
+- if (im && pair->key == 63)
+- {
+- /* Check for the Doodle IMV, no IMvironment for federated buddies */
+- if (im->from != NULL && im->fed == YAHOO_FEDERATION_NONE)
+- {
+- g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value));
+-
+- if (strstr(pair->value, "doodle;") != NULL)
+- {
+- PurpleWhiteboard *wb;
+-
+- if (!purple_privacy_check(account, im->from)) {
+- purple_debug_info("yahoo", "Doodle request from %s dropped.\n",
+- im->from);
+- g_free(im->fed_from);
+- g_free(im);
+- return;
+- }
+- /* I'm not sure the following ever happens -DAA */
+- wb = purple_whiteboard_get_session(account, im->from);
+-
+- /* If a Doodle session doesn't exist between this user */
+- if(wb == NULL)
+- {
+- doodle_session *ds;
+- wb = purple_whiteboard_create(account, im->from,
+- DOODLE_STATE_REQUESTED);
+- ds = wb->proto_data;
+- ds->imv_key = g_strdup(pair->value);
+-
+- yahoo_doodle_command_send_request(gc, im->from, pair->value);
+- yahoo_doodle_command_send_ready(gc, im->from, pair->value);
+- }
+- }
+- }
+- }
+- if (pair->key == 429)
+- if (im)
+- im->id = pair->value;
+- l = l->next;
+- }
+- } else if (pkt->status == 2) {
+- purple_notify_error(gc, NULL,
+- _("Your Yahoo! message did not get sent."), NULL);
+- }
+-
+- for (l = list; l; l = l->next) {
+- YahooFriend *f;
+- char *m, *m2;
+- im = l->data;
+-
+- if (!im->fed_from || !im->msg) {
+- g_free(im->fed_from);
+- g_free(im);
+- continue;
+- }
+-
+- if (!purple_privacy_check(account, im->fed_from)) {
+- purple_debug_info("yahoo", "Message from %s dropped.\n", im->fed_from);
+- return;
+- }
+-
+- /*
+- * TODO: Is there anything else we should check when determining whether
+- * we should send an acknowledgement?
+- */
+- if (im->id != NULL) {
+- /* Send acknowledgement. If we don't do this then the official
+- * Yahoo Messenger client for Windows will send us the same
+- * message 7 seconds later as an offline message. This is true
+- * for at least version 9.0.0.2162 on Windows XP. */
+- struct yahoo_packet *pkt2;
+- pkt2 = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_ACK,
+- YAHOO_STATUS_AVAILABLE, pkt->id);
+- yahoo_packet_hash(pkt2, "ssisii",
+- 1, im->active_id, /* May not always be the connection's display name */
+- 5, im->from,
+- 302, 430,
+- 430, im->id,
+- 303, 430,
+- 450, 0);
+- yahoo_packet_send_and_free(pkt2, yd);
+- }
+-
+- m = yahoo_string_decode(gc, im->msg, im->utf8);
+- /* This may actually not be necessary, but it appears
+- * that at least at one point some clients were sending
+- * "\r\n" as line delimiters, so we want to avoid double
+- * lines. */
+- m2 = purple_strreplace(m, "\r\n", "\n");
+- g_free(m);
+- m = m2;
+- purple_util_chrreplace(m, '\r', '\n');
+- if (!strcmp(m, "<ding>")) {
+- PurpleConversation *conv = NULL;
+- char *username;
+-
+- username = g_markup_escape_text(im->fed_from, -1);
+- conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_ANY,
+- username, account);
+- purple_prpl_got_attention(gc, username, YAHOO_BUZZ);
+- g_free(username);
+- g_free(m);
+- g_free(im->fed_from);
+- g_free(im);
+- continue;
+- }
+-
+- m2 = yahoo_codes_to_html(m);
+- g_free(m);
+-
+- serv_got_im(gc, im->fed_from, m2, 0, im->time);
+- g_free(m2);
+-
+- /* Official clients don't share buddy images with federated buddies */
+- if (im->fed == YAHOO_FEDERATION_NONE) {
+- if ((f = yahoo_friend_find(gc, im->from)) && im->buddy_icon == 2) {
+- if (yahoo_friend_get_buddy_icon_need_request(f)) {
+- yahoo_send_picture_request(gc, im->from);
+- yahoo_friend_set_buddy_icon_need_request(f, FALSE);
+- }
+- }
+- }
+-
+- g_free(im->fed_from);
+- g_free(im);
+- }
+-
+- g_slist_free(list);
+-}
+-
+-static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- char *prim, *me = NULL, *msg = NULL;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- if (pair->key == 5)
+- me = pair->value;
+- if (pair->key == 14)
+- msg = pair->value;
+-
+- l = l->next;
+- }
+-
+- if (!msg || !g_utf8_validate(msg, -1, NULL))
+- return;
+-
+- prim = g_strdup_printf(_("Yahoo! system message for %s:"),
+- me?me:purple_connection_get_display_name(gc));
+- purple_notify_info(NULL, NULL, prim, msg);
+- g_free(prim);
+-}
+-
+-struct yahoo_add_request {
+- PurpleConnection *gc;
+- char *id;
+- char *who;
+- YahooFederation fed;
+-};
+-
+-static void
+-yahoo_buddy_add_authorize_cb(gpointer data)
+-{
+- struct yahoo_add_request *add_req = data;
+- struct yahoo_packet *pkt;
+- YahooData *yd = add_req->gc->proto_data;
+- const char *who = add_req->who;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- if (add_req->fed) {
+- who += 4;
+- yahoo_packet_hash(pkt, "ssiii",
+- 1, add_req->id,
+- 5, who,
+- 241, add_req->fed,
+- 13, 1,
+- 334, 0);
+- }
+- else {
+- yahoo_packet_hash(pkt, "ssii",
+- 1, add_req->id,
+- 5, who,
+- 13, 1,
+- 334, 0);
+- }
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(add_req->id);
+- g_free(add_req->who);
+- g_free(add_req);
+-}
+-
+-static void
+-yahoo_buddy_add_deny_cb(struct yahoo_add_request *add_req, const char *msg)
+-{
+- YahooData *yd = add_req->gc->proto_data;
+- struct yahoo_packet *pkt;
+- char *encoded_msg = NULL;
+- const char *who = add_req->who;
+-
+- if (msg && *msg)
+- encoded_msg = yahoo_string_encode(add_req->gc, msg, NULL);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- if (add_req->fed) {
+- who += 4; /* Skip fed identifier (msn|ocs|ibm)/' */
+- yahoo_packet_hash(pkt, "ssiiiis",
+- 1, add_req->id,
+- 5, who,
+- 241, add_req->fed,
+- 13, 2,
+- 334, 0,
+- 97, 1,
+- 14, encoded_msg ? encoded_msg : "");
+- }
+- else {
+- yahoo_packet_hash(pkt, "ssiiis",
+- 1, add_req->id,
+- 5, who,
+- 13, 2,
+- 334, 0,
+- 97, 1,
+- 14, encoded_msg ? encoded_msg : "");
+- }
+-
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(encoded_msg);
+-
+- g_free(add_req->id);
+- g_free(add_req->who);
+- g_free(add_req);
+-}
+-
+-static void
+-yahoo_buddy_add_deny_noreason_cb(struct yahoo_add_request *add_req, const char*msg)
+-{
+- yahoo_buddy_add_deny_cb(add_req, NULL);
+-}
+-
+-static void
+-yahoo_buddy_add_deny_reason_cb(gpointer data) {
+- struct yahoo_add_request *add_req = data;
+- purple_request_input(add_req->gc, NULL, _("Authorization denied message:"),
+- NULL, _("No reason given."), TRUE, FALSE, NULL,
+- _("OK"), G_CALLBACK(yahoo_buddy_add_deny_cb),
+- _("Cancel"), G_CALLBACK(yahoo_buddy_add_deny_noreason_cb),
+- purple_connection_get_account(add_req->gc), add_req->who, NULL,
+- add_req);
+-}
+-
+-static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
+-{
+- char *notify_msg;
+- YahooData *yd = gc->proto_data;
+-
+- if (who == NULL)
+- return;
+-
+- if (reason != NULL) {
+- char *msg2 = yahoo_string_decode(gc, reason, FALSE);
+- notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list for the following reason: %s."), who, msg2);
+- g_free(msg2);
+- } else
+- notify_msg = g_strdup_printf(_("%s has (retroactively) denied your request to add them to your list."), who);
+-
+- purple_notify_info(gc, NULL, _("Add buddy rejected"), notify_msg);
+- g_free(notify_msg);
+-
+- g_hash_table_remove(yd->friends, who);
+- purple_prpl_got_user_status(purple_connection_get_account(gc), who, "offline", NULL); /* FIXME: make this set not on list status instead */
+- /* TODO: Shouldn't we remove the buddy from our local list? */
+-}
+-
+-static void yahoo_buddy_auth_req_15(PurpleConnection *gc, struct yahoo_packet *pkt) {
+- PurpleAccount *account;
+- GSList *l = pkt->hash;
+- const char *msg = NULL;
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Buddy authorized/declined our addition */
+- if (pkt->status == 1) {
+- char *temp = NULL;
+- char *who = NULL;
+- int response = 0;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- temp = pair->value;
+- break;
+- case 13:
+- response = strtol(pair->value, NULL, 10);
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- case 241:
+- fed = strtol(pair->value, NULL, 10);
+- break;
+- }
+- l = l->next;
+- }
+-
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- who = g_strconcat("msn/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- who = g_strconcat("ocs/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- who = g_strconcat("ibm/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- who = g_strdup(temp);
+- break;
+- }
+-
+- if (response == 1) /* Authorized */
+- purple_debug_info("yahoo", "Received authorization from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
+- else if (response == 2) { /* Declined */
+- purple_debug_info("yahoo", "Received authorization decline from buddy '%s'.\n", who ? who : "(Unknown Buddy)");
+- yahoo_buddy_denied_our_add(gc, who, msg);
+- } else
+- purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)");
+- g_free(who);
+- }
+- /* Buddy requested authorization to add us. */
+- else if (pkt->status == 3) {
+- struct yahoo_add_request *add_req;
+- const char *firstname = NULL, *lastname = NULL;
+- char *temp = NULL;
+-
+- add_req = g_new0(struct yahoo_add_request, 1);
+- add_req->gc = gc;
+- add_req->fed = YAHOO_FEDERATION_NONE;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- temp = pair->value;
+- break;
+- case 5:
+- add_req->id = g_strdup(pair->value);
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- case 216:
+- firstname = pair->value;
+- break;
+- case 241:
+- add_req->fed = strtol(pair->value, NULL, 10);
+- break;
+- case 254:
+- lastname = pair->value;
+- break;
+-
+- }
+- l = l->next;
+- }
+- switch (add_req->fed) {
+- case YAHOO_FEDERATION_MSN:
+- add_req->who = g_strconcat("msn/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- add_req->who = g_strconcat("ocs/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- add_req->who = g_strconcat("ibm/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- add_req->who = g_strdup(temp);
+- break;
+- }
+-
+- if (add_req->id && add_req->who) {
+- char *alias = NULL, *dec_msg = NULL;
+-
+- if (!purple_privacy_check(account, add_req->who))
+- {
+- purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
+- add_req->who);
+- yahoo_buddy_add_deny_cb(add_req, NULL);
+- return;
+- }
+-
+- if (msg)
+- dec_msg = yahoo_string_decode(gc, msg, FALSE);
+-
+- if (firstname && lastname)
+- alias = g_strdup_printf("%s %s", firstname, lastname);
+- else if (firstname)
+- alias = g_strdup(firstname);
+- else if (lastname)
+- alias = g_strdup(lastname);
+-
+- /* DONE! this is almost exactly the same as what MSN does,
+- * this should probably be moved to the core.
+- */
+- purple_account_request_authorization(account, add_req->who, add_req->id,
+- alias, dec_msg,
+- purple_find_buddy(account, add_req->who) != NULL,
+- yahoo_buddy_add_authorize_cb,
+- yahoo_buddy_add_deny_reason_cb,
+- add_req);
+- g_free(alias);
+- g_free(dec_msg);
+- } else {
+- g_free(add_req->id);
+- g_free(add_req->who);
+- g_free(add_req);
+- }
+- } else {
+- purple_debug_error("yahoo", "Received authorization of unknown status (%d).\n", pkt->status);
+- }
+-}
+-
+-/* I don't think this happens anymore in Version 15 */
+-static void yahoo_buddy_added_us(PurpleConnection *gc, struct yahoo_packet *pkt) {
+- PurpleAccount *account;
+- struct yahoo_add_request *add_req;
+- char *msg = NULL;
+- GSList *l = pkt->hash;
+-
+- account = purple_connection_get_account(gc);
+-
+- add_req = g_new0(struct yahoo_add_request, 1);
+- add_req->gc = gc;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 1:
+- add_req->id = g_strdup(pair->value);
+- break;
+- case 3:
+- add_req->who = g_strdup(pair->value);
+- break;
+- case 15: /* time, for when they add us and we're offline */
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- }
+- l = l->next;
+- }
+-
+- if (add_req->id && add_req->who) {
+- char *dec_msg = NULL;
+-
+- if (!purple_privacy_check(account, add_req->who)) {
+- purple_debug_misc("yahoo", "Auth. request from %s dropped and automatically denied due to privacy settings!\n",
+- add_req->who);
+- yahoo_buddy_add_deny_cb(add_req, NULL);
+- return;
+- }
+-
+- if (msg)
+- dec_msg = yahoo_string_decode(gc, msg, FALSE);
+-
+- /* DONE! this is almost exactly the same as what MSN does,
+- * this should probably be moved to the core.
+- */
+- purple_account_request_authorization(account, add_req->who, add_req->id,
+- NULL, dec_msg,
+- purple_find_buddy(account,add_req->who) != NULL,
+- yahoo_buddy_add_authorize_cb,
+- yahoo_buddy_add_deny_reason_cb, add_req);
+- g_free(dec_msg);
+- } else {
+- g_free(add_req->id);
+- g_free(add_req->who);
+- g_free(add_req);
+- }
+-}
+-
+-/* I have no idea if this every gets called in version 15 */
+-static void yahoo_buddy_denied_our_add_old(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *who = NULL;
+- char *msg = NULL;
+- GSList *l = pkt->hash;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 3:
+- who = pair->value;
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- }
+- l = l->next;
+- }
+-
+- yahoo_buddy_denied_our_add(gc, who, msg);
+-}
+-
+-static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- switch (pkt->status) {
+- case 1:
+- yahoo_process_status(gc, pkt);
+- return;
+- case 3:
+- yahoo_buddy_added_us(gc, pkt);
+- break;
+- case 7:
+- yahoo_buddy_denied_our_add_old(gc, pkt);
+- break;
+- default:
+- break;
+- }
+-}
+-
+-#define OUT_CHARSET "utf-8"
+-
+-static char *yahoo_decode(const char *text)
+-{
+- char *converted = NULL;
+- char *n, *new;
+- const char *end, *p;
+- int i, k;
+-
+- n = new = g_malloc(strlen (text) + 1);
+- end = text + strlen(text);
+-
+- for (p = text; p < end; p++, n++) {
+- if (*p == '\\') {
+- if (p[1] >= '0' && p[1] <= '7') {
+- p += 1;
+- for (i = 0, k = 0; k < 3; k += 1) {
+- char c = p[k];
+- if (c < '0' || c > '7') break;
+- i *= 8;
+- i += c - '0';
+- }
+- *n = i;
+- p += k - 1;
+- } else { /* bug 959248 */
+- /* If we see a \ not followed by an octal number,
+- * it means that it is actually a \\ with one \
+- * already eaten by some unknown function.
+- * This is arguably broken.
+- *
+- * I think wing is wrong here, there is no function
+- * called that I see that could have done it. I guess
+- * it is just really sending single \'s. That's yahoo
+- * for you.
+- */
+- *n = *p;
+- }
+- }
+- else
+- *n = *p;
+- }
+-
+- *n = '\0';
+-
+- if (strstr(text, "\033$B"))
+- converted = g_convert(new, n - new, OUT_CHARSET, "iso-2022-jp", NULL, NULL, NULL);
+- if (!converted)
+- converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
+- g_free(new);
+-
+- return converted;
+-}
+-
+-static void yahoo_process_mail(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- const char *who = NULL;
+- const char *email = NULL;
+- const char *subj = NULL;
+- const char *yahoo_mail_url = (yd->jp? YAHOOJP_MAIL_URL: YAHOO_MAIL_URL);
+- int count = 0;
+- GSList *l = pkt->hash;
+-
+- if (!purple_account_get_check_mail(account))
+- return;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 9)
+- count = strtol(pair->value, NULL, 10);
+- else if (pair->key == 43)
+- who = pair->value;
+- else if (pair->key == 42)
+- email = pair->value;
+- else if (pair->key == 18)
+- subj = pair->value;
+- l = l->next;
+- }
+-
+- if (who && subj && email && *email) {
+- char *dec_who = yahoo_decode(who);
+- char *dec_subj = yahoo_decode(subj);
+- char *from = g_strdup_printf("%s (%s)", dec_who, email);
+-
+- purple_notify_email(gc, dec_subj, from, purple_account_get_username(account),
+- yahoo_mail_url, NULL, NULL);
+-
+- g_free(dec_who);
+- g_free(dec_subj);
+- g_free(from);
+- } else if (count > 0) {
+- const char *tos[2] = { purple_account_get_username(account) };
+- const char *urls[2] = { yahoo_mail_url };
+-
+- purple_notify_emails(gc, count, FALSE, NULL, NULL, tos, urls,
+- NULL, NULL);
+- }
+-}
+-
+-/* We use this structure once while we authenticate */
+-struct yahoo_auth_data
+-{
+- PurpleConnection *gc;
+- char *seed;
+-};
+-
+-/* This is the y64 alphabet... it's like base64, but has a . and a _ */
+-static const char base64digits[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789._";
+-
+-/* This is taken from Sylpheed by Hiroyuki Yamamoto. We have our own tobase64 function
+- * in util.c, but it is different from the one yahoo uses */
+-static void to_y64(char *out, const unsigned char *in, gsize inlen)
+- /* raw bytes in quasi-big-endian order to base 64 string (NUL-terminated) */
+-{
+- for (; inlen >= 3; inlen -= 3)
+- {
+- *out++ = base64digits[in[0] >> 2];
+- *out++ = base64digits[((in[0] << 4) & 0x30) | (in[1] >> 4)];
+- *out++ = base64digits[((in[1] << 2) & 0x3c) | (in[2] >> 6)];
+- *out++ = base64digits[in[2] & 0x3f];
+- in += 3;
+- }
+- if (inlen > 0)
+- {
+- unsigned char fragment;
+-
+- *out++ = base64digits[in[0] >> 2];
+- fragment = (in[0] << 4) & 0x30;
+- if (inlen > 1)
+- fragment |= in[1] >> 4;
+- *out++ = base64digits[fragment];
+- *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];
+- *out++ = '-';
+- }
+- *out = '\0';
+-}
+-
+-static void yahoo_auth16_stage3(PurpleConnection *gc, const char *crypt)
+-{
+- YahooData *yd = gc->proto_data;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- const char *name = purple_normalize(account, purple_account_get_username(account));
+- PurpleCipher *md5_cipher;
+- PurpleCipherContext *md5_ctx;
+- guchar md5_digest[16];
+- gchar base64_string[25];
+- struct yahoo_packet *pkt;
+-
+- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n");
+-
+- md5_cipher = purple_ciphers_find_cipher("md5");
+- md5_ctx = purple_cipher_context_new(md5_cipher, NULL);
+- purple_cipher_context_append(md5_ctx, (guchar *)crypt, strlen(crypt));
+- purple_cipher_context_digest(md5_ctx, sizeof(md5_digest), md5_digest, NULL);
+-
+- to_y64(base64_string, md5_digest, 16);
+-
+- purple_debug_info("yahoo", "yahoo status: %d\n", yd->current_status);
+- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTHRESP, yd->current_status, yd->session_id);
+-
+- if(yd->cookie_b) { /* send B cookie if we have it */
+- yahoo_packet_hash(pkt, "ssssssssss",
+- 1, name,
+- 0, name,
+- 277, yd->cookie_y,
+- 278, yd->cookie_t,
+- 307, base64_string,
+- 244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
+- 2, name,
+- 2, "1",
+- 59, yd->cookie_b,
+- 98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
+- 135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
+- } else { /* don't try to send an empty B cookie - the server will be mad */
+- yahoo_packet_hash(pkt, "sssssssss",
+- 1, name,
+- 0, name,
+- 277, yd->cookie_y,
+- 278, yd->cookie_t,
+- 307, base64_string,
+- 244, yd->jp ? YAHOOJP_CLIENT_VERSION_ID : YAHOO_CLIENT_VERSION_ID,
+- 2, name,
+- 2, "1",
+- 98, purple_account_get_string(account, "room_list_locale", yd->jp ? "jp" : "us"),
+- 135, yd->jp ? YAHOOJP_CLIENT_VERSION : YAHOO_CLIENT_VERSION);
+- }
+-
+- if (yd->picture_checksum)
+- yahoo_packet_hash_int(pkt, 192, yd->picture_checksum);
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- purple_cipher_context_destroy(md5_ctx);
+-}
+-
+-static gchar *yahoo_auth16_get_cookie_b(gchar *headers)
+-{
+- gchar **splits = g_strsplit(headers, "\r\n", -1);
+- gchar *tmp = NULL, *tmp2 = NULL, *sem = NULL;
+- int elements = g_strv_length(splits), i;
+-
+- if(elements > 1) {
+- for(i = 0; i < elements; i++) {
+- if(g_ascii_strncasecmp(splits[i], "Set-Cookie: B=", 14) == 0) {
+- tmp = &splits[i][14];
+- sem = strchr(tmp, ';');
+-
+- if (sem != NULL) {
+- tmp2 = g_strndup(tmp, sem - tmp);
+- purple_debug_info("yahoo", "Got needed part of B cookie: %s\n",
+- tmp2 ? tmp2 : "(null)");
+- break;
+- }
+- }
+- }
+- }
+-
+- g_strfreev(splits);
+- return tmp2;
+-}
+-
+-static void yahoo_auth16_stage2(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
+-{
+- struct yahoo_auth_data *auth_data = user_data;
+- PurpleConnection *gc = auth_data->gc;
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+- gboolean try_login_on_error = FALSE;
+-
+- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n");
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL) {
+- purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+- g_free(auth_data->seed);
+- g_free(auth_data);
+- return;
+- }
+- else if (len > 0 && ret_data && *ret_data) {
+- gchar **splits = g_strsplit(ret_data, "\r\n\r\n", -1), **split_data = NULL;
+- int totalelements = 0;
+- int response_no = -1;
+- char *crumb = NULL;
+- char *crypt = NULL;
+-
+- if(g_strv_length(splits) > 1) {
+- yd->cookie_b = yahoo_auth16_get_cookie_b(splits[0]);
+- split_data = g_strsplit(splits[1], "\r\n", -1);
+- totalelements = g_strv_length(split_data);
+- }
+-
+- if (totalelements >= 4) {
+- int i;
+-
+- for(i = 0; i < totalelements; i++) {
+- /* I'm not exactly a fan of the magic numbers, but it's obvious,
+- * so no sense in wasting a bajillion vars or calls to strlen */
+-
+- if(g_ascii_isdigit(split_data[i][0])) {
+- /* if the current line and the next line both start with numbers,
+- * the current line is the length of the body, so skip. If not,
+- * then the current line is the response code from the login process. */
+- if(!g_ascii_isdigit(split_data[i + 1][0])) {
+- response_no = strtol(split_data[i], NULL, 10);
+- purple_debug_info("yahoo", "Got auth16 stage 2 response code: %d\n",
+- response_no);
+- }
+- } else if(strncmp(split_data[i], "crumb=", 6) == 0) {
+- crumb = g_strdup(&split_data[i][6]);
+-
+- if(purple_debug_is_unsafe())
+- purple_debug_info("yahoo", "Got crumb: %s\n", crumb);
+-
+- } else if(strncmp(split_data[i], "Y=", 2) == 0) {
+- yd->cookie_y = g_strdup(&split_data[i][2]);
+-
+- if(purple_debug_is_unsafe())
+- purple_debug_info("yahoo", "Got Y cookie: %s\n", yd->cookie_y);
+-
+- } else if(strncmp(split_data[i], "T=", 2) == 0) {
+- yd->cookie_t = g_strdup(&split_data[i][2]);
+-
+- if(purple_debug_is_unsafe())
+- purple_debug_info("yahoo", "Got T cookie: %s\n", yd->cookie_t);
+- }
+- }
+- }
+-
+- g_strfreev(splits);
+- g_strfreev(split_data);
+-
+- if(response_no != 0) {
+- /* Some error in the login process */
+- PurpleConnectionError error;
+- char *error_reason = NULL;
+-
+- switch(response_no) {
+- case -1:
+- /* Some error in the received stream */
+- error_reason = g_strdup(_("Received invalid data"));
+- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- break;
+- case 100:
+- /* Unknown error */
+- error_reason = g_strdup(_("Unknown error"));
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- default:
+- /* if we have everything we need, why not try to login irrespective of response */
+- if((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
+- try_login_on_error = TRUE;
+- break;
+- }
+- error_reason = g_strdup(_("Unknown error"));
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- }
+- if(error_reason) {
+- purple_debug_error("yahoo", "Authentication error: %s. "
+- "Code %d\n", error_reason, response_no);
+- purple_connection_error_reason(gc, error, error_reason);
+- g_free(error_reason);
+- g_free(auth_data->seed);
+- g_free(auth_data);
+- return;
+- }
+- }
+-
+- crypt = g_strconcat(crumb, auth_data->seed, NULL);
+- yahoo_auth16_stage3(gc, crypt);
+- g_free(crypt);
+- g_free(crumb);
+- }
+- g_free(auth_data->seed);
+- g_free(auth_data);
+-}
+-
+-static void yahoo_auth16_stage1_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *ret_data, size_t len, const gchar *error_message)
+-{
+- struct yahoo_auth_data *auth_data = user_data;
+- PurpleConnection *gc = auth_data->gc;
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+-
+- purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage1_cb\n");
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL) {
+- purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message);
+- g_free(auth_data->seed);
+- g_free(auth_data);
+- return;
+- }
+- else if (len > 0 && ret_data && *ret_data) {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- gchar **split_data = g_strsplit(ret_data, "\r\n", -1);
+- int totalelements = 0;
+- int response_no = -1;
+- char *token = NULL;
+-
+- totalelements = g_strv_length(split_data);
+-
+- if(totalelements == 1) { /* Received an error code */
+- response_no = strtol(split_data[0], NULL, 10);
+- } else if(totalelements == 2 || totalelements == 3 ) { /* received valid data */
+- response_no = strtol(split_data[0], NULL, 10);
+- token = g_strdup(split_data[1] + strlen("ymsgr="));
+- } else { /* It looks like a transparent proxy has returned a document we don't want */
+- response_no = -1;
+- }
+-
+- g_strfreev(split_data);
+-
+- if(response_no != 0) {
+- /* Some error in the login process */
+- PurpleConnectionError error;
+- char *error_reason;
+-
+- switch(response_no) {
+- case -1:
+- /* Some error in the received stream */
+- error_reason = g_strdup(_("Received invalid data"));
+- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- break;
+- case 1212:
+- /* Password incorrect */
+- /* Set password to NULL. Avoids account locking. Brings dialog to enter password if clicked on Re-enable account */
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+- error_reason = g_strdup(_("Incorrect password"));
+- error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+- case 1213:
+- /* security lock from too many failed login attempts */
+- error_reason = g_strdup(_("Account locked: Too many failed login "
+- "attempts. Logging into the Yahoo! website may fix this."));
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- case 1235:
+- /* the username does not exist */
+- error_reason = g_strdup(_("Username does not exist"));
+- error = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
+- break;
+- case 1214:
+- /* indicates a lock of some description */
+- error_reason = g_strdup(_("Account locked: Unknown reason. Logging "
+- "into the Yahoo! website may fix this."));
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- case 1236:
+- /* indicates a lock due to logging in too frequently */
+- error_reason = g_strdup(_("Account locked: You have been logging in too "
+- "frequently. Wait a few minutes before trying to connect "
+- "again. Logging into the Yahoo! website may help."));
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- case 100:
+- /* username or password missing */
+- error_reason = g_strdup(_("Username or password missing"));
+- error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+- default:
+- /* Unknown error! */
+- error_reason = g_strdup_printf(_("Unknown error (%d)"), response_no);
+- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+- break;
+- }
+- purple_debug_error("yahoo", "Authentication error: %s. Code %d\n",
+- error_reason, response_no);
+- purple_connection_error_reason(gc, error, error_reason);
+- g_free(error_reason);
+- g_free(auth_data->seed);
+- g_free(auth_data);
+- g_free(token);
+- }
+- else {
+- /* OK to login, correct information provided */
+- PurpleUtilFetchUrlData *url_data = NULL;
+- char *url = NULL;
+- gboolean yahoojp = yahoo_is_japan(account);
+- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
+-
+- url = g_strdup_printf(yahoojp ? YAHOOJP_LOGIN_URL : YAHOO_LOGIN_URL, token);
+- url_data = purple_util_fetch_url_request_len_with_account(
+- proxy_ssl ? account : NULL, url, TRUE, YAHOO_CLIENT_USERAGENT,
+- TRUE, NULL, TRUE, -1, yahoo_auth16_stage2, auth_data);
+- if (url_data)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- g_free(url);
+- g_free(token);
+- }
+- }
+-}
+-
+-static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed)
+-{
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleUtilFetchUrlData *url_data = NULL;
+- struct yahoo_auth_data *auth_data = NULL;
+- char *url = NULL;
+- char *encoded_username;
+- char *encoded_password;
+- gboolean yahoojp = yahoo_is_japan(account);
+- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
+-
+- purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n");
+-
+- if(!purple_ssl_is_supported()) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NO_SSL_SUPPORT, _("SSL support unavailable"));
+- return;
+- }
+-
+- auth_data = g_new0(struct yahoo_auth_data, 1);
+- auth_data->gc = gc;
+- auth_data->seed = g_strdup(seed);
+-
+- encoded_username = g_strdup(purple_url_encode(purple_account_get_username(purple_connection_get_account(gc))));
+- encoded_password = g_strdup(purple_url_encode(purple_connection_get_password(gc)));
+- url = g_strdup_printf(yahoojp ? YAHOOJP_TOKEN_URL : YAHOO_TOKEN_URL,
+- encoded_username, encoded_password, purple_url_encode(seed));
+- g_free(encoded_password);
+- g_free(encoded_username);
+-
+- url_data = purple_util_fetch_url_request_len_with_account(
+- proxy_ssl ? account : NULL, url, TRUE,
+- YAHOO_CLIENT_USERAGENT, TRUE, NULL, FALSE, -1,
+- yahoo_auth16_stage1_cb, auth_data);
+- if (url_data)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- g_free(url);
+-}
+-
+-static void yahoo_process_auth(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *seed = NULL;
+- char *sn = NULL;
+- GSList *l = pkt->hash;
+- int m = 0;
+- gchar *buf;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 94)
+- seed = pair->value;
+- if (pair->key == 1)
+- sn = pair->value;
+- if (pair->key == 13)
+- m = atoi(pair->value);
+- l = l->next;
+- }
+-
+- if (seed) {
+- switch (m) {
+- case 0:
+- /* used to be for really old auth routine, dont support now */
+- case 1:
+- case 2: /* Yahoo ver 16 authentication */
+- yahoo_auth16_stage1(gc, seed);
+- break;
+- default:
+- {
+- GHashTable *ui_info = purple_core_get_ui_info();
+-
+- buf = g_strdup_printf(_("The Yahoo server has requested the use of an unrecognized "
+- "authentication method. You will probably not be able "
+- "to successfully sign on to Yahoo. Check %s for updates."),
+- ((ui_info && g_hash_table_lookup(ui_info, "website")) ? (char *)g_hash_table_lookup(ui_info, "website") : PURPLE_WEBSITE));
+- purple_notify_error(gc, "", _("Failed Yahoo! Authentication"),
+- buf);
+- g_free(buf);
+- yahoo_auth16_stage1(gc, seed); /* Can't hurt to try it anyway. */
+- break;
+- }
+- }
+- }
+-}
+-
+-static void ignore_buddy(PurpleBuddy *buddy) {
+- PurpleGroup *group;
+- PurpleAccount *account;
+- gchar *name;
+-
+- if (!buddy)
+- return;
+-
+- group = purple_buddy_get_group(buddy);
+- name = g_strdup(purple_buddy_get_name(buddy));
+- account = purple_buddy_get_account(buddy);
+-
+- purple_debug_info("yahoo", "blist: Removing '%s' from buddy list.\n", name);
+- purple_account_remove_buddy(account, buddy, group);
+- purple_blist_remove_buddy(buddy);
+-
+- serv_add_deny(purple_account_get_connection(account), name);
+-
+- g_free(name);
+-}
+-
+-static void keep_buddy(PurpleBuddy *b)
+-{
+- purple_privacy_deny_remove(purple_buddy_get_account(b),
+- purple_buddy_get_name(b), 1);
+-}
+-
+-static void yahoo_process_ignore(PurpleConnection *gc, struct yahoo_packet *pkt) {
+- PurpleBuddy *b;
+- GSList *l;
+- gchar *who = NULL;
+- gchar *me = NULL;
+- gchar buf[BUF_LONG];
+- gboolean ignore = TRUE;
+- gint status = 0;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+- switch (pair->key) {
+- case 0:
+- who = pair->value;
+- break;
+- case 1:
+- me = pair->value;
+- break;
+- case 13:
+- /* 1 == ignore, 2 == unignore */
+- ignore = (strtol(pair->value, NULL, 10) == 1);
+- break;
+- case 66:
+- status = strtol(pair->value, NULL, 10);
+- break;
+- default:
+- break;
+- }
+- }
+-
+- /*
+- * status
+- * 0 - ok
+- * 2 - already in ignore list, could not add
+- * 3 - not in ignore list, could not delete
+- * 12 - is a buddy, could not add (and possibly also a not-in-ignore list condition?)
+- */
+- switch (status) {
+- case 12:
+- purple_debug_info("yahoo", "Server reported \"is a buddy\" for %s while %s",
+- who, (ignore ? "ignoring" : "unignoring"));
+-
+- if (ignore) {
+- b = purple_find_buddy(gc->account, who);
+- g_snprintf(buf, sizeof(buf), _("You have tried to ignore %s, but the "
+- "user is on your buddy list. Clicking \"Yes\" "
+- "will remove and ignore the buddy."), who);
+- purple_request_yes_no(gc, NULL, _("Ignore buddy?"), buf, 0,
+- gc->account, who, NULL,
+- b,
+- G_CALLBACK(ignore_buddy),
+- G_CALLBACK(keep_buddy));
+- break;
+- }
+- case 2:
+- purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.\n",
+- who);
+- break;
+- case 3:
+- purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete\n",
+- who);
+- case 0:
+- default:
+- break;
+- }
+-}
+-
+-static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+-#ifdef TRY_WEBMESSENGER_LOGIN
+- YahooData *yd = gc->proto_data;
+-#endif /* TRY_WEBMESSENGER_LOGIN */
+- GSList *l = pkt->hash;
+- int err = 0;
+- char *msg;
+- char *url = NULL;
+- char *fullmsg;
+- PurpleAccount *account = gc->account;
+- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- if (pair->key == 66)
+- err = strtol(pair->value, NULL, 10);
+- else if (pair->key == 20)
+- url = pair->value;
+-
+- l = l->next;
+- }
+-
+- switch (err) {
+- case 0:
+- msg = g_strdup(_("Unknown error"));
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- break;
+- case 3:
+- msg = g_strdup(_("Username does not exist"));
+- reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
+- break;
+- case 13:
+-#ifdef TRY_WEBMESSENGER_LOGIN
+- if (!yd->wm) {
+- PurpleUtilFetchUrlData *url_data;
+- yd->wm = TRUE;
+- if (yd->fd >= 0)
+- close(yd->fd);
+- if (gc->inpa)
+- purple_input_remove(gc->inpa);
+- url_data = purple_util_fetch_url(WEBMESSENGER_URL, TRUE,
+- "Purple/" VERSION, FALSE, yahoo_login_page_cb, gc);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- return;
+- }
+-#endif /* TRY_WEBMESSENGER_LOGIN */
+- if (!purple_account_get_remember_password(account))
+- purple_account_set_password(account, NULL);
+-
+- msg = g_strdup(_("Invalid username or password"));
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+- case 14:
+- msg = g_strdup(_("Your account has been locked due to too many failed login attempts."
+- " Please try logging into the Yahoo! website."));
+- reason = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
+- break;
+- case 52:
+- /* See #9660. As much as we know, reconnecting shouldn't hurt */
+- purple_debug_info("yahoo", "Got error 52, Set to autoreconnect\n");
+- msg = g_strdup_printf(_("Unknown error 52. Reconnecting should fix this."));
+- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
+- break;
+- case 1013:
+- msg = g_strdup(_("Error 1013: The username you have entered is invalid."
+- " The most common cause of this error is entering your email"
+- " address instead of your Yahoo! ID."));
+- reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
+- break;
+- default:
+- msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err);
+- }
+-
+- if (url)
+- fullmsg = g_strdup_printf("%s\n%s", msg, url);
+- else
+- fullmsg = g_strdup(msg);
+-
+- purple_connection_error_reason(gc, reason, fullmsg);
+- g_free(msg);
+- g_free(fullmsg);
+-}
+-
+-static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- int err = 0;
+- char *who = NULL;
+- char *temp = NULL;
+- char *group = NULL;
+- char *decoded_group;
+- char *buf;
+- YahooFriend *f;
+- GSList *l = pkt->hash;
+- YahooData *yd = gc->proto_data;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 66:
+- err = strtol(pair->value, NULL, 10);
+- break;
+- case 7:
+- temp = pair->value;
+- break;
+- case 65:
+- group = pair->value;
+- break;
+- case 241:
+- fed = strtol(pair->value, NULL, 10);
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- if (!temp)
+- return;
+- if (!group)
+- group = "";
+-
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- who = g_strconcat("msn/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- who = g_strconcat("ocs/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- who = g_strconcat("ibm/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- who = g_strdup(temp);
+- break;
+- }
+-
+- if (!err || (err == 2)) { /* 0 = ok, 2 = already on serv list */
+- f = yahoo_friend_find_or_new(gc, who);
+- yahoo_update_status(gc, who, f);
+- f->fed = fed;
+-
+- if( !g_hash_table_lookup(yd->peers, who) ) {
+- /* we are not connected as client, so set friend to not connected */
+- if(fed)
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_DO_NOT_CONNECT);
+- else {
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
+- f->p2p_packet_sent = 0;
+- }
+- }
+- else /* we are already connected. set friend to YAHOO_P2PSTATUS_WE_ARE_CLIENT */
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
+- g_free(who);
+- return;
+- }
+-
+- decoded_group = yahoo_string_decode(gc, group, FALSE);
+- buf = g_strdup_printf(_("Unable to add buddy %s to group %s to the server list on account %s."),
+- who, decoded_group, purple_connection_get_display_name(gc));
+- if (!purple_conv_present_error(who, purple_connection_get_account(gc), buf))
+- purple_notify_error(gc, NULL, _("Unable to add buddy to server list"), buf);
+- g_free(buf);
+- g_free(decoded_group);
+- g_free(who);
+-}
+-
+-/* write pkt to the source */
+-static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
+-{
+- size_t pkt_len;
+- guchar *raw_packet;
+-
+- /*build the raw packet and send it to the host*/
+- pkt_len = yahoo_packet_build(pkt, 0, 0, 0, &raw_packet);
+- if(write(source, raw_packet, pkt_len) != pkt_len)
+- purple_debug_warning("yahoo","p2p: couldn't write to the source\n");
+- g_free(raw_packet);
+-}
+-
+-static void yahoo_p2p_keepalive_cb(gpointer key, gpointer value, gpointer user_data)
+-{
+- struct yahoo_p2p_data *p2p_data = value;
+- PurpleConnection *gc = user_data;
+- struct yahoo_packet *pkt_to_send;
+- PurpleAccount *account;
+- YahooData *yd = gc->proto_data;
+-
+- account = purple_connection_get_account(gc);
+-
+- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt_to_send, "ssisi",
+- 4, purple_normalize(account, purple_account_get_username(account)),
+- 5, p2p_data->host_username,
+- 241, 0, /* Protocol identifier */
+- 49, "PEERTOPEER",
+- 13, 7);
+- yahoo_p2p_write_pkt(p2p_data->source, pkt_to_send);
+-
+- yahoo_packet_free(pkt_to_send);
+-}
+-
+-static gboolean yahoo_p2p_keepalive(gpointer data)
+-{
+- PurpleConnection *gc = data;
+- YahooData *yd = gc->proto_data;
+-
+- g_hash_table_foreach(yd->peers, yahoo_p2p_keepalive_cb, gc);
+-
+- return TRUE;
+-}
+-
+-/* destroy p2p_data associated with a peer and close p2p connection.
+- * g_hash_table_remove() calls this function to destroy p2p_data associated with the peer,
+- * call g_hash_table_remove() instead of this fucntion if peer has an entry in the table */
+-static void yahoo_p2p_disconnect_destroy_data(gpointer data)
+-{
+- struct yahoo_p2p_data *p2p_data;
+- YahooFriend *f;
+-
+- if(!(p2p_data = data))
+- return ;
+-
+- /* If friend, set him not connected */
+- f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
+- if (f)
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
+-
+- if(p2p_data->source >= 0)
+- close(p2p_data->source);
+- if (p2p_data->input_event > 0)
+- purple_input_remove(p2p_data->input_event);
+- g_free(p2p_data->host_ip);
+- g_free(p2p_data->host_username);
+- g_free(p2p_data);
+-}
+-
+-/* exchange of initial p2pfilexfer packets, service type YAHOO_SERVICE_P2PFILEXFER */
+-static void yahoo_p2p_process_p2pfilexfer(gpointer data, gint source, struct yahoo_packet *pkt)
+-{
+- struct yahoo_p2p_data *p2p_data;
+- char *who = NULL;
+- GSList *l = pkt->hash;
+- struct yahoo_packet *pkt_to_send;
+- PurpleAccount *account;
+- int val_13_to_send = 0;
+- YahooData *yd;
+- YahooFriend *f;
+-
+- if(!(p2p_data = data))
+- return ;
+-
+- yd = p2p_data->gc->proto_data;
+-
+- /* lets see whats in the packet */
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- who = pair->value;
+- if(strncmp(who, p2p_data->host_username, strlen(p2p_data->host_username)) != 0) {
+- /* from whom are we receiving the packets ?? */
+- purple_debug_warning("yahoo","p2p: received data from wrong user\n");
+- return;
+- }
+- break;
+- case 13:
+- p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */
+- break;
+- /* case 5, 49 look laters, no use right now */
+- }
+- l = l->next;
+- }
+-
+- account = purple_connection_get_account(p2p_data->gc);
+-
+- /* key_13: sort of a counter.
+- * WHEN WE ARE CLIENT: yahoo server sends val_13 = 0, we send to peer val_13 = 1, receive back val_13 = 5,
+- * we send val_13=6, receive val_13=7, we send val_13=7, HALT. Keep sending val_13 = 7 as keep alive.
+- * WHEN WE ARE SERVER: we send val_13 = 0 to yahoo server, peer sends us val_13 = 1, we send val_13 = 5,
+- * receive val_13 = 6, send val_13 = 7, receive val_13 = 7. HALT. Keep sending val_13 = 7 as keep alive. */
+-
+- switch(p2p_data->val_13) {
+- case 1 : val_13_to_send = 5; break;
+- case 5 : val_13_to_send = 6; break;
+- case 6 : val_13_to_send = 7; break;
+- case 7 : if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
+- return;
+- val_13_to_send = 7; break;
+- default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n");
+- return;
+- }
+-
+- /* Build the yahoo packet */
+- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt_to_send, "ssisi",
+- 4, purple_normalize(account, purple_account_get_username(account)),
+- 5, p2p_data->host_username,
+- 241, 0, /* Protocol identifier */
+- 49, "PEERTOPEER",
+- 13, val_13_to_send);
+-
+- /* build the raw packet and send it to the host */
+- yahoo_p2p_write_pkt(source, pkt_to_send);
+- yahoo_packet_free(pkt_to_send);
+-
+- if( val_13_to_send == 7 )
+- if( !g_hash_table_lookup(yd->peers, p2p_data->host_username) ) {
+- g_hash_table_insert(yd->peers, g_strdup(p2p_data->host_username), p2p_data);
+- /* If the peer is a friend, set him connected */
+- f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
+- if (f) {
+- if(p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) {
+- p2p_data->session_id = f->session_id;
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_SERVER);
+- }
+- else
+- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_WE_ARE_CLIENT);
+- }
+- }
+-}
+-
+-/* callback function associated with receiving of data, not considering receipt of multiple YMSG packets in a single TCP packet */
+-static void yahoo_p2p_read_pkt_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- guchar buf[1024]; /* is it safe to assume a fixed array length of 1024 ?? */
+- int len;
+- int pos = 0;
+- int pktlen;
+- struct yahoo_packet *pkt;
+- guchar *start = NULL;
+- struct yahoo_p2p_data *p2p_data;
+- YahooData *yd;
+-
+- if(!(p2p_data = data))
+- return ;
+- yd = p2p_data->gc->proto_data;
+-
+- len = read(source, buf, sizeof(buf));
+- if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+- return ; /* No Worries*/
+- else if (len <= 0)
+- {
+- purple_debug_warning("yahoo","p2p: Error in connection, or host disconnected\n");
+- /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */
+- if( g_hash_table_lookup(yd->peers, p2p_data->host_username) )
+- g_hash_table_remove(yd->peers,p2p_data->host_username);
+- else
+- yahoo_p2p_disconnect_destroy_data(data);
+- return;
+- }
+-
+- if(len < YAHOO_PACKET_HDRLEN)
+- return;
+-
+- if(strncmp((char *)buf, "YMSG", MIN(4, len)) != 0) {
+- /* Not a YMSG packet */
+- purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n");
+-
+- start = memchr(buf + 1, 'Y', len - 1);
+- if (start == NULL)
+- return;
+-
+- g_memmove(buf, start, len - (start - buf));
+- len -= start - buf;
+- }
+-
+- pos += 4; /* YMSG */
+- pos += 2;
+- pos += 2;
+-
+- pktlen = yahoo_get16(buf + pos); pos += 2;
+- purple_debug_misc("yahoo", "p2p: %d bytes to read\n", len);
+-
+- pkt = yahoo_packet_new(0, 0, 0);
+- pkt->service = yahoo_get16(buf + pos); pos += 2;
+- pkt->status = yahoo_get32(buf + pos); pos += 4;
+- pkt->id = yahoo_get32(buf + pos); pos += 4;
+-
+- purple_debug_misc("yahoo", "p2p: Yahoo Service: 0x%02x Status: %d\n",pkt->service, pkt->status);
+- yahoo_packet_read(pkt, buf + pos, pktlen);
+-
+- /* packet processing */
+- switch(pkt->service) {
+- case YAHOO_SERVICE_P2PFILEXFER:
+- yahoo_p2p_process_p2pfilexfer(data, source, pkt);
+- break;
+- case YAHOO_SERVICE_MESSAGE:
+- yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
+- break;
+- case YAHOO_SERVICE_NOTIFY:
+- yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
+- break;
+- default:
+- purple_debug_warning("yahoo","p2p: p2p service %d Unhandled\n",pkt->service);
+- }
+-
+- yahoo_packet_free(pkt);
+-}
+-
+-static void yahoo_p2p_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- int acceptfd;
+- struct yahoo_p2p_data *p2p_data;
+- YahooData *yd;
+-
+- if(!(p2p_data = data))
+- return ;
+- yd = p2p_data->gc->proto_data;
+-
+- acceptfd = accept(source, NULL, 0);
+- if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+- return;
+- else if(acceptfd == -1) {
+- purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
+- yahoo_p2p_disconnect_destroy_data(data);
+- return;
+- }
+-
+- /* remove timeout */
+- if (yd->yahoo_p2p_server_timeout_handle) {
+- purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
+- yd->yahoo_p2p_server_timeout_handle = 0;
+- }
+-
+- /* remove watcher and close p2p server */
+- if (yd->yahoo_p2p_server_watcher) {
+- purple_input_remove(yd->yahoo_p2p_server_watcher);
+- yd->yahoo_p2p_server_watcher = 0;
+- }
+- if (yd->yahoo_local_p2p_server_fd >= 0) {
+- close(yd->yahoo_local_p2p_server_fd);
+- yd->yahoo_local_p2p_server_fd = -1;
+- }
+-
+- /* Add an Input Read event to the file descriptor */
+- p2p_data->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
+- p2p_data->source = acceptfd;
+-}
+-
+-static gboolean yahoo_cancel_p2p_server_listen_cb(gpointer data)
+-{
+- struct yahoo_p2p_data *p2p_data;
+- YahooData *yd;
+-
+- if(!(p2p_data = data))
+- return FALSE;
+-
+- yd = p2p_data->gc->proto_data;
+-
+- purple_debug_warning("yahoo","yahoo p2p server timeout, peer failed to connect\n");
+- yahoo_p2p_disconnect_destroy_data(data);
+- purple_input_remove(yd->yahoo_p2p_server_watcher);
+- yd->yahoo_p2p_server_watcher = 0;
+- close(yd->yahoo_local_p2p_server_fd);
+- yd->yahoo_local_p2p_server_fd = -1;
+- yd->yahoo_p2p_server_timeout_handle = 0;
+-
+- return FALSE;
+-}
+-
+-static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
+-{
+- struct yahoo_p2p_data *p2p_data;
+- YahooData *yd;
+-
+- if(!(p2p_data = data))
+- return ;
+-
+- yd = p2p_data->gc->proto_data;
+- yd->listen_data = NULL;
+-
+- if(listenfd == -1) {
+- purple_debug_warning("yahoo","p2p: error starting p2p server\n");
+- yahoo_p2p_disconnect_destroy_data(data);
+- return;
+- }
+-
+- /* Add an Input Read event to the file descriptor */
+- yd->yahoo_local_p2p_server_fd = listenfd;
+- yd->yahoo_p2p_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_server_send_connected_cb,data);
+-
+- /* add timeout */
+- yd->yahoo_p2p_server_timeout_handle = purple_timeout_add_seconds(YAHOO_P2P_SERVER_TIMEOUT, yahoo_cancel_p2p_server_listen_cb, data);
+-}
+-
+-/* send p2p pkt containing our encoded ip, asking peer to connect to us */
+-void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13)
+-{
+- const char *public_ip;
+- guint32 temp[4];
+- guint32 ip;
+- char temp_str[100];
+- gchar *base64_ip = NULL;
+- YahooFriend *f;
+- struct yahoo_packet *pkt;
+- PurpleAccount *account;
+- YahooData *yd = gc->proto_data;
+- struct yahoo_p2p_data *p2p_data;
+- const char *norm_username;
+-
+- f = yahoo_friend_find(gc, who);
+- account = purple_connection_get_account(gc);
+-
+- /* Do not send invitation if already listening for other connection */
+- if(yd->yahoo_local_p2p_server_fd >= 0)
+- return;
+-
+- /* One shouldn't try to connect to self */
+- if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0)
+- return;
+-
+- /* send packet to only those friends who arent p2p connected and to whom we havent already sent. Do not send if this condition doesn't hold good */
+- if( !( f && (yahoo_friend_get_p2p_status(f) == YAHOO_P2PSTATUS_NOT_CONNECTED) && (f->p2p_packet_sent == 0)) )
+- return;
+-
+- /* Dont send p2p packet to buddies of other protocols */
+- if(f->fed)
+- return;
+-
+- /* Finally, don't try to connect to buddies not online or on sms */
+- if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms )
+- return;
+-
+- public_ip = purple_network_get_public_ip();
+- if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 )
+- return ;
+-
+- ip = (temp[3] << 24) | (temp[2] <<16) | (temp[1] << 8) | temp[0];
+- sprintf(temp_str, "%d", ip);
+- base64_ip = purple_base64_encode( (guchar *)temp_str, strlen(temp_str) );
+-
+- norm_username = purple_normalize(account, purple_account_get_username(account));
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PEERTOPEER, YAHOO_STATUS_AVAILABLE, 0);
+- yahoo_packet_hash(pkt, "sssissis",
+- 1, norm_username,
+- 4, norm_username,
+- 12, base64_ip, /* base64 encode ip */
+- 61, 0, /* To-do : figure out what is 61 for?? */
+- 2, "",
+- 5, who,
+- 13, val_13,
+- 49, "PEERTOPEER");
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- f->p2p_packet_sent = 1; /* set p2p_packet_sent to sent */
+-
+- p2p_data = g_new0(struct yahoo_p2p_data, 1);
+-
+- p2p_data->gc = gc;
+- p2p_data->host_ip = NULL;
+- p2p_data->host_username = g_strdup(who);
+- p2p_data->val_13 = val_13;
+- p2p_data->connection_type = YAHOO_P2P_WE_ARE_SERVER;
+- p2p_data->source = -1;
+-
+- /* FIXME: If the port is already used, purple_network_listener returns NULL and old listener won't be canceled
+- * in yahoo_close function. */
+- if (yd->listen_data)
+- purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n");
+- else {
+- yd->listen_data = purple_network_listen(YAHOO_PAGER_PORT_P2P, SOCK_STREAM, yahoo_p2p_server_listen_cb, p2p_data);
+- if (yd->listen_data == NULL)
+- purple_debug_warning("yahoo","p2p: Failed to created p2p server\n");
+- }
+-
+- g_free(base64_ip);
+-}
+-
+-/* function called when connection to p2p host is setup */
+-static void yahoo_p2p_init_cb(gpointer data, gint source, const gchar *error_message)
+-{
+- struct yahoo_p2p_data *p2p_data;
+- struct yahoo_packet *pkt_to_send;
+- PurpleAccount *account;
+- YahooData *yd;
+-
+- p2p_data = data;
+- yd = p2p_data->gc->proto_data;
+-
+- if(error_message != NULL) {
+- purple_debug_warning("yahoo","p2p: %s\n",error_message);
+- yahoo_send_p2p_pkt(p2p_data->gc, p2p_data->host_username, 2);/* send p2p init packet with val_13=2 */
+-
+- yahoo_p2p_disconnect_destroy_data(p2p_data);
+- return;
+- }
+-
+- /* Add an Input Read event to the file descriptor */
+- p2p_data->input_event = purple_input_add(source, PURPLE_INPUT_READ, yahoo_p2p_read_pkt_cb, data);
+- p2p_data->source = source;
+-
+- account = purple_connection_get_account(p2p_data->gc);
+-
+- /* Build the yahoo packet */
+- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt_to_send, "ssisi",
+- 4, purple_normalize(account, purple_account_get_username(account)),
+- 5, p2p_data->host_username,
+- 241, 0, /* Protocol identifier */
+- 49, "PEERTOPEER",
+- 13, 1); /* we receive key13= 0 or 2, we send key13=1 */
+-
+- yahoo_p2p_write_pkt(source, pkt_to_send); /* build raw packet and send */
+- yahoo_packet_free(pkt_to_send);
+-}
+-
+-static void yahoo_process_p2p(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- char *who = NULL;
+- char *base64 = NULL;
+- guchar *decoded;
+- gsize len;
+- gint val_13 = 0;
+- gint val_11 = 0;
+- PurpleAccount *account;
+- YahooFriend *f;
+-
+- /* if status is not YAHOO_STATUS_BRB or YAHOO_STATUS_P2P, the packet bounced back,
+- * so it contains our own ip */
+- if(pkt->status != YAHOO_STATUS_BRB && pkt->status != YAHOO_STATUS_P2P)
+- return ;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 5:
+- /* our identity */
+- break;
+- case 4:
+- who = pair->value;
+- break;
+- case 1:
+- /* who again, the master identity this time? */
+- break;
+- case 12:
+- base64 = pair->value;
+- /* so, this is an ip address. in base64. decoded it's in ascii.
+- after strtol, it's in reversed byte order. Who thought this up?*/
+- break;
+- case 13:
+- val_13 = strtol(pair->value, NULL, 10);
+- break;
+- case 11:
+- val_11 = strtol(pair->value, NULL, 10); /* session id of peer */
+- if( (f = yahoo_friend_find(gc, who)) )
+- f->session_id = val_11;
+- break;
+- /*
+- TODO: figure these out
+- yahoo: Key: 61 Value: 0
+- yahoo: Key: 2 Value:
+- yahoo: Key: 13 Value: 0 packet count ??
+- yahoo: Key: 49 Value: PEERTOPEER
+- yahoo: Key: 140 Value: 1
+- */
+-
+- }
+-
+- l = l->next;
+- }
+-
+- if (base64) {
+- guint32 ip;
+- YahooFriend *f;
+- char *host_ip, *tmp;
+- struct yahoo_p2p_data *p2p_data;
+-
+- decoded = purple_base64_decode(base64, &len);
+- if (decoded == NULL) {
+- purple_debug_info("yahoo","p2p: Unable to decode base64 IP (%s) \n", base64);
+- return;
+- }
+- tmp = purple_str_binary_to_ascii(decoded, len);
+- purple_debug_info("yahoo", "Got P2P service packet (from server): who = %s, ip = %s\n", who, tmp);
+- g_free(tmp);
+-
+- ip = strtol((gchar *)decoded, NULL, 10);
+- g_free(decoded);
+- host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
+- (ip >> 24) & 0xff);
+- f = yahoo_friend_find(gc, who);
+- if (f)
+- yahoo_friend_set_ip(f, host_ip);
+- purple_debug_info("yahoo", "IP : %s\n", host_ip);
+-
+- account = purple_connection_get_account(gc);
+-
+- if(val_11==0) {
+- if(!f)
+- return;
+- else
+- val_11 = f->session_id;
+- }
+-
+- p2p_data = g_new0(struct yahoo_p2p_data, 1);
+- p2p_data->host_username = g_strdup(who);
+- p2p_data->val_13 = val_13;
+- p2p_data->session_id = val_11;
+- p2p_data->host_ip = host_ip;
+- p2p_data->gc = gc;
+- p2p_data->connection_type = YAHOO_P2P_WE_ARE_CLIENT;
+- p2p_data->source = -1;
+-
+- /* connect to host */
+- if((purple_proxy_connect(gc, account, host_ip, YAHOO_PAGER_PORT_P2P, yahoo_p2p_init_cb, p2p_data))==NULL) {
+- purple_debug_info("yahoo","p2p: Connection to %s failed\n", host_ip);
+- g_free(p2p_data->host_ip);
+- g_free(p2p_data->host_username);
+- g_free(p2p_data);
+- }
+- }
+-}
+-
+-static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account;
+- char *who = NULL, *msg = NULL, *id = NULL;
+- GSList *l = pkt->hash;
+-
+- account = purple_connection_get_account(gc);
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- who = pair->value;
+- break;
+- case 5:
+- /* us */
+- break;
+- case 230:
+- /* the audible, in foo.locale.bar.baz format
+- eg: base.tw.smiley.smiley43 */
+- id = pair->value;
+- break;
+- case 231:
+- /* the text of the audible */
+- msg = pair->value;
+- break;
+- case 232:
+- /* SHA-1 hash of audible SWF file (eg: 4e8691499d9c0fb8374478ff9720f4a9ea4a4915) */
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- if (!msg)
+- msg = id;
+- if (!who || !msg)
+- return;
+- if (!g_utf8_validate(msg, -1, NULL)) {
+- purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
+- return;
+- }
+- if (!purple_privacy_check(account, who)) {
+- purple_debug_misc("yahoo", "Audible message from %s for %s dropped!\n",
+- purple_account_get_username(account), who);
+- return;
+- }
+- if (id) {
+- /* "http://l.yimg.com/pu/dl/aud/"+locale+"/"+id+".swf" */
+- char **audible_locale = g_strsplit(id, ".", 0);
+- char *buf = g_strdup_printf(_("[ Audible %s/%s/%s.swf ] %s"), YAHOO_AUDIBLE_URL, audible_locale[1], id, msg);
+- g_strfreev(audible_locale);
+-
+- serv_got_im(gc, who, buf, 0, time(NULL));
+- g_free(buf);
+- } else
+- serv_got_im(gc, who, msg, 0, time(NULL));
+-}
+-
+-static void yahoo_packet_process(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- switch (pkt->service) {
+- case YAHOO_SERVICE_LOGON:
+- case YAHOO_SERVICE_LOGOFF:
+- case YAHOO_SERVICE_ISAWAY:
+- case YAHOO_SERVICE_ISBACK:
+- case YAHOO_SERVICE_GAMELOGON:
+- case YAHOO_SERVICE_GAMELOGOFF:
+- case YAHOO_SERVICE_CHATLOGON:
+- case YAHOO_SERVICE_CHATLOGOFF:
+- case YAHOO_SERVICE_Y6_STATUS_UPDATE:
+- case YAHOO_SERVICE_STATUS_15:
+- yahoo_process_status(gc, pkt);
+- break;
+- case YAHOO_SERVICE_NOTIFY:
+- yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER);
+- break;
+- case YAHOO_SERVICE_MESSAGE:
+- case YAHOO_SERVICE_GAMEMSG:
+- case YAHOO_SERVICE_CHATMSG:
+- yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER);
+- break;
+- case YAHOO_SERVICE_SYSMESSAGE:
+- yahoo_process_sysmessage(gc, pkt);
+- break;
+- case YAHOO_SERVICE_NEWMAIL:
+- yahoo_process_mail(gc, pkt);
+- break;
+- case YAHOO_SERVICE_NEWCONTACT:
+- yahoo_process_contact(gc, pkt);
+- break;
+- case YAHOO_SERVICE_AUTHRESP:
+- yahoo_process_authresp(gc, pkt);
+- break;
+- case YAHOO_SERVICE_LIST:
+- yahoo_process_list(gc, pkt);
+- break;
+- case YAHOO_SERVICE_LIST_15:
+- yahoo_process_list_15(gc, pkt);
+- break;
+- case YAHOO_SERVICE_AUTH:
+- yahoo_process_auth(gc, pkt);
+- break;
+- case YAHOO_SERVICE_AUTH_REQ_15:
+- yahoo_buddy_auth_req_15(gc, pkt);
+- break;
+- case YAHOO_SERVICE_ADDBUDDY:
+- yahoo_process_addbuddy(gc, pkt);
+- break;
+- case YAHOO_SERVICE_IGNORECONTACT:
+- yahoo_process_ignore(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONFINVITE:
+- case YAHOO_SERVICE_CONFADDINVITE:
+- yahoo_process_conference_invite(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONFDECLINE:
+- yahoo_process_conference_decline(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONFLOGON:
+- yahoo_process_conference_logon(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONFLOGOFF:
+- yahoo_process_conference_logoff(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONFMSG:
+- yahoo_process_conference_message(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATONLINE:
+- yahoo_process_chat_online(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATLOGOUT:
+- yahoo_process_chat_logout(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATGOTO:
+- yahoo_process_chat_goto(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATJOIN:
+- yahoo_process_chat_join(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */
+- case YAHOO_SERVICE_CHATEXIT:
+- yahoo_process_chat_exit(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */
+- case YAHOO_SERVICE_CHATADDINVITE:
+- yahoo_process_chat_addinvite(gc, pkt);
+- break;
+- case YAHOO_SERVICE_COMMENT:
+- yahoo_process_chat_message(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PRESENCE_PERM:
+- case YAHOO_SERVICE_PRESENCE_SESSION:
+- yahoo_process_presence(gc, pkt);
+- break;
+- case YAHOO_SERVICE_P2PFILEXFER:
+- /* This case had no break and continued; thus keeping it this way.*/
+- yahoo_process_p2p(gc, pkt); /* P2PFILEXFER handled the same way as process_p2p */
+- yahoo_process_p2pfilexfer(gc, pkt); /* redundant ??, need to have a break now */
+- case YAHOO_SERVICE_FILETRANSFER:
+- yahoo_process_filetransfer(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PEERTOPEER:
+- yahoo_process_p2p(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PICTURE:
+- yahoo_process_picture(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PICTURE_CHECKSUM:
+- yahoo_process_picture_checksum(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PICTURE_UPLOAD:
+- yahoo_process_picture_upload(gc, pkt);
+- break;
+- case YAHOO_SERVICE_PICTURE_UPDATE:
+- case YAHOO_SERVICE_AVATAR_UPDATE:
+- yahoo_process_avatar_update(gc, pkt);
+- break;
+- case YAHOO_SERVICE_AUDIBLE:
+- yahoo_process_audible(gc, pkt);
+- break;
+- case YAHOO_SERVICE_CONTACT_DETAILS:
+- yahoo_process_contact_details(gc, pkt);
+- break;
+- case YAHOO_SERVICE_FILETRANS_15:
+- yahoo_process_filetrans_15(gc, pkt);
+- break;
+- case YAHOO_SERVICE_FILETRANS_INFO_15:
+- yahoo_process_filetrans_info_15(gc, pkt);
+- break;
+- case YAHOO_SERVICE_FILETRANS_ACC_15:
+- yahoo_process_filetrans_acc_15(gc, pkt);
+- break;
+- case YAHOO_SERVICE_SMS_MSG:
+- yahoo_process_sms_message(gc, pkt);
+- break;
+-
+- default:
+- purple_debug_error("yahoo", "Unhandled service 0x%02x\n", pkt->service);
+- break;
+- }
+-}
+-
+-static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = data;
+- YahooData *yd = gc->proto_data;
+- char buf[1024];
+- int len;
+-
+- len = read(yd->fd, buf, sizeof(buf));
+-
+- if (len < 0) {
+- gchar *tmp;
+-
+- if (errno == EAGAIN)
+- /* No worries */
+- return;
+-
+- tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- } else if (len == 0) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Server closed the connection"));
+- return;
+- }
+- gc->last_received = time(NULL);
+- yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
+- memcpy(yd->rxqueue + yd->rxlen, buf, len);
+- yd->rxlen += len;
+-
+- while (1) {
+- struct yahoo_packet *pkt;
+- int pos = 0;
+- int pktlen;
+-
+- if (yd->rxlen < YAHOO_PACKET_HDRLEN)
+- return;
+-
+- if (strncmp((char *)yd->rxqueue, "YMSG", MIN(4, yd->rxlen)) != 0) {
+- /* HEY! This isn't even a YMSG packet. What
+- * are you trying to pull? */
+- guchar *start;
+-
+- 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) {
+- g_memmove(yd->rxqueue, start, yd->rxlen - (start - yd->rxqueue));
+- yd->rxlen -= start - yd->rxqueue;
+- continue;
+- } else {
+- g_free(yd->rxqueue);
+- yd->rxqueue = NULL;
+- yd->rxlen = 0;
+- return;
+- }
+- }
+-
+- pos += 4; /* YMSG */
+- pos += 2;
+- pos += 2;
+-
+- pktlen = yahoo_get16(yd->rxqueue + pos); pos += 2;
+- purple_debug_misc("yahoo", "%d bytes to read, rxlen is %d\n", pktlen, yd->rxlen);
+-
+- if (yd->rxlen < (YAHOO_PACKET_HDRLEN + pktlen))
+- return;
+-
+- yahoo_packet_dump(yd->rxqueue, YAHOO_PACKET_HDRLEN + pktlen);
+-
+- pkt = yahoo_packet_new(0, 0, 0);
+-
+- pkt->service = yahoo_get16(yd->rxqueue + pos); pos += 2;
+- pkt->status = yahoo_get32(yd->rxqueue + pos); pos += 4;
+- purple_debug_misc("yahoo", "Yahoo Service: 0x%02x Status: %d\n",
+- pkt->service, pkt->status);
+- pkt->id = yahoo_get32(yd->rxqueue + pos); pos += 4;
+-
+- yahoo_packet_read(pkt, yd->rxqueue + pos, pktlen);
+-
+- yd->rxlen -= YAHOO_PACKET_HDRLEN + pktlen;
+- if (yd->rxlen) {
+- guchar *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen);
+- g_free(yd->rxqueue);
+- yd->rxqueue = tmp;
+- } else {
+- g_free(yd->rxqueue);
+- yd->rxqueue = NULL;
+- }
+-
+- yahoo_packet_process(gc, pkt);
+-
+- yahoo_packet_free(pkt);
+- }
+-}
+-
+-static void yahoo_got_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleConnection *gc = data;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- if (source < 0) {
+- gchar *tmp;
+- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- yd = gc->proto_data;
+- yd->fd = source;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id);
+-
+- yahoo_packet_hash_str(pkt, 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))));
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
+-}
+-
+-#ifdef TRY_WEBMESSENGER_LOGIN
+-static void yahoo_got_web_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleConnection *gc = data;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- if (source < 0) {
+- gchar *tmp;
+- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- yd = gc->proto_data;
+- yd->fd = source;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sss", 0,
+- purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
+- 1, purple_normalize(gc->account, purple_account_get_username(purple_connection_get_account(gc))),
+- 6, yd->auth);
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(yd->auth);
+- gc->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
+-}
+-
+-static void yahoo_web_pending(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc = data;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- char bufread[2048], *i = bufread, *buf = bufread;
+- int len;
+- GString *s;
+-
+- len = read(source, bufread, sizeof(bufread) - 1);
+-
+- if (len < 0) {
+- gchar *tmp;
+-
+- if (errno == EAGAIN)
+- /* No worries */
+- return;
+-
+- tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- } else if (len == 0) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Server closed the connection"));
+- return;
+- }
+-
+- if (yd->rxlen > 0 || !g_strstr_len(buf, len, "\r\n\r\n")) {
+- yd->rxqueue = g_realloc(yd->rxqueue, yd->rxlen + len + 1);
+- memcpy(yd->rxqueue + yd->rxlen, buf, len);
+- yd->rxlen += len;
+- i = buf = (char *)yd->rxqueue;
+- len = yd->rxlen;
+- }
+- buf[len] = '\0';
+-
+- if ((strncmp(buf, "HTTP/1.0 302", strlen("HTTP/1.0 302")) &&
+- strncmp(buf, "HTTP/1.1 302", strlen("HTTP/1.1 302")))) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Received unexpected HTTP response from server"));
+- purple_debug_misc("yahoo", "Unexpected HTTP response: %s\n", buf);
+- return;
+- }
+-
+- s = g_string_sized_new(len);
+-
+- while ((i = strstr(i, "Set-Cookie: "))) {
+-
+- i += strlen("Set-Cookie: ");
+- for (;*i != ';' && *i != '\0'; i++)
+- g_string_append_c(s, *i);
+-
+- g_string_append(s, "; ");
+- /* Should these cookies be included too when trying for xfer?
+- * It seems to work without these
+- */
+- }
+-
+- yd->auth = g_string_free(s, FALSE);
+- purple_input_remove(gc->inpa);
+- close(source);
+- g_free(yd->rxqueue);
+- yd->rxqueue = NULL;
+- yd->rxlen = 0;
+- /* Now we have our cookies to login with. I'll go get the milk. */
+- if (purple_proxy_connect(gc, account, "wcs2.msg.dcn.yahoo.com",
+- purple_account_get_int(account, "port", YAHOO_PAGER_PORT),
+- yahoo_got_web_connected, gc) == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- return;
+- }
+-}
+-
+-static void yahoo_got_cookies_send_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PurpleConnection *gc;
+- YahooData *yd;
+- int written, remaining;
+-
+- gc = data;
+- yd = gc->proto_data;
+-
+- remaining = strlen(yd->auth) - yd->auth_written;
+- written = write(source, yd->auth + yd->auth_written, remaining);
+-
+- 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;
+- tmp = g_strdup_printf(_("Lost connection with %s: %s"),
+- "login.yahoo.com:80", g_strerror(errno));
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- if (written < remaining) {
+- yd->auth_written += written;
+- return;
+- }
+-
+- g_free(yd->auth);
+- yd->auth = NULL;
+- yd->auth_written = 0;
+- purple_input_remove(gc->inpa);
+- gc->inpa = purple_input_add(source, PURPLE_INPUT_READ, yahoo_web_pending, gc);
+-}
+-
+-static void yahoo_got_cookies(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleConnection *gc = data;
+-
+- if (source < 0) {
+- gchar *tmp;
+- tmp = g_strdup_printf(_("Unable to establish a connection with %s: %s"),
+- "login.yahoo.com:80", error_message);
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+- return;
+- }
+-
+- if (gc->inpa == 0)
+- {
+- gc->inpa = purple_input_add(source, PURPLE_INPUT_WRITE,
+- yahoo_got_cookies_send_cb, gc);
+- yahoo_got_cookies_send_cb(gc, source, PURPLE_INPUT_WRITE);
+- }
+-}
+-
+-static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url)
+-{
+- if (!strcmp(key, "passwd") || !strcmp(key, "login"))
+- return;
+- g_string_append_c(url, '&');
+- g_string_append(url, key);
+- g_string_append_c(url, '=');
+- if (!strcmp(key, ".save") || !strcmp(key, ".js"))
+- g_string_append_c(url, '1');
+- else if (!strcmp(key, ".challenge"))
+- g_string_append(url, val);
+- else
+- g_string_append(url, purple_url_encode(val));
+-}
+-
+-static GHashTable *yahoo_login_page_hash(const char *buf, size_t len)
+-{
+- GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- const char *c = buf;
+- char *d;
+- char name[64], value[64];
+- int count;
+- int input_len = strlen("<input ");
+- int name_len = strlen("name=\"");
+- int value_len = strlen("value=\"");
+- while ((len > ((c - buf) + input_len))
+- && (c = strstr(c, "<input "))) {
+- if (!(c = g_strstr_len(c, len - (c - buf), "name=\"")))
+- continue;
+- c += name_len;
+- count = sizeof(name)-1;
+- for (d = name; (len > ((c - buf) + 1)) && *c!='"'
+- && count; c++, d++, count--)
+- *d = *c;
+- *d = '\0';
+- count = sizeof(value)-1;
+- if (!(d = g_strstr_len(c, len - (c - buf), "value=\"")))
+- continue;
+- d += value_len;
+- if (strchr(c, '>') < d)
+- break;
+- for (c = d, d = value; (len > ((c - buf) + 1))
+- && *c!='"' && count; c++, d++, count--)
+- *d = *c;
+- *d = '\0';
+- g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
+- }
+- return hash;
+-}
+-
+-static void
+-yahoo_login_page_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- PurpleConnection *gc = (PurpleConnection *)user_data;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- const char *sn = purple_account_get_username(account);
+- const char *pass = purple_connection_get_password(gc);
+- GHashTable *hash = yahoo_login_page_hash(url_text, len);
+- GString *url = g_string_new("GET http://login.yahoo.com/config/login?login=");
+- char md5[33], *hashp = md5, *chal;
+- int i;
+- PurpleCipher *cipher;
+- PurpleCipherContext *context;
+- guchar digest[16];
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL)
+- {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- error_message);
+- return;
+- }
+-
+- url = g_string_append(url, sn);
+- url = g_string_append(url, "&passwd=");
+-
+- cipher = purple_ciphers_find_cipher("md5");
+- context = purple_cipher_context_new(cipher, NULL);
+-
+- purple_cipher_context_append(context, (const guchar *)pass, strlen(pass));
+- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+- for (i = 0; i < 16; ++i) {
+- g_snprintf(hashp, 3, "%02x", digest[i]);
+- hashp += 2;
+- }
+-
+- chal = g_strconcat(md5, g_hash_table_lookup(hash, ".challenge"), NULL);
+- purple_cipher_context_reset(context, NULL);
+- purple_cipher_context_append(context, (const guchar *)chal, strlen(chal));
+- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+- hashp = md5;
+- for (i = 0; i < 16; ++i) {
+- g_snprintf(hashp, 3, "%02x", digest[i]);
+- hashp += 2;
+- }
+- /*
+- * I dunno why this is here and commented out.. but in case it's needed
+- * I updated it..
+-
+- purple_cipher_context_reset(context, NULL);
+- purple_cipher_context_append(context, md5, strlen(md5));
+- purple_cipher_context_digest(context, sizeof(digest), digest, NULL);
+- hashp = md5;
+- for (i = 0; i < 16; ++i) {
+- g_snprintf(hashp, 3, "%02x", digest[i]);
+- hashp += 2;
+- }
+- */
+- g_free(chal);
+-
+- url = g_string_append(url, md5);
+- g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url);
+-
+- url = g_string_append(url, "&.hash=1&.md5=1 HTTP/1.1\r\n"
+- "Host: login.yahoo.com\r\n\r\n");
+- g_hash_table_destroy(hash);
+- yd->auth = g_string_free(url, FALSE);
+- if (purple_proxy_connect(gc, account, "login.yahoo.com", 80, yahoo_got_cookies, gc) == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- return;
+- }
+-
+- purple_cipher_context_destroy(context);
+-}
+-#endif /* TRY_WEBMESSENGER_LOGIN */
+-
+-static void yahoo_picture_check(PurpleAccount *account)
+-{
+- PurpleConnection *gc = purple_account_get_connection(account);
+- PurpleStoredImage *img = purple_buddy_icons_find_account_icon(account);
+-
+- yahoo_set_buddy_icon(gc, img);
+- purple_imgstore_unref(img);
+-}
+-
+-static int get_yahoo_status_from_purple_status(PurpleStatus *status)
+-{
+- PurplePresence *presence;
+- const char *status_id;
+- const char *msg;
+-
+- presence = purple_status_get_presence(status);
+- status_id = purple_status_get_id(status);
+- msg = purple_status_get_attr_string(status, "message");
+-
+- if ((msg != NULL) && (*msg != '\0')) {
+- return YAHOO_STATUS_CUSTOM;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AVAILABLE)) {
+- return YAHOO_STATUS_AVAILABLE;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BRB)) {
+- return YAHOO_STATUS_BRB;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_BUSY)) {
+- return YAHOO_STATUS_BUSY;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATHOME)) {
+- return YAHOO_STATUS_NOTATHOME;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTATDESK)) {
+- return YAHOO_STATUS_NOTATDESK;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_NOTINOFFICE)) {
+- return YAHOO_STATUS_NOTINOFFICE;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONPHONE)) {
+- return YAHOO_STATUS_ONPHONE;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_ONVACATION)) {
+- return YAHOO_STATUS_ONVACATION;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_OUTTOLUNCH)) {
+- return YAHOO_STATUS_OUTTOLUNCH;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_STEPPEDOUT)) {
+- return YAHOO_STATUS_STEPPEDOUT;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_INVISIBLE)) {
+- return YAHOO_STATUS_INVISIBLE;
+- } else if (!strcmp(status_id, YAHOO_STATUS_TYPE_AWAY)) {
+- return YAHOO_STATUS_CUSTOM;
+- } else if (purple_presence_is_idle(presence)) {
+- return YAHOO_STATUS_IDLE;
+- } else {
+- purple_debug_error("yahoo", "Unexpected PurpleStatus!\n");
+- return YAHOO_STATUS_AVAILABLE;
+- }
+-}
+-
+-static void yahoo_got_pager_server(PurpleUtilFetchUrlData *url_data,
+- gpointer user_data, const gchar *url_text, gsize len, const gchar *error_message)
+-{
+- YahooData *yd = user_data;
+- PurpleConnection *gc = yd->gc;
+- PurpleAccount *a = purple_connection_get_account(gc);
+- gchar **strings = NULL, *cs_server = NULL;
+- int port = purple_account_get_int(a, "port", YAHOO_PAGER_PORT);
+- int stringslen = 0;
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if(error_message != NULL || len == 0) {
+- purple_debug_error("yahoo", "Unable to retrieve server info. %"
+- G_GSIZE_FORMAT " bytes retrieved with error message: %s\n", len,
+- error_message ? error_message : "(null)");
+-
+- if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect: The server returned an empty response."));
+- } else {
+- if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
+- yahoo_got_connected, gc) == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- }
+- }
+- } else {
+- strings = g_strsplit(url_text, "\r\n", -1);
+-
+- if((stringslen = g_strv_length(strings)) > 1) {
+- int i;
+-
+- for(i = 0; i < stringslen; i++) {
+- if(g_ascii_strncasecmp(strings[i], "COLO_CAPACITY=", 14) == 0) {
+- purple_debug_info("yahoo", "Got COLO Capacity: %s\n", &(strings[i][14]));
+- } else if(g_ascii_strncasecmp(strings[i], "CS_IP_ADDRESS=", 14) == 0) {
+- cs_server = g_strdup(&strings[i][14]);
+- purple_debug_info("yahoo", "Got CS IP address: %s\n", cs_server);
+- }
+- }
+- }
+-
+- if(cs_server) { /* got an address; get on with connecting */
+- if(purple_proxy_connect(gc, a, cs_server, port, yahoo_got_connected, gc) == NULL)
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- } else {
+- purple_debug_error("yahoo", "No CS address retrieved! Server "
+- "response:\n%s\n", url_text ? url_text : "(null)");
+-
+- if(yahoo_is_japan(a)) { /* We don't know fallback hosts for Yahoo Japan :( */
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect: The server's response did not contain "
+- "the necessary information"));
+- } else
+- if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port,
+- yahoo_got_connected, gc) == NULL) {
+- purple_connection_error_reason(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Unable to connect"));
+- }
+- }
+- }
+-
+- g_strfreev(strings);
+- g_free(cs_server);
+-}
+-
+-void yahoo_login(PurpleAccount *account) {
+- PurpleConnection *gc = purple_account_get_connection(account);
+- YahooData *yd = gc->proto_data = g_new0(YahooData, 1);
+- PurpleStatus *status = purple_account_get_active_status(account);
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
+- PurpleUtilFetchUrlData *url_data;
+-
+- gc->flags |= PURPLE_CONNECTION_HTML | PURPLE_CONNECTION_NO_BGCOLOR | PURPLE_CONNECTION_NO_URLDESC;
+-
+- purple_connection_update_progress(gc, _("Connecting"), 1, 2);
+-
+- purple_connection_set_display_name(gc, purple_account_get_username(account));
+-
+- yd->gc = gc;
+- yd->jp = yahoo_is_japan(account);
+- yd->yahoo_local_p2p_server_fd = -1;
+- yd->fd = -1;
+- yd->txhandler = 0;
+- /* TODO: Is there a good grow size for the buffer? */
+- yd->txbuf = purple_circ_buffer_new(0);
+- yd->friends = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, yahoo_friend_free);
+- yd->imvironments = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- yd->xfer_peer_idstring_map = g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
+- yd->peers = g_hash_table_new_full(g_str_hash, g_str_equal, g_free,
+- yahoo_p2p_disconnect_destroy_data);
+- yd->sms_carrier = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- yd->yahoo_p2p_timer = purple_timeout_add_seconds(YAHOO_P2P_KEEPALIVE_SECS,
+- yahoo_p2p_keepalive, gc);
+- yd->confs = NULL;
+- yd->conf_id = 2;
+- yd->last_keepalive = yd->last_ping = time(NULL);
+-
+- yd->current_status = get_yahoo_status_from_purple_status(status);
+-
+- yahoo_picture_check(account);
+-
+- /* Get the pager server. Actually start connecting in the callback since we
+- * must have the contents of the HTTP response to proceed. */
+- url_data = purple_util_fetch_url_request_len_with_account(
+- proxy_ssl ? purple_connection_get_account(gc) : NULL,
+- yd->jp ? YAHOOJP_PAGER_HOST_REQ_URL : YAHOO_PAGER_HOST_REQ_URL,
+- use_whole_url ? TRUE : FALSE,
+- YAHOO_CLIENT_USERAGENT, FALSE, NULL, FALSE, -1,
+- yahoo_got_pager_server, yd);
+- if (url_data)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- return;
+-}
+-
+-void yahoo_close(PurpleConnection *gc) {
+- YahooData *yd = (YahooData *)gc->proto_data;
+- GSList *l;
+-
+- if (gc->inpa)
+- purple_input_remove(gc->inpa);
+-
+- while (yd->url_datas) {
+- purple_util_fetch_url_cancel(yd->url_datas->data);
+- yd->url_datas = g_slist_delete_link(yd->url_datas, yd->url_datas);
+- }
+-
+- for (l = yd->confs; l; l = l->next) {
+- PurpleConversation *conv = l->data;
+-
+- yahoo_conf_leave(yd, purple_conversation_get_name(conv),
+- purple_connection_get_display_name(gc),
+- purple_conv_chat_get_users(PURPLE_CONV_CHAT(conv)));
+- }
+- g_slist_free(yd->confs);
+-
+- for (l = yd->cookies; l; l = l->next) {
+- g_free(l->data);
+- l->data=NULL;
+- }
+- g_slist_free(yd->cookies);
+-
+- yd->chat_online = FALSE;
+- if (yd->in_chat)
+- yahoo_c_leave(gc, 1); /* 1 = YAHOO_CHAT_ID */
+-
+- purple_timeout_remove(yd->yahoo_p2p_timer);
+- if(yd->yahoo_p2p_server_timeout_handle != 0) {
+- purple_timeout_remove(yd->yahoo_p2p_server_timeout_handle);
+- yd->yahoo_p2p_server_timeout_handle = 0;
+- }
+-
+- /* close p2p server if it is waiting for a peer to connect */
+- if (yd->yahoo_p2p_server_watcher) {
+- purple_input_remove(yd->yahoo_p2p_server_watcher);
+- yd->yahoo_p2p_server_watcher = 0;
+- }
+- if (yd->yahoo_local_p2p_server_fd >= 0) {
+- close(yd->yahoo_local_p2p_server_fd);
+- yd->yahoo_local_p2p_server_fd = -1;
+- }
+-
+- g_hash_table_destroy(yd->sms_carrier);
+- g_hash_table_destroy(yd->peers);
+- g_hash_table_destroy(yd->friends);
+- g_hash_table_destroy(yd->imvironments);
+- g_hash_table_destroy(yd->xfer_peer_idstring_map);
+- g_free(yd->chat_name);
+-
+- g_free(yd->cookie_y);
+- g_free(yd->cookie_t);
+- g_free(yd->cookie_b);
+-
+- if (yd->txhandler)
+- purple_input_remove(yd->txhandler);
+-
+- purple_circ_buffer_destroy(yd->txbuf);
+-
+- if (yd->fd >= 0)
+- close(yd->fd);
+-
+- g_free(yd->rxqueue);
+- yd->rxlen = 0;
+- g_free(yd->picture_url);
+-
+- if (yd->buddy_icon_connect_data)
+- purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
+- if (yd->picture_upload_todo)
+- yahoo_buddy_icon_upload_data_free(yd->picture_upload_todo);
+- if (yd->ycht)
+- ycht_connection_close(yd->ycht);
+- if (yd->listen_data != NULL)
+- purple_network_listen_cancel(yd->listen_data);
+-
+- g_free(yd->pending_chat_room);
+- g_free(yd->pending_chat_id);
+- g_free(yd->pending_chat_topic);
+- g_free(yd->pending_chat_goto);
+- g_strfreev(yd->profiles);
+-
+- yahoo_personal_details_reset(&yd->ypd, TRUE);
+-
+- g_free(yd->current_list15_grp);
+-
+- g_free(yd);
+- gc->proto_data = NULL;
+-}
+-
+-const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b)
+-{
+- return "yahoo";
+-}
+-
+-const char *yahoo_list_emblem(PurpleBuddy *b)
+-{
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- YahooFriend *f;
+- PurplePresence *presence;
+-
+- if (!b || !(account = purple_buddy_get_account(b)) ||
+- !(gc = purple_account_get_connection(account)) ||
+- !gc->proto_data)
+- return NULL;
+-
+- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
+- if (!f) {
+- return "not-authorized";
+- }
+-
+- presence = purple_buddy_get_presence(b);
+-
+- if (purple_presence_is_online(presence)) {
+- if (yahoo_friend_get_game(f))
+- return "game";
+-
+- if (f->fed)
+- return "external";
+- }
+- return NULL;
+-}
+-
+-static const char *yahoo_get_status_string(enum yahoo_status a)
+-{
+- switch (a) {
+- case YAHOO_STATUS_BRB:
+- return _("Be Right Back");
+- case YAHOO_STATUS_BUSY:
+- return _("Busy");
+- case YAHOO_STATUS_NOTATHOME:
+- return _("Not at Home");
+- case YAHOO_STATUS_NOTATDESK:
+- return _("Not at Desk");
+- case YAHOO_STATUS_NOTINOFFICE:
+- return _("Not in Office");
+- case YAHOO_STATUS_ONPHONE:
+- return _("On the Phone");
+- case YAHOO_STATUS_ONVACATION:
+- return _("On Vacation");
+- case YAHOO_STATUS_OUTTOLUNCH:
+- return _("Out to Lunch");
+- case YAHOO_STATUS_STEPPEDOUT:
+- return _("Stepped Out");
+- case YAHOO_STATUS_INVISIBLE:
+- return _("Invisible");
+- case YAHOO_STATUS_IDLE:
+- return _("Idle");
+- case YAHOO_STATUS_OFFLINE:
+- return _("Offline");
+- default:
+- return _("Available");
+- }
+-}
+-
+-static void yahoo_initiate_conference(PurpleBlistNode *node, gpointer data) {
+-
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+-
+- GHashTable *components;
+- YahooData *yd;
+- int id;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- yd = gc->proto_data;
+- id = yd->conf_id;
+-
+- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- g_hash_table_replace(components, g_strdup("room"),
+- g_strdup_printf("%s-%d", purple_connection_get_display_name(gc), id));
+- g_hash_table_replace(components, g_strdup("topic"), g_strdup("Join my conference..."));
+- g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
+- yahoo_c_join(gc, components);
+- g_hash_table_destroy(components);
+-
+- yahoo_c_invite(gc, id, "Join my conference...", purple_buddy_get_name(buddy));
+-}
+-
+-static void yahoo_presence_settings(PurpleBlistNode *node, gpointer data) {
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+- int presence_val = GPOINTER_TO_INT(data);
+-
+- buddy = (PurpleBuddy *) node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+-
+- yahoo_friend_update_presence(gc, purple_buddy_get_name(buddy), presence_val);
+-}
+-
+-static void yahoo_game(PurpleBlistNode *node, gpointer data) {
+-
+- PurpleBuddy *buddy;
+- PurpleConnection *gc;
+-
+- const char *game;
+- char *game2;
+- char *t;
+- char url[256];
+- YahooFriend *f;
+-
+- g_return_if_fail(PURPLE_BLIST_NODE_IS_BUDDY(node));
+-
+- buddy = (PurpleBuddy *) node;
+- gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+-
+- f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
+- if (!f)
+- return;
+-
+- game = yahoo_friend_get_game(f);
+- if (!game)
+- return;
+-
+- t = game2 = g_strdup(strstr(game, "ante?room="));
+- while (*t && *t != '\t')
+- t++;
+- *t = 0;
+- g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2);
+- purple_notify_uri(gc, url);
+- g_free(game2);
+-}
+-
+-char *yahoo_status_text(PurpleBuddy *b)
+-{
+- YahooFriend *f = NULL;
+- const char *msg;
+- char *msg2;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+-
+- account = purple_buddy_get_account(b);
+- gc = purple_account_get_connection(account);
+- if (!gc || !purple_connection_get_protocol_data(gc))
+- return NULL;
+-
+- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
+- if (!f)
+- return g_strdup(_("Not on server list"));
+-
+- switch (f->status) {
+- case YAHOO_STATUS_AVAILABLE:
+- return NULL;
+- case YAHOO_STATUS_IDLE:
+- if (f->idle == -1)
+- return g_strdup(yahoo_get_status_string(f->status));
+- return NULL;
+- case YAHOO_STATUS_CUSTOM:
+- if (!(msg = yahoo_friend_get_status_message(f)))
+- return NULL;
+- msg2 = g_markup_escape_text(msg, strlen(msg));
+- purple_util_chrreplace(msg2, '\n', ' ');
+- return msg2;
+-
+- default:
+- return g_strdup(yahoo_get_status_string(f->status));
+- }
+-}
+-
+-void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
+-{
+- YahooFriend *f;
+- char *status = NULL;
+- const char *presence = NULL;
+- PurpleAccount *account;
+-
+- account = purple_buddy_get_account(b);
+- f = yahoo_friend_find(purple_account_get_connection(account), purple_buddy_get_name(b));
+- if (!f)
+- status = g_strdup_printf("\n%s", _("Not on server list"));
+- else {
+- switch (f->status) {
+- case YAHOO_STATUS_CUSTOM:
+- if (!yahoo_friend_get_status_message(f))
+- return;
+- status = g_strdup(yahoo_friend_get_status_message(f));
+- break;
+- case YAHOO_STATUS_OFFLINE:
+- break;
+- default:
+- status = g_strdup(yahoo_get_status_string(f->status));
+- break;
+- }
+-
+- switch (f->presence) {
+- case YAHOO_PRESENCE_ONLINE:
+- presence = _("Appear Online");
+- break;
+- case YAHOO_PRESENCE_PERM_OFFLINE:
+- presence = _("Appear Permanently Offline");
+- break;
+- case YAHOO_PRESENCE_DEFAULT:
+- break;
+- default:
+- purple_debug_error("yahoo", "Unknown presence in yahoo_tooltip_text\n");
+- break;
+- }
+- }
+-
+- if (status != NULL) {
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
+- g_free(status);
+- }
+-
+- if (presence != NULL)
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Presence"), presence);
+-
+- if (f && full) {
+- YahooPersonalDetails *ypd = &f->ypd;
+- int i;
+- struct {
+- char *id;
+- char *text;
+- char *value;
+- } yfields[] = {
+- {"hp", N_("Home Phone Number"), ypd->phone.home},
+- {"wp", N_("Work Phone Number"), ypd->phone.work},
+- {"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
+- {NULL, NULL, NULL}
+- };
+- for (i = 0; yfields[i].id; i++) {
+- if (!yfields[i].value || !*yfields[i].value)
+- continue;
+- purple_notify_user_info_add_pair(user_info, _(yfields[i].text), yfields[i].value);
+- }
+- }
+-}
+-
+-static void yahoo_addbuddyfrommenu_cb(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(purple_buddy_get_account(buddy));
+-
+- yahoo_add_buddy(gc, buddy, NULL);
+-}
+-
+-
+-static void yahoo_chat_goto_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(purple_buddy_get_account(buddy));
+-
+- yahoo_chat_goto(gc, purple_buddy_get_name(buddy));
+-}
+-
+-static GList *build_presence_submenu(YahooFriend *f, PurpleConnection *gc) {
+- GList *m = NULL;
+- PurpleMenuAction *act;
+- YahooData *yd = (YahooData *) gc->proto_data;
+-
+- if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
+- if (f->presence != YAHOO_PRESENCE_ONLINE) {
+- act = purple_menu_action_new(_("Appear Online"),
+- PURPLE_CALLBACK(yahoo_presence_settings),
+- GINT_TO_POINTER(YAHOO_PRESENCE_ONLINE),
+- NULL);
+- m = g_list_append(m, act);
+- } else if (f->presence != YAHOO_PRESENCE_DEFAULT) {
+- act = purple_menu_action_new(_("Appear Offline"),
+- PURPLE_CALLBACK(yahoo_presence_settings),
+- GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
+- NULL);
+- m = g_list_append(m, act);
+- }
+- }
+-
+- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
+- act = purple_menu_action_new(_("Don't Appear Permanently Offline"),
+- PURPLE_CALLBACK(yahoo_presence_settings),
+- GINT_TO_POINTER(YAHOO_PRESENCE_DEFAULT),
+- NULL);
+- m = g_list_append(m, act);
+- } else {
+- act = purple_menu_action_new(_("Appear Permanently Offline"),
+- PURPLE_CALLBACK(yahoo_presence_settings),
+- GINT_TO_POINTER(YAHOO_PRESENCE_PERM_OFFLINE),
+- NULL);
+- m = g_list_append(m, act);
+- }
+-
+- return m;
+-}
+-
+-static void yahoo_doodle_blist_node(PurpleBlistNode *node, gpointer data)
+-{
+- PurpleBuddy *b = (PurpleBuddy *)node;
+- PurpleAccount *account = purple_buddy_get_account(b);
+- PurpleConnection *gc = purple_account_get_connection(account);
+-
+- yahoo_doodle_initiate(gc, purple_buddy_get_name(b));
+-}
+-
+-static void
+-yahoo_userinfo_blist_node(PurpleBlistNode *node, gpointer data)
+-{
+- PurpleBuddy *b = (PurpleBuddy *)node;
+- PurpleAccount *account = purple_buddy_get_account(b);
+- PurpleConnection *gc = purple_account_get_connection(account);
+-
+- yahoo_set_userinfo_for_buddy(gc, b);
+-}
+-
+-static GList *yahoo_buddy_menu(PurpleBuddy *buddy)
+-{
+- GList *m = NULL;
+- PurpleMenuAction *act;
+-
+- PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
+- YahooData *yd = gc->proto_data;
+- static char buf2[1024];
+- YahooFriend *f;
+-
+- f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
+-
+- if (!f && !yd->wm) {
+- act = purple_menu_action_new(_("Add Buddy"),
+- PURPLE_CALLBACK(yahoo_addbuddyfrommenu_cb),
+- NULL, NULL);
+- m = g_list_append(m, act);
+-
+- return m;
+-
+- }
+-
+- if (f && f->status != YAHOO_STATUS_OFFLINE && f->fed == YAHOO_FEDERATION_NONE) {
+- if (!yd->wm) {
+- act = purple_menu_action_new(_("Join in Chat"),
+- PURPLE_CALLBACK(yahoo_chat_goto_menu),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+-
+- act = purple_menu_action_new(_("Initiate Conference"),
+- PURPLE_CALLBACK(yahoo_initiate_conference),
+- NULL, NULL);
+- m = g_list_append(m, act);
+-
+- if (yahoo_friend_get_game(f)) {
+- const char *game = yahoo_friend_get_game(f);
+- char *room;
+- char *t;
+-
+- if ((room = strstr(game, "&follow="))) {/* skip ahead to the url */
+- while (*room && *room != '\t') /* skip to the tab */
+- room++;
+- t = room++; /* room as now at the name */
+- while (*t != '\n')
+- t++; /* replace the \n with a space */
+- *t = ' ';
+- g_snprintf(buf2, sizeof buf2, "%s", room);
+-
+- act = purple_menu_action_new(buf2,
+- PURPLE_CALLBACK(yahoo_game),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+- }
+- }
+-
+- if (f) {
+- act = purple_menu_action_new(_("Presence Settings"), NULL, NULL,
+- build_presence_submenu(f, gc));
+- m = g_list_append(m, act);
+-
+- if (f->fed == YAHOO_FEDERATION_NONE) {
+- act = purple_menu_action_new(_("Start Doodling"),
+- PURPLE_CALLBACK(yahoo_doodle_blist_node),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+-
+- act = purple_menu_action_new(_("Set User Info..."),
+- PURPLE_CALLBACK(yahoo_userinfo_blist_node),
+- NULL, NULL);
+- m = g_list_append(m, act);
+- }
+-
+- return m;
+-}
+-
+-GList *yahoo_blist_node_menu(PurpleBlistNode *node)
+-{
+- if(PURPLE_BLIST_NODE_IS_BUDDY(node)) {
+- return yahoo_buddy_menu((PurpleBuddy *) node);
+- } else {
+- return NULL;
+- }
+-}
+-
+-static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- YahooData *yd = gc->proto_data;
+- const char *name = yd->profiles[purple_request_fields_get_choice(fields, "id")];
+-
+- struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_IDACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 3, name);
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- purple_connection_set_display_name(gc, name);
+-}
+-
+-static void
+-yahoo_get_inbox_token_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *token, size_t len, const gchar *error_message)
+-{
+- PurpleConnection *gc = user_data;
+- gboolean set_cookie = FALSE;
+- gchar *url;
+- YahooData *yd = gc->proto_data;
+-
+- g_return_if_fail(PURPLE_CONNECTION_IS_VALID(gc));
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL)
+- purple_debug_error("yahoo", "Requesting mail login token failed: %s\n", error_message);
+- else if (len > 0 && token && *token) {
+- /* Should we not be hardcoding the rd url? */
+- url = g_strdup_printf(
+- "http://login.yahoo.com/config/reset_cookies_token?"
+- ".token=%s"
+- "&.done=http://us.rd.yahoo.com/messenger/client/%%3fhttp://mail.yahoo.com/",
+- token);
+- set_cookie = TRUE;
+- }
+-
+- if (!set_cookie) {
+- purple_debug_error("yahoo", "No mail login token; forwarding to login screen.\n");
+- url = g_strdup(yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
+- }
+-
+- /* Open the mailbox with the parsed url data */
+- purple_notify_uri(gc, url);
+-
+- g_free(url);
+-}
+-
+-
+-static void yahoo_show_inbox(PurplePluginAction *action)
+-{
+- /* Setup a cookie that can be used by the browser */
+- /* XXX I have no idea how this will work with Yahoo! Japan. */
+-
+- PurpleConnection *gc = action->context;
+- YahooData *yd = gc->proto_data;
+-
+- PurpleUtilFetchUrlData *url_data;
+- const char* base_url = "http://login.yahoo.com";
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+- gchar *request = g_strdup_printf(
+- "POST %s/config/cookie_token HTTP/1.0\r\n"
+- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: login.yahoo.com\r\n"
+- "Content-Length: 0\r\n\r\n",
+- use_whole_url ? base_url : "",
+- yd->cookie_t, yd->cookie_y);
+-
+- url_data = purple_util_fetch_url_request_len_with_account(
+- purple_connection_get_account(gc), base_url, use_whole_url,
+- YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
+- yahoo_get_inbox_token_cb, gc);
+-
+- g_free(request);
+-
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- else {
+- const char *yahoo_mail_url = (yd->jp ? YAHOOJP_MAIL_URL : YAHOO_MAIL_URL);
+- purple_debug_error("yahoo",
+- "Unable to request mail login token; forwarding to login screen.");
+- purple_notify_uri(gc, yahoo_mail_url);
+- }
+-}
+-
+-static void
+-yahoo_set_userinfo_fn(PurplePluginAction *action)
+-{
+- yahoo_set_userinfo(action->context);
+-}
+-
+-static void yahoo_show_act_id(PurplePluginAction *action)
+-{
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+- const char *name = purple_connection_get_display_name(gc);
+- int iter;
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+- field = purple_request_field_choice_new("id", "Activate which ID?", 0);
+- purple_request_field_group_add_field(group, field);
+-
+- for (iter = 0; yd->profiles[iter]; iter++) {
+- purple_request_field_choice_add(field, yd->profiles[iter]);
+- if (purple_strequal(yd->profiles[iter], name))
+- purple_request_field_choice_set_default_value(field, iter);
+- }
+-
+- purple_request_fields(gc, NULL, _("Select the ID you want to activate"), NULL,
+- fields,
+- _("OK"), G_CALLBACK(yahoo_act_id),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-static void yahoo_show_chat_goto(PurplePluginAction *action)
+-{
+- PurpleConnection *gc = (PurpleConnection *) action->context;
+- purple_request_input(gc, NULL, _("Join whom in chat?"), NULL,
+- "", FALSE, FALSE, NULL,
+- _("OK"), G_CALLBACK(yahoo_chat_goto),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL,
+- gc);
+-}
+-
+-GList *yahoo_actions(PurplePlugin *plugin, gpointer context) {
+- GList *m = NULL;
+- PurplePluginAction *act;
+-
+- act = purple_plugin_action_new(_("Set User Info..."),
+- yahoo_set_userinfo_fn);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Activate ID..."),
+- yahoo_show_act_id);
+- m = g_list_append(m, act);
+-
+- act = purple_plugin_action_new(_("Join User in Chat..."),
+- yahoo_show_chat_goto);
+- m = g_list_append(m, act);
+-
+- m = g_list_append(m, NULL);
+- act = purple_plugin_action_new(_("Open Inbox"),
+- yahoo_show_inbox);
+- m = g_list_append(m, act);
+-
+- return m;
+-}
+-
+-struct yahoo_sms_carrier_cb_data {
+- PurpleConnection *gc;
+- char *who;
+- char *what;
+-};
+-
+-static void yahoo_get_sms_carrier_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *webdata, size_t len, const gchar *error_message)
+-{
+- struct yahoo_sms_carrier_cb_data *sms_cb_data = user_data;
+- PurpleConnection *gc = sms_cb_data->gc;
+- YahooData *yd = gc->proto_data;
+- char *status = NULL;
+- char *carrier = NULL;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL) {
+- purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+-
+- g_free(sms_cb_data->who);
+- g_free(sms_cb_data->what);
+- g_free(sms_cb_data);
+- return ;
+- }
+- else if (len > 0 && webdata && *webdata) {
+- xmlnode *validate_data_root = xmlnode_from_str(webdata, -1);
+- xmlnode *validate_data_child = xmlnode_get_child(validate_data_root, "mobile_no");
+- const char *mobile_no = xmlnode_get_attrib(validate_data_child, "msisdn");
+-
+- validate_data_root = xmlnode_copy(validate_data_child);
+- validate_data_child = xmlnode_get_child(validate_data_root, "status");
+- status = xmlnode_get_data(validate_data_child);
+-
+- validate_data_child = xmlnode_get_child(validate_data_root, "carrier");
+- carrier = xmlnode_get_data(validate_data_child);
+-
+- purple_debug_info("yahoo", "SMS validate data: %s\n", webdata);
+-
+- if (status && g_str_equal(status, "Valid")) {
+- g_hash_table_insert(yd->sms_carrier,
+- g_strdup_printf("+%s", mobile_no), g_strdup(carrier));
+- yahoo_send_im(sms_cb_data->gc, sms_cb_data->who,
+- sms_cb_data->what, PURPLE_MESSAGE_SEND);
+- } else {
+- g_hash_table_insert(yd->sms_carrier,
+- g_strdup_printf("+%s", mobile_no), g_strdup("Unknown"));
+- purple_conversation_write(conv, NULL,
+- _("Can't send SMS. Unknown mobile carrier."),
+- PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+-
+- xmlnode_free(validate_data_child);
+- xmlnode_free(validate_data_root);
+- g_free(sms_cb_data->who);
+- g_free(sms_cb_data->what);
+- g_free(sms_cb_data);
+- g_free(status);
+- g_free(carrier);
+- }
+-}
+-
+-static void yahoo_get_sms_carrier(PurpleConnection *gc, gpointer data)
+-{
+- YahooData *yd = gc->proto_data;
+- PurpleUtilFetchUrlData *url_data;
+- struct yahoo_sms_carrier_cb_data *sms_cb_data;
+- char *validate_request_str = NULL;
+- char *request = NULL;
+- gboolean use_whole_url = FALSE;
+- xmlnode *validate_request_root = NULL;
+- xmlnode *validate_request_child = NULL;
+-
+- if(!(sms_cb_data = data))
+- return;
+-
+- validate_request_root = xmlnode_new("validate");
+- xmlnode_set_attrib(validate_request_root, "intl", "us");
+- xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION);
+- xmlnode_set_attrib(validate_request_root, "qos", "0");
+-
+- validate_request_child = xmlnode_new_child(validate_request_root, "mobile_no");
+- xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1);
+-
+- validate_request_str = xmlnode_to_str(validate_request_root, NULL);
+-
+- xmlnode_free(validate_request_child);
+- xmlnode_free(validate_request_root);
+-
+- request = g_strdup_printf(
+- "POST /mobileno?intl=us&version=%s HTTP/1.1\r\n"
+- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s; path=/; domain=.yahoo.com;\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: validate.msg.yahoo.com\r\n"
+- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
+- "Cache-Control: no-cache\r\n\r\n%s",
+- YAHOO_CLIENT_VERSION, yd->cookie_t, yd->cookie_y, strlen(validate_request_str), validate_request_str);
+-
+- /* use whole URL if using HTTP Proxy */
+- if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+- use_whole_url = TRUE;
+-
+- url_data = purple_util_fetch_url_request_len_with_account(
+- purple_connection_get_account(gc), YAHOO_SMS_CARRIER_URL, use_whole_url,
+- YAHOO_CLIENT_USERAGENT, TRUE, request, FALSE, -1,
+- yahoo_get_sms_carrier_cb, data);
+-
+- g_free(request);
+- g_free(validate_request_str);
+-
+- if (url_data)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- else {
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, sms_cb_data->who, account);
+- purple_conversation_write(conv, NULL, _("Can't send SMS. Unable to obtain mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(sms_cb_data->who);
+- g_free(sms_cb_data->what);
+- g_free(sms_cb_data);
+- }
+-}
+-
+-int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt = NULL;
+- char *msg = yahoo_html_to_codes(what);
+- char *msg2;
+- gboolean utf8 = TRUE;
+- PurpleWhiteboard *wb;
+- int ret = 1;
+- const char *fed_who;
+- gsize lenb = 0;
+- glong lenc = 0;
+- struct yahoo_p2p_data *p2p_data;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+- msg2 = yahoo_string_encode(gc, msg, &utf8);
+-
+- if(msg2) {
+- lenb = strlen(msg2);
+- lenc = g_utf8_strlen(msg2, -1);
+-
+- if(lenb > YAHOO_MAX_MESSAGE_LENGTH_BYTES || lenc > YAHOO_MAX_MESSAGE_LENGTH_CHARS) {
+- purple_debug_info("yahoo", "Message too big. Length is %" G_GSIZE_FORMAT
+- " bytes, %ld characters. Max is %d bytes, %d chars."
+- " Message is '%s'.\n", lenb, lenc, YAHOO_MAX_MESSAGE_LENGTH_BYTES,
+- YAHOO_MAX_MESSAGE_LENGTH_CHARS, msg2);
+- g_free(msg);
+- g_free(msg2);
+- return -E2BIG;
+- }
+- }
+-
+- fed = yahoo_get_federation_from_name(who);
+-
+- if (who[0] == '+') {
+- /* we have an sms to be sent */
+- gchar *carrier = NULL;
+- const char *alias = NULL;
+- PurpleAccount *account = purple_connection_get_account(gc);
+- PurpleConversation *conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, who, account);
+-
+- carrier = g_hash_table_lookup(yd->sms_carrier, who);
+- if (!carrier) {
+- struct yahoo_sms_carrier_cb_data *sms_cb_data;
+- sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data));
+- sms_cb_data->gc = gc;
+- sms_cb_data->who = g_strdup(who);
+- sms_cb_data->what = g_strdup(what);
+-
+- purple_conversation_write(conv, NULL, _("Getting mobile carrier to send the SMS."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+-
+- yahoo_get_sms_carrier(gc, sms_cb_data);
+-
+- g_free(msg);
+- g_free(msg2);
+- return ret;
+- }
+- else if( strcmp(carrier,"Unknown") == 0 ) {
+- purple_conversation_write(conv, NULL, _("Can't send SMS. Unknown mobile carrier."), PURPLE_MESSAGE_SYSTEM, time(NULL));
+-
+- g_free(msg);
+- g_free(msg2);
+- return -1;
+- }
+-
+- alias = purple_account_get_alias(account);
+- pkt = yahoo_packet_new(YAHOO_SERVICE_SMS_MSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sssss",
+- 1, purple_connection_get_display_name(gc),
+- 69, alias,
+- 5, who + 1,
+- 68, carrier,
+- 14, msg2);
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(msg);
+- g_free(msg2);
+-
+- return ret;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_MESSAGE, YAHOO_STATUS_OFFLINE, yd->session_id);
+- fed_who = who;
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- case YAHOO_FEDERATION_OCS:
+- case YAHOO_FEDERATION_IBM:
+- case YAHOO_FEDERATION_PBX:
+- fed_who += 4;
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- break;
+- }
+- yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, fed_who);
+- if (fed)
+- yahoo_packet_hash_int(pkt, 241, fed);
+-
+- if (utf8)
+- yahoo_packet_hash_str(pkt, 97, "1");
+- yahoo_packet_hash_str(pkt, 14, msg2);
+-
+- /*
+- * IMVironment.
+- *
+- * If this message is to a user who is also Doodling with the local user,
+- * format the chat packet with the correct IMV information (thanks Yahoo!)
+- *
+- * Otherwise attempt to use the same IMVironment as the remote user,
+- * just so that we don't inadvertantly reset their IMVironment back
+- * to nothing.
+- *
+- * If they have not set an IMVironment, then use the default.
+- */
+- wb = purple_whiteboard_get_session(gc->account, who);
+- if (wb)
+- yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY);
+- else
+- {
+- const char *imv;
+- imv = g_hash_table_lookup(yd->imvironments, who);
+- if (imv != NULL)
+- yahoo_packet_hash_str(pkt, 63, imv);
+- else
+- yahoo_packet_hash_str(pkt, 63, ";0");
+- }
+-
+- yahoo_packet_hash_str(pkt, 64, "0"); /* no idea */
+- yahoo_packet_hash_str(pkt, 1002, "1"); /* no idea, Yahoo 6 or later only it seems */
+- if (!yd->picture_url)
+- yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */
+- else
+- yahoo_packet_hash_str(pkt, 206, "2");
+-
+- /* We may need to not send any packets over 2000 bytes, but I'm not sure yet. */
+- if ((YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt)) <= 2000) {
+- /* if p2p link exists, send through it. To-do: key 15, time value to be sent in case of p2p */
+- if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
+- yahoo_packet_hash_int(pkt, 11, p2p_data->session_id);
+- yahoo_p2p_write_pkt(p2p_data->source, pkt);
+- }
+- else {
+- yahoo_packet_send(pkt, yd);
+- if(!fed)
+- yahoo_send_p2p_pkt(gc, who, 0); /* send p2p packet, with val_13=0 */
+- }
+- }
+- else
+- ret = -E2BIG;
+-
+- yahoo_packet_free(pkt);
+-
+- g_free(msg);
+- g_free(msg2);
+-
+- return ret;
+-}
+-
+-unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_p2p_data *p2p_data;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+- struct yahoo_packet *pkt = NULL;
+-
+- fed = yahoo_get_federation_from_name(who);
+-
+- /* Don't do anything if sms is being typed */
+- if( strncmp(who, "+", 1) == 0 )
+- return 0;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_NOTIFY, YAHOO_STATUS_TYPING, yd->session_id);
+-
+- /* check to see if p2p link exists, send through it */
+- if( (p2p_data = g_hash_table_lookup(yd->peers, who)) && !fed) {
+- yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc),
+- 14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
+- 5, who, 11, p2p_data->session_id, 1002, "1"); /* To-do: key 15 to be sent in case of p2p */
+- yahoo_p2p_write_pkt(p2p_data->source, pkt);
+- yahoo_packet_free(pkt);
+- }
+- else { /* send through yahoo server */
+-
+- const char *fed_who = who;
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- case YAHOO_FEDERATION_OCS:
+- case YAHOO_FEDERATION_IBM:
+- case YAHOO_FEDERATION_PBX:
+- fed_who += 4;
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- break;
+- }
+-
+- yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc),
+- 14, " ", 13, state == PURPLE_TYPING ? "1" : "0",
+- 5, fed_who, 1002, "1");
+- if (fed)
+- yahoo_packet_hash_int(pkt, 241, fed);
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-
+- return 0;
+-}
+-
+-static void yahoo_session_presence_remove(gpointer key, gpointer value, gpointer data)
+-{
+- YahooFriend *f = value;
+- if (f && f->presence == YAHOO_PRESENCE_ONLINE)
+- f->presence = YAHOO_PRESENCE_DEFAULT;
+-}
+-
+-void yahoo_set_status(PurpleAccount *account, PurpleStatus *status)
+-{
+- PurpleConnection *gc;
+- PurplePresence *presence;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+- int old_status;
+- const char *msg = NULL;
+- char *tmp = NULL;
+- char *conv_msg = NULL;
+- gboolean utf8 = TRUE;
+-
+- if (!purple_status_is_active(status))
+- return;
+-
+- gc = purple_account_get_connection(account);
+- presence = purple_status_get_presence(status);
+- yd = (YahooData *)gc->proto_data;
+- old_status = yd->current_status;
+-
+- yd->current_status = get_yahoo_status_from_purple_status(status);
+-
+- if (yd->current_status == YAHOO_STATUS_CUSTOM)
+- {
+- msg = purple_status_get_attr_string(status, "message");
+-
+- if (purple_status_is_available(status)) {
+- tmp = yahoo_string_encode(gc, msg, &utf8);
+- conv_msg = purple_markup_strip_html(tmp);
+- g_free(tmp);
+- } else {
+- if ((msg == NULL) || (*msg == '\0'))
+- msg = _("Away");
+- tmp = yahoo_string_encode(gc, msg, &utf8);
+- conv_msg = purple_markup_strip_html(tmp);
+- g_free(tmp);
+- }
+- }
+-
+- if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 13, "2");
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_int(pkt, 10, yd->current_status);
+-
+- if (yd->current_status == YAHOO_STATUS_CUSTOM) {
+- yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
+- yahoo_packet_hash_str(pkt, 19, conv_msg);
+- } else {
+- yahoo_packet_hash_str(pkt, 19, "");
+- }
+-
+- g_free(conv_msg);
+-
+- if (purple_presence_is_idle(presence))
+- yahoo_packet_hash_str(pkt, 47, "2");
+- else {
+- if (!purple_status_is_available(status))
+- yahoo_packet_hash_str(pkt, 47, "1");
+- else
+- yahoo_packet_hash_str(pkt, 47, "0");
+- }
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- if (old_status == YAHOO_STATUS_INVISIBLE) {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_VISIBLE_TOGGLE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 13, "1");
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- /* Any per-session presence settings are removed */
+- g_hash_table_foreach(yd->friends, yahoo_session_presence_remove, NULL);
+-
+- }
+-}
+-
+-void yahoo_set_idle(PurpleConnection *gc, int idle)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt = NULL;
+- char *msg = NULL, *msg2 = NULL;
+- PurpleStatus *status = NULL;
+- gboolean invisible = FALSE;
+-
+- if (idle && yd->current_status != YAHOO_STATUS_CUSTOM)
+- yd->current_status = YAHOO_STATUS_IDLE;
+- else if (!idle && yd->current_status == YAHOO_STATUS_IDLE) {
+- status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
+- yd->current_status = get_yahoo_status_from_purple_status(status);
+- }
+-
+- invisible = (yd->current_status == YAHOO_STATUS_INVISIBLE);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_Y6_STATUS_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- if (!idle && invisible)
+- yahoo_packet_hash_int(pkt, 10, YAHOO_STATUS_AVAILABLE);
+- else
+- yahoo_packet_hash_int(pkt, 10, yd->current_status);
+-
+- if (yd->current_status == YAHOO_STATUS_CUSTOM) {
+- const char *tmp;
+- if (status == NULL)
+- status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
+- tmp = purple_status_get_attr_string(status, "message");
+- if (tmp != NULL) {
+- gboolean utf8 = TRUE;
+- msg = yahoo_string_encode(gc, tmp, &utf8);
+- msg2 = purple_markup_strip_html(msg);
+- yahoo_packet_hash_str(pkt, 97, utf8 ? "1" : 0);
+- yahoo_packet_hash_str(pkt, 19, msg2);
+- } else {
+- /* get_yahoo_status_from_purple_status() returns YAHOO_STATUS_CUSTOM for
+- * the generic away state (YAHOO_STATUS_TYPE_AWAY) with no message */
+- yahoo_packet_hash_str(pkt, 19, _("Away"));
+- }
+- } else {
+- yahoo_packet_hash_str(pkt, 19, "");
+- }
+-
+- if (idle)
+- yahoo_packet_hash_str(pkt, 47, "2");
+- else if (yd->current_status == YAHOO_STATUS_CUSTOM &&
+- !purple_status_is_available(status))
+- /* We are still unavailable in this case.
+- * Make sure Yahoo knows that */
+- yahoo_packet_hash_str(pkt, 47, "1");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(msg);
+- g_free(msg2);
+-}
+-
+-GList *yahoo_status_types(PurpleAccount *account)
+-{
+- PurpleStatusType *type;
+- GList *types = NULL;
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AVAILABLE, YAHOO_STATUS_TYPE_AVAILABLE,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_AWAY,
+- NULL, TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_BRB, _("Be Right Back"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_with_attrs(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_BUSY,
+- _("Busy"), TRUE, TRUE, FALSE,
+- "message", _("Message"),
+- purple_value_new(PURPLE_TYPE_STRING), NULL);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATHOME, _("Not at Home"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTATDESK, _("Not at Desk"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_NOTINOFFICE, _("Not in Office"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_UNAVAILABLE, YAHOO_STATUS_TYPE_ONPHONE, _("On the Phone"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_EXTENDED_AWAY, YAHOO_STATUS_TYPE_ONVACATION, _("On Vacation"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_OUTTOLUNCH, _("Out to Lunch"), TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_AWAY, YAHOO_STATUS_TYPE_STEPPEDOUT, _("Stepped Out"), TRUE);
+- types = g_list_append(types, type);
+-
+-
+- type = purple_status_type_new(PURPLE_STATUS_INVISIBLE, YAHOO_STATUS_TYPE_INVISIBLE, NULL, TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new(PURPLE_STATUS_OFFLINE, YAHOO_STATUS_TYPE_OFFLINE, NULL, TRUE);
+- types = g_list_append(types, type);
+-
+- type = purple_status_type_new_full(PURPLE_STATUS_MOBILE, YAHOO_STATUS_TYPE_MOBILE, NULL, FALSE, FALSE, TRUE);
+- types = g_list_append(types, type);
+-
+- return types;
+-}
+-
+-void yahoo_keepalive(PurpleConnection *gc)
+-{
+- struct yahoo_packet *pkt;
+- YahooData *yd = gc->proto_data;
+- time_t now = time(NULL);
+-
+- /* We're only allowed to send a ping once an hour or the servers will boot us */
+- if ((now - yd->last_ping) >= PING_TIMEOUT) {
+- yd->last_ping = now;
+-
+- /* The native client will only send PING or CHATPING */
+- if (yd->chat_online) {
+- if (yd->wm) {
+- ycht_chat_send_keepalive(yd->ycht);
+- } else {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATPING, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 109, purple_connection_get_display_name(gc));
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+- } else {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PING, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+- }
+-
+- if ((now - yd->last_keepalive) >= KEEPALIVE_TIMEOUT) {
+- yd->last_keepalive = now;
+- pkt = yahoo_packet_new(YAHOO_SERVICE_KEEPALIVE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-
+-}
+-
+-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g)
+-{
+- YahooData *yd = (YahooData *)gc->proto_data;
+- struct yahoo_packet *pkt;
+- const char *group = NULL;
+- char *group2;
+- const char *bname;
+- const char *fed_bname;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- if (!yd->logged_in)
+- return;
+-
+- fed_bname = bname = purple_buddy_get_name(buddy);
+- if (!purple_privacy_check(purple_connection_get_account(gc), bname))
+- return;
+-
+- fed = yahoo_get_federation_from_name(bname);
+- if (fed != YAHOO_FEDERATION_NONE)
+- fed_bname += 4;
+-
+- g = purple_buddy_get_group(buddy);
+- if (g)
+- group = purple_group_get_name(g);
+- else
+- group = "Buddies";
+-
+- group2 = yahoo_string_encode(gc, group, NULL);
+- pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- if (fed) {
+- yahoo_packet_hash(pkt, "sssssssisss",
+- 14, "",
+- 65, group2,
+- 97, "1",
+- 1, purple_connection_get_display_name(gc),
+- 302, "319",
+- 300, "319",
+- 7, fed_bname,
+- 241, fed,
+- 334, "0",
+- 301, "319",
+- 303, "319"
+- );
+- }
+- else {
+- yahoo_packet_hash(pkt, "ssssssssss",
+- 14, "",
+- 65, group2,
+- 97, "1",
+- 1, purple_connection_get_display_name(gc),
+- 302, "319",
+- 300, "319",
+- 7, fed_bname,
+- 334, "0",
+- 301, "319",
+- 303, "319"
+- );
+- }
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(group2);
+-}
+-
+-void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
+-{
+- YahooData *yd = (YahooData *)gc->proto_data;
+- struct yahoo_packet *pkt;
+- GSList *buddies, *l;
+- PurpleGroup *g;
+- gboolean remove = TRUE;
+- char *cg;
+- const char *bname, *gname;
+- YahooFriend *f = NULL;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- bname = purple_buddy_get_name(buddy);
+- f = yahoo_friend_find(gc, bname);
+- if (!f)
+- return;
+- fed = f->fed;
+-
+- gname = purple_group_get_name(group);
+- buddies = purple_find_buddies(purple_connection_get_account(gc), bname);
+- for (l = buddies; l; l = l->next) {
+- g = purple_buddy_get_group(l->data);
+- if (purple_utf8_strcasecmp(gname, purple_group_get_name(g))) {
+- remove = FALSE;
+- break;
+- }
+- }
+-
+- g_slist_free(buddies);
+-
+- if (remove) {
+- g_hash_table_remove(yd->friends, bname);
+- f = NULL; /* f no longer valid - Just making it clear */
+- }
+-
+- cg = yahoo_string_encode(gc, gname, NULL);
+- pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- case YAHOO_FEDERATION_OCS:
+- case YAHOO_FEDERATION_IBM:
+- bname += 4;
+- break;
+- case YAHOO_FEDERATION_NONE:
+- default:
+- break;
+- }
+-
+- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
+- 7, bname, 65, cg);
+- if (fed)
+- yahoo_packet_hash_int(pkt, 241, fed);
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(cg);
+-}
+-
+-void yahoo_add_deny(PurpleConnection *gc, const char *who) {
+- YahooData *yd = (YahooData *)gc->proto_data;
+- struct yahoo_packet *pkt;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- if (!yd->logged_in)
+- return;
+-
+- if (!who || who[0] == '\0')
+- return;
+-
+- fed = yahoo_get_federation_from_name(who);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- if(fed)
+- yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "1");
+- else
+- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "1");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_rem_deny(PurpleConnection *gc, const char *who) {
+- YahooData *yd = (YahooData *)gc->proto_data;
+- struct yahoo_packet *pkt;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- if (!yd->logged_in)
+- return;
+-
+- if (!who || who[0] == '\0')
+- return;
+- fed = yahoo_get_federation_from_name(who);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- if(fed)
+- yahoo_packet_hash(pkt, "ssis", 1, purple_connection_get_display_name(gc), 7, who+4, 241, fed, 13, "2");
+- else
+- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), 7, who, 13, "2");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_set_permit_deny(PurpleConnection *gc)
+-{
+- PurpleAccount *account;
+- GSList *deny;
+-
+- account = purple_connection_get_account(gc);
+-
+- switch (account->perm_deny)
+- {
+- case PURPLE_PRIVACY_ALLOW_ALL:
+- for (deny = account->deny; deny; deny = deny->next)
+- yahoo_rem_deny(gc, deny->data);
+- break;
+-
+- case PURPLE_PRIVACY_ALLOW_BUDDYLIST:
+- case PURPLE_PRIVACY_ALLOW_USERS:
+- case PURPLE_PRIVACY_DENY_USERS:
+- case PURPLE_PRIVACY_DENY_ALL:
+- for (deny = account->deny; deny; deny = deny->next)
+- yahoo_add_deny(gc, deny->data);
+- break;
+- }
+-}
+-
+-void yahoo_change_buddys_group(PurpleConnection *gc, const char *who,
+- const char *old_group, const char *new_group)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- char *gpn, *gpo;
+- YahooFriend *f = yahoo_friend_find(gc, who);
+- const char *temp = NULL;
+-
+- /* Step 0: If they aren't on the server list anyway,
+- * don't bother letting the server know.
+- */
+- if (!f)
+- return;
+-
+- if(f->fed) {
+- temp = who+4;
+- } else
+- temp = who;
+-
+- /* If old and new are the same, we would probably
+- * end up deleting the buddy, which would be bad.
+- * This might happen because of the charset conversation.
+- */
+- gpn = yahoo_string_encode(gc, new_group, NULL);
+- gpo = yahoo_string_encode(gc, old_group, NULL);
+- if (!strcmp(gpn, gpo)) {
+- g_free(gpn);
+- g_free(gpo);
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHGRP_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- if(f->fed)
+- yahoo_packet_hash(pkt, "ssssissss", 1, purple_connection_get_display_name(gc),
+- 302, "240", 300, "240", 7, temp, 241, f->fed, 224, gpo, 264, gpn, 301,
+- "240", 303, "240");
+- else
+- yahoo_packet_hash(pkt, "ssssssss", 1, purple_connection_get_display_name(gc),
+- 302, "240", 300, "240", 7, temp, 224, gpo, 264, gpn, 301,
+- "240", 303, "240");
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(gpn);
+- g_free(gpo);
+-}
+-
+-void yahoo_rename_group(PurpleConnection *gc, const char *old_name,
+- PurpleGroup *group, GList *moved_buddies)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- char *gpn, *gpo;
+-
+- gpn = yahoo_string_encode(gc, purple_group_get_name(group), NULL);
+- gpo = yahoo_string_encode(gc, old_name, NULL);
+- if (!strcmp(gpn, gpo)) {
+- g_free(gpn);
+- g_free(gpo);
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_GROUPRENAME, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc),
+- 65, gpo, 67, gpn);
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(gpn);
+- g_free(gpo);
+-}
+-
+-/********************************* Commands **********************************/
+-
+-PurpleCmdRet
+-yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) {
+- PurpleAccount *account = purple_conversation_get_account(c);
+-
+- if (*args && args[0])
+- return PURPLE_CMD_RET_FAILED;
+-
+- purple_prpl_send_attention(account->gc, c->name, YAHOO_BUZZ);
+-
+- return PURPLE_CMD_RET_OK;
+-}
+-
+-PurpleCmdRet
+-yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd,
+- char **args, char **error, void *data)
+-{
+- GHashTable *comp;
+- PurpleConnection *gc;
+-
+- if (!args || !args[0])
+- return PURPLE_CMD_RET_FAILED;
+-
+- gc = purple_conversation_get_gc(conv);
+- purple_debug_info("yahoo", "Trying to join %s \n", args[0]);
+-
+- comp = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- g_hash_table_replace(comp, g_strdup("room"), g_ascii_strdown(args[0], -1));
+- g_hash_table_replace(comp, g_strdup("type"), g_strdup("Chat"));
+-
+- yahoo_c_join(gc, comp);
+-
+- g_hash_table_destroy(comp);
+- return PURPLE_CMD_RET_OK;
+-}
+-
+-PurpleCmdRet
+-yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd,
+- char **args, char **error, void *data)
+-{
+- PurpleAccount *account = purple_conversation_get_account(conv);
+- if (*args && args[0])
+- return PURPLE_CMD_RET_FAILED;
+- purple_roomlist_show_with_account(account);
+- return PURPLE_CMD_RET_OK;
+-}
+-
+-gboolean yahoo_offline_message(const PurpleBuddy *buddy)
+-{
+- return TRUE;
+-}
+-
+-gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type)
+-{
+- PurpleConversation *c;
+-
+- c = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM,
+- username, gc->account);
+-
+- g_return_val_if_fail(c != NULL, FALSE);
+-
+- purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n",
+- username, c->name);
+- purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "<ding>", PURPLE_MESSAGE_INVISIBLE);
+-
+- return TRUE;
+-}
+-
+-GList *yahoo_attention_types(PurpleAccount *account)
+-{
+- static GList *list = NULL;
+-
+- if (!list) {
+- /* Yahoo only supports one attention command: the 'buzz'. */
+- /* This is index number YAHOO_BUZZ. */
+- list = g_list_append(list, purple_attention_type_new("Buzz", _("Buzz"),
+- _("%s has buzzed you!"), _("Buzzing %s...")));
+- }
+-
+- return list;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/libymsg.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/libymsg.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,402 +0,0 @@
+-/**
+- * @file libymsg.h The Yahoo! and Yahoo! JAPAN Protocol Plugins
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _LIBYMSG_H_
+-#define _LIBYMSG_H_
+-
+-#include "circbuffer.h"
+-#include "cmds.h"
+-#include "prpl.h"
+-#include "network.h"
+-
+-#define YAHOO_PAGER_HOST_REQ_URL "http://vcs1.msg.yahoo.com/capacity"
+-#define YAHOO_PAGER_HOST_FALLBACK "scsa.msg.yahoo.com"
+-#define YAHOO_PAGER_PORT 5050
+-#define YAHOO_PAGER_PORT_P2P 5101
+-#define YAHOO_LOGIN_URL "https://login.yahoo.com/config/pwtoken_login?src=ymsgr&ts=&token=%s"
+-#define YAHOO_TOKEN_URL "https://login.yahoo.com/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
+-#define YAHOO_P2P_KEEPALIVE_SECS 300
+-#define YAHOO_P2P_SERVER_TIMEOUT 10
+-#define YAHOO_PROFILE_URL "http://profiles.yahoo.com/"
+-#define YAHOO_MAIL_URL "http://rd.yahoo.com/messenger/client/?http://mail.yahoo.com/"
+-#define YAHOO_XFER_HOST "filetransfer.msg.yahoo.com"
+-#define YAHOO_XFER_PORT 80
+-#define YAHOO_XFER_RELAY_HOST "relay.msg.yahoo.com"
+-#define YAHOO_XFER_RELAY_PORT 80
+-#define YAHOO_ROOMLIST_URL "http://insider.msg.yahoo.com/ycontent/"
+-#define YAHOO_ROOMLIST_LOCALE "us"
+-
+-/* Yahoo! JAPAN stuff */
+-#define YAHOOJP_PAGER_HOST_REQ_URL "http://cs1.yahoo.co.jp/capacity"
+-#define YAHOOJP_TOKEN_URL "https://login.yahoo.co.jp/config/pwtoken_get?src=ymsgr&ts=&login=%s&passwd=%s&chal=%s"
+-#define YAHOOJP_LOGIN_URL "https://login.yahoo.co.jp/config/pwtoken_login?src=ymsgr&ts=&token=%s"
+-#define YAHOOJP_PROFILE_URL "http://profiles.yahoo.co.jp/"
+-#define YAHOOJP_MAIL_URL "http://mail.yahoo.co.jp/"
+-#define YAHOOJP_XFER_HOST "filetransfer.msg.yahoo.co.jp"
+-#define YAHOOJP_WEBCAM_HOST "wc.yahoo.co.jp"
+-/* not sure, must test: */
+-#define YAHOOJP_XFER_RELAY_HOST "relay.msg.yahoo.co.jp"
+-#define YAHOOJP_XFER_RELAY_PORT 80
+-#define YAHOOJP_ROOMLIST_URL "http://insider.msg.yahoo.co.jp/ycontent/"
+-#define YAHOOJP_ROOMLIST_LOCALE "ja"
+-
+-#define YAHOO_AUDIBLE_URL "http://l.yimg.com/pu/dl/aud"
+-
+-#define WEBMESSENGER_URL "http://login.yahoo.com/config/login?.src=pg"
+-
+-#define YAHOO_SMS_CARRIER_URL "http://validate.msg.yahoo.com"
+-
+-#define YAHOO_USERINFO_URL "http://address.yahoo.com/yab/us?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
+-#define YAHOOJP_USERINFO_URL "http://address.yahoo.co.jp/yab/jp?v=XM&sync=1&tags=short&useutf8=1&noclear=1&legenc=codepage-1252"
+-
+-#define YAHOO_PICURL_SETTING "picture_url"
+-#define YAHOO_PICCKSUM_SETTING "picture_checksum"
+-#define YAHOO_PICEXPIRE_SETTING "picture_expire"
+-
+-#define YAHOO_STATUS_TYPE_OFFLINE "offline"
+-#define YAHOO_STATUS_TYPE_AVAILABLE "available"
+-#define YAHOO_STATUS_TYPE_BRB "brb"
+-#define YAHOO_STATUS_TYPE_BUSY "busy"
+-#define YAHOO_STATUS_TYPE_NOTATHOME "notathome"
+-#define YAHOO_STATUS_TYPE_NOTATDESK "notatdesk"
+-#define YAHOO_STATUS_TYPE_NOTINOFFICE "notinoffice"
+-#define YAHOO_STATUS_TYPE_ONPHONE "onphone"
+-#define YAHOO_STATUS_TYPE_ONVACATION "onvacation"
+-#define YAHOO_STATUS_TYPE_OUTTOLUNCH "outtolunch"
+-#define YAHOO_STATUS_TYPE_STEPPEDOUT "steppedout"
+-#define YAHOO_STATUS_TYPE_AWAY "away"
+-#define YAHOO_STATUS_TYPE_INVISIBLE "invisible"
+-#define YAHOO_STATUS_TYPE_MOBILE "mobile"
+-
+-#define YAHOO_CLIENT_VERSION_ID "4194239"
+-#define YAHOO_CLIENT_VERSION "9.0.0.2162"
+-
+-#define YAHOOJP_CLIENT_VERSION_ID "4186047"
+-#define YAHOOJP_CLIENT_VERSION "9.0.0.1727"
+-
+-#define YAHOO_CLIENT_USERAGENT "Mozilla/5.0"
+-#define YAHOO_CLIENT_USERAGENT_ALIAS "Mozilla/4.0 (compatible; MSIE 5.5)"
+-
+-/* Index into attention types list. */
+-#define YAHOO_BUZZ 0
+-
+-typedef enum {
+- YAHOO_PKT_TYPE_SERVER = 0,
+- YAHOO_PKT_TYPE_P2P
+-} yahoo_pkt_type;
+-
+-typedef enum {
+- YAHOO_P2P_WE_ARE_CLIENT =0,
+- YAHOO_P2P_WE_ARE_SERVER
+-} yahoo_p2p_connection_type;
+-
+-enum yahoo_status {
+- YAHOO_STATUS_AVAILABLE = 0,
+- YAHOO_STATUS_BRB,
+- YAHOO_STATUS_BUSY,
+- YAHOO_STATUS_NOTATHOME,
+- YAHOO_STATUS_NOTATDESK,
+- YAHOO_STATUS_NOTINOFFICE,
+- YAHOO_STATUS_ONPHONE,
+- YAHOO_STATUS_ONVACATION,
+- YAHOO_STATUS_OUTTOLUNCH,
+- YAHOO_STATUS_STEPPEDOUT,
+- YAHOO_STATUS_P2P = 11,
+- YAHOO_STATUS_INVISIBLE = 12,
+- YAHOO_STATUS_CUSTOM = 99,
+- YAHOO_STATUS_IDLE = 999,
+- YAHOO_STATUS_WEBLOGIN = 0x5a55aa55,
+- YAHOO_STATUS_OFFLINE = 0x5a55aa56, /* don't ask */
+- YAHOO_STATUS_TYPING = 0x16,
+- YAHOO_STATUS_DISCONNECTED = 0xffffffff /* in ymsg 15. doesnt mean the normal sense of 'disconnected' */
+-};
+-
+-/*
+- * Yahoo federated networks. Key 241 in ymsg.
+- * If it doesn't exist, it is on Yahoo's netowrk.
+- * It if does exist, send to another IM network.
+- */
+-
+-typedef enum {
+- YAHOO_FEDERATION_NONE = 0, /* No federation - Yahoo! network */
+- YAHOO_FEDERATION_OCS = 1, /* LCS or OCS private networks */
+- YAHOO_FEDERATION_MSN = 2, /* MSN or Windows Live network */
+- YAHOO_FEDERATION_IBM = 9, /* IBM/Sametime network */
+- YAHOO_FEDERATION_PBX = 100 /* Yahoo! Pingbox service */
+-} YahooFederation;
+-
+-
+-struct yahoo_buddy_icon_upload_data {
+- PurpleConnection *gc;
+- GString *str;
+- char *filename;
+- int pos;
+- int fd;
+- guint watcher;
+-};
+-
+-struct yahoo_p2p_data {
+- PurpleConnection *gc;
+- char *host_ip;
+- char *host_username;
+- int val_13;
+- guint input_event;
+- gint source;
+- int session_id;
+- yahoo_p2p_connection_type connection_type;
+-};
+-
+-struct _YchtConn;
+-
+-typedef struct _YahooPersonalDetails {
+- char *id;
+-
+- struct {
+- char *first;
+- char *last;
+- char *middle;
+- char *nick;
+- } names;
+-
+- struct {
+- char *work;
+- char *home;
+- char *mobile;
+- } phone;
+-} YahooPersonalDetails;
+-
+-typedef struct {
+- PurpleConnection *gc;
+- int fd;
+- guchar *rxqueue;
+- int rxlen;
+- PurpleCircBuffer *txbuf;
+- guint txhandler;
+- GHashTable *friends;
+-
+- char **profiles; /* Multiple profiles can be associated with an account */
+- YahooPersonalDetails ypd;
+-
+- /**
+- * This is used to keep track of the IMVironment chosen
+- * by people you talk to. We don't do very much with
+- * this right now... but at least now if the remote user
+- * selects an IMVironment we won't reset it back to the
+- * default of nothing.
+- */
+- GHashTable *imvironments;
+-
+- int current_status;
+- gboolean logged_in;
+- GString *tmp_serv_blist, *tmp_serv_ilist, *tmp_serv_plist;
+- GSList *confs;
+- unsigned int conf_id; /* just a counter */
+- gboolean chat_online;
+- gboolean in_chat;
+- char *chat_name;
+- char *pending_chat_room;
+- char *pending_chat_id;
+- char *pending_chat_topic;
+- char *pending_chat_goto;
+- char *auth;
+- gsize auth_written;
+- char *cookie_y;
+- char *cookie_t;
+- char *cookie_b;
+- int session_id;
+- gboolean jp;
+- gboolean wm; /* connected w/ web messenger method */
+- /* picture aka buddy icon stuff */
+- char *picture_url;
+- int picture_checksum;
+-
+- /* ew. we have to check the icon before we connect,
+- * but can't upload it til we're connected. */
+- struct yahoo_buddy_icon_upload_data *picture_upload_todo;
+- PurpleProxyConnectData *buddy_icon_connect_data;
+-
+- struct _YchtConn *ycht;
+-
+- /**
+- * This linked list contains PurpleUtilFetchUrlData structs
+- * for when we lookup people profile or photo information.
+- */
+- GSList *url_datas;
+- GHashTable *xfer_peer_idstring_map;/* Hey, i dont know, but putting this HashTable next to friends gives a run time fault... */
+- GSList *cookies;/* contains all cookies, including _y and _t */
+- PurpleNetworkListenData *listen_data;
+-
+- /**
+- * We may receive a list15 in multiple packets with no prior warning as to how many we'll be getting;
+- * the server expects us to keep track of the group for which it is sending us contact names.
+- */
+- char *current_list15_grp;
+- time_t last_ping;
+- time_t last_keepalive;
+- GHashTable *peers; /* information about p2p data */
+- int yahoo_p2p_timer;
+- int yahoo_local_p2p_server_fd;
+- int yahoo_p2p_server_watcher;
+- GHashTable *sms_carrier; /* sms carrier data */
+- guint yahoo_p2p_server_timeout_handle;
+-} YahooData;
+-
+-#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255)
+-
+-/*
+- * Current Maximum Length for Instant Messages
+- *
+- * This was found by experiment.
+- *
+- * The YMSG protocol allows a message of up to 948 bytes, but the official client
+- * limits to 800 characters. According to experiments I conducted, it seems that
+- * the discrepancy is to allow some leeway for messages with mixed single- and
+- * multi-byte characters, as I was able to send messages of 840 and 932 bytes
+- * by using some multibyte characters (some random Chinese or Japanese characters,
+- * to be precise). - rekkanoryo
+- */
+-#define YAHOO_MAX_MESSAGE_LENGTH_BYTES 948
+-#define YAHOO_MAX_MESSAGE_LENGTH_CHARS 800
+-
+-/* sometimes i wish prpls could #include things from other prpls. then i could just
+- * use the routines from libfaim and not have to admit to knowing how they work. */
+-#define yahoo_put16(buf, data) ( \
+- (*(buf) = (unsigned char)((data)>>8)&0xff), \
+- (*((buf)+1) = (unsigned char)(data)&0xff), \
+- 2)
+-#define yahoo_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff))
+-#define yahoo_put32(buf, data) ( \
+- (*((buf)) = (unsigned char)((data)>>24)&0xff), \
+- (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \
+- (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \
+- (*((buf)+3) = (unsigned char)(data)&0xff), \
+- 4)
+-#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \
+- (((*((buf)+1))<<16)&0x00ff0000) + \
+- (((*((buf)+2))<< 8)&0x0000ff00) + \
+- (((*((buf)+3) )&0x000000ff)))
+-
+-/* util.c */
+-void yahoo_init_colorht(void);
+-void yahoo_dest_colorht(void);
+-char *yahoo_codes_to_html(const char *x);
+-
+-/**
+- * This function takes a normal HTML message and converts it to the message
+- * format used by Yahoo, which uses a frankensteinish combination of ANSI
+- * escape codes and broken HTML.
+- *
+- * It results in slightly different output than would be sent by official
+- * Yahoo clients. The two main differences are:
+- *
+- * 1. We always close all tags, whereas official Yahoo clients leave tags
+- * dangling open at the end of each message (and the client treats them
+- * as closed).
+- * 2. We always close inner tags first before closing outter tags.
+- *
+- * For example, if you want to send this message:
+- * <b> bold <i> bolditalic </i></b><i> italic </i>
+- * Official Yahoo clients would send:
+- * ESC[1m bold ESC[2m bolditalic ESC[x1m italic
+- * But we will send:
+- * ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m
+- */
+-char *yahoo_html_to_codes(const char *src);
+-
+-gboolean
+-yahoo_account_use_http_proxy(PurpleConnection *conn);
+-
+-/**
+- * Encode some text to send to the yahoo server.
+- *
+- * @param gc The connection handle.
+- * @param str The null terminated utf8 string to encode.
+- * @param utf8 If not @c NULL, whether utf8 is okay or not.
+- * Even if it is okay, we may not use it. If we
+- * used it, we set this to @c TRUE, else to
+- * @c FALSE. If @c NULL, false is assumed, and
+- * it is not dereferenced.
+- * @return The g_malloced string in the appropriate encoding.
+- */
+-char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8);
+-
+-/**
+- * Decode some text received from the server.
+- *
+- * @param gc The gc handle.
+- * @param str The null terminated string to decode.
+- * @param utf8 Did the server tell us it was supposed to be utf8?
+- * @return The decoded, utf-8 string, which must be g_free()'d.
+- */
+-char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8);
+-
+-char *yahoo_convert_to_numeric(const char *str);
+-
+-YahooFederation yahoo_get_federation_from_name(const char *who);
+-
+-/* yahoo_profile.c */
+-void yahoo_get_info(PurpleConnection *gc, const char *name);
+-
+-/* libymsg.h - these functions were formerly static but need not to be for the
+- * new two-prpl model. */
+-const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b);
+-const char *yahoo_list_emblem(PurpleBuddy *b);
+-char *yahoo_status_text(PurpleBuddy *b);
+-void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full);
+-GList *yahoo_status_types(PurpleAccount *account);
+-GList *yahoo_blist_node_menu(PurpleBlistNode *node);
+-void yahoo_login(PurpleAccount *account);
+-void yahoo_close(PurpleConnection *gc);
+-int yahoo_send_im(PurpleConnection *gc, const char *who, const char *what, PurpleMessageFlags flags);
+-unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleTypingState state);
+-void yahoo_set_status(PurpleAccount *account, PurpleStatus *status);
+-void yahoo_set_idle(PurpleConnection *gc, int idle);
+-void yahoo_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *g);
+-void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group);
+-void yahoo_add_deny(PurpleConnection *gc, const char *who);
+-void yahoo_rem_deny(PurpleConnection *gc, const char *who);
+-void yahoo_set_permit_deny(PurpleConnection *gc);
+-void yahoo_keepalive(PurpleConnection *gc);
+-void yahoo_change_buddys_group(PurpleConnection *gc, const char *who, const char *old_group, const char *new_group);
+-void yahoo_rename_group(PurpleConnection *gc, const char *old_name, PurpleGroup *group, GList *moved_buddies);
+-gboolean yahoo_offline_message(const PurpleBuddy *buddy);
+-gboolean yahoo_send_attention(PurpleConnection *gc, const char *username, guint type);
+-GList *yahoo_attention_types(PurpleAccount *account);
+-
+-GList *yahoo_actions(PurplePlugin *plugin, gpointer context);
+-void yahoopurple_register_commands(void);
+-
+-PurpleCmdRet yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data);
+-PurpleCmdRet yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
+-PurpleCmdRet yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data);
+-/* needed for xfer, thought theyd be useful for other enhancements later on
+- Returns list of cookies stored in yahoo_data formatted as a single null terminated string
+- returned value must be g_freed
+-*/
+-gchar* yahoo_get_cookies(PurpleConnection *gc);
+-
+-/* send p2p pkt containing our encoded ip, asking peer to connect to us */
+-void yahoo_send_p2p_pkt(PurpleConnection *gc, const char *who, int val_13);
+-
+-#endif /* _LIBYMSG_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.am pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.am
+--- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.am 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.am 1969-12-31 21:00:00.000000000 -0300
+@@ -1,60 +0,0 @@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-
+-YAHOOSOURCES = \
+- libymsg.c \
+- libymsg.h \
+- util.c \
+- yahoochat.h \
+- yahoochat.c \
+- yahoo_aliases.c \
+- yahoo_aliases.h \
+- yahoo_doodle.h \
+- yahoo_doodle.c \
+- yahoo_filexfer.h \
+- yahoo_filexfer.c \
+- yahoo_friend.h \
+- yahoo_friend.c \
+- yahoo_packet.h \
+- yahoo_packet.c \
+- yahoo_picture.c \
+- yahoo_picture.h \
+- yahoo_profile.c \
+- ycht.c \
+- ycht.h
+-
+-AM_CFLAGS = $(st)
+-
+-libyahoo_la_LDFLAGS = -module -avoid-version
+-libyahoojp_la_LDFLAGS = -module -avoid-version
+-
+-if STATIC_YAHOO
+-
+-st = -DPURPLE_STATIC_PRPL
+-noinst_LTLIBRARIES = libymsg.la
+-libymsg_la_SOURCES = $(YAHOOSOURCES) libyahoo.c libyahoojp.c
+-libymsg_la_CFLAGS = $(AM_CFLAGS)
+-
+-else
+-
+-st =
+-pkg_LTLIBRARIES = libymsg.la libyahoo.la libyahoojp.la
+-
+-libymsg_la_SOURCES = $(YAHOOSOURCES)
+-libymsg_la_LIBADD = $(GLIB_LIBS)
+-
+-libyahoo_la_SOURCES = libyahoo.c
+-libyahoo_la_LIBADD = libymsg.la
+-
+-libyahoojp_la_SOURCES = libyahoojp.c
+-libyahoojp_la_LIBADD = libymsg.la
+-
+-endif
+-
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.in 2013-02-11 07:17:22.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,904 +0,0 @@
+-# Makefile.in generated by automake 1.11.6 from Makefile.am.
+-# @configure_input@
+-
+-# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+-# 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011 Free Software
+-# Foundation, Inc.
+-# This Makefile.in is free software; the Free Software Foundation
+-# gives unlimited permission to copy and/or distribute it,
+-# with or without modifications, as long as this notice is preserved.
+-
+-# This program is distributed in the hope that it will be useful,
+-# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+-# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+-# PARTICULAR PURPOSE.
+-
+-@SET_MAKE@
+-
+-VPATH = @srcdir@
+-am__make_dryrun = \
+- { \
+- am__dry=no; \
+- case $$MAKEFLAGS in \
+- *\\[\ \ ]*) \
+- echo 'am--echo: ; @echo "AM" OK' | $(MAKE) -f - 2>/dev/null \
+- | grep '^AM OK$$' >/dev/null || am__dry=yes;; \
+- *) \
+- for am__flg in $$MAKEFLAGS; do \
+- case $$am__flg in \
+- *=*|--*) ;; \
+- *n*) am__dry=yes; break;; \
+- esac; \
+- done;; \
+- esac; \
+- test $$am__dry = yes; \
+- }
+-pkgdatadir = $(datadir)/@PACKAGE@
+-pkgincludedir = $(includedir)/@PACKAGE@
+-pkglibdir = $(libdir)/@PACKAGE@
+-pkglibexecdir = $(libexecdir)/@PACKAGE@
+-am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+-install_sh_DATA = $(install_sh) -c -m 644
+-install_sh_PROGRAM = $(install_sh) -c
+-install_sh_SCRIPT = $(install_sh) -c
+-INSTALL_HEADER = $(INSTALL_DATA)
+-transform = $(program_transform_name)
+-NORMAL_INSTALL = :
+-PRE_INSTALL = :
+-POST_INSTALL = :
+-NORMAL_UNINSTALL = :
+-PRE_UNINSTALL = :
+-POST_UNINSTALL = :
+-build_triplet = @build@
+-host_triplet = @host@
+-subdir = libpurple/protocols/yahoo
+-DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+-ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+-am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+- $(top_srcdir)/configure.ac
+-am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+- $(ACLOCAL_M4)
+-mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+-CONFIG_HEADER = $(top_builddir)/config.h
+-CONFIG_CLEAN_FILES =
+-CONFIG_CLEAN_VPATH_FILES =
+-am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`;
+-am__vpath_adj = case $$p in \
+- $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \
+- *) f=$$p;; \
+- esac;
+-am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`;
+-am__install_max = 40
+-am__nobase_strip_setup = \
+- srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'`
+-am__nobase_strip = \
+- for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||"
+-am__nobase_list = $(am__nobase_strip_setup); \
+- for p in $$list; do echo "$$p $$p"; done | \
+- sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \
+- $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \
+- if (++n[$$2] == $(am__install_max)) \
+- { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \
+- END { for (dir in files) print dir, files[dir] }'
+-am__base_list = \
+- sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \
+- sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g'
+-am__uninstall_files_from_dir = { \
+- test -z "$$files" \
+- || { test ! -d "$$dir" && test ! -f "$$dir" && test ! -r "$$dir"; } \
+- || { echo " ( cd '$$dir' && rm -f" $$files ")"; \
+- $(am__cd) "$$dir" && rm -f $$files; }; \
+- }
+-am__installdirs = "$(DESTDIR)$(pkgdir)"
+-LTLIBRARIES = $(noinst_LTLIBRARIES) $(pkg_LTLIBRARIES)
+-@STATIC_YAHOO_FALSE@libyahoo_la_DEPENDENCIES = libymsg.la
+-am__libyahoo_la_SOURCES_DIST = libyahoo.c
+-@STATIC_YAHOO_FALSE@am_libyahoo_la_OBJECTS = libyahoo.lo
+-libyahoo_la_OBJECTS = $(am_libyahoo_la_OBJECTS)
+-AM_V_lt = $(am__v_lt_@AM_V@)
+-am__v_lt_ = $(am__v_lt_@AM_DEFAULT_V@)
+-am__v_lt_0 = --silent
+-libyahoo_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(libyahoo_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_YAHOO_FALSE@am_libyahoo_la_rpath = -rpath $(pkgdir)
+-@STATIC_YAHOO_FALSE@libyahoojp_la_DEPENDENCIES = libymsg.la
+-am__libyahoojp_la_SOURCES_DIST = libyahoojp.c
+-@STATIC_YAHOO_FALSE@am_libyahoojp_la_OBJECTS = libyahoojp.lo
+-libyahoojp_la_OBJECTS = $(am_libyahoojp_la_OBJECTS)
+-libyahoojp_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(libyahoojp_la_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_YAHOO_FALSE@am_libyahoojp_la_rpath = -rpath $(pkgdir)
+-am__DEPENDENCIES_1 =
+-@STATIC_YAHOO_FALSE@libymsg_la_DEPENDENCIES = $(am__DEPENDENCIES_1)
+-am__libymsg_la_SOURCES_DIST = libymsg.c libymsg.h util.c yahoochat.h \
+- yahoochat.c yahoo_aliases.c yahoo_aliases.h yahoo_doodle.h \
+- yahoo_doodle.c yahoo_filexfer.h yahoo_filexfer.c \
+- yahoo_friend.h yahoo_friend.c yahoo_packet.h yahoo_packet.c \
+- yahoo_picture.c yahoo_picture.h yahoo_profile.c ycht.c ycht.h \
+- libyahoo.c libyahoojp.c
+-am__objects_1 = libymsg_la-libymsg.lo libymsg_la-util.lo \
+- libymsg_la-yahoochat.lo libymsg_la-yahoo_aliases.lo \
+- libymsg_la-yahoo_doodle.lo libymsg_la-yahoo_filexfer.lo \
+- libymsg_la-yahoo_friend.lo libymsg_la-yahoo_packet.lo \
+- libymsg_la-yahoo_picture.lo libymsg_la-yahoo_profile.lo \
+- libymsg_la-ycht.lo
+-@STATIC_YAHOO_FALSE@am_libymsg_la_OBJECTS = $(am__objects_1)
+-@STATIC_YAHOO_TRUE@am_libymsg_la_OBJECTS = $(am__objects_1) \
+-@STATIC_YAHOO_TRUE@ libymsg_la-libyahoo.lo \
+-@STATIC_YAHOO_TRUE@ libymsg_la-libyahoojp.lo
+-libymsg_la_OBJECTS = $(am_libymsg_la_OBJECTS)
+-libymsg_la_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(libymsg_la_CFLAGS) \
+- $(CFLAGS) $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-@STATIC_YAHOO_FALSE@am_libymsg_la_rpath = -rpath $(pkgdir)
+-@STATIC_YAHOO_TRUE@am_libymsg_la_rpath =
+-DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir)
+-depcomp = $(SHELL) $(top_srcdir)/depcomp
+-am__depfiles_maybe = depfiles
+-am__mv = mv -f
+-COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+- $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+-LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \
+- $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+- $(AM_CFLAGS) $(CFLAGS)
+-AM_V_CC = $(am__v_CC_@AM_V@)
+-am__v_CC_ = $(am__v_CC_@AM_DEFAULT_V@)
+-am__v_CC_0 = @echo " CC " $@;
+-AM_V_at = $(am__v_at_@AM_V@)
+-am__v_at_ = $(am__v_at_@AM_DEFAULT_V@)
+-am__v_at_0 = @
+-CCLD = $(CC)
+-LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \
+- $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+- $(AM_LDFLAGS) $(LDFLAGS) -o $@
+-AM_V_CCLD = $(am__v_CCLD_@AM_V@)
+-am__v_CCLD_ = $(am__v_CCLD_@AM_DEFAULT_V@)
+-am__v_CCLD_0 = @echo " CCLD " $@;
+-AM_V_GEN = $(am__v_GEN_@AM_V@)
+-am__v_GEN_ = $(am__v_GEN_@AM_DEFAULT_V@)
+-am__v_GEN_0 = @echo " GEN " $@;
+-SOURCES = $(libyahoo_la_SOURCES) $(libyahoojp_la_SOURCES) \
+- $(libymsg_la_SOURCES)
+-DIST_SOURCES = $(am__libyahoo_la_SOURCES_DIST) \
+- $(am__libyahoojp_la_SOURCES_DIST) \
+- $(am__libymsg_la_SOURCES_DIST)
+-am__can_run_installinfo = \
+- case $$AM_UPDATE_INFO_DIR in \
+- n|no|NO) false;; \
+- *) (install-info --version) >/dev/null 2>&1;; \
+- esac
+-ETAGS = etags
+-CTAGS = ctags
+-DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+-ACLOCAL = @ACLOCAL@
+-ALLOCA = @ALLOCA@
+-ALL_LINGUAS = @ALL_LINGUAS@
+-AMTAR = @AMTAR@
+-AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@
+-AR = @AR@
+-AUTOCONF = @AUTOCONF@
+-AUTOHEADER = @AUTOHEADER@
+-AUTOMAKE = @AUTOMAKE@
+-AVAHI_CFLAGS = @AVAHI_CFLAGS@
+-AVAHI_LIBS = @AVAHI_LIBS@
+-AWK = @AWK@
+-CATALOGS = @CATALOGS@
+-CATOBJEXT = @CATOBJEXT@
+-CC = @CC@
+-CCDEPMODE = @CCDEPMODE@
+-CFLAGS = @CFLAGS@
+-CHECK_CFLAGS = @CHECK_CFLAGS@
+-CHECK_LIBS = @CHECK_LIBS@
+-CPP = @CPP@
+-CPPFLAGS = @CPPFLAGS@
+-CYGPATH_W = @CYGPATH_W@
+-DATADIRNAME = @DATADIRNAME@
+-DBUS_CFLAGS = @DBUS_CFLAGS@
+-DBUS_LIBS = @DBUS_LIBS@
+-DBUS_SERVICES_DIR = @DBUS_SERVICES_DIR@
+-DEBUG_CFLAGS = @DEBUG_CFLAGS@
+-DEFS = @DEFS@
+-DEPDIR = @DEPDIR@
+-DLLTOOL = @DLLTOOL@
+-DOT = @DOT@
+-DOXYGEN = @DOXYGEN@
+-DSYMUTIL = @DSYMUTIL@
+-DUMPBIN = @DUMPBIN@
+-DYNALOADER_A = @DYNALOADER_A@
+-DYNAMIC_PRPLS = @DYNAMIC_PRPLS@
+-ECHO_C = @ECHO_C@
+-ECHO_N = @ECHO_N@
+-ECHO_T = @ECHO_T@
+-EGREP = @EGREP@
+-EVOLUTION_ADDRESSBOOK_CFLAGS = @EVOLUTION_ADDRESSBOOK_CFLAGS@
+-EVOLUTION_ADDRESSBOOK_LIBS = @EVOLUTION_ADDRESSBOOK_LIBS@
+-EXEEXT = @EXEEXT@
+-FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+-FARSTREAM_LIBS = @FARSTREAM_LIBS@
+-FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+-GCONFTOOL = @GCONFTOOL@
+-GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+-GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+-GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+-GLIB_CFLAGS = @GLIB_CFLAGS@
+-GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+-GLIB_LIBS = @GLIB_LIBS@
+-GMOFILES = @GMOFILES@
+-GMSGFMT = @GMSGFMT@
+-GNT_CFLAGS = @GNT_CFLAGS@
+-GNT_LIBS = @GNT_LIBS@
+-GNT_LT_VERSION_INFO = @GNT_LT_VERSION_INFO@
+-GNT_MAJOR_VERSION = @GNT_MAJOR_VERSION@
+-GNT_MICRO_VERSION = @GNT_MICRO_VERSION@
+-GNT_MINOR_VERSION = @GNT_MINOR_VERSION@
+-GNT_VERSION = @GNT_VERSION@
+-GNUTLS_CFLAGS = @GNUTLS_CFLAGS@
+-GNUTLS_LIBS = @GNUTLS_LIBS@
+-GREP = @GREP@
+-GSTINTERFACES_CFLAGS = @GSTINTERFACES_CFLAGS@
+-GSTINTERFACES_LIBS = @GSTINTERFACES_LIBS@
+-GSTREAMER_CFLAGS = @GSTREAMER_CFLAGS@
+-GSTREAMER_LIBS = @GSTREAMER_LIBS@
+-GTKSPELL_CFLAGS = @GTKSPELL_CFLAGS@
+-GTKSPELL_LIBS = @GTKSPELL_LIBS@
+-GTK_CFLAGS = @GTK_CFLAGS@
+-GTK_LIBS = @GTK_LIBS@
+-IDN_CFLAGS = @IDN_CFLAGS@
+-IDN_LIBS = @IDN_LIBS@
+-INSTALL = @INSTALL@
+-INSTALL_DATA = @INSTALL_DATA@
+-INSTALL_PROGRAM = @INSTALL_PROGRAM@
+-INSTALL_SCRIPT = @INSTALL_SCRIPT@
+-INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+-INSTOBJEXT = @INSTOBJEXT@
+-INTLLIBS = @INTLLIBS@
+-INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+-INTLTOOL_MERGE = @INTLTOOL_MERGE@
+-INTLTOOL_PERL = @INTLTOOL_PERL@
+-INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+-INTLTOOL_V_MERGE = @INTLTOOL_V_MERGE@
+-INTLTOOL_V_MERGE_OPTIONS = @INTLTOOL_V_MERGE_OPTIONS@
+-INTLTOOL__v_MERGE_ = @INTLTOOL__v_MERGE_@
+-INTLTOOL__v_MERGE_0 = @INTLTOOL__v_MERGE_0@
+-KRB4_CFLAGS = @KRB4_CFLAGS@
+-KRB4_LDFLAGS = @KRB4_LDFLAGS@
+-KRB4_LIBS = @KRB4_LIBS@
+-LD = @LD@
+-LDADD = @LDADD@
+-LDFLAGS = @LDFLAGS@
+-LIBOBJS = @LIBOBJS@
+-LIBPERL_A = @LIBPERL_A@
+-LIBS = @LIBS@
+-LIBTOOL = @LIBTOOL@
+-LIBXML_CFLAGS = @LIBXML_CFLAGS@
+-LIBXML_LIBS = @LIBXML_LIBS@
+-LIPO = @LIPO@
+-LN_S = @LN_S@
+-LTLIBOBJS = @LTLIBOBJS@
+-MAKEINFO = @MAKEINFO@
+-MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+-MKDIR_P = @MKDIR_P@
+-MKINSTALLDIRS = @MKINSTALLDIRS@
+-MONO_CFLAGS = @MONO_CFLAGS@
+-MONO_LIBS = @MONO_LIBS@
+-MSGFMT = @MSGFMT@
+-MSGFMT_OPTS = @MSGFMT_OPTS@
+-MSGMERGE = @MSGMERGE@
+-NETWORKMANAGER_CFLAGS = @NETWORKMANAGER_CFLAGS@
+-NETWORKMANAGER_LIBS = @NETWORKMANAGER_LIBS@
+-NM = @NM@
+-NMEDIT = @NMEDIT@
+-NSS_CFLAGS = @NSS_CFLAGS@
+-NSS_LIBS = @NSS_LIBS@
+-OBJDUMP = @OBJDUMP@
+-OBJEXT = @OBJEXT@
+-OTOOL = @OTOOL@
+-OTOOL64 = @OTOOL64@
+-PACKAGE = @PACKAGE@
+-PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+-PACKAGE_NAME = @PACKAGE_NAME@
+-PACKAGE_STRING = @PACKAGE_STRING@
+-PACKAGE_TARNAME = @PACKAGE_TARNAME@
+-PACKAGE_URL = @PACKAGE_URL@
+-PACKAGE_VERSION = @PACKAGE_VERSION@
+-PANGO_CFLAGS = @PANGO_CFLAGS@
+-PANGO_LIBS = @PANGO_LIBS@
+-PATH_SEPARATOR = @PATH_SEPARATOR@
+-PERL = @PERL@
+-PERL_CFLAGS = @PERL_CFLAGS@
+-PERL_LIBS = @PERL_LIBS@
+-PKG_CONFIG = @PKG_CONFIG@
+-PKG_CONFIG_LIBDIR = @PKG_CONFIG_LIBDIR@
+-PKG_CONFIG_PATH = @PKG_CONFIG_PATH@
+-PLUGINS_DEFINE = @PLUGINS_DEFINE@
+-POFILES = @POFILES@
+-POSUB = @POSUB@
+-PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+-PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+-PURPLE_LT_VERSION_INFO = @PURPLE_LT_VERSION_INFO@
+-PURPLE_MAJOR_VERSION = @PURPLE_MAJOR_VERSION@
+-PURPLE_MICRO_VERSION = @PURPLE_MICRO_VERSION@
+-PURPLE_MINOR_VERSION = @PURPLE_MINOR_VERSION@
+-PURPLE_VERSION = @PURPLE_VERSION@
+-PYTHON = @PYTHON@
+-PY_CFLAGS = @PY_CFLAGS@
+-PY_LIBS = @PY_LIBS@
+-RANLIB = @RANLIB@
+-SASL_LIBS = @SASL_LIBS@
+-SED = @SED@
+-SET_MAKE = @SET_MAKE@
+-SHELL = @SHELL@
+-SILC_CFLAGS = @SILC_CFLAGS@
+-SILC_LIBS = @SILC_LIBS@
+-SM_LIBS = @SM_LIBS@
+-SQLITE3_CFLAGS = @SQLITE3_CFLAGS@
+-SQLITE3_LIBS = @SQLITE3_LIBS@
+-SSL_CERTIFICATES_DIR = @SSL_CERTIFICATES_DIR@
+-STATIC_LINK_LIBS = @STATIC_LINK_LIBS@
+-STATIC_PRPLS = @STATIC_PRPLS@
+-STRIP = @STRIP@
+-TCL_CFLAGS = @TCL_CFLAGS@
+-TCL_LIBS = @TCL_LIBS@
+-TK_LIBS = @TK_LIBS@
+-USE_NLS = @USE_NLS@
+-VERSION = @VERSION@
+-X11_CFLAGS = @X11_CFLAGS@
+-X11_LIBS = @X11_LIBS@
+-XGETTEXT = @XGETTEXT@
+-XMKMF = @XMKMF@
+-XSLTPROC = @XSLTPROC@
+-XSS_LIBS = @XSS_LIBS@
+-X_CFLAGS = @X_CFLAGS@
+-X_EXTRA_LIBS = @X_EXTRA_LIBS@
+-X_LIBS = @X_LIBS@
+-X_PRE_LIBS = @X_PRE_LIBS@
+-ZEPHYR_CFLAGS = @ZEPHYR_CFLAGS@
+-ZEPHYR_LDFLAGS = @ZEPHYR_LDFLAGS@
+-ZEPHYR_LIBS = @ZEPHYR_LIBS@
+-abs_builddir = @abs_builddir@
+-abs_srcdir = @abs_srcdir@
+-abs_top_builddir = @abs_top_builddir@
+-abs_top_srcdir = @abs_top_srcdir@
+-ac_ct_AR = @ac_ct_AR@
+-ac_ct_CC = @ac_ct_CC@
+-ac_ct_DUMPBIN = @ac_ct_DUMPBIN@
+-am__include = @am__include@
+-am__leading_dot = @am__leading_dot@
+-am__quote = @am__quote@
+-am__tar = @am__tar@
+-am__untar = @am__untar@
+-bindir = @bindir@
+-build = @build@
+-build_alias = @build_alias@
+-build_cpu = @build_cpu@
+-build_os = @build_os@
+-build_vendor = @build_vendor@
+-builddir = @builddir@
+-datadir = @datadir@
+-datarootdir = @datarootdir@
+-docdir = @docdir@
+-dvidir = @dvidir@
+-enable_dbus = @enable_dbus@
+-enable_devhelp = @enable_devhelp@
+-enable_dot = @enable_dot@
+-enable_doxygen = @enable_doxygen@
+-exec_prefix = @exec_prefix@
+-host = @host@
+-host_alias = @host_alias@
+-host_cpu = @host_cpu@
+-host_os = @host_os@
+-host_vendor = @host_vendor@
+-htmldir = @htmldir@
+-includedir = @includedir@
+-infodir = @infodir@
+-install_sh = @install_sh@
+-intltool__v_merge_options_ = @intltool__v_merge_options_@
+-intltool__v_merge_options_0 = @intltool__v_merge_options_0@
+-libdir = @libdir@
+-libexecdir = @libexecdir@
+-localedir = @localedir@
+-localstatedir = @localstatedir@
+-mandir = @mandir@
+-mkdir_p = @mkdir_p@
+-oldincludedir = @oldincludedir@
+-pdfdir = @pdfdir@
+-perlpath = @perlpath@
+-pidginpath = @pidginpath@
+-prefix = @prefix@
+-program_transform_name = @program_transform_name@
+-psdir = @psdir@
+-sbindir = @sbindir@
+-sedpath = @sedpath@
+-sharedstatedir = @sharedstatedir@
+-srcdir = @srcdir@
+-sysconfdir = @sysconfdir@
+-target_alias = @target_alias@
+-top_build_prefix = @top_build_prefix@
+-top_builddir = @top_builddir@
+-top_srcdir = @top_srcdir@
+-EXTRA_DIST = \
+- Makefile.mingw
+-
+-pkgdir = $(libdir)/purple-$(PURPLE_MAJOR_VERSION)
+-YAHOOSOURCES = \
+- libymsg.c \
+- libymsg.h \
+- util.c \
+- yahoochat.h \
+- yahoochat.c \
+- yahoo_aliases.c \
+- yahoo_aliases.h \
+- yahoo_doodle.h \
+- yahoo_doodle.c \
+- yahoo_filexfer.h \
+- yahoo_filexfer.c \
+- yahoo_friend.h \
+- yahoo_friend.c \
+- yahoo_packet.h \
+- yahoo_packet.c \
+- yahoo_picture.c \
+- yahoo_picture.h \
+- yahoo_profile.c \
+- ycht.c \
+- ycht.h
+-
+-AM_CFLAGS = $(st)
+-libyahoo_la_LDFLAGS = -module -avoid-version
+-libyahoojp_la_LDFLAGS = -module -avoid-version
+-@STATIC_YAHOO_FALSE@st =
+-@STATIC_YAHOO_TRUE@st = -DPURPLE_STATIC_PRPL
+-@STATIC_YAHOO_TRUE@noinst_LTLIBRARIES = libymsg.la
+-@STATIC_YAHOO_FALSE@libymsg_la_SOURCES = $(YAHOOSOURCES)
+-@STATIC_YAHOO_TRUE@libymsg_la_SOURCES = $(YAHOOSOURCES) libyahoo.c libyahoojp.c
+-@STATIC_YAHOO_TRUE@libymsg_la_CFLAGS = $(AM_CFLAGS)
+-@STATIC_YAHOO_FALSE@pkg_LTLIBRARIES = libymsg.la libyahoo.la libyahoojp.la
+-@STATIC_YAHOO_FALSE@libymsg_la_LIBADD = $(GLIB_LIBS)
+-@STATIC_YAHOO_FALSE@libyahoo_la_SOURCES = libyahoo.c
+-@STATIC_YAHOO_FALSE@libyahoo_la_LIBADD = libymsg.la
+-@STATIC_YAHOO_FALSE@libyahoojp_la_SOURCES = libyahoojp.c
+-@STATIC_YAHOO_FALSE@libyahoojp_la_LIBADD = libymsg.la
+-AM_CPPFLAGS = \
+- -I$(top_srcdir)/libpurple \
+- -I$(top_builddir)/libpurple \
+- $(GLIB_CFLAGS) \
+- $(DEBUG_CFLAGS)
+-
+-all: all-am
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .lo .o .obj
+-$(srcdir)/Makefile.in: $(srcdir)/Makefile.am $(am__configure_deps)
+- @for dep in $?; do \
+- case '$(am__configure_deps)' in \
+- *$$dep*) \
+- ( cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh ) \
+- && { if test -f $@; then exit 0; else break; fi; }; \
+- exit 1;; \
+- esac; \
+- done; \
+- echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu libpurple/protocols/yahoo/Makefile'; \
+- $(am__cd) $(top_srcdir) && \
+- $(AUTOMAKE) --gnu libpurple/protocols/yahoo/Makefile
+-.PRECIOUS: Makefile
+-Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+- @case '$?' in \
+- *config.status*) \
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+- *) \
+- echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+- cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+- esac;
+-
+-$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-
+-$(top_srcdir)/configure: $(am__configure_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(ACLOCAL_M4): $(am__aclocal_m4_deps)
+- cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+-$(am__aclocal_m4_deps):
+-
+-clean-noinstLTLIBRARIES:
+- -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES)
+- @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-install-pkgLTLIBRARIES: $(pkg_LTLIBRARIES)
+- @$(NORMAL_INSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- list2=; for p in $$list; do \
+- if test -f $$p; then \
+- list2="$$list2 $$p"; \
+- else :; fi; \
+- done; \
+- test -z "$$list2" || { \
+- echo " $(MKDIR_P) '$(DESTDIR)$(pkgdir)'"; \
+- $(MKDIR_P) "$(DESTDIR)$(pkgdir)" || exit 1; \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 '$(DESTDIR)$(pkgdir)'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL) $(INSTALL_STRIP_FLAG) $$list2 "$(DESTDIR)$(pkgdir)"; \
+- }
+-
+-uninstall-pkgLTLIBRARIES:
+- @$(NORMAL_UNINSTALL)
+- @list='$(pkg_LTLIBRARIES)'; test -n "$(pkgdir)" || list=; \
+- for p in $$list; do \
+- $(am__strip_dir) \
+- echo " $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f '$(DESTDIR)$(pkgdir)/$$f'"; \
+- $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=uninstall rm -f "$(DESTDIR)$(pkgdir)/$$f"; \
+- done
+-
+-clean-pkgLTLIBRARIES:
+- -test -z "$(pkg_LTLIBRARIES)" || rm -f $(pkg_LTLIBRARIES)
+- @list='$(pkg_LTLIBRARIES)'; for p in $$list; do \
+- dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \
+- test "$$dir" != "$$p" || dir=.; \
+- echo "rm -f \"$${dir}/so_locations\""; \
+- rm -f "$${dir}/so_locations"; \
+- done
+-libyahoo.la: $(libyahoo_la_OBJECTS) $(libyahoo_la_DEPENDENCIES) $(EXTRA_libyahoo_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libyahoo_la_LINK) $(am_libyahoo_la_rpath) $(libyahoo_la_OBJECTS) $(libyahoo_la_LIBADD) $(LIBS)
+-libyahoojp.la: $(libyahoojp_la_OBJECTS) $(libyahoojp_la_DEPENDENCIES) $(EXTRA_libyahoojp_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libyahoojp_la_LINK) $(am_libyahoojp_la_rpath) $(libyahoojp_la_OBJECTS) $(libyahoojp_la_LIBADD) $(LIBS)
+-libymsg.la: $(libymsg_la_OBJECTS) $(libymsg_la_DEPENDENCIES) $(EXTRA_libymsg_la_DEPENDENCIES)
+- $(AM_V_CCLD)$(libymsg_la_LINK) $(am_libymsg_la_rpath) $(libymsg_la_OBJECTS) $(libymsg_la_LIBADD) $(LIBS)
+-
+-mostlyclean-compile:
+- -rm -f *.$(OBJEXT)
+-
+-distclean-compile:
+- -rm -f *.tab.c
+-
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libyahoo.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libyahoojp.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libyahoo.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libyahoojp.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-libymsg.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-util.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_aliases.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_doodle.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_filexfer.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_friend.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_packet.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_picture.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoo_profile.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-yahoochat.Plo@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/libymsg_la-ycht.Plo@am__quote@
+-
+-.c.o:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c $<
+-
+-.c.obj:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(COMPILE) -c `$(CYGPATH_W) '$<'`
+-
+-.c.lo:
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LTCOMPILE) -c -o $@ $<
+-
+-libymsg_la-libymsg.lo: libymsg.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libymsg.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libymsg.Tpo -c -o libymsg_la-libymsg.lo `test -f 'libymsg.c' || echo '$(srcdir)/'`libymsg.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libymsg.Tpo $(DEPDIR)/libymsg_la-libymsg.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libymsg.c' object='libymsg_la-libymsg.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libymsg.lo `test -f 'libymsg.c' || echo '$(srcdir)/'`libymsg.c
+-
+-libymsg_la-util.lo: util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-util.lo -MD -MP -MF $(DEPDIR)/libymsg_la-util.Tpo -c -o libymsg_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-util.Tpo $(DEPDIR)/libymsg_la-util.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='util.c' object='libymsg_la-util.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-util.lo `test -f 'util.c' || echo '$(srcdir)/'`util.c
+-
+-libymsg_la-yahoochat.lo: yahoochat.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoochat.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoochat.Tpo -c -o libymsg_la-yahoochat.lo `test -f 'yahoochat.c' || echo '$(srcdir)/'`yahoochat.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoochat.Tpo $(DEPDIR)/libymsg_la-yahoochat.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoochat.c' object='libymsg_la-yahoochat.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoochat.lo `test -f 'yahoochat.c' || echo '$(srcdir)/'`yahoochat.c
+-
+-libymsg_la-yahoo_aliases.lo: yahoo_aliases.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_aliases.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_aliases.Tpo -c -o libymsg_la-yahoo_aliases.lo `test -f 'yahoo_aliases.c' || echo '$(srcdir)/'`yahoo_aliases.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_aliases.Tpo $(DEPDIR)/libymsg_la-yahoo_aliases.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_aliases.c' object='libymsg_la-yahoo_aliases.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_aliases.lo `test -f 'yahoo_aliases.c' || echo '$(srcdir)/'`yahoo_aliases.c
+-
+-libymsg_la-yahoo_doodle.lo: yahoo_doodle.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_doodle.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_doodle.Tpo -c -o libymsg_la-yahoo_doodle.lo `test -f 'yahoo_doodle.c' || echo '$(srcdir)/'`yahoo_doodle.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_doodle.Tpo $(DEPDIR)/libymsg_la-yahoo_doodle.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_doodle.c' object='libymsg_la-yahoo_doodle.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_doodle.lo `test -f 'yahoo_doodle.c' || echo '$(srcdir)/'`yahoo_doodle.c
+-
+-libymsg_la-yahoo_filexfer.lo: yahoo_filexfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_filexfer.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_filexfer.Tpo -c -o libymsg_la-yahoo_filexfer.lo `test -f 'yahoo_filexfer.c' || echo '$(srcdir)/'`yahoo_filexfer.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_filexfer.Tpo $(DEPDIR)/libymsg_la-yahoo_filexfer.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_filexfer.c' object='libymsg_la-yahoo_filexfer.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_filexfer.lo `test -f 'yahoo_filexfer.c' || echo '$(srcdir)/'`yahoo_filexfer.c
+-
+-libymsg_la-yahoo_friend.lo: yahoo_friend.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_friend.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_friend.Tpo -c -o libymsg_la-yahoo_friend.lo `test -f 'yahoo_friend.c' || echo '$(srcdir)/'`yahoo_friend.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_friend.Tpo $(DEPDIR)/libymsg_la-yahoo_friend.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_friend.c' object='libymsg_la-yahoo_friend.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_friend.lo `test -f 'yahoo_friend.c' || echo '$(srcdir)/'`yahoo_friend.c
+-
+-libymsg_la-yahoo_packet.lo: yahoo_packet.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_packet.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_packet.Tpo -c -o libymsg_la-yahoo_packet.lo `test -f 'yahoo_packet.c' || echo '$(srcdir)/'`yahoo_packet.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_packet.Tpo $(DEPDIR)/libymsg_la-yahoo_packet.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_packet.c' object='libymsg_la-yahoo_packet.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_packet.lo `test -f 'yahoo_packet.c' || echo '$(srcdir)/'`yahoo_packet.c
+-
+-libymsg_la-yahoo_picture.lo: yahoo_picture.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_picture.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_picture.Tpo -c -o libymsg_la-yahoo_picture.lo `test -f 'yahoo_picture.c' || echo '$(srcdir)/'`yahoo_picture.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_picture.Tpo $(DEPDIR)/libymsg_la-yahoo_picture.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_picture.c' object='libymsg_la-yahoo_picture.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_picture.lo `test -f 'yahoo_picture.c' || echo '$(srcdir)/'`yahoo_picture.c
+-
+-libymsg_la-yahoo_profile.lo: yahoo_profile.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-yahoo_profile.lo -MD -MP -MF $(DEPDIR)/libymsg_la-yahoo_profile.Tpo -c -o libymsg_la-yahoo_profile.lo `test -f 'yahoo_profile.c' || echo '$(srcdir)/'`yahoo_profile.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-yahoo_profile.Tpo $(DEPDIR)/libymsg_la-yahoo_profile.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='yahoo_profile.c' object='libymsg_la-yahoo_profile.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-yahoo_profile.lo `test -f 'yahoo_profile.c' || echo '$(srcdir)/'`yahoo_profile.c
+-
+-libymsg_la-ycht.lo: ycht.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-ycht.lo -MD -MP -MF $(DEPDIR)/libymsg_la-ycht.Tpo -c -o libymsg_la-ycht.lo `test -f 'ycht.c' || echo '$(srcdir)/'`ycht.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-ycht.Tpo $(DEPDIR)/libymsg_la-ycht.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='ycht.c' object='libymsg_la-ycht.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-ycht.lo `test -f 'ycht.c' || echo '$(srcdir)/'`ycht.c
+-
+-libymsg_la-libyahoo.lo: libyahoo.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libyahoo.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libyahoo.Tpo -c -o libymsg_la-libyahoo.lo `test -f 'libyahoo.c' || echo '$(srcdir)/'`libyahoo.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libyahoo.Tpo $(DEPDIR)/libymsg_la-libyahoo.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libyahoo.c' object='libymsg_la-libyahoo.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libyahoo.lo `test -f 'libyahoo.c' || echo '$(srcdir)/'`libyahoo.c
+-
+-libymsg_la-libyahoojp.lo: libyahoojp.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -MT libymsg_la-libyahoojp.lo -MD -MP -MF $(DEPDIR)/libymsg_la-libyahoojp.Tpo -c -o libymsg_la-libyahoojp.lo `test -f 'libyahoojp.c' || echo '$(srcdir)/'`libyahoojp.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/libymsg_la-libyahoojp.Tpo $(DEPDIR)/libymsg_la-libyahoojp.Plo
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='libyahoojp.c' object='libymsg_la-libyahoojp.lo' libtool=yes @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(libymsg_la_CFLAGS) $(CFLAGS) -c -o libymsg_la-libyahoojp.lo `test -f 'libyahoojp.c' || echo '$(srcdir)/'`libyahoojp.c
+-
+-mostlyclean-libtool:
+- -rm -f *.lo
+-
+-clean-libtool:
+- -rm -rf .libs _libs
+-
+-ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- mkid -fID $$unique
+-tags: TAGS
+-
+-TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- set x; \
+- here=`pwd`; \
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- shift; \
+- if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \
+- test -n "$$unique" || unique=$$empty_fix; \
+- if test $$# -gt 0; then \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- "$$@" $$unique; \
+- else \
+- $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+- $$unique; \
+- fi; \
+- fi
+-ctags: CTAGS
+-CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+- $(TAGS_FILES) $(LISP)
+- list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+- unique=`for i in $$list; do \
+- if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+- done | \
+- $(AWK) '{ files[$$0] = 1; nonempty = 1; } \
+- END { if (nonempty) { for (i in files) print i; }; }'`; \
+- test -z "$(CTAGS_ARGS)$$unique" \
+- || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+- $$unique
+-
+-GTAGS:
+- here=`$(am__cd) $(top_builddir) && pwd` \
+- && $(am__cd) $(top_srcdir) \
+- && gtags -i $(GTAGS_ARGS) "$$here"
+-
+-distclean-tags:
+- -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+-
+-distdir: $(DISTFILES)
+- @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \
+- list='$(DISTFILES)'; \
+- dist_files=`for file in $$list; do echo $$file; done | \
+- sed -e "s|^$$srcdirstrip/||;t" \
+- -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \
+- case $$dist_files in \
+- */*) $(MKDIR_P) `echo "$$dist_files" | \
+- sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \
+- sort -u` ;; \
+- esac; \
+- for file in $$dist_files; do \
+- if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+- if test -d $$d/$$file; then \
+- dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \
+- if test -d "$(distdir)/$$file"; then \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+- cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \
+- find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \
+- fi; \
+- cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \
+- else \
+- test -f "$(distdir)/$$file" \
+- || cp -p $$d/$$file "$(distdir)/$$file" \
+- || exit 1; \
+- fi; \
+- done
+-check-am: all-am
+-check: check-am
+-all-am: Makefile $(LTLIBRARIES)
+-installdirs:
+- for dir in "$(DESTDIR)$(pkgdir)"; do \
+- test -z "$$dir" || $(MKDIR_P) "$$dir"; \
+- done
+-install: install-am
+-install-exec: install-exec-am
+-install-data: install-data-am
+-uninstall: uninstall-am
+-
+-install-am: all-am
+- @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+-
+-installcheck: installcheck-am
+-install-strip:
+- if test -z '$(STRIP)'; then \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- install; \
+- else \
+- $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+- install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+- "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'" install; \
+- fi
+-mostlyclean-generic:
+-
+-clean-generic:
+-
+-distclean-generic:
+- -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+- -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES)
+-
+-maintainer-clean-generic:
+- @echo "This command is intended for maintainers to use"
+- @echo "it deletes files that may require special tools to rebuild."
+-clean: clean-am
+-
+-clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \
+- clean-pkgLTLIBRARIES mostlyclean-am
+-
+-distclean: distclean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-distclean-am: clean-am distclean-compile distclean-generic \
+- distclean-tags
+-
+-dvi: dvi-am
+-
+-dvi-am:
+-
+-html: html-am
+-
+-html-am:
+-
+-info: info-am
+-
+-info-am:
+-
+-install-data-am: install-pkgLTLIBRARIES
+-
+-install-dvi: install-dvi-am
+-
+-install-dvi-am:
+-
+-install-exec-am:
+-
+-install-html: install-html-am
+-
+-install-html-am:
+-
+-install-info: install-info-am
+-
+-install-info-am:
+-
+-install-man:
+-
+-install-pdf: install-pdf-am
+-
+-install-pdf-am:
+-
+-install-ps: install-ps-am
+-
+-install-ps-am:
+-
+-installcheck-am:
+-
+-maintainer-clean: maintainer-clean-am
+- -rm -rf ./$(DEPDIR)
+- -rm -f Makefile
+-maintainer-clean-am: distclean-am maintainer-clean-generic
+-
+-mostlyclean: mostlyclean-am
+-
+-mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+- mostlyclean-libtool
+-
+-pdf: pdf-am
+-
+-pdf-am:
+-
+-ps: ps-am
+-
+-ps-am:
+-
+-uninstall-am: uninstall-pkgLTLIBRARIES
+-
+-.MAKE: install-am install-strip
+-
+-.PHONY: CTAGS GTAGS all all-am check check-am clean clean-generic \
+- clean-libtool clean-noinstLTLIBRARIES clean-pkgLTLIBRARIES \
+- ctags distclean distclean-compile distclean-generic \
+- distclean-libtool distclean-tags distdir dvi dvi-am html \
+- html-am info info-am install install-am install-data \
+- install-data-am install-dvi install-dvi-am install-exec \
+- install-exec-am install-html install-html-am install-info \
+- install-info-am install-man install-pdf install-pdf-am \
+- install-pkgLTLIBRARIES install-ps install-ps-am install-strip \
+- installcheck installcheck-am installdirs maintainer-clean \
+- maintainer-clean-generic mostlyclean mostlyclean-compile \
+- mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \
+- tags uninstall uninstall-am uninstall-pkgLTLIBRARIES
+-
+-
+-# Tell versions [3.59,3.63) of GNU make to not export all variables.
+-# Otherwise a system limit (for SysV at least) may be exceeded.
+-.NOEXPORT:
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.mingw pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.mingw
+--- pidgin-2.10.7/libpurple/protocols/yahoo/Makefile.mingw 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,105 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of libyahoo
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = libymsg
+-YAHOO_TARGET = libyahoo
+-YAHOOJP_TARGET = libyahoojp
+-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. \
+- -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = util.c \
+- libymsg.c \
+- yahoochat.c \
+- yahoo_aliases.c \
+- yahoo_doodle.c \
+- yahoo_filexfer.c \
+- yahoo_friend.c \
+- yahoo_packet.c \
+- yahoo_picture.c \
+- yahoo_profile.c \
+- ycht.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-YAHOO_C_SRC = libyahoo.c
+-YAHOO_OBJECTS = $(YAHOO_C_SRC:%.c=%.o)
+-
+-YAHOOJP_C_SRC = libyahoojp.c
+-YAHOOJP_OBJECTS = $(YAHOOJP_C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = \
+- -lglib-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll
+-
+-install: all $(DLL_INSTALL_DIR)
+- cp $(YAHOO_TARGET).dll $(YAHOOJP_TARGET).dll $(DLL_INSTALL_DIR)
+- cp $(TARGET).dll $(PURPLE_INSTALL_DIR)
+-
+-$(OBJECTS): $(PURPLE_CONFIG_H)
+-
+-$(TARGET).dll.a $(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -Wl,--output-def,$(TARGET).def,--out-implib,$(TARGET).dll.a -o $(TARGET).dll
+-
+-$(YAHOO_TARGET).dll: $(TARGET).dll.a $(YAHOO_OBJECTS)
+- $(CC) -shared $(YAHOO_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOO_TARGET).dll
+-
+-$(YAHOOJP_TARGET).dll: $(TARGET).dll.a $(YAHOOJP_OBJECTS)
+- $(CC) -shared $(YAHOOJP_OBJECTS) $(LIB_PATHS) $(LIBS) -lymsg $(DLL_LD_FLAGS) -o $(YAHOOJP_TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f $(OBJECTS) $(TARGET).dll $(TARGET).dll.a
+- rm -f $(YAHOO_OBJECTS) $(YAHOO_TARGET).dll
+- rm -f $(YAHOOJP_OBJECTS) $(YAHOOJP_TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/util.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/util.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/util.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/util.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,951 +0,0 @@
+-/*
+- * purple
+- *
+- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
+- * (marv on irc.freenode.net)
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif /* HAVE_CONFIG_H */
+-
+-#include "debug.h"
+-#include "internal.h"
+-#include "prpl.h"
+-
+-#include "libymsg.h"
+-
+-#include <string.h>
+-
+-gboolean
+-yahoo_account_use_http_proxy(PurpleConnection *pc)
+-{
+- PurpleAccount *account = purple_connection_get_account(pc);
+- PurpleProxyInfo *ppi = NULL;
+- PurpleProxyType type = PURPLE_PROXY_NONE;
+- gboolean proxy_ssl = purple_account_get_bool(account, "proxy_ssl", FALSE);
+-
+- if(proxy_ssl)
+- ppi = purple_proxy_get_setup(account);
+- else
+- ppi = purple_proxy_get_setup(NULL);
+-
+- type = purple_proxy_info_get_type(ppi);
+-
+- return (type == PURPLE_PROXY_HTTP || type == PURPLE_PROXY_USE_ENVVAR);
+-}
+-
+-/*
+- * Returns cookies formatted as a null terminated string for the given connection.
+- * Must g_free return value.
+- *
+- * TODO:will work, but must test for strict correctness
+- */
+-gchar* yahoo_get_cookies(PurpleConnection *gc)
+-{
+- gchar *ans = NULL;
+- gchar *cur;
+- char firstflag = 1;
+- gchar *t1,*t2,*t3;
+- GSList *tmp;
+- GSList *cookies;
+- cookies = ((YahooData*)(gc->proto_data))->cookies;
+- tmp = cookies;
+- while(tmp)
+- {
+- cur = tmp->data;
+- t1 = ans;
+- t2 = g_strrstr(cur, ";expires=");
+- if(t2 == NULL)
+- t2 = g_strrstr(cur, "; expires=");
+- if(t2 == NULL)
+- {
+- if(firstflag)
+- ans = g_strdup_printf("%c=%s", cur[0], cur+2);
+- else
+- ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
+- }
+- else
+- {
+- t3 = strstr(t2+1, ";");
+- if(t3 != NULL)
+- {
+- t2[0] = '\0';
+-
+- if(firstflag)
+- ans = g_strdup_printf("%c=%s%s", cur[0], cur+2, t3);
+- else
+- ans = g_strdup_printf("%s; %c=%s%s", t1, cur[0], cur+2, t3);
+-
+- t2[0] = ';';
+- }
+- else
+- {
+- t2[0] = '\0';
+-
+- if(firstflag)
+- ans = g_strdup_printf("%c=%s", cur[0], cur+2);
+- else
+- ans = g_strdup_printf("%s; %c=%s", t1, cur[0], cur+2);
+-
+- t2[0] = ';';
+- }
+- }
+- if(firstflag)
+- firstflag = 0;
+- else
+- g_free(t1);
+- tmp = g_slist_next(tmp);
+- }
+- return ans;
+-}
+-
+-/**
+- * Encode some text to send to the yahoo server.
+- *
+- * @param gc The connection handle.
+- * @param str The null terminated utf8 string to encode.
+- * @param utf8 If not @c NULL, whether utf8 is okay or not.
+- * Even if it is okay, we may not use it. If we
+- * used it, we set this to @c TRUE, else to
+- * @c FALSE. If @c NULL, false is assumed, and
+- * it is not dereferenced.
+- * @return The g_malloced string in the appropriate encoding.
+- */
+-char *yahoo_string_encode(PurpleConnection *gc, const char *str, gboolean *utf8)
+-{
+- YahooData *yd = gc->proto_data;
+- char *ret;
+- const char *to_codeset;
+-
+- if (yd->jp)
+- return g_strdup(str);
+-
+- if (utf8 && *utf8) /* FIXME: maybe don't use utf8 if it'll fit in latin1 */
+- return g_strdup(str);
+-
+- to_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset", "ISO-8859-1");
+- ret = g_convert_with_fallback(str, -1, to_codeset, "UTF-8", "?", NULL, NULL, NULL);
+-
+- if (ret)
+- return ret;
+- else
+- return g_strdup("");
+-}
+-
+-/**
+- * Decode some text received from the server.
+- *
+- * @param gc The gc handle.
+- * @param str The null terminated string to decode.
+- * @param utf8 Did the server tell us it was supposed to be utf8?
+- * @return The decoded, utf-8 string, which must be g_free()'d.
+- */
+-char *yahoo_string_decode(PurpleConnection *gc, const char *str, gboolean utf8)
+-{
+- YahooData *yd = gc->proto_data;
+- char *ret;
+- const char *from_codeset;
+-
+- if (utf8) {
+- if (g_utf8_validate(str, -1, NULL))
+- return g_strdup(str);
+- }
+-
+- if (yd->jp)
+- from_codeset = "SHIFT_JIS";
+- else
+- from_codeset = purple_account_get_string(purple_connection_get_account(gc), "local_charset", "ISO-8859-1");
+-
+- ret = g_convert_with_fallback(str, -1, "UTF-8", from_codeset, NULL, NULL, NULL, NULL);
+-
+- if (ret)
+- return ret;
+- else
+- return g_strdup("");
+-}
+-
+-char *yahoo_convert_to_numeric(const char *str)
+-{
+- GString *gstr = NULL;
+- const unsigned char *p;
+-
+- gstr = g_string_sized_new(strlen(str) * 6 + 1);
+-
+- for (p = (unsigned char *)str; *p; p++) {
+- g_string_append_printf(gstr, "&#%u;", *p);
+- }
+-
+- return g_string_free(gstr, FALSE);
+-}
+-
+-/*
+- * The values in this hash table should probably be lowercase, since that's
+- * what xhtml expects. Also because yahoo_codes_to_html() does
+- * case-sensitive comparisons.
+- *
+- * I found these on some website but i don't know that they actually
+- * work (or are supposed to work). I didn't implement them yet.
+- *
+- * [0;30m ---black
+- * [1;37m ---white
+- * [0;37m ---tan
+- * [0;38m ---light black
+- * [1;39m ---dark blue
+- * [0;32m ---green
+- * [0;33m ---yellow
+- * [0;35m ---pink
+- * [1;35m ---purple
+- * [1;30m ---light blue
+- * [0;31m ---red
+- * [0;34m ---blue
+- * [0;36m ---aqua
+- * (shift+comma)lyellow(shift+period) ---light yellow
+- * (shift+comma)lgreen(shift+period) ---light green
+- * [2;30m <--white out
+- */
+-
+-static GHashTable *esc_codes_ht = NULL;
+-static GHashTable *tags_ht = NULL;
+-
+-void yahoo_init_colorht()
+-{
+- if (esc_codes_ht != NULL)
+- /* Hash table has already been initialized */
+- return;
+-
+- /* Key is the escape code string. Value is the HTML that should be
+- * inserted in place of the escape code. */
+- esc_codes_ht = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- /* Key is the name of the HTML tag, for example "font" or "/font"
+- * value is the HTML that should be inserted in place of the old tag */
+- tags_ht = g_hash_table_new(g_str_hash, g_str_equal);
+-
+- /* the numbers in comments are what gyach uses, but i think they're incorrect */
+-#ifdef USE_CSS_FORMATTING
+- g_hash_table_insert(esc_codes_ht, "30", "<span style=\"color: #000000\">"); /* black */
+- g_hash_table_insert(esc_codes_ht, "31", "<span style=\"color: #0000FF\">"); /* blue */
+- g_hash_table_insert(esc_codes_ht, "32", "<span style=\"color: #008080\">"); /* cyan */ /* 00b2b2 */
+- g_hash_table_insert(esc_codes_ht, "33", "<span style=\"color: #808080\">"); /* gray */ /* 808080 */
+- g_hash_table_insert(esc_codes_ht, "34", "<span style=\"color: #008000\">"); /* green */ /* 00c200 */
+- g_hash_table_insert(esc_codes_ht, "35", "<span style=\"color: #FF0080\">"); /* pink */ /* ffafaf */
+- g_hash_table_insert(esc_codes_ht, "36", "<span style=\"color: #800080\">"); /* purple */ /* b200b2 */
+- g_hash_table_insert(esc_codes_ht, "37", "<span style=\"color: #FF8000\">"); /* orange */ /* ffff00 */
+- g_hash_table_insert(esc_codes_ht, "38", "<span style=\"color: #FF0000\">"); /* red */
+- g_hash_table_insert(esc_codes_ht, "39", "<span style=\"color: #808000\">"); /* olive */ /* 546b50 */
+-#else
+- g_hash_table_insert(esc_codes_ht, "30", "<font color=\"#000000\">"); /* black */
+- g_hash_table_insert(esc_codes_ht, "31", "<font color=\"#0000FF\">"); /* blue */
+- g_hash_table_insert(esc_codes_ht, "32", "<font color=\"#008080\">"); /* cyan */ /* 00b2b2 */
+- g_hash_table_insert(esc_codes_ht, "33", "<font color=\"#808080\">"); /* gray */ /* 808080 */
+- g_hash_table_insert(esc_codes_ht, "34", "<font color=\"#008000\">"); /* green */ /* 00c200 */
+- g_hash_table_insert(esc_codes_ht, "35", "<font color=\"#FF0080\">"); /* pink */ /* ffafaf */
+- g_hash_table_insert(esc_codes_ht, "36", "<font color=\"#800080\">"); /* purple */ /* b200b2 */
+- g_hash_table_insert(esc_codes_ht, "37", "<font color=\"#FF8000\">"); /* orange */ /* ffff00 */
+- g_hash_table_insert(esc_codes_ht, "38", "<font color=\"#FF0000\">"); /* red */
+- g_hash_table_insert(esc_codes_ht, "39", "<font color=\"#808000\">"); /* olive */ /* 546b50 */
+-#endif /* !USE_CSS_FORMATTING */
+-
+- g_hash_table_insert(esc_codes_ht, "1", "<b>");
+- g_hash_table_insert(esc_codes_ht, "x1", "</b>");
+- g_hash_table_insert(esc_codes_ht, "2", "<i>");
+- g_hash_table_insert(esc_codes_ht, "x2", "</i>");
+- g_hash_table_insert(esc_codes_ht, "4", "<u>");
+- g_hash_table_insert(esc_codes_ht, "x4", "</u>");
+-
+- /* these just tell us the text they surround is supposed
+- * to be a link. purple figures that out on its own so we
+- * just ignore it.
+- */
+- g_hash_table_insert(esc_codes_ht, "l", ""); /* link start */
+- g_hash_table_insert(esc_codes_ht, "xl", ""); /* link end */
+-
+-#ifdef USE_CSS_FORMATTING
+- g_hash_table_insert(tags_ht, "black", "<span style=\"color: #000000\">");
+- g_hash_table_insert(tags_ht, "blue", "<span style=\"color: #0000FF\">");
+- g_hash_table_insert(tags_ht, "cyan", "<span style=\"color: #008284\">");
+- g_hash_table_insert(tags_ht, "gray", "<span style=\"color: #848284\">");
+- g_hash_table_insert(tags_ht, "green", "<span style=\"color: #008200\">");
+- g_hash_table_insert(tags_ht, "pink", "<span style=\"color: #FF0084\">");
+- g_hash_table_insert(tags_ht, "purple", "<span style=\"color: #840084\">");
+- g_hash_table_insert(tags_ht, "orange", "<span style=\"color: #FF8000\">");
+- g_hash_table_insert(tags_ht, "red", "<span style=\"color: #FF0000\">");
+- g_hash_table_insert(tags_ht, "yellow", "<span style=\"color: #848200\">");
+-
+- g_hash_table_insert(tags_ht, "/black", "</span>");
+- g_hash_table_insert(tags_ht, "/blue", "</span>");
+- g_hash_table_insert(tags_ht, "/cyan", "</span>");
+- g_hash_table_insert(tags_ht, "/gray", "</span>");
+- g_hash_table_insert(tags_ht, "/green", "</span>");
+- g_hash_table_insert(tags_ht, "/pink", "</span>");
+- g_hash_table_insert(tags_ht, "/purple", "</span>");
+- g_hash_table_insert(tags_ht, "/orange", "</span>");
+- g_hash_table_insert(tags_ht, "/red", "</span>");
+- g_hash_table_insert(tags_ht, "/yellow", "</span>");
+-#else
+- g_hash_table_insert(tags_ht, "black", "<font color=\"#000000\">");
+- g_hash_table_insert(tags_ht, "blue", "<font color=\"#0000FF\">");
+- g_hash_table_insert(tags_ht, "cyan", "<font color=\"#008284\">");
+- g_hash_table_insert(tags_ht, "gray", "<font color=\"#848284\">");
+- g_hash_table_insert(tags_ht, "green", "<font color=\"#008200\">");
+- g_hash_table_insert(tags_ht, "pink", "<font color=\"#FF0084\">");
+- g_hash_table_insert(tags_ht, "purple", "<font color=\"#840084\">");
+- g_hash_table_insert(tags_ht, "orange", "<font color=\"#FF8000\">");
+- g_hash_table_insert(tags_ht, "red", "<font color=\"#FF0000\">");
+- g_hash_table_insert(tags_ht, "yellow", "<font color=\"#848200\">");
+-
+- g_hash_table_insert(tags_ht, "/black", "</font>");
+- g_hash_table_insert(tags_ht, "/blue", "</font>");
+- g_hash_table_insert(tags_ht, "/cyan", "</font>");
+- g_hash_table_insert(tags_ht, "/gray", "</font>");
+- g_hash_table_insert(tags_ht, "/green", "</font>");
+- g_hash_table_insert(tags_ht, "/pink", "</font>");
+- g_hash_table_insert(tags_ht, "/purple", "</font>");
+- g_hash_table_insert(tags_ht, "/orange", "</font>");
+- g_hash_table_insert(tags_ht, "/red", "</font>");
+- g_hash_table_insert(tags_ht, "/yellow", "</font>");
+-#endif /* !USE_CSS_FORMATTING */
+-
+- /* We don't support these tags, so discard them */
+- g_hash_table_insert(tags_ht, "alt", "");
+- g_hash_table_insert(tags_ht, "fade", "");
+- g_hash_table_insert(tags_ht, "snd", "");
+- g_hash_table_insert(tags_ht, "/alt", "");
+- g_hash_table_insert(tags_ht, "/fade", "");
+-
+- /* Official clients don't seem to send b, i or u tags. They use
+- * the escape codes listed above. Official clients definitely send
+- * font tags, though. I wonder if we can remove the opening and
+- * closing b, i and u tags from here? */
+- g_hash_table_insert(tags_ht, "b", "<b>");
+- g_hash_table_insert(tags_ht, "i", "<i>");
+- g_hash_table_insert(tags_ht, "u", "<u>");
+- g_hash_table_insert(tags_ht, "font", "<font>");
+-
+- g_hash_table_insert(tags_ht, "/b", "</b>");
+- g_hash_table_insert(tags_ht, "/i", "</i>");
+- g_hash_table_insert(tags_ht, "/u", "</u>");
+- g_hash_table_insert(tags_ht, "/font", "</font>");
+-}
+-
+-void yahoo_dest_colorht()
+-{
+- if (esc_codes_ht == NULL)
+- /* Hash table has already been destroyed */
+- return;
+-
+- g_hash_table_destroy(esc_codes_ht);
+- esc_codes_ht = NULL;
+- g_hash_table_destroy(tags_ht);
+- tags_ht = NULL;
+-}
+-
+-#ifndef USE_CSS_FORMATTING
+-static int point_to_html(int x)
+-{
+- if (x < 9)
+- return 1;
+- if (x < 11)
+- return 2;
+- if (x < 13)
+- return 3;
+- if (x < 17)
+- return 4;
+- if (x < 25)
+- return 5;
+- if (x < 35)
+- return 6;
+- return 7;
+-}
+-#endif /* !USE_CSS_FORMATTING */
+-
+-static void append_attrs_datalist_foreach_cb(GQuark key_id, gpointer data, gpointer user_data)
+-{
+- const char *key;
+- const char *value;
+- xmlnode *cur;
+-
+- key = g_quark_to_string(key_id);
+- value = data;
+- cur = user_data;
+-
+- xmlnode_set_attrib(cur, key, value);
+-}
+-
+-/**
+- * @param cur A pointer to the position in the XML tree that we're
+- * currently building. This will be modified when opening a tag
+- * or closing an existing tag.
+- */
+-static void yahoo_codes_to_html_add_tag(xmlnode **cur, const char *tag, gboolean is_closing_tag, const gchar *tag_name, gboolean is_font_tag)
+-{
+- if (is_closing_tag) {
+- xmlnode *tmp;
+- GSList *dangling_tags = NULL;
+-
+- /* Move up the DOM until we find the opening tag */
+- for (tmp = *cur; tmp != NULL; tmp = xmlnode_get_parent(tmp)) {
+- /* Add one to tag_name when doing this comparison because it starts with a / */
+- if (g_str_equal(tmp->name, tag_name + 1))
+- /* Found */
+- break;
+- dangling_tags = g_slist_prepend(dangling_tags, tmp);
+- }
+- if (tmp == NULL) {
+- /* This is a closing tag with no opening tag. Useless. */
+- purple_debug_error("yahoo", "Ignoring unmatched tag %s", tag);
+- g_slist_free(dangling_tags);
+- return;
+- }
+-
+- /* Move our current position up, now that we've closed a tag */
+- *cur = xmlnode_get_parent(tmp);
+-
+- /* Re-open any tags that were nested below the tag we just closed */
+- while (dangling_tags != NULL) {
+- tmp = dangling_tags->data;
+- dangling_tags = g_slist_delete_link(dangling_tags, dangling_tags);
+-
+- /* Create a copy of this tag+attributes (but not child tags or
+- * data) at our new location */
+- *cur = xmlnode_new_child(*cur, tmp->name);
+- for (tmp = tmp->child; tmp != NULL; tmp = tmp->next)
+- if (tmp->type == XMLNODE_TYPE_ATTRIB)
+- xmlnode_set_attrib_full(*cur, tmp->name,
+- tmp->xmlns, tmp->prefix, tmp->data);
+- }
+- } else {
+- const char *start;
+- const char *end;
+- GData *attributes;
+- char *fontsize = NULL;
+-
+- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+- *cur = xmlnode_new_child(*cur, tag_name);
+-
+- if (is_font_tag) {
+- /* Special case for the font size attribute */
+- fontsize = g_strdup(g_datalist_get_data(&attributes, "size"));
+- if (fontsize != NULL)
+- g_datalist_remove_data(&attributes, "size");
+- }
+-
+- /* Add all font tag attributes */
+- g_datalist_foreach(&attributes, append_attrs_datalist_foreach_cb, *cur);
+- g_datalist_clear(&attributes);
+-
+- if (fontsize != NULL) {
+-#ifdef USE_CSS_FORMATTING
+- /*
+- * The Yahoo font size value is given in pt, even though the HTML
+- * standard for <font size="x"> treats the size as a number on a
+- * scale between 1 and 7. So we insert the font size as a CSS
+- * style on a span tag.
+- */
+- gchar *tmp = g_strdup_printf("font-size: %spt", fontsize);
+- *cur = xmlnode_new_child(*cur, "span");
+- xmlnode_set_attrib(*cur, "style", tmp);
+- g_free(tmp);
+-#else
+- /*
+- * The Yahoo font size value is given in pt, even though the HTML
+- * standard for <font size="x"> treats the size as a number on a
+- * scale between 1 and 7. So we convert it to an appropriate
+- * value. This loses precision, which is why CSS formatting is
+- * preferred. The "absz" attribute remains here for backward
+- * compatibility with UIs that might use it, but it is totally
+- * not standard at all.
+- */
+- int size, htmlsize;
+- gchar tmp[11];
+- size = strtol(fontsize, NULL, 10);
+- htmlsize = point_to_html(size);
+- sprintf(tmp, "%u", htmlsize);
+- xmlnode_set_attrib(*cur, "size", tmp);
+- xmlnode_set_attrib(*cur, "absz", fontsize);
+-#endif /* !USE_CSS_FORMATTING */
+- g_free(fontsize);
+- }
+- }
+-}
+-
+-/**
+- * Similar to purple_markup_get_tag_name(), but works with closing tags.
+- *
+- * @return The lowercase name of the tag. If this is a closing tag then
+- * this value starts with a forward slash. The caller must free
+- * this string with g_free.
+- */
+-static gchar *yahoo_markup_get_tag_name(const char *tag, gboolean *is_closing_tag)
+-{
+- size_t len;
+-
+- *is_closing_tag = (tag[1] == '/');
+- if (*is_closing_tag)
+- len = strcspn(tag + 1, "> ");
+- else
+- len = strcspn(tag + 1, "> /");
+-
+- return g_utf8_strdown(tag + 1, len);
+-}
+-
+-/*
+- * Yahoo! messages generally aren't well-formed. Their markup is
+- * more of a flow from start to finish rather than a hierarchy from
+- * outer to inner. They tend to open tags and close them only when
+- * necessary.
+- *
+- * Example: <font size="8">size 8 <font size="16">size 16 <font size="8">size 8 again
+- *
+- * But we want to send well-formed HTML to the core, so we step through
+- * the input string and build an xmlnode tree containing sanitized HTML.
+- */
+-char *yahoo_codes_to_html(const char *x)
+-{
+- size_t x_len;
+- xmlnode *html, *cur;
+- GString *cdata = g_string_new(NULL);
+- int i, j;
+- gboolean no_more_gt_brackets = FALSE;
+- const char *match;
+- gchar *xmlstr1, *xmlstr2, *esc;
+-
+- x_len = strlen(x);
+- html = xmlnode_new("html");
+-
+- cur = html;
+- for (i = 0; i < x_len; i++) {
+- if ((x[i] == 0x1b) && (x[i+1] == '[')) {
+- /* This escape sequence signifies the beginning of some
+- * text formatting code */
+- j = i + 1;
+-
+- while (j++ < x_len) {
+- gchar *code;
+-
+- if (x[j] != 'm')
+- /* Keep looking for the end of this sequence */
+- continue;
+-
+- /* We've reached the end of the formatting sequence, yay */
+-
+- /* Append any character data that belongs in the current node */
+- if (cdata->len > 0) {
+- xmlnode_insert_data(cur, cdata->str, cdata->len);
+- g_string_truncate(cdata, 0);
+- }
+-
+- code = g_strndup(x + i + 2, j - i - 2);
+- if (code[0] == '#') {
+-#ifdef USE_CSS_FORMATTING
+- gchar *tmp = g_strdup_printf("color: %s", code);
+- cur = xmlnode_new_child(cur, "span");
+- xmlnode_set_attrib(cur, "style", tmp);
+- g_free(tmp);
+-#else
+- cur = xmlnode_new_child(cur, "font");
+- xmlnode_set_attrib(cur, "color", code);
+-#endif /* !USE_CSS_FORMATTING */
+-
+- } else if ((match = g_hash_table_lookup(esc_codes_ht, code))) {
+- /* Some tags are in the hash table only because we
+- * want to ignore them */
+- if (match[0] != '\0') {
+- gboolean is_closing_tag;
+- gchar *tag_name;
+- tag_name = yahoo_markup_get_tag_name(match, &is_closing_tag);
+- yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
+- g_free(tag_name);
+- }
+-
+- } else {
+- purple_debug_error("yahoo",
+- "Ignoring unknown ansi code 'ESC[%sm'.\n", code);
+- }
+-
+- g_free(code);
+- i = j;
+- break;
+- }
+-
+- } else if (x[i] == '<' && !no_more_gt_brackets) {
+- /* The start of an HTML tag */
+- j = i;
+-
+- while (j++ < x_len) {
+- gchar *tag;
+- gboolean is_closing_tag;
+- gchar *tag_name;
+-
+- if (x[j] != '>') {
+- if (x[j] == '"') {
+- /* We're inside a quoted attribute value. Skip to the end */
+- j++;
+- while (j != x_len && x[j] != '"')
+- j++;
+- } else if (x[j] == '\'') {
+- /* We're inside a quoted attribute value. Skip to the end */
+- j++;
+- while (j != x_len && x[j] != '\'')
+- j++;
+- }
+- if (j != x_len)
+- /* Keep looking for the end of this tag */
+- continue;
+-
+- /* This < has no corresponding > */
+- g_string_append_c(cdata, x[i]);
+- no_more_gt_brackets = TRUE;
+- break;
+- }
+-
+- tag = g_strndup(x + i, j - i + 1);
+- tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
+-
+- match = g_hash_table_lookup(tags_ht, tag_name);
+- if (match == NULL) {
+- /* Unknown tag. The user probably typed a less-than sign */
+- g_string_append_c(cdata, x[i]);
+- g_free(tag);
+- g_free(tag_name);
+- break;
+- }
+-
+- /* Some tags are in the hash table only because we
+- * want to ignore them */
+- if (match[0] != '\0') {
+- /* Append any character data that belongs in the current node */
+- if (cdata->len > 0) {
+- xmlnode_insert_data(cur, cdata->str, cdata->len);
+- g_string_truncate(cdata, 0);
+- }
+- if (g_str_equal(tag_name, "font"))
+- /* Font tags are a special case. We don't
+- * necessarily want to replace the whole thing--
+- * we just want to fix the size attribute. */
+- yahoo_codes_to_html_add_tag(&cur, tag, is_closing_tag, tag_name, TRUE);
+- else
+- yahoo_codes_to_html_add_tag(&cur, match, is_closing_tag, tag_name, FALSE);
+- }
+-
+- i = j;
+- g_free(tag);
+- g_free(tag_name);
+- break;
+- }
+-
+- } else {
+- g_string_append_c(cdata, x[i]);
+- }
+- }
+-
+- /* Append any remaining character data */
+- if (cdata->len > 0)
+- xmlnode_insert_data(cur, cdata->str, cdata->len);
+- g_string_free(cdata, TRUE);
+-
+- /* Serialize our HTML */
+- xmlstr1 = xmlnode_to_str(html, NULL);
+- xmlnode_free(html);
+-
+- /* Strip off the outter HTML node */
+- /* This probably isn't necessary, especially if we made the outter HTML
+- * node an empty span. But the HTML is simpler this way. */
+- if (!purple_strequal(xmlstr1, "<html/>"))
+- xmlstr2 = g_strndup(xmlstr1 + 6, strlen(xmlstr1) - 13);
+- else
+- xmlstr2 = g_strdup("");
+- g_free(xmlstr1);
+-
+- esc = g_strescape(x, NULL);
+- purple_debug_misc("yahoo", "yahoo_codes_to_html(%s)=%s\n", esc, xmlstr2);
+- g_free(esc);
+-
+- return xmlstr2;
+-}
+-
+-/* borrowed from gtkimhtml */
+-#define MAX_FONT_SIZE 7
+-#define POINT_SIZE(x) (_point_sizes [MIN ((x > 0 ? x : 1), MAX_FONT_SIZE) - 1])
+-static const gint _point_sizes [] = { 8, 10, 12, 14, 20, 30, 40 };
+-
+-typedef struct
+-{
+- gboolean bold;
+- gboolean italic;
+- gboolean underline;
+- gboolean in_link;
+- int font_size;
+- char *font_face;
+- char *font_color;
+-} CurrentMsgState;
+-
+-static void yahoo_htc_list_cleanup(GSList *l)
+-{
+- while (l != NULL) {
+- g_free(l->data);
+- l = g_slist_delete_link(l, l);
+- }
+-}
+-
+-static void parse_font_tag(GString *dest, const char *tag_name, const char *tag,
+- GSList **colors, GSList **tags)
+-{
+- const char *start;
+- const char *end;
+- GData *attributes;
+- const char *attribute;
+- gboolean needendtag;
+- GString *tmp;
+-
+- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+-
+- needendtag = FALSE;
+- tmp = g_string_new(NULL);
+-
+- attribute = g_datalist_get_data(&attributes, "color");
+- if (attribute != NULL) {
+- g_string_append(tmp, *colors ? (*colors)->data : "\033[#000000m");
+- g_string_append_printf(dest, "\033[%sm", attribute);
+- *colors = g_slist_prepend(*colors,
+- g_strdup_printf("\033[%sm", attribute));
+- } else {
+- /* We need to add a value to the colors stack even if we're not
+- * setting a color because we ALWAYS pop exactly 1 element from
+- * this stack for every </font> tag. If we don't add anything
+- * then we'll pop something that we shouldn't when we hit this
+- * corresponding </font>. */
+- *colors = g_slist_prepend(*colors,
+- *colors ? g_strdup((*colors)->data) : g_strdup("\033[#000000m"));
+- }
+-
+- attribute = g_datalist_get_data(&attributes, "face");
+- if (attribute != NULL) {
+- needendtag = TRUE;
+- g_string_append(dest, "<font ");
+- g_string_append_printf(dest, "face=\"%s\" ", attribute);
+- }
+-
+- attribute = g_datalist_get_data(&attributes, "size");
+- if (attribute != NULL) {
+- if (!needendtag) {
+- needendtag = TRUE;
+- g_string_append(dest, "<font ");
+- }
+-
+- g_string_append_printf(dest, "size=\"%d\" ",
+- POINT_SIZE(strtol(attribute, NULL, 10)));
+- }
+-
+- if (needendtag) {
+- dest->str[dest->len-1] = '>';
+- *tags = g_slist_prepend(*tags, g_strdup("</font>"));
+- g_string_free(tmp, TRUE);
+- } else {
+- *tags = g_slist_prepend(*tags, tmp->str);
+- g_string_free(tmp, FALSE);
+- }
+-
+- g_datalist_clear(&attributes);
+-}
+-
+-char *yahoo_html_to_codes(const char *src)
+-{
+- GSList *colors = NULL;
+-
+- /**
+- * A stack of char*s where each char* is the string that should be
+- * appended to dest in order to close all the tags that were opened
+- * by a <font> tag.
+- */
+- GSList *tags = NULL;
+-
+- size_t src_len;
+- int i, j;
+- GString *dest;
+- char *esc;
+- gboolean no_more_gt_brackets = FALSE;
+- gchar *tag, *tag_name;
+- gboolean is_closing_tag;
+- CurrentMsgState current_state;
+-
+- memset(&current_state, 0, sizeof(current_state));
+-
+- src_len = strlen(src);
+- dest = g_string_sized_new(src_len);
+-
+- for (i = 0; i < src_len; i++) {
+- if (src[i] == '<' && !no_more_gt_brackets) {
+- /* The start of an HTML tag */
+- j = i;
+-
+- while (j++ < src_len) {
+- if (src[j] != '>') {
+- if (src[j] == '"') {
+- /* We're inside a quoted attribute value. Skip to the end */
+- j++;
+- while (j != src_len && src[j] != '"')
+- j++;
+- } else if (src[j] == '\'') {
+- /* We're inside a quoted attribute value. Skip to the end */
+- j++;
+- while (j != src_len && src[j] != '\'')
+- j++;
+- }
+- if (j != src_len)
+- /* Keep looking for the end of this tag */
+- continue;
+-
+- /* This < has no corresponding > */
+- g_string_append_c(dest, src[i]);
+- no_more_gt_brackets = TRUE;
+- break;
+- }
+-
+- tag = g_strndup(src + i, j - i + 1);
+- tag_name = yahoo_markup_get_tag_name(tag, &is_closing_tag);
+-
+- if (g_str_equal(tag_name, "a")) {
+- const char *start;
+- const char *end;
+- GData *attributes;
+- const char *attribute;
+-
+- /*
+- * TODO: Ideally we would replace this:
+- * <a href="http://pidgin.im/">Pidgin</a>
+- * with this:
+- * Pidgin (http://pidgin.im/)
+- *
+- * Currently we drop the text within the <a> tag and
+- * just show the URL. Doing it the fancy way is
+- * complicated when dealing with HTML tags within the
+- * <a> tag.
+- */
+-
+- /* Append the URL */
+- purple_markup_find_tag(tag_name, tag, &start, &end, &attributes);
+- attribute = g_datalist_get_data(&attributes, "href");
+- if (attribute != NULL) {
+- if (purple_str_has_prefix(attribute, "mailto:"))
+- attribute += 7;
+- g_string_append(dest, attribute);
+- }
+- g_datalist_clear(&attributes);
+-
+- /* Skip past the closing </a> tag */
+- end = purple_strcasestr(src + j, "</a>");
+- if (end != NULL)
+- j = end - src + 3;
+-
+- } else if (g_str_equal(tag_name, "font")) {
+- parse_font_tag(dest, tag_name, tag, &colors, &tags);
+- } else if (g_str_equal(tag_name, "b")) {
+- g_string_append(dest, "\033[1m");
+- current_state.bold = TRUE;
+- } else if (g_str_equal(tag_name, "/b")) {
+- if (current_state.bold) {
+- g_string_append(dest, "\033[x1m");
+- current_state.bold = FALSE;
+- }
+- } else if (g_str_equal(tag_name, "i")) {
+- current_state.italic = TRUE;
+- g_string_append(dest, "\033[2m");
+- } else if (g_str_equal(tag_name, "/i")) {
+- if (current_state.italic) {
+- g_string_append(dest, "\033[x2m");
+- current_state.italic = FALSE;
+- }
+- } else if (g_str_equal(tag_name, "u")) {
+- current_state.underline = TRUE;
+- g_string_append(dest, "\033[4m");
+- } else if (g_str_equal(tag_name, "/u")) {
+- if (current_state.underline) {
+- g_string_append(dest, "\033[x4m");
+- current_state.underline = FALSE;
+- }
+- } else if (g_str_equal(tag_name, "/a")) {
+- /* Do nothing */
+- } else if (g_str_equal(tag_name, "br")) {
+- g_string_append_c(dest, '\n');
+- } else if (g_str_equal(tag_name, "/font")) {
+- if (tags != NULL) {
+- char *etag = tags->data;
+- tags = g_slist_delete_link(tags, tags);
+- g_string_append(dest, etag);
+- if (colors != NULL) {
+- g_free(colors->data);
+- colors = g_slist_delete_link(colors, colors);
+- }
+- g_free(etag);
+- }
+- } else if (g_str_equal(tag_name, "span") || g_str_equal(tag_name, "/span")) {
+- /* Do nothing */
+- } else {
+- /* We don't know what the tag is. Send it unmodified. */
+- g_string_append(dest, tag);
+- }
+-
+- i = j;
+- g_free(tag);
+- g_free(tag_name);
+- break;
+- }
+-
+- } else {
+- const char *entity;
+- int length;
+-
+- entity = purple_markup_unescape_entity(src + i, &length);
+- if (entity != NULL) {
+- /* src[i] is the start of an HTML entity */
+- g_string_append(dest, entity);
+- i += length - 1;
+- } else
+- /* src[i] is a normal character */
+- g_string_append_c(dest, src[i]);
+- }
+- }
+-
+- esc = g_strescape(dest->str, NULL);
+- purple_debug_misc("yahoo", "yahoo_html_to_codes(%s)=%s\n", src, esc);
+- g_free(esc);
+-
+- yahoo_htc_list_cleanup(colors);
+- yahoo_htc_list_cleanup(tags);
+-
+- return g_string_free(dest, FALSE);
+-}
+-
+-YahooFederation yahoo_get_federation_from_name(const char *who)
+-{
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+- if (who[3] == '/') {
+- if (!g_ascii_strncasecmp(who, "msn", 3))
+- fed = YAHOO_FEDERATION_MSN;
+- else if (!g_ascii_strncasecmp(who, "ocs", 3))
+- fed = YAHOO_FEDERATION_OCS;
+- else if (!g_ascii_strncasecmp(who, "ibm", 3))
+- fed = YAHOO_FEDERATION_IBM;
+- else if (!g_ascii_strncasecmp(who, "pbx", 3))
+- fed = YAHOO_FEDERATION_PBX;
+- }
+- return fed;
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,718 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "blist.h"
+-#include "debug.h"
+-#include "util.h"
+-#include "request.h"
+-#include "version.h"
+-#include "libymsg.h"
+-#include "yahoo_aliases.h"
+-#include "yahoo_friend.h"
+-#include "yahoo_packet.h"
+-
+-/* I hate hardcoding this stuff, but Yahoo never sends us anything to use. Someone in the know may be able to tweak this URL */
+-#define YAHOO_ALIAS_FETCH_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOO_CLIENT_VERSION "&useutf8=1&legenc=codepage-1252"
+-#define YAHOO_ALIAS_UPDATE_URL "http://address.yahoo.com/yab/us?v=XM&prog=ymsgr&.intl=us&sync=1&tags=short&noclear=1&useutf8=1&legenc=codepage-1252"
+-#define YAHOOJP_ALIAS_FETCH_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&diffs=1&t=0&tags=short&rt=0&prog-ver=" YAHOOJP_CLIENT_VERSION
+-#define YAHOOJP_ALIAS_UPDATE_URL "http://address.yahoo.co.jp/yab/jp?v=XM&prog=ymsgr&.intl=jp&sync=1&tags=short&noclear=1"
+-
+-void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
+-
+-/**
+- * Stuff we want passed to the callback function
+- */
+-struct callback_data {
+- PurpleConnection *gc;
+- gchar *id;
+- gchar *who;
+-};
+-
+-void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all)
+-{
+- if (all)
+- g_free(ypd->id);
+- g_free(ypd->names.first);
+- g_free(ypd->names.last);
+- g_free(ypd->names.middle);
+- g_free(ypd->names.nick);
+- g_free(ypd->phone.work);
+- g_free(ypd->phone.home);
+- g_free(ypd->phone.mobile);
+-}
+-
+-/**************************************************************************
+- * Alias Fetch Functions
+- **************************************************************************/
+-
+-static void
+-yahoo_fetch_aliases_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- PurpleConnection *gc = user_data;
+- YahooData *yd = gc->proto_data;
+-
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (len == 0) {
+- purple_debug_info("yahoo", "No Aliases to process.%s%s\n",
+- error_message ? " Error:" : "", error_message ? error_message : "");
+- } else {
+- gchar *full_name, *nick_name;
+- const char *yid, *id, *fn, *ln, *nn, *alias, *mn;
+- const char *hp, *wp, *mo;
+- YahooFriend *f;
+- PurpleBuddy *b;
+- xmlnode *item, *contacts;
+- PurpleAccount *account;
+-
+- account = purple_connection_get_account(gc);
+- /* Put our web response into a xmlnode for easy management */
+- contacts = xmlnode_from_str(url_text, -1);
+-
+- if (contacts == NULL) {
+- purple_debug_error("yahoo", "Badly formed Alias XML\n");
+- return;
+- }
+- purple_debug_info("yahoo", "Fetched %" G_GSIZE_FORMAT
+- " bytes of alias data\n", len);
+-
+- /* Loop around and around and around until we have gone through all the received aliases */
+- for(item = xmlnode_get_child(contacts, "ct"); item; item = xmlnode_get_next_twin(item)) {
+- /* Yahoo replies with two types of contact (ct) record, we are only interested in the alias ones */
+- if ((yid = xmlnode_get_attrib(item, "yi"))) {
+- YahooPersonalDetails *ypd = NULL;
+- /* Grab all the bits of information we can */
+- fn = xmlnode_get_attrib(item, "fn");
+- ln = xmlnode_get_attrib(item, "ln");
+- nn = xmlnode_get_attrib(item, "nn");
+- mn = xmlnode_get_attrib(item, "mn");
+- id = xmlnode_get_attrib(item, "id");
+-
+- hp = xmlnode_get_attrib(item, "hp");
+- wp = xmlnode_get_attrib(item, "wp");
+- mo = xmlnode_get_attrib(item, "mo");
+-
+- full_name = nick_name = NULL;
+- alias = NULL;
+-
+- /* Yahoo stores first and last names separately, lets put them together into a full name */
+- if (yd->jp)
+- full_name = g_strstrip(g_strdup_printf("%s %s", (ln != NULL ? ln : "") , (fn != NULL ? fn : "")));
+- else
+- full_name = g_strstrip(g_strdup_printf("%s %s", (fn != NULL ? fn : "") , (ln != NULL ? ln : "")));
+- nick_name = (nn != NULL ? g_strstrip(g_strdup(nn)) : NULL);
+-
+- if (nick_name != NULL)
+- alias = nick_name; /* If we have a nickname from Yahoo, let's use it */
+- else if (strlen(full_name) != 0)
+- alias = full_name; /* If no Yahoo nickname, we can use the full_name created above */
+-
+- /* Find the local buddy that matches */
+- f = yahoo_friend_find(gc, yid);
+- b = purple_find_buddy(account, yid);
+-
+- /* If we don't find a matching buddy, ignore the alias !! */
+- if (f != NULL && b != NULL) {
+- const char *buddy_alias = purple_buddy_get_alias(b);
+- yahoo_friend_set_alias_id(f, id);
+-
+- /* Finally, if we received an alias, we better update the buddy list */
+- if (alias != NULL) {
+- serv_got_alias(gc, yid, alias);
+- purple_debug_info("yahoo", "Fetched alias '%s' (%s)\n", alias, id);
+- } else if (buddy_alias && *buddy_alias && !g_str_equal(buddy_alias, yid)) {
+- /* Or if we have an alias that Yahoo doesn't, send it up */
+- yahoo_update_alias(gc, yid, buddy_alias);
+- purple_debug_info("yahoo", "Sent updated alias '%s'\n", buddy_alias);
+- }
+- }
+-
+- if (f != NULL)
+- ypd = &f->ypd;
+- else {
+- /* May be the alias is for the account? */
+- const char *yidn = purple_normalize(account, yid);
+- if (purple_strequal(yidn, purple_connection_get_display_name(gc))) {
+- ypd = &yd->ypd;
+- }
+- }
+-
+- if (ypd) {
+- yahoo_personal_details_reset(ypd, TRUE);
+- ypd->id = g_strdup(id);
+- ypd->names.first = g_strdup(fn);
+- ypd->names.middle = g_strdup(mn);
+- ypd->names.last = g_strdup(ln);
+- ypd->names.nick = g_strdup(nn);
+-
+- ypd->phone.work = g_strdup(wp);
+- ypd->phone.home = g_strdup(hp);
+- ypd->phone.mobile = g_strdup(mo);
+- }
+-
+- g_free(full_name);
+- g_free(nick_name);
+- }
+- }
+- xmlnode_free(contacts);
+- }
+-}
+-
+-void
+-yahoo_fetch_aliases(PurpleConnection *gc)
+-{
+- YahooData *yd = gc->proto_data;
+- const char *url;
+- gchar *request, *webpage, *webaddress;
+- PurpleUtilFetchUrlData *url_data;
+-
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+-
+- /* Build all the info to make the web request */
+- url = yd->jp ? YAHOOJP_ALIAS_FETCH_URL : YAHOO_ALIAS_FETCH_URL;
+- purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
+- request = g_strdup_printf("GET %s%s/%s HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
+- "Cookie: T=%s; Y=%s\r\n"
+- "Host: %s\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
+- yd->cookie_t, yd->cookie_y,
+- webaddress);
+-
+- /* We have a URL and some header information, let's connect and get some aliases */
+- url_data = purple_util_fetch_url_request_len_with_account(purple_connection_get_account(gc),
+- url, use_whole_url, NULL, TRUE, request, FALSE, -1,
+- yahoo_fetch_aliases_cb, gc);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- g_free(webaddress);
+- g_free(webpage);
+- g_free(request);
+-}
+-
+-/**************************************************************************
+- * Alias Update Functions
+- **************************************************************************/
+-
+-static void
+-yahoo_update_alias_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- xmlnode *node, *result;
+- struct callback_data *cb = user_data;
+- PurpleConnection *gc = cb->gc;
+- YahooData *yd;
+-
+- yd = gc->proto_data;
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (len == 0 || error_message != NULL) {
+- purple_debug_info("yahoo", "Error updating alias for %s: %s\n",
+- cb->who,
+- error_message ? error_message : "");
+- g_free(cb->who);
+- g_free(cb->id);
+- g_free(cb);
+- return;
+- }
+-
+- result = xmlnode_from_str(url_text, -1);
+-
+- if (result == NULL) {
+- purple_debug_error("yahoo", "Alias update for %s failed: Badly formed response\n",
+- cb->who);
+- g_free(cb->who);
+- g_free(cb->id);
+- g_free(cb);
+- return;
+- }
+-
+- if ((node = xmlnode_get_child(result, "ct"))) {
+- if (cb->id == NULL) {
+- const char *new_id = xmlnode_get_attrib(node, "id");
+- if (new_id != NULL) {
+- /* We now have an addressbook id for the friend; we should save it */
+- YahooFriend *f = yahoo_friend_find(cb->gc, cb->who);
+-
+- purple_debug_info("yahoo", "Alias creation for %s succeeded\n", cb->who);
+-
+- if (f)
+- yahoo_friend_set_alias_id(f, new_id);
+- else
+- purple_debug_error("yahoo", "Missing YahooFriend. Unable to store new addressbook id.\n");
+- } else
+- purple_debug_error("yahoo", "Missing new addressbook id in add response for %s (weird).\n",
+- cb->who);
+- } else {
+- if (g_ascii_strncasecmp(xmlnode_get_attrib(node, "id"), cb->id, strlen(cb->id))==0)
+- purple_debug_info("yahoo", "Alias update for %s succeeded\n", cb->who);
+- else
+- purple_debug_error("yahoo", "Alias update for %s failed (Contact record return mismatch)\n",
+- cb->who);
+- }
+- } else
+- purple_debug_info("yahoo", "Alias update for %s failed (No contact record returned)\n", cb->who);
+-
+- g_free(cb->who);
+- g_free(cb->id);
+- g_free(cb);
+- xmlnode_free(result);
+-}
+-
+-void
+-yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias)
+-{
+- YahooData *yd;
+- const char *url;
+- gchar *content, *request, *webpage, *webaddress;
+- struct callback_data *cb;
+- PurpleUtilFetchUrlData *url_data;
+- YahooFriend *f;
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+-
+- g_return_if_fail(who != NULL);
+- g_return_if_fail(gc != NULL);
+-
+- if (alias == NULL)
+- alias = "";
+-
+- f = yahoo_friend_find(gc, who);
+- if (f == NULL) {
+- purple_debug_error("yahoo", "Missing YahooFriend. Unable to set server alias.\n");
+- return;
+- }
+-
+- yd = gc->proto_data;
+-
+- /* Using callback_data so I have access to gc in the callback function */
+- cb = g_new0(struct callback_data, 1);
+- cb->who = g_strdup(who);
+- cb->id = g_strdup(yahoo_friend_get_alias_id(f));
+- cb->gc = gc;
+-
+- /* Build all the info to make the web request */
+- url = yd->jp ? YAHOOJP_ALIAS_UPDATE_URL: YAHOO_ALIAS_UPDATE_URL;
+- purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
+-
+- if (cb->id == NULL) {
+- /* No id for this buddy, so create an address book entry */
+- purple_debug_info("yahoo", "Creating '%s' as new alias for user '%s'\n", alias, who);
+-
+- if (yd->jp) {
+- gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
+- gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
+- content = g_strdup_printf("<ab k=\"%s\" cc=\"9\">\n"
+- "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
+- purple_account_get_username(gc->account),
+- who, converted_alias_jp);
+- g_free(converted_alias_jp);
+- g_free(alias_jp);
+- } else {
+- gchar *escaped_alias = g_markup_escape_text(alias, -1);
+- content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"9\">\n"
+- "<ct a=\"1\" yi='%s' nn='%s' />\n</ab>\r\n",
+- purple_account_get_username(gc->account),
+- who, escaped_alias);
+- g_free(escaped_alias);
+- }
+- } else {
+- purple_debug_info("yahoo", "Updating '%s' as new alias for user '%s'\n", alias, who);
+-
+- if (yd->jp) {
+- gchar *alias_jp = g_convert(alias, -1, "EUC-JP", "UTF-8", NULL, NULL, NULL);
+- gchar *converted_alias_jp = yahoo_convert_to_numeric(alias_jp);
+- content = g_strdup_printf("<ab k=\"%s\" cc=\"1\">\n"
+- "<ct e=\"1\" yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
+- purple_account_get_username(gc->account),
+- who, cb->id, converted_alias_jp);
+- g_free(converted_alias_jp);
+- g_free(alias_jp);
+- } else {
+- gchar *escaped_alias = g_markup_escape_text(alias, -1);
+- content = g_strdup_printf("<?xml version=\"1.0\" encoding=\"utf-8\"?><ab k=\"%s\" cc=\"1\">\n"
+- "<ct e=\"1\" yi='%s' id='%s' nn='%s' pr='0' />\n</ab>\r\n",
+- purple_account_get_username(gc->account),
+- who, cb->id, escaped_alias);
+- g_free(escaped_alias);
+- }
+- }
+-
+- request = g_strdup_printf("POST %s%s/%s HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
+- "Cookie: T=%s; Y=%s\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
+- "Cache-Control: no-cache\r\n\r\n"
+- "%s",
+- use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage,
+- yd->cookie_t, yd->cookie_y,
+- webaddress,
+- strlen(content),
+- content);
+-
+- /* We have a URL and some header information, let's connect and update the alias */
+- url_data = purple_util_fetch_url_request_len_with_account(
+- purple_connection_get_account(gc), url, use_whole_url, NULL, TRUE,
+- request, FALSE, -1, yahoo_update_alias_cb, cb);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- g_free(webpage);
+- g_free(webaddress);
+- g_free(content);
+- g_free(request);
+-}
+-
+-
+-/**************************************************************************
+- * User Info Update Functions
+- **************************************************************************/
+-
+-#if 0
+-/* This block of code can be used to send our contact details to
+- * everyone in the buddylist. But with the official messenger,
+- * doing this pops a conversation window at the receiver's end,
+- * which is stupid, and thus not really surprising. */
+-
+-struct yahoo_userinfo {
+- YahooData *yd;
+- char *xml;
+-};
+-
+-static void
+-yahoo_send_userinfo_to_user(struct yahoo_userinfo *yui, const char *who)
+-{
+- struct yahoo_packet *pkt;
+- PurpleConnection *gc;
+-
+- gc = yui->yd->gc;
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CONTACT_DETAILS, 0, 0);
+- yahoo_packet_hash(pkt, "siisis",
+- 1, purple_connection_get_display_name(gc),
+- 13, 1, /* This creates a conversation window in the official client */
+- 302, 5,
+- 5, who,
+- 303, 5,
+- 280, yui->xml);
+- yahoo_packet_send_and_free(pkt, yui->yd);
+-}
+-
+-static void
+-yahoo_send_userinfo_foreach(gpointer key, gpointer value, gpointer data)
+-{
+- const char *who = key;
+- YahooFriend *f = value;
+-
+- if (f->status != YAHOO_STATUS_OFFLINE) {
+- yahoo_send_userinfo_to_user(data, who);
+- }
+-}
+-
+-static void
+-yahoo_sent_userinfo_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data, const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- struct yahoo_userinfo *yui = user_data;
+- yahoo_fetch_aliases_cb(url_data, yui->yd->gc, url_text, len, error_message);
+- g_hash_table_foreach(yui->yd->friends, yahoo_send_userinfo_foreach, yui);
+- g_free(yui->xml);
+- g_free(yui);
+-}
+-#endif
+-
+-static void
+-yahoo_set_userinfo_cb(PurpleConnection *gc, PurpleRequestFields *fields)
+-{
+- xmlnode *node = xmlnode_new("ab");
+- xmlnode *ct = xmlnode_new_child(node, "ct");
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+- PurpleAccount *account;
+- PurpleUtilFetchUrlData *url_data;
+- char *webaddress, *webpage;
+- char *request, *content;
+- int len;
+- int i;
+- char * yfields[] = { "fn", "ln", "nn", "mn", "hp", "wp", "mo", NULL };
+-
+- account = purple_connection_get_account(gc);
+-
+- xmlnode_set_attrib(node, "k", purple_connection_get_display_name(gc));
+- xmlnode_set_attrib(node, "cc", "1"); /* XXX: ? */
+-
+- xmlnode_set_attrib(ct, "e", "1");
+- xmlnode_set_attrib(ct, "yi", purple_request_fields_get_string(fields, "yname"));
+- xmlnode_set_attrib(ct, "id", purple_request_fields_get_string(fields, "yid"));
+- xmlnode_set_attrib(ct, "pr", "0");
+-
+- for (i = 0; yfields[i]; i++) {
+- const char *v = purple_request_fields_get_string(fields, yfields[i]);
+- xmlnode_set_attrib(ct, yfields[i], v ? v : "");
+- }
+-
+- content = xmlnode_to_formatted_str(node, &len);
+- xmlnode_free(node);
+- purple_url_parse(yd->jp ? YAHOOJP_USERINFO_URL : YAHOO_USERINFO_URL, &webaddress, NULL, &webpage, NULL, NULL);
+-
+- request = g_strdup_printf("POST %s HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT_ALIAS "\r\n"
+- "Cookie: T=%s; path=/; domain=.yahoo.com; Y=%s;\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %d\r\n"
+- "Cache-Control: no-cache\r\n\r\n"
+- "%s\r\n\r\n",
+- webpage,
+- yd->cookie_t, yd->cookie_y,
+- webaddress,
+- len + 4,
+- content);
+-
+-#if 0
+- {
+- /* This is if we wanted to send our contact details to everyone
+- * in the buddylist. But this cannot be done now, because in the
+- * official messenger, doing this pops a conversation window at
+- * the receiver's end, which is stupid, and thus not really
+- * surprising. */
+- struct yahoo_userinfo *ui = g_new(struct yahoo_userinfo, 1);
+- node = xmlnode_new("contact");
+-
+- for (i = 0; yfields[i]; i++) {
+- const char *v = purple_request_fields_get_string(fields, yfields[i]);
+- if (v) {
+- xmlnode *nd = xmlnode_new_child(node, yfields[i]);
+- xmlnode_insert_data(nd, v, -1);
+- }
+- }
+-
+- ui->yd = yd;
+- ui->xml = xmlnode_to_str(node, NULL);
+- xmlnode_free(node);
+- }
+-#endif
+-
+- url_data = purple_util_fetch_url_request_len_with_account(account, webaddress, FALSE,
+- YAHOO_CLIENT_USERAGENT_ALIAS, TRUE, request, FALSE, -1,
+- yahoo_fetch_aliases_cb, gc);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- g_free(webaddress);
+- g_free(webpage);
+- g_free(content);
+- g_free(request);
+-}
+-
+-static PurpleRequestFields *
+-request_fields_from_personal_details(YahooPersonalDetails *ypd, const char *id)
+-{
+- PurpleRequestFields *fields;
+- PurpleRequestFieldGroup *group;
+- PurpleRequestField *field;
+- int i;
+- struct {
+- char *id;
+- char *text;
+- char *value;
+- } yfields[] = {
+- {"fn", N_("First Name"), ypd->names.first},
+- {"ln", N_("Last Name"), ypd->names.last},
+- {"nn", N_("Nickname"), ypd->names.nick},
+- {"mn", N_("Middle Name"), ypd->names.middle},
+- {"hp", N_("Home Phone Number"), ypd->phone.home},
+- {"wp", N_("Work Phone Number"), ypd->phone.work},
+- {"mo", N_("Mobile Phone Number"), ypd->phone.mobile},
+- {NULL, NULL, NULL}
+- };
+-
+- fields = purple_request_fields_new();
+- group = purple_request_field_group_new(NULL);
+- purple_request_fields_add_group(fields, group);
+-
+- field = purple_request_field_string_new("yname", "", id, FALSE);
+- purple_request_field_set_visible(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- field = purple_request_field_string_new("yid", "", ypd->id, FALSE);
+- purple_request_field_set_visible(field, FALSE);
+- purple_request_field_group_add_field(group, field);
+-
+- for (i = 0; yfields[i].id; i++) {
+- field = purple_request_field_string_new(yfields[i].id, _(yfields[i].text),
+- yfields[i].value, FALSE);
+- purple_request_field_group_add_field(group, field);
+- }
+-
+- return fields;
+-}
+-
+-void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy)
+-{
+- PurpleRequestFields *fields;
+- YahooFriend *f;
+- const char *name;
+-
+- name = purple_buddy_get_name(buddy);
+- f = yahoo_friend_find(gc, name);
+- if (!f)
+- return;
+-
+- fields = request_fields_from_personal_details(&f->ypd, name);
+- purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
+- _("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL, gc);
+-}
+-
+-void yahoo_set_userinfo(PurpleConnection *gc)
+-{
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+- PurpleRequestFields *fields = request_fields_from_personal_details(&yd->ypd,
+- purple_connection_get_display_name(gc));
+- purple_request_fields(gc, NULL, _("Set User Info"), NULL, fields,
+- _("OK"), G_CALLBACK(yahoo_set_userinfo_cb),
+- _("Cancel"), NULL,
+- purple_connection_get_account(gc), NULL, NULL, gc);
+-}
+-
+-static gboolean
+-parse_contact_details(YahooData *yd, const char *who, const char *xml)
+-{
+- xmlnode *node, *nd;
+- YahooFriend *f;
+- char *yid;
+-
+- node = xmlnode_from_str(xml, -1);
+- if (!node) {
+- purple_debug_info("yahoo", "Received malformed XML for contact details from '%s':\n%s\n",
+- who, xml);
+- return FALSE;
+- }
+-
+- nd = xmlnode_get_child(node, "yi");
+- if (!nd || !(yid = xmlnode_get_data(nd))) {
+- xmlnode_free(node);
+- return FALSE;
+- }
+-
+- if (!purple_strequal(yid, who)) {
+- /* The user may not want to set the contact details about folks in the buddylist
+- to what some random dude might have sent. So it would be good if we popped
+- up a prompt requiring the user to confirm the details before we set them.
+- However, someone could send details about hundreds of users at the same time,
+- which would make things really bad. So for now, until we have a better way of
+- dealing with this, ignore this details. */
+- purple_debug_info("yahoo", "Ignoring contact details sent by %s about %s\n",
+- who, yid);
+- g_free(yid);
+- xmlnode_free(node);
+- return FALSE;
+- }
+-
+- f = yahoo_friend_find(yd->gc, yid);
+- if (!f) {
+- g_free(yid);
+- xmlnode_free(node);
+- return FALSE;
+- } else {
+- int i;
+- YahooPersonalDetails *ypd = &f->ypd;
+- char *alias = NULL;
+- struct {
+- char *id;
+- char **field;
+- } details[] = {
+- {"fn", &ypd->names.first},
+- {"mn", &ypd->names.middle},
+- {"ln", &ypd->names.last},
+- {"nn", &ypd->names.nick},
+- {"wp", &ypd->phone.work},
+- {"hp", &ypd->phone.home},
+- {"mo", &ypd->phone.mobile},
+- {NULL, NULL}
+- };
+-
+- yahoo_personal_details_reset(ypd, FALSE);
+-
+- for (i = 0; details[i].id; i++) {
+- nd = xmlnode_get_child(node, details[i].id);
+- *details[i].field = nd ? xmlnode_get_data(nd) : NULL;
+- }
+-
+- if (ypd->names.nick)
+- alias = ypd->names.nick;
+- else if (ypd->names.first || ypd->names.last) {
+- alias = g_strstrip(g_strdup_printf("%s %s",
+- ypd->names.first ? ypd->names.first : "",
+- ypd->names.last ? ypd->names.last : ""));
+- }
+-
+- if (alias) {
+- serv_got_alias(yd->gc, yid, alias);
+- if (alias != ypd->names.nick)
+- g_free(alias);
+- }
+- }
+-
+- xmlnode_free(node);
+- g_free(yid);
+- return TRUE;
+-}
+-
+-/* I don't think this happens for MSN buddies. -- sad */
+-void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- const char *who = NULL, *xml = NULL;
+- YahooData *yd = purple_connection_get_protocol_data(gc);
+-
+- for (; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+- switch (pair->key) {
+- case 4:
+- who = pair->value; /* This is the person who sent us the details.
+- But not necessarily about himself. */
+- break;
+- case 5:
+- break;
+- case 13:
+- /* This is '1' if 'who' is sending the contact details about herself,
+- '0' if 'who' is sending the contact details she has about buddies
+- in her list. However, in all cases, the xml in key 280 always seems
+- to contain the yid of the person, so we may as well ignore this field
+- and look into the xml instead to see who the information is about. */
+- break;
+- case 280:
+- xml = pair->value;
+- parse_contact_details(yd, who, xml);
+- break;
+- }
+- }
+-}
+-
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_aliases.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_aliases.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,41 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "blist.h"
+-#include "debug.h"
+-#include "util.h"
+-#include "version.h"
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-
+-void yahoo_update_alias(PurpleConnection *gc, const char *who, const char *alias);
+-void yahoo_fetch_aliases(PurpleConnection *gc);
+-void yahoo_set_userinfo(PurpleConnection *gc);
+-void yahoo_set_userinfo_for_buddy(PurpleConnection *gc, PurpleBuddy *buddy);
+-void yahoo_personal_details_reset(YahooPersonalDetails *ypd, gboolean all);
+-void yahoo_process_contact_details(PurpleConnection *gc, struct yahoo_packet *pkt);
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1633 +0,0 @@
+-/*
+- * 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.
+- *
+- * Some code copyright 2003 Tim Ringenbach <omarvo@hotmail.com>
+- * (marv on irc.freenode.net)
+- * Some code borrowed from libyahoo2, copyright (C) 2002, Philip
+- * S Tellis <philip . tellis AT gmx . net>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#ifdef HAVE_CONFIG_H
+-#include "config.h"
+-#endif /* HAVE_CONFIG_H */
+-
+-#include "debug.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-
+-#include "conversation.h"
+-#include "notify.h"
+-#include "util.h"
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-#include "yahoochat.h"
+-#include "ycht.h"
+-
+-#define YAHOO_CHAT_ID (1)
+-
+-/* prototype(s) */
+-static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout);
+-
+-/* special function to log us on to the yahoo chat service */
+-static void yahoo_chat_online(PurpleConnection *gc)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- const char *rll;
+-
+- if (yd->wm) {
+- ycht_connection_open(gc);
+- return;
+- }
+-
+- rll = purple_account_get_string(purple_connection_get_account(gc),
+- "room_list_locale", YAHOO_ROOMLIST_LOCALE);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATONLINE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sssss",
+- 109, purple_connection_get_display_name(gc),
+- 1, purple_connection_get_display_name(gc),
+- 6, "abcde",
+- /* I'm not sure this is the correct way to set this. */
+- 98, rll,
+- 135, yd->jp ? YAHOO_CLIENT_VERSION : YAHOOJP_CLIENT_VERSION);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-/* this is slow, and different from the purple_* version in that it (hopefully) won't add a user twice */
+-void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers)
+-{
+- GList *i;
+-
+- for (i = newusers; i; i = i->next) {
+- if (purple_conv_chat_find_user(chat, i->data))
+- continue;
+- purple_conv_chat_add_user(chat, i->data, NULL, PURPLE_CBFLAGS_NONE, TRUE);
+- }
+-}
+-
+-void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason)
+-{
+- if (purple_conv_chat_find_user(chat, user))
+- return;
+-
+- purple_conv_chat_add_user(chat, user, reason, PURPLE_CBFLAGS_NONE, TRUE);
+-}
+-
+-static PurpleConversation *yahoo_find_conference(PurpleConnection *gc, const char *name)
+-{
+- YahooData *yd;
+- GSList *l;
+-
+- yd = gc->proto_data;
+-
+- for (l = yd->confs; l; l = l->next) {
+- PurpleConversation *c = l->data;
+- if (!purple_utf8_strcasecmp(purple_conversation_get_name(c), name))
+- return c;
+- }
+- return NULL;
+-}
+-
+-
+-void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account;
+- GSList *l;
+- char *room = NULL;
+- char *who = NULL;
+- char *msg = NULL;
+- GString *members = NULL;
+- GHashTable *components;
+-
+- if ( (pkt->status == 2) || (pkt->status == 11) )
+- return; /* Status is 11 when we are being notified about invitation being sent to someone else */
+-
+- account = purple_connection_get_account(gc);
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+- if (pair->key == 57)
+- {
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- if (yahoo_find_conference(gc, room) != NULL)
+- {
+- /* Looks like we got invited to an already open conference. */
+- /* Laters: Should we accept this conference rather than ignoring the invitation ? */
+- purple_debug_info("yahoo","Ignoring invitation for an already existing chat, room:%s\n",room);
+- g_free(room);
+- return;
+- }
+- }
+- }
+-
+- members = g_string_sized_new(512);
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 1: /* us, but we already know who we are */
+- break;
+- case 57:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 50: /* inviter */
+- who = pair->value;
+- g_string_append_printf(members, "%s\n", who);
+- break;
+- case 51: /* This user is being invited to the conference. Comes with status = 11, so we wont reach here */
+- break;
+- case 52: /* Invited users. Assuming us invited, since we got this packet */
+- break; /* break needed, or else we add the users to the conference before they accept the invitation */
+- case 53: /* members who have already joined the conference */
+- g_string_append_printf(members, "%s\n", pair->value);
+- break;
+- case 58:
+- g_free(msg);
+- msg = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 13: /* ? */
+- break;
+- }
+- }
+-
+- if (!room) {
+- g_string_free(members, TRUE);
+- g_free(msg);
+- return;
+- }
+-
+- if (!purple_privacy_check(account, who) ||
+- (purple_account_get_bool(account, "ignore_invites", FALSE)))
+- {
+- purple_debug_info("yahoo",
+- "Invite to conference %s from %s has been dropped.\n", room, who);
+- g_free(room);
+- g_free(msg);
+- g_string_free(members, TRUE);
+- return;
+- }
+-
+- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- g_hash_table_replace(components, g_strdup("room"), room);
+- if (msg)
+- g_hash_table_replace(components, g_strdup("topic"), msg);
+- g_hash_table_replace(components, g_strdup("type"), g_strdup("Conference"));
+- g_hash_table_replace(components, g_strdup("members"), g_string_free(members, FALSE));
+- serv_got_chat_invite(gc, room, who, msg, components);
+-
+-}
+-
+-void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l;
+- char *room = NULL;
+- char *who = NULL;
+- char *msg = NULL;
+- PurpleConversation *c = NULL;
+- int utf8 = 0;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 57:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 54:
+- who = pair->value;
+- break;
+- case 14:
+- g_free(msg);
+- msg = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 97:
+- utf8 = strtol(pair->value, NULL, 10);
+- break;
+- }
+- }
+- if (!purple_privacy_check(purple_connection_get_account(gc), who))
+- {
+- g_free(room);
+- g_free(msg);
+- return;
+- }
+-
+- if (who && room) {
+- /* make sure we're in the room before we process a decline message for it */
+- if((c = yahoo_find_conference(gc, room))) {
+- char *tmp = NULL, *msg_tmp = NULL;
+- if(msg)
+- {
+- msg_tmp = yahoo_string_decode(gc, msg, utf8);
+- msg = yahoo_codes_to_html(msg_tmp);
+- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
+- g_free(msg_tmp);
+- g_free(msg);
+- }
+-
+- tmp = g_strdup_printf(_("%s has declined to join."), who);
+- purple_conversation_write(c, NULL, tmp, PURPLE_MESSAGE_SYSTEM | PURPLE_MESSAGE_NO_LINKIFY, time(NULL));
+-
+- g_free(tmp);
+- }
+-
+- g_free(room);
+- }
+-}
+-
+-void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l;
+- char *room = NULL;
+- char *who = NULL;
+- PurpleConversation *c;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 57:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 53:
+- who = pair->value;
+- break;
+- }
+- }
+-
+- if (who && room) {
+- c = yahoo_find_conference(gc, room);
+- if (c)
+- { /* Prevent duplicate users in the chat */
+- if( !purple_conv_chat_find_user(PURPLE_CONV_CHAT(c), who) )
+- yahoo_chat_add_user(PURPLE_CONV_CHAT(c), who, NULL);
+- }
+- g_free(room);
+- }
+-}
+-
+-void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l;
+- char *room = NULL;
+- char *who = NULL;
+- PurpleConversation *c;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 57:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 56:
+- who = pair->value;
+- break;
+- }
+- }
+-
+- if (who && room) {
+- c = yahoo_find_conference(gc, room);
+- if (c)
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
+- g_free(room);
+- }
+-}
+-
+-void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l;
+- char *room = NULL;
+- char *who = NULL;
+- char *msg = NULL;
+- int utf8 = 0;
+- PurpleConversation *c;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 57:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 3:
+- who = pair->value;
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- case 97:
+- utf8 = strtol(pair->value, NULL, 10);
+- break;
+- }
+- }
+-
+- if (room && who && msg) {
+- char *msg2;
+-
+- c = yahoo_find_conference(gc, room);
+- if (!c) {
+- g_free(room);
+- return;
+- }
+-
+- msg2 = yahoo_string_decode(gc, msg, utf8);
+- msg = yahoo_codes_to_html(msg2);
+- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)), who, 0, msg, time(NULL));
+- g_free(msg);
+- g_free(msg2);
+- }
+-
+- g_free(room);
+-}
+-
+-static void yahoo_chat_join(PurpleConnection *gc, const char *dn, const char *room, const char *topic, const char *id)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- char *room2;
+- gboolean utf8 = TRUE;
+-
+- if (yd->wm) {
+- g_return_if_fail(yd->ycht != NULL);
+- ycht_chat_join(yd->ycht, room);
+- return;
+- }
+-
+- /* apparently room names are always utf8, or else always not utf8,
+- * so we don't have to actually pass the flag in the packet. Or something. */
+- room2 = yahoo_string_encode(gc, room, &utf8);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATJOIN, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "ssss",
+- 1, purple_connection_get_display_name(gc),
+- 104, room2,
+- 62, "2",
+- 129, id ? id : "0");
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(room2);
+-}
+-
+-/* this is a confirmation of yahoo_chat_online(); */
+-void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- YahooData *yd = (YahooData *) gc->proto_data;
+-
+- if (pkt->status == 1) {
+- yd->chat_online = TRUE;
+-
+- /* We need to goto a user in chat */
+- if (yd->pending_chat_goto) {
+- struct yahoo_packet *pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sss",
+- 109, yd->pending_chat_goto,
+- 1, purple_connection_get_display_name(gc),
+- 62, "2");
+- yahoo_packet_send_and_free(pkt, yd);
+- } else if (yd->pending_chat_room) {
+- yahoo_chat_join(gc, purple_connection_get_display_name(gc), yd->pending_chat_room,
+- yd->pending_chat_topic, yd->pending_chat_id);
+- }
+-
+- g_free(yd->pending_chat_room);
+- yd->pending_chat_room = NULL;
+- g_free(yd->pending_chat_id);
+- yd->pending_chat_id = NULL;
+- g_free(yd->pending_chat_topic);
+- yd->pending_chat_topic = NULL;
+- g_free(yd->pending_chat_goto);
+- yd->pending_chat_goto = NULL;
+- }
+-}
+-
+-/* this is basicly the opposite of chat_online */
+-void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- YahooData *yd = (YahooData *) gc->proto_data;
+- GSList *l;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- if (pair->key == 1)
+- if (g_ascii_strcasecmp(pair->value,
+- purple_connection_get_display_name(gc)))
+- return;
+- }
+-
+- if (pkt->status == 1) {
+- yd->chat_online = FALSE;
+- g_free(yd->pending_chat_room);
+- yd->pending_chat_room = NULL;
+- g_free(yd->pending_chat_id);
+- yd->pending_chat_id = NULL;
+- g_free(yd->pending_chat_topic);
+- yd->pending_chat_topic = NULL;
+- g_free(yd->pending_chat_goto);
+- yd->pending_chat_goto = NULL;
+- if (yd->in_chat)
+- yahoo_c_leave(gc, YAHOO_CHAT_ID);
+- }
+-}
+-
+-void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = (YahooData *) gc->proto_data;
+- PurpleConversation *c = NULL;
+- GSList *l;
+- GList *members = NULL;
+- GList *roomies = NULL;
+- char *room = NULL;
+- char *topic = NULL;
+- char *someid, *someotherid, *somebase64orhashosomething, *somenegativenumber;
+-
+- if (pkt->status == -1) {
+- /* We can't join */
+- struct yahoo_pair *pair = pkt->hash->data;
+- gchar const *failed_to_join = _("Failed to join chat");
+- switch (atoi(pair->value)) {
+- case 0xFFFFFFFA: /* -6 */
+- purple_notify_error(gc, NULL, failed_to_join, _("Unknown room"));
+- break;
+- case 0xFFFFFFF1: /* -15 */
+- purple_notify_error(gc, NULL, failed_to_join, _("Maybe the room is full"));
+- break;
+- case 0xFFFFFFDD: /* -35 */
+- purple_notify_error(gc, NULL, failed_to_join, _("Not available"));
+- break;
+- default:
+- purple_notify_error(gc, NULL, failed_to_join,
+- _("Unknown error. You may need to logout and wait five minutes before being able to rejoin a chatroom"));
+- }
+- return;
+- }
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+-
+- case 104:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, TRUE);
+- break;
+- case 105:
+- g_free(topic);
+- topic = yahoo_string_decode(gc, pair->value, TRUE);
+- break;
+- case 128:
+- someid = pair->value;
+- break;
+- case 108: /* number of joiners */
+- break;
+- case 129:
+- someotherid = pair->value;
+- break;
+- case 130:
+- somebase64orhashosomething = pair->value;
+- break;
+- case 126:
+- somenegativenumber = pair->value;
+- break;
+- case 13: /* this is 1. maybe its the type of room? (normal, user created, private, etc?) */
+- break;
+- case 61: /*this looks similar to 130 */
+- break;
+-
+- /* the previous section was just room info. this next section is
+- info about individual room members, (including us) */
+-
+- case 109: /* the yahoo id */
+- members = g_list_append(members, pair->value);
+- break;
+- case 110: /* age */
+- break;
+- case 141: /* nickname */
+- break;
+- case 142: /* location */
+- break;
+- case 113: /* bitmask */
+- break;
+- }
+- }
+-
+- if (room && yd->chat_name && purple_utf8_strcasecmp(room, yd->chat_name))
+- yahoo_chat_leave(gc, room,
+- purple_connection_get_display_name(gc), FALSE);
+-
+- c = purple_find_chat(gc, YAHOO_CHAT_ID);
+-
+- if (room && (!c || purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) &&
+- members && (members->next ||
+- !g_ascii_strcasecmp(members->data, purple_connection_get_display_name(gc)))) {
+- GList *l;
+- GList *flags = NULL;
+- for (l = members; l; l = l->next)
+- flags = g_list_prepend(flags, GINT_TO_POINTER(PURPLE_CBFLAGS_NONE));
+- if (c && purple_conv_chat_has_left(PURPLE_CONV_CHAT(c))) {
+- /* this might be a hack, but oh well, it should nicely */
+- char *tmpmsg;
+-
+- purple_conversation_set_name(c, room);
+-
+- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
+- if (topic) {
+- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+- /* Also print the topic to the backlog so that the captcha link is clickable */
+- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+- yd->in_chat = 1;
+- yd->chat_name = g_strdup(room);
+- purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
+-
+- tmpmsg = g_strdup_printf(_("You are now chatting in %s."), room);
+- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", tmpmsg, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- g_free(tmpmsg);
+- } else {
+- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
+- if (topic) {
+- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+- /* Also print the topic to the backlog so that the captcha link is clickable */
+- purple_conv_chat_write(PURPLE_CONV_CHAT(c), "", topic, PURPLE_MESSAGE_SYSTEM, time(NULL));
+- }
+- yd->in_chat = 1;
+- yd->chat_name = g_strdup(room);
+- purple_conv_chat_add_users(PURPLE_CONV_CHAT(c), members, NULL, flags, FALSE);
+- }
+- g_list_free(flags);
+- } else if (c) {
+- if (topic) {
+- const char *cur_topic = purple_conv_chat_get_topic(PURPLE_CONV_CHAT(c));
+- if (cur_topic == NULL || strcmp(cur_topic, topic) != 0)
+- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+- }
+- yahoo_chat_add_users(PURPLE_CONV_CHAT(c), members);
+- }
+-
+- if (account->deny && c) {
+- PurpleConversationUiOps *ops = purple_conversation_get_ui_ops(c);
+- for (l = account->deny; l != NULL; l = l->next) {
+- for (roomies = members; roomies; roomies = roomies->next) {
+- if (!purple_utf8_strcasecmp((char *)l->data, roomies->data)) {
+- purple_debug_info("yahoo", "Ignoring room member %s in room %s\n" , (char *)roomies->data, room ? room : "");
+- purple_conv_chat_ignore(PURPLE_CONV_CHAT(c),roomies->data);
+- ops->chat_update_user(c, roomies->data);
+- }
+- }
+- }
+- }
+- g_list_free(roomies);
+- g_list_free(members);
+- g_free(room);
+- g_free(topic);
+-}
+-
+-void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *who = NULL;
+- char *room = NULL;
+- GSList *l;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- if (pair->key == 104) {
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, TRUE);
+- }
+- if (pair->key == 109)
+- who = pair->value;
+- }
+-
+- if (who && room) {
+- PurpleConversation *c = purple_find_chat(gc, YAHOO_CHAT_ID);
+- if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
+-
+- }
+- g_free(room);
+-}
+-
+-void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *room = NULL, *who = NULL, *msg = NULL, *msg2;
+- int msgtype = 1, utf8 = 1; /* default to utf8 */
+- PurpleConversation *c = NULL;
+- GSList *l;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+-
+- case 97:
+- utf8 = strtol(pair->value, NULL, 10);
+- break;
+- case 104:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, TRUE);
+- break;
+- case 109:
+- who = pair->value;
+- break;
+- case 117:
+- msg = pair->value;
+- break;
+- case 124:
+- msgtype = strtol(pair->value, NULL, 10);
+- break;
+- }
+- }
+-
+- c = purple_find_chat(gc, YAHOO_CHAT_ID);
+- if (!who || !c) {
+- if (room)
+- g_free(room);
+- /* we still get messages after we part, funny that */
+- return;
+- }
+-
+- if (!msg) {
+- purple_debug_misc("yahoo", "Got a message packet with no message.\nThis probably means something important, but we're ignoring it.\n");
+- return;
+- }
+- msg2 = yahoo_string_decode(gc, msg, utf8);
+- msg = yahoo_codes_to_html(msg2);
+- g_free(msg2);
+-
+- if (msgtype == 2 || msgtype == 3) {
+- char *tmp;
+- tmp = g_strdup_printf("/me %s", msg);
+- g_free(msg);
+- msg = tmp;
+- }
+-
+- serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, msg, time(NULL));
+- g_free(msg);
+- g_free(room);
+-}
+-
+-void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account;
+- GSList *l;
+- char *room = NULL;
+- char *msg = NULL;
+- char *who = NULL;
+-
+- account = purple_connection_get_account(gc);
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 104:
+- g_free(room);
+- room = yahoo_string_decode(gc, pair->value, TRUE);
+- break;
+- case 129: /* room id? */
+- break;
+- case 126: /* ??? */
+- break;
+- case 117:
+- g_free(msg);
+- msg = yahoo_string_decode(gc, pair->value, FALSE);
+- break;
+- case 119:
+- who = pair->value;
+- break;
+- case 118: /* us */
+- break;
+- }
+- }
+-
+- if (room && who) {
+- GHashTable *components;
+-
+- if (!purple_privacy_check(account, who) ||
+- (purple_account_get_bool(account, "ignore_invites", FALSE)))
+- {
+- purple_debug_info("yahoo", "Invite to room %s from %s has been dropped.\n", room, who);
+- g_free(room);
+- g_free(msg);
+- return;
+- }
+-
+- components = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free);
+- g_hash_table_replace(components, g_strdup("room"), g_strdup(room));
+- serv_got_chat_invite(gc, room, who, msg, components);
+- }
+-
+- g_free(room);
+- g_free(msg);
+-}
+-
+-void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- if (pkt->status == -1)
+- purple_notify_error(gc, NULL, _("Failed to join buddy in chat"),
+- _("Maybe they're not in a chat?"));
+-}
+-
+-/*
+- * Functions dealing with conferences
+- * I think conference names are always ascii.
+- */
+-
+-void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who)
+-{
+- struct yahoo_packet *pkt;
+- GList *w;
+-
+- purple_debug_misc("yahoo", "leaving conference %s\n", room);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGOFF, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash_str(pkt, 1, dn);
+- for (w = who; w; w = w->next) {
+- const char *name = purple_conv_chat_cb_get_name(w->data);
+- yahoo_packet_hash_str(pkt, 3, name);
+- }
+-
+- yahoo_packet_hash_str(pkt, 57, room);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
+- GList *members, const char *what)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- GList *who;
+- char *msg, *msg2;
+- int utf8 = 1;
+-
+- msg = yahoo_html_to_codes(what);
+- msg2 = yahoo_string_encode(gc, msg, &utf8);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFMSG, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash_str(pkt, 1, dn);
+- for (who = members; who; who = who->next) {
+- const char *name = purple_conv_chat_cb_get_name(who->data);
+- yahoo_packet_hash_str(pkt, 53, name);
+- }
+- yahoo_packet_hash(pkt, "ss", 57, room, 14, msg2);
+- if (utf8)
+- yahoo_packet_hash_str(pkt, 97, "1"); /* utf-8 */
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(msg);
+- g_free(msg2);
+-
+- return 0;
+-}
+-
+-static void yahoo_conf_join(YahooData *yd, PurpleConversation *c, const char *dn, const char *room,
+- const char *topic, const char *members)
+-{
+- struct yahoo_packet *pkt;
+- char **memarr = NULL;
+- int i;
+-
+- if (members)
+- memarr = g_strsplit(members, "\n", 0);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFLOGON, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sss", 1, dn, 3, dn, 57, room);
+- if (memarr) {
+- for(i = 0 ; memarr[i]; i++) {
+- if (!strcmp(memarr[i], "") || !strcmp(memarr[i], dn))
+- continue;
+- yahoo_packet_hash_str(pkt, 3, memarr[i]);
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), memarr[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
+- }
+- }
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- if (memarr)
+- g_strfreev(memarr);
+-}
+-
+-static void yahoo_conf_invite(PurpleConnection *gc, PurpleConversation *c,
+- const char *dn, const char *buddy, const char *room, const char *msg)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- GList *members;
+- char *msg2 = NULL;
+-
+- if (msg)
+- msg2 = yahoo_string_encode(gc, msg, NULL);
+-
+- members = purple_conv_chat_get_users(PURPLE_CONV_CHAT(c));
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CONFADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sssss", 1, dn, 51, buddy, 57, room, 58, msg?msg2:"", 13, "0");
+- for(; members; members = members->next) {
+- const char *name = purple_conv_chat_cb_get_name(members->data);
+- if (!strcmp(name, dn))
+- continue;
+- yahoo_packet_hash(pkt, "ss", 52, name, 53, name);
+- }
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(msg2);
+-}
+-
+-/*
+- * Functions dealing with chats
+- */
+-
+-static void yahoo_chat_leave(PurpleConnection *gc, const char *room, const char *dn, gboolean logout)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+-
+- char *eroom;
+- gboolean utf8 = 1;
+-
+- if (yd->wm) {
+- g_return_if_fail(yd->ycht != NULL);
+-
+- ycht_chat_leave(yd->ycht, room, logout);
+- return;
+- }
+-
+- eroom = yahoo_string_encode(gc, room, &utf8);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATEXIT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sss", 104, eroom, 109, dn, 108, "1");
+- yahoo_packet_hash_str(pkt, 112, "0"); /* what does this one mean? */
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- yd->in_chat = 0;
+- if (yd->chat_name) {
+- g_free(yd->chat_name);
+- yd->chat_name = NULL;
+- }
+-
+- if (purple_find_chat(gc, YAHOO_CHAT_ID) != NULL)
+- serv_got_chat_left(gc, YAHOO_CHAT_ID);
+-
+- if (!logout)
+- return;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATLOGOUT,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 1, dn);
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- yd->chat_online = FALSE;
+- g_free(yd->pending_chat_room);
+- yd->pending_chat_room = NULL;
+- g_free(yd->pending_chat_id);
+- yd->pending_chat_id = NULL;
+- g_free(yd->pending_chat_topic);
+- yd->pending_chat_topic = NULL;
+- g_free(yd->pending_chat_goto);
+- yd->pending_chat_goto = NULL;
+- g_free(eroom);
+-}
+-
+-static int yahoo_chat_send(PurpleConnection *gc, const char *dn, const char *room, const char *what, PurpleMessageFlags flags)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- int me = 0;
+- char *msg1, *msg2, *room2;
+- gboolean utf8 = TRUE;
+-
+- if (yd->wm) {
+- g_return_val_if_fail(yd->ycht != NULL, 1);
+-
+- return ycht_chat_send(yd->ycht, room, what);
+- }
+-
+- msg1 = g_strdup(what);
+-
+- if (purple_message_meify(msg1, -1))
+- me = 1;
+-
+- msg2 = yahoo_html_to_codes(msg1);
+- g_free(msg1);
+- msg1 = yahoo_string_encode(gc, msg2, &utf8);
+- g_free(msg2);
+- room2 = yahoo_string_encode(gc, room, NULL);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_COMMENT, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sss", 1, dn, 104, room2, 117, msg1);
+- if (me)
+- yahoo_packet_hash_str(pkt, 124, "2");
+- else
+- yahoo_packet_hash_str(pkt, 124, "1");
+- /* fixme: what about /think? (124=3) */
+- if (utf8)
+- yahoo_packet_hash_str(pkt, 97, "1");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- g_free(msg1);
+- g_free(room2);
+-
+- return 0;
+-}
+-
+-
+-static void yahoo_chat_invite(PurpleConnection *gc, const char *dn, const char *buddy,
+- const char *room, const char *msg)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+- char *room2, *msg2 = NULL;
+- gboolean utf8 = TRUE;
+-
+- if (yd->wm) {
+- g_return_if_fail(yd->ycht != NULL);
+- ycht_chat_send_invite(yd->ycht, room, buddy, msg);
+- return;
+- }
+-
+- room2 = yahoo_string_encode(gc, room, &utf8);
+- if (msg)
+- msg2 = yahoo_string_encode(gc, msg, NULL);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATADDINVITE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sssss", 1, dn, 118, buddy, 104, room2, 117, (msg2?msg2:""), 129, "0");
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(room2);
+- g_free(msg2);
+-}
+-
+-void yahoo_chat_goto(PurpleConnection *gc, const char *name)
+-{
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- yd = gc->proto_data;
+-
+- if (yd->wm) {
+- g_return_if_fail(yd->ycht != NULL);
+- ycht_chat_goto_user(yd->ycht, name);
+- return;
+- }
+-
+- if (!yd->chat_online) {
+- yahoo_chat_online(gc);
+- g_free(yd->pending_chat_room);
+- yd->pending_chat_room = NULL;
+- g_free(yd->pending_chat_id);
+- yd->pending_chat_id = NULL;
+- g_free(yd->pending_chat_topic);
+- yd->pending_chat_topic = NULL;
+- g_free(yd->pending_chat_goto);
+- yd->pending_chat_goto = g_strdup(name);
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_CHATGOTO, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "sss", 109, name, 1, purple_connection_get_display_name(gc), 62, "2");
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-/*
+- * These are the functions registered with the core
+- * which get called for both chats and conferences.
+- */
+-
+-void yahoo_c_leave(PurpleConnection *gc, int id)
+-{
+- YahooData *yd = (YahooData *) gc->proto_data;
+- PurpleConversation *c;
+-
+- if (!yd)
+- return;
+-
+- c = purple_find_chat(gc, id);
+- if (!c)
+- return;
+-
+- if (id != YAHOO_CHAT_ID) {
+- yahoo_conf_leave(yd, purple_conversation_get_name(c),
+- purple_connection_get_display_name(gc), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)));
+- yd->confs = g_slist_remove(yd->confs, c);
+- } else {
+- yahoo_chat_leave(gc, purple_conversation_get_name(c), purple_connection_get_display_name(gc), TRUE);
+- }
+-
+- serv_got_chat_left(gc, id);
+-}
+-
+-int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags)
+-{
+- PurpleConversation *c;
+- int ret;
+- YahooData *yd;
+-
+- yd = (YahooData *) gc->proto_data;
+- if (!yd)
+- return -1;
+-
+- c = purple_find_chat(gc, id);
+- if (!c)
+- return -1;
+-
+- if (id != YAHOO_CHAT_ID) {
+- ret = yahoo_conf_send(gc, purple_connection_get_display_name(gc),
+- purple_conversation_get_name(c), purple_conv_chat_get_users(PURPLE_CONV_CHAT(c)), what);
+- } else {
+- ret = yahoo_chat_send(gc, purple_connection_get_display_name(gc),
+- purple_conversation_get_name(c), what, flags);
+- if (!ret)
+- serv_got_chat_in(gc, purple_conv_chat_get_id(PURPLE_CONV_CHAT(c)),
+- purple_connection_get_display_name(gc), flags, what, time(NULL));
+- }
+- return ret;
+-}
+-
+-GList *yahoo_c_info(PurpleConnection *gc)
+-{
+- GList *m = NULL;
+- struct proto_chat_entry *pce;
+-
+- pce = g_new0(struct proto_chat_entry, 1);
+- pce->label = _("_Room:");
+- pce->identifier = "room";
+- pce->required = TRUE;
+- m = g_list_append(m, pce);
+-
+- return m;
+-}
+-
+-GHashTable *yahoo_c_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, "room", g_strdup(chat_name));
+-
+- return defaults;
+-}
+-
+-char *yahoo_get_chat_name(GHashTable *data)
+-{
+- return g_strdup(g_hash_table_lookup(data, "room"));
+-}
+-
+-void yahoo_c_join(PurpleConnection *gc, GHashTable *data)
+-{
+- YahooData *yd;
+- char *room, *topic, *type;
+- PurpleConversation *c;
+-
+- yd = (YahooData *) gc->proto_data;
+- if (!yd)
+- return;
+-
+- room = g_hash_table_lookup(data, "room");
+- if (!room)
+- return;
+-
+- topic = g_hash_table_lookup(data, "topic");
+- if (!topic)
+- topic = "";
+-
+- if ((type = g_hash_table_lookup(data, "type")) && !strcmp(type, "Conference")) {
+- int id;
+- const char *members = g_hash_table_lookup(data, "members");
+- id = yd->conf_id++;
+- c = serv_got_joined_chat(gc, id, room);
+- yd->confs = g_slist_prepend(yd->confs, c);
+- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), purple_connection_get_display_name(gc), topic);
+- yahoo_conf_join(yd, c, purple_connection_get_display_name(gc), room, topic, members);
+- return;
+- } else {
+- const char *id;
+- /*if (yd->in_chat)
+- yahoo_chat_leave(gc, room,
+- purple_connection_get_display_name(gc),
+- FALSE);*/
+-
+- id = g_hash_table_lookup(data, "id");
+-
+- if (!yd->chat_online) {
+- yahoo_chat_online(gc);
+- g_free(yd->pending_chat_room);
+- yd->pending_chat_room = g_strdup(room);
+- g_free(yd->pending_chat_id);
+- yd->pending_chat_id = g_strdup(id);
+- g_free(yd->pending_chat_topic);
+- yd->pending_chat_topic = g_strdup(topic);
+- g_free(yd->pending_chat_goto);
+- yd->pending_chat_goto = NULL;
+- } else {
+- yahoo_chat_join(gc, purple_connection_get_display_name(gc), room, topic, id);
+- }
+- return;
+- }
+-}
+-
+-void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name)
+-{
+- PurpleConversation *c;
+-
+- c = purple_find_chat(gc, id);
+- if (!c || !c->name)
+- return;
+-
+- if (id != YAHOO_CHAT_ID) {
+- yahoo_conf_invite(gc, c, purple_connection_get_display_name(gc), name,
+- purple_conversation_get_name(c), msg);
+- } else {
+- yahoo_chat_invite(gc, purple_connection_get_display_name(gc), name,
+- purple_conversation_get_name(c), msg);
+- }
+-}
+-
+-struct yahoo_roomlist {
+- int fd;
+- int inpa;
+- gchar *txbuf;
+- gsize tx_written;
+- guchar *rxqueue;
+- int rxlen;
+- gboolean started;
+- char *path;
+- char *host;
+- PurpleRoomlist *list;
+- PurpleRoomlistRoom *cat;
+- PurpleRoomlistRoom *ucat;
+- GMarkupParseContext *parse;
+-};
+-
+-static void yahoo_roomlist_destroy(struct yahoo_roomlist *yrl)
+-{
+- if (yrl->inpa)
+- purple_input_remove(yrl->inpa);
+- g_free(yrl->txbuf);
+- g_free(yrl->rxqueue);
+- g_free(yrl->path);
+- g_free(yrl->host);
+- if (yrl->parse)
+- g_markup_parse_context_free(yrl->parse);
+- g_free(yrl);
+-}
+-
+-enum yahoo_room_type {
+- yrt_yahoo,
+- yrt_user
+-};
+-
+-struct yahoo_chatxml_state {
+- PurpleRoomlist *list;
+- struct yahoo_roomlist *yrl;
+- GQueue *q;
+- struct {
+- enum yahoo_room_type type;
+- char *name;
+- char *topic;
+- char *id;
+- int users, voices, webcams;
+- } room;
+-};
+-
+-struct yahoo_lobby {
+- int count, users, voices, webcams;
+-};
+-
+-static struct yahoo_chatxml_state *yahoo_chatxml_state_new(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
+-{
+- struct yahoo_chatxml_state *s;
+-
+- s = g_new0(struct yahoo_chatxml_state, 1);
+- s->list = list;
+- s->yrl = yrl;
+- s->q = g_queue_new();
+-
+- return s;
+-}
+-
+-static void yahoo_chatxml_state_destroy(struct yahoo_chatxml_state *s)
+-{
+- g_queue_free(s->q);
+- g_free(s->room.name);
+- g_free(s->room.topic);
+- g_free(s->room.id);
+- g_free(s);
+-}
+-
+-static void yahoo_chatlist_start_element(GMarkupParseContext *context,
+- const gchar *ename, const gchar **anames,
+- const gchar **avalues, gpointer user_data,
+- GError **error)
+-{
+- struct yahoo_chatxml_state *s = user_data;
+- PurpleRoomlist *list = s->list;
+- PurpleRoomlistRoom *r;
+- PurpleRoomlistRoom *parent;
+- int i;
+-
+- if (!strcmp(ename, "category")) {
+- const gchar *name = NULL, *id = NULL;
+-
+- for (i = 0; anames[i]; i++) {
+- if (!strcmp(anames[i], "id"))
+- id = avalues[i];
+- if (!strcmp(anames[i], "name"))
+- name = avalues[i];
+- }
+- if (!name || !id)
+- return;
+-
+- parent = g_queue_peek_head(s->q);
+- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, name, parent);
+- purple_roomlist_room_add_field(list, r, (gpointer)name);
+- purple_roomlist_room_add_field(list, r, (gpointer)id);
+- purple_roomlist_room_add(list, r);
+- g_queue_push_head(s->q, r);
+- } else if (!strcmp(ename, "room")) {
+- s->room.users = s->room.voices = s->room.webcams = 0;
+-
+- for (i = 0; anames[i]; i++) {
+- if (!strcmp(anames[i], "id")) {
+- g_free(s->room.id);
+- s->room.id = g_strdup(avalues[i]);
+- } else if (!strcmp(anames[i], "name")) {
+- g_free(s->room.name);
+- s->room.name = g_strdup(avalues[i]);
+- } else if (!strcmp(anames[i], "topic")) {
+- g_free(s->room.topic);
+- s->room.topic = g_strdup(avalues[i]);
+- } else if (!strcmp(anames[i], "type")) {
+- if (!strcmp("yahoo", avalues[i]))
+- s->room.type = yrt_yahoo;
+- else
+- s->room.type = yrt_user;
+- }
+- }
+-
+- } else if (!strcmp(ename, "lobby")) {
+- struct yahoo_lobby *lob = g_new0(struct yahoo_lobby, 1);
+-
+- for (i = 0; anames[i]; i++) {
+- if (!strcmp(anames[i], "count")) {
+- lob->count = strtol(avalues[i], NULL, 10);
+- } else if (!strcmp(anames[i], "users")) {
+- s->room.users += lob->users = strtol(avalues[i], NULL, 10);
+- } else if (!strcmp(anames[i], "voices")) {
+- s->room.voices += lob->voices = strtol(avalues[i], NULL, 10);
+- } else if (!strcmp(anames[i], "webcams")) {
+- s->room.webcams += lob->webcams = strtol(avalues[i], NULL, 10);
+- }
+- }
+- g_queue_push_head(s->q, lob);
+- }
+-}
+-
+-static void yahoo_chatlist_end_element(GMarkupParseContext *context, const gchar *ename,
+- gpointer user_data, GError **error)
+-{
+- struct yahoo_chatxml_state *s = user_data;
+-
+- if (!strcmp(ename, "category")) {
+- g_queue_pop_head(s->q);
+- } else if (!strcmp(ename, "room")) {
+- struct yahoo_lobby *lob;
+- PurpleRoomlistRoom *r, *l;
+-
+- if (s->room.type == yrt_yahoo)
+- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
+- s->room.name, s->yrl->cat);
+- else
+- r = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY|PURPLE_ROOMLIST_ROOMTYPE_ROOM,
+- s->room.name, s->yrl->ucat);
+-
+- purple_roomlist_room_add_field(s->list, r, s->room.name);
+- purple_roomlist_room_add_field(s->list, r, s->room.id);
+- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.users));
+- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.voices));
+- purple_roomlist_room_add_field(s->list, r, GINT_TO_POINTER(s->room.webcams));
+- purple_roomlist_room_add_field(s->list, r, s->room.topic);
+- purple_roomlist_room_add(s->list, r);
+-
+- while ((lob = g_queue_pop_head(s->q))) {
+- char *name = g_strdup_printf("%s:%d", s->room.name, lob->count);
+- l = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_ROOM, name, r);
+-
+- purple_roomlist_room_add_field(s->list, l, name);
+- purple_roomlist_room_add_field(s->list, l, s->room.id);
+- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->users));
+- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->voices));
+- purple_roomlist_room_add_field(s->list, l, GINT_TO_POINTER(lob->webcams));
+- purple_roomlist_room_add_field(s->list, l, s->room.topic);
+- purple_roomlist_room_add(s->list, l);
+-
+- g_free(name);
+- g_free(lob);
+- }
+- }
+-}
+-
+-static GMarkupParser parser = {
+- yahoo_chatlist_start_element,
+- yahoo_chatlist_end_element,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void yahoo_roomlist_cleanup(PurpleRoomlist *list, struct yahoo_roomlist *yrl)
+-{
+- purple_roomlist_set_in_progress(list, FALSE);
+-
+- if (yrl) {
+- list->proto_data = g_list_remove(list->proto_data, yrl);
+- yahoo_roomlist_destroy(yrl);
+- }
+-
+- purple_roomlist_unref(list);
+-}
+-
+-static void yahoo_roomlist_pending(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- struct yahoo_roomlist *yrl = data;
+- PurpleRoomlist *list = yrl->list;
+- char buf[1024];
+- int len;
+- guchar *start;
+- struct yahoo_chatxml_state *s;
+-
+- len = read(yrl->fd, buf, sizeof(buf));
+-
+- if (len < 0 && errno == EAGAIN)
+- return;
+-
+- if (len <= 0) {
+- if (yrl->parse)
+- g_markup_parse_context_end_parse(yrl->parse, NULL);
+- yahoo_roomlist_cleanup(list, yrl);
+- return;
+- }
+-
+- yrl->rxqueue = g_realloc(yrl->rxqueue, len + yrl->rxlen);
+- memcpy(yrl->rxqueue + yrl->rxlen, buf, len);
+- yrl->rxlen += len;
+-
+- if (!yrl->started) {
+- yrl->started = TRUE;
+- start = (guchar *)g_strstr_len((char *)yrl->rxqueue, yrl->rxlen, "\r\n\r\n");
+- if (!start || (start - yrl->rxqueue + 4) >= yrl->rxlen)
+- return;
+- start += 4;
+- } else {
+- start = yrl->rxqueue;
+- }
+-
+- if (yrl->parse == NULL) {
+- s = yahoo_chatxml_state_new(list, yrl);
+- yrl->parse = g_markup_parse_context_new(&parser, 0, s,
+- (GDestroyNotify)yahoo_chatxml_state_destroy);
+- }
+-
+- if (!g_markup_parse_context_parse(yrl->parse, (char *)start, (yrl->rxlen - (start - yrl->rxqueue)), NULL)) {
+-
+- yahoo_roomlist_cleanup(list, yrl);
+- return;
+- }
+-
+- yrl->rxlen = 0;
+-}
+-
+-static void yahoo_roomlist_send_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- struct yahoo_roomlist *yrl;
+- PurpleRoomlist *list;
+- int written, remaining;
+-
+- yrl = data;
+- list = yrl->list;
+-
+- remaining = strlen(yrl->txbuf) - yrl->tx_written;
+- written = write(yrl->fd, yrl->txbuf + yrl->tx_written, remaining);
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0) {
+- purple_input_remove(yrl->inpa);
+- yrl->inpa = 0;
+- g_free(yrl->txbuf);
+- yrl->txbuf = NULL;
+- purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
+- yahoo_roomlist_cleanup(list, yrl);
+- return;
+- }
+-
+- if (written < remaining) {
+- yrl->tx_written += written;
+- return;
+- }
+-
+- g_free(yrl->txbuf);
+- yrl->txbuf = NULL;
+-
+- purple_input_remove(yrl->inpa);
+- yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_READ,
+- yahoo_roomlist_pending, yrl);
+-
+-}
+-
+-static void yahoo_roomlist_got_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- struct yahoo_roomlist *yrl = data;
+- PurpleRoomlist *list = yrl->list;
+- YahooData *yd = purple_account_get_connection(list->account)->proto_data;
+-
+- if (source < 0) {
+- purple_notify_error(purple_account_get_connection(list->account), NULL, _("Unable to connect"), _("Fetching the room list failed."));
+- yahoo_roomlist_cleanup(list, yrl);
+- return;
+- }
+-
+- yrl->fd = source;
+-
+- yrl->txbuf = g_strdup_printf(
+- "GET http://%s/%s HTTP/1.0\r\n"
+- "Host: %s\r\n"
+- "Cookie: Y=%s; T=%s\r\n\r\n",
+- yrl->host, yrl->path, yrl->host, yd->cookie_y,
+- yd->cookie_t);
+-
+-
+- yrl->inpa = purple_input_add(yrl->fd, PURPLE_INPUT_WRITE,
+- yahoo_roomlist_send_cb, yrl);
+- yahoo_roomlist_send_cb(yrl, yrl->fd, PURPLE_INPUT_WRITE);
+-}
+-
+-PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc)
+-{
+- PurpleAccount *account;
+- PurpleRoomlist *rl;
+- PurpleRoomlistField *f;
+- GList *fields = NULL;
+- struct yahoo_roomlist *yrl;
+- const char *rll, *rlurl;
+- char *url;
+-
+- account = purple_connection_get_account(gc);
+-
+- /* for Yahoo Japan, it appears there is only one valid URL and locale */
+- if(purple_account_get_bool(account, "yahoojp", FALSE)) {
+- rll = YAHOOJP_ROOMLIST_LOCALE;
+- rlurl = YAHOOJP_ROOMLIST_URL;
+- }
+- else { /* but for the rest of the world that isn't the case */
+- rll = purple_account_get_string(account, "room_list_locale", YAHOO_ROOMLIST_LOCALE);
+- rlurl = purple_account_get_string(account, "room_list", YAHOO_ROOMLIST_URL);
+- }
+-
+- url = g_strdup_printf("%s?chatcat=0&intl=%s", rlurl, rll);
+-
+- yrl = g_new0(struct yahoo_roomlist, 1);
+- rl = purple_roomlist_new(account);
+- yrl->list = rl;
+-
+- purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
+- g_free(url);
+-
+- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "room", TRUE);
+- fields = g_list_append(fields, f);
+-
+- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_STRING, "", "id", 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_INT, _("Voices"), "voices", FALSE);
+- fields = g_list_append(fields, f);
+-
+- f = purple_roomlist_field_new(PURPLE_ROOMLIST_FIELD_INT, _("Webcams"), "webcams", 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(rl, fields);
+-
+- if (purple_proxy_connect(gc, account, yrl->host, 80,
+- yahoo_roomlist_got_connected, yrl) == NULL)
+- {
+- purple_notify_error(gc, NULL, _("Connection problem"), _("Unable to fetch room list."));
+- yahoo_roomlist_cleanup(rl, yrl);
+- return NULL;
+- }
+-
+- rl->proto_data = g_list_append(rl->proto_data, yrl);
+-
+- purple_roomlist_set_in_progress(rl, TRUE);
+- return rl;
+-}
+-
+-void yahoo_roomlist_cancel(PurpleRoomlist *list)
+-{
+- GList *l, *k;
+-
+- k = l = list->proto_data;
+- list->proto_data = NULL;
+-
+- purple_roomlist_set_in_progress(list, FALSE);
+-
+- for (; l; l = l->next) {
+- yahoo_roomlist_destroy(l->data);
+- purple_roomlist_unref(list);
+- }
+- g_list_free(k);
+-}
+-
+-void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category)
+-{
+- struct yahoo_roomlist *yrl;
+- char *url;
+- char *id;
+- const char *rll;
+-
+- if (category->type != PURPLE_ROOMLIST_ROOMTYPE_CATEGORY)
+- return;
+-
+- if (!(id = g_list_nth_data(category->fields, 1))) {
+- purple_roomlist_set_in_progress(list, FALSE);
+- return;
+- }
+-
+- rll = purple_account_get_string(list->account, "room_list_locale",
+- YAHOO_ROOMLIST_LOCALE);
+-
+- if (rll != NULL && *rll != '\0') {
+- url = g_strdup_printf("%s?chatroom_%s=0&intl=%s",
+- purple_account_get_string(list->account,"room_list",
+- YAHOO_ROOMLIST_URL), id, rll);
+- } else {
+- url = g_strdup_printf("%s?chatroom_%s=0",
+- purple_account_get_string(list->account,"room_list",
+- YAHOO_ROOMLIST_URL), id);
+- }
+-
+- yrl = g_new0(struct yahoo_roomlist, 1);
+- yrl->list = list;
+- yrl->cat = category;
+- list->proto_data = g_list_append(list->proto_data, yrl);
+-
+- purple_url_parse(url, &(yrl->host), NULL, &(yrl->path), NULL, NULL);
+- g_free(url);
+-
+- yrl->ucat = purple_roomlist_room_new(PURPLE_ROOMLIST_ROOMTYPE_CATEGORY, _("User Rooms"), yrl->cat);
+- purple_roomlist_room_add(list, yrl->ucat);
+-
+- if (purple_proxy_connect(purple_account_get_connection(list->account),
+- list->account, yrl->host, 80,
+- yahoo_roomlist_got_connected, yrl) == NULL)
+- {
+- purple_notify_error(purple_account_get_connection(list->account),
+- NULL, _("Connection problem"), _("Unable to fetch room list."));
+- purple_roomlist_ref(list);
+- yahoo_roomlist_cleanup(list, yrl);
+- return;
+- }
+-
+- purple_roomlist_set_in_progress(list, TRUE);
+- purple_roomlist_ref(list);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoochat.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoochat.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,66 +0,0 @@
+-/**
+- * @file yahoochat.h The Yahoo! protocol plugin, chat and conference stuff
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _YAHOOCHAT_H_
+-#define _YAHOOCHAT_H_
+-
+-#include "roomlist.h"
+-#include "yahoo_packet.h"
+-
+-void yahoo_process_conference_invite(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_conference_decline(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_conference_logon(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_conference_logoff(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_conference_message(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-void yahoo_process_chat_online(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_logout(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_join(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_exit(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_message(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_addinvite(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_chat_goto(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-void yahoo_c_leave(PurpleConnection *gc, int id);
+-int yahoo_c_send(PurpleConnection *gc, int id, const char *what, PurpleMessageFlags flags);
+-GList *yahoo_c_info(PurpleConnection *gc);
+-GHashTable *yahoo_c_info_defaults(PurpleConnection *gc, const char *chat_name);
+-void yahoo_c_join(PurpleConnection *gc, GHashTable *data);
+-char *yahoo_get_chat_name(GHashTable *data);
+-void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
+-
+-void yahoo_conf_leave(YahooData *yd, const char *room, const char *dn, GList *who);
+-
+-void yahoo_chat_goto(PurpleConnection *gc, const char *name);
+-
+-/* room listing functions */
+-PurpleRoomlist *yahoo_roomlist_get_list(PurpleConnection *gc);
+-void yahoo_roomlist_cancel(PurpleRoomlist *list);
+-void yahoo_roomlist_expand_category(PurpleRoomlist *list, PurpleRoomlistRoom *category);
+-
+-/* util */
+-void yahoo_chat_add_users(PurpleConvChat *chat, GList *newusers);
+-void yahoo_chat_add_user(PurpleConvChat *chat, const char *user, const char *reason);
+-
+-#endif /* _YAHOO_CHAT_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,611 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/******************************************************************************
+- * INCLUDES
+- *****************************************************************************/
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "blist.h"
+-#include "cipher.h"
+-#include "cmds.h"
+-#include "debug.h"
+-#include "notify.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-#include "proxy.h"
+-#include "request.h"
+-#include "server.h"
+-#include "util.h"
+-#include "version.h"
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-#include "yahoo_friend.h"
+-#include "yahoochat.h"
+-#include "ycht.h"
+-#include "yahoo_filexfer.h"
+-#include "yahoo_picture.h"
+-
+-#include "whiteboard.h"
+-#include "yahoo_doodle.h"
+-
+-/******************************************************************************
+- * Globals
+- *****************************************************************************/
+-#if 0
+-const int DefaultColorRGB24[] =
+-{
+- DOODLE_COLOR_RED,
+- DOODLE_COLOR_ORANGE,
+- DOODLE_COLOR_YELLOW,
+- DOODLE_COLOR_GREEN,
+- DOODLE_COLOR_CYAN,
+- DOODLE_COLOR_BLUE,
+- DOODLE_COLOR_VIOLET,
+- DOODLE_COLOR_PURPLE,
+- DOODLE_COLOR_TAN,
+- DOODLE_COLOR_BROWN,
+- DOODLE_COLOR_BLACK,
+- DOODLE_COLOR_GREY,
+- DOODLE_COLOR_WHITE
+-};
+-#endif
+-
+-/******************************************************************************
+- * Functions
+- *****************************************************************************/
+-PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args, char **error, void *data)
+-{
+- PurpleAccount *account;
+- PurpleConnection *gc;
+- const gchar *name;
+-
+- if(*args && args[0])
+- return PURPLE_CMD_RET_FAILED;
+-
+- account = purple_conversation_get_account(conv);
+- gc = purple_account_get_connection(account);
+- name = purple_conversation_get_name(conv);
+- yahoo_doodle_initiate(gc, name);
+-
+- /* Write a local message to this conversation showing that a request for a
+- * Doodle session has been made
+- */
+- purple_conv_im_write(PURPLE_CONV_IM(conv), "", _("Sent Doodle request."),
+- PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL));
+-
+- return PURPLE_CMD_RET_OK;
+-}
+-
+-void yahoo_doodle_initiate(PurpleConnection *gc, const char *name)
+-{
+- PurpleAccount *account;
+- char *to = (char*)name;
+- PurpleWhiteboard *wb;
+-
+- g_return_if_fail(gc);
+- g_return_if_fail(name);
+-
+- account = purple_connection_get_account(gc);
+- wb = purple_whiteboard_get_session(account, to);
+-
+- if(wb == NULL)
+- {
+- /* Insert this 'session' in the list. At this point, it's only a
+- * requested session.
+- */
+- wb = purple_whiteboard_create(account, to, DOODLE_STATE_REQUESTING);
+- }
+-
+- /* NOTE Perhaps some careful handling of remote assumed established
+- * sessions
+- */
+-
+- yahoo_doodle_command_send_ready(gc, to, DOODLE_IMV_KEY);
+- yahoo_doodle_command_send_request(gc, to, DOODLE_IMV_KEY);
+-
+-}
+-
+-static void yahoo_doodle_command_got_request(PurpleConnection *gc, const char *from, const char *imv_key)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+-
+- purple_debug_info("yahoo", "doodle: Got Request (%s)\n", from);
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- /* If a session with the remote user doesn't exist */
+- if(wb == NULL)
+- {
+- doodle_session *ds;
+- /* Ask user if they wish to accept the request for a doodle session */
+- /* TODO Ask local user to start Doodle session with remote user */
+- /* NOTE This if/else statement won't work right--must use dialog
+- * results
+- */
+-
+- /* char dialog_message[64];
+- g_sprintf(dialog_message, "%s is requesting to start a Doodle session with you.", from);
+-
+- purple_notify_message(NULL, PURPLE_NOTIFY_MSG_INFO, "Doodle",
+- dialog_message, NULL, NULL, NULL);
+- */
+-
+- wb = purple_whiteboard_create(account, from, DOODLE_STATE_REQUESTED);
+- ds = wb->proto_data;
+- ds->imv_key = g_strdup(imv_key);
+-
+- yahoo_doodle_command_send_ready(gc, from, imv_key);
+- }
+-
+- /* TODO Might be required to clear the canvas of an existing doodle
+- * session at this point
+- */
+-}
+-
+-static void yahoo_doodle_command_got_ready(PurpleConnection *gc, const char *from, const char *imv_key)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+-
+- purple_debug_info("yahoo", "doodle: Got Ready(%s)\n", from);
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- if(wb == NULL)
+- return;
+-
+- if(wb->state == DOODLE_STATE_REQUESTING)
+- {
+- doodle_session *ds = wb->proto_data;
+- purple_whiteboard_start(wb);
+-
+- wb->state = DOODLE_STATE_ESTABLISHED;
+-
+- yahoo_doodle_command_send_confirm(gc, from, imv_key);
+- /* Let's steal the imv_key and reuse it */
+- g_free(ds->imv_key);
+- ds->imv_key = g_strdup(imv_key);
+- }
+- else if(wb->state == DOODLE_STATE_ESTABLISHED)
+- {
+- /* TODO Ask whether to save picture too */
+- purple_whiteboard_clear(wb);
+- }
+-
+- /* NOTE Not sure about this... I am trying to handle if the remote user
+- * already thinks we're in a session with them (when their chat message
+- * contains the doodle imv key)
+- */
+- else if(wb->state == DOODLE_STATE_REQUESTED)
+- {
+- /* purple_whiteboard_start(wb); */
+- yahoo_doodle_command_send_ready(gc, from, imv_key);
+- }
+-}
+-
+-static void yahoo_doodle_command_got_draw(PurpleConnection *gc, const char *from, const char *message)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+- char **tokens;
+- int i;
+- GList *d_list = NULL; /* a local list of drawing info */
+-
+- g_return_if_fail(message != NULL);
+-
+- purple_debug_info("yahoo", "doodle: Got Draw (%s)\n", from);
+- purple_debug_info("yahoo", "doodle: Draw message: %s\n", message);
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- if(wb == NULL)
+- return;
+-
+- /* TODO Functionalize
+- * Convert drawing packet message to an integer list
+- */
+-
+- /* Check to see if the message begans and ends with quotes */
+- if((message[0] != '\"') || (message[strlen(message) - 1] != '\"'))
+- return;
+-
+- /* Ignore the inital quotation mark. */
+- message += 1;
+-
+- tokens = g_strsplit(message, ",", 0);
+-
+- /* Traverse and extract all integers divided by commas */
+- for (i = 0; tokens[i] != NULL; i++)
+- {
+- int last = strlen(tokens[i]) - 1;
+- if (tokens[i][last] == '"')
+- tokens[i][last] = '\0';
+-
+- d_list = g_list_prepend(d_list, GINT_TO_POINTER(atoi(tokens[i])));
+- }
+- d_list = g_list_reverse(d_list);
+-
+- g_strfreev(tokens);
+-
+- yahoo_doodle_draw_stroke(wb, d_list);
+-
+- /* goodle_doodle_session_set_canvas_as_icon(ds); */
+-
+- g_list_free(d_list);
+-}
+-
+-
+-static void yahoo_doodle_command_got_clear(PurpleConnection *gc, const char *from)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+-
+- purple_debug_info("yahoo", "doodle: Got Clear (%s)\n", from);
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- if(wb == NULL)
+- return;
+-
+- if(wb->state == DOODLE_STATE_ESTABLISHED)
+- {
+- /* TODO Ask user whether to save the image before clearing it */
+-
+- purple_whiteboard_clear(wb);
+- }
+-}
+-
+-
+-static void
+-yahoo_doodle_command_got_extra(PurpleConnection *gc, const char *from, const char *message, const char *imv_key)
+-{
+- purple_debug_info("yahoo", "doodle: Got Extra (%s)\n", from);
+-
+- /* I do not like these 'extra' features, so I'll only handle them in one
+- * way, which is returning them with the command/packet to turn them off
+- */
+- yahoo_doodle_command_send_extra(gc, from, DOODLE_EXTRA_NONE, imv_key);
+-}
+-
+-static void yahoo_doodle_command_got_confirm(PurpleConnection *gc, const char *from)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+-
+- purple_debug_info("yahoo", "doodle: Got Confirm (%s)\n", from);
+-
+- /* Get the doodle session */
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- if(wb == NULL)
+- return;
+-
+- /* TODO Combine the following IF's? */
+-
+- /* Check if we requested a doodle session */
+- /*if(wb->state == DOODLE_STATE_REQUESTING)
+- {
+- wb->state = DOODLE_STATE_ESTABLISHED;
+-
+- purple_whiteboard_start(wb);
+-
+- yahoo_doodle_command_send_confirm(gc, from);
+- }*/
+-
+- /* Check if we accepted a request for a doodle session */
+- if(wb->state == DOODLE_STATE_REQUESTED)
+- {
+- wb->state = DOODLE_STATE_ESTABLISHED;
+-
+- purple_whiteboard_start(wb);
+- }
+-}
+-
+-void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from)
+-{
+- PurpleAccount *account;
+- PurpleWhiteboard *wb;
+-
+- g_return_if_fail(from != NULL);
+-
+- purple_debug_info("yahoo", "doodle: Got Shutdown (%s)\n", from);
+-
+- account = purple_connection_get_account(gc);
+-
+- /* Only handle this if local client requested Doodle session (else local
+- * client would have sent one)
+- */
+- wb = purple_whiteboard_get_session(account, from);
+-
+- if(wb == NULL)
+- return;
+-
+- /* TODO Ask if user wants to save picture before the session is closed */
+-
+- wb->state = DOODLE_STATE_CANCELLED;
+- purple_whiteboard_destroy(wb);
+-}
+-
+-static void yahoo_doodle_command_send_generic(const char *type,
+- PurpleConnection *gc,
+- const char *to,
+- const char *message,
+- int command,
+- const char *imv,
+- const char *sixtyfour)
+-{
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- purple_debug_info("yahoo", "doodle: Sent %s (%s)\n", type, to);
+-
+- yd = gc->proto_data;
+-
+- /* Make and send an acknowledge (ready) Doodle packet */
+- pkt = yahoo_packet_new(YAHOO_SERVICE_P2PFILEXFER, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 49, "IMVIRONMENT");
+- yahoo_packet_hash_str(pkt, 1, purple_account_get_username(gc->account));
+- yahoo_packet_hash_str(pkt, 14, message);
+- yahoo_packet_hash_int(pkt, 13, command);
+- yahoo_packet_hash_str(pkt, 5, to);
+- yahoo_packet_hash_str(pkt, 63, imv ? imv : DOODLE_IMV_KEY);
+- yahoo_packet_hash_str(pkt, 64, sixtyfour);
+- yahoo_packet_hash_str(pkt, 1002, "1");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Ready", gc, to, "1", DOODLE_CMD_READY, imv_key, "1");
+-}
+-
+-void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Request", gc, to, "", DOODLE_CMD_REQUEST, imv_key, "0");
+-}
+-
+-void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Draw", gc, to, message, DOODLE_CMD_DRAW, imv_key, "1");
+-}
+-
+-void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Clear", gc, to, " ", DOODLE_CMD_CLEAR, imv_key, "1");
+-}
+-
+-void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Extra", gc, to, message, DOODLE_CMD_EXTRA, imv_key, "1");
+-}
+-
+-void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key)
+-{
+- yahoo_doodle_command_send_generic("Confirm", gc, to, "1", DOODLE_CMD_CONFIRM, imv_key, "1");
+-}
+-
+-void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to)
+-{
+- yahoo_doodle_command_send_generic("Shutdown", gc, to, "", DOODLE_CMD_SHUTDOWN, ";0", "0");
+-}
+-
+-void yahoo_doodle_start(PurpleWhiteboard *wb)
+-{
+- doodle_session *ds = g_new0(doodle_session, 1);
+-
+- /* purple_debug_debug("yahoo", "doodle: yahoo_doodle_start()\n"); */
+-
+- /* Set default brush size and color */
+- ds->brush_size = DOODLE_BRUSH_SMALL;
+- ds->brush_color = DOODLE_COLOR_RED;
+-
+- wb->proto_data = ds;
+-}
+-
+-void yahoo_doodle_end(PurpleWhiteboard *wb)
+-{
+- PurpleConnection *gc = purple_account_get_connection(wb->account);
+- doodle_session *ds = wb->proto_data;
+-
+- /* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
+-
+- if (gc && wb->state != DOODLE_STATE_CANCELLED)
+- yahoo_doodle_command_send_shutdown(gc, wb->who);
+-
+- g_free(ds->imv_key);
+- g_free(wb->proto_data);
+-}
+-
+-void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height)
+-{
+- /* standard Doodle canvases are of one size: 368x256 */
+- *width = DOODLE_CANVAS_WIDTH;
+- *height = DOODLE_CANVAS_HEIGHT;
+-}
+-
+-static char *yahoo_doodle_build_draw_string(doodle_session *ds, GList *draw_list)
+-{
+- GString *message;
+-
+- g_return_val_if_fail(draw_list != NULL, NULL);
+-
+- message = g_string_new("");
+- g_string_printf(message, "\"%d,%d", ds->brush_color, ds->brush_size);
+-
+- for(; draw_list != NULL; draw_list = draw_list->next)
+- {
+- g_string_append_printf(message, ",%d", GPOINTER_TO_INT(draw_list->data));
+- }
+- g_string_append_c(message, '"');
+-
+- return g_string_free(message, FALSE);
+-}
+-
+-void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list)
+-{
+- doodle_session *ds = wb->proto_data;
+- char *message;
+-
+- g_return_if_fail(draw_list != NULL);
+-
+- message = yahoo_doodle_build_draw_string(ds, draw_list);
+- yahoo_doodle_command_send_draw(wb->account->gc, wb->who, message, ds->imv_key);
+- g_free(message);
+-}
+-
+-void yahoo_doodle_clear(PurpleWhiteboard *wb)
+-{
+- doodle_session *ds = wb->proto_data;
+- yahoo_doodle_command_send_clear(wb->account->gc, wb->who, ds->imv_key);
+-}
+-
+-
+-/* Traverse through the list and draw the points and lines */
+-void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list)
+-{
+- int brush_color;
+- int brush_size;
+- int x;
+- int y;
+-
+- g_return_if_fail(draw_list != NULL);
+-
+- brush_color = GPOINTER_TO_INT(draw_list->data);
+- draw_list = draw_list->next;
+- g_return_if_fail(draw_list != NULL);
+-
+- brush_size = GPOINTER_TO_INT(draw_list->data);
+- draw_list = draw_list->next;
+- g_return_if_fail(draw_list != NULL);
+-
+- x = GPOINTER_TO_INT(draw_list->data);
+- draw_list = draw_list->next;
+- g_return_if_fail(draw_list != NULL);
+-
+- y = GPOINTER_TO_INT(draw_list->data);
+- draw_list = draw_list->next;
+- g_return_if_fail(draw_list != NULL);
+-
+- /*
+- purple_debug_debug("yahoo", "doodle: Drawing: color=%d, size=%d, (%d,%d)\n", brush_color, brush_size, x, y);
+- */
+-
+- while(draw_list != NULL && draw_list->next != NULL)
+- {
+- int dx = GPOINTER_TO_INT(draw_list->data);
+- int dy = GPOINTER_TO_INT(draw_list->next->data);
+-
+- purple_whiteboard_draw_line(wb,
+- x, y,
+- x + dx, y + dy,
+- brush_color, brush_size);
+-
+- x += dx;
+- y += dy;
+-
+- draw_list = draw_list->next->next;
+- }
+-}
+-
+-void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color)
+-{
+- doodle_session *ds = wb->proto_data;
+- *size = ds->brush_size;
+- *color = ds->brush_color;
+-}
+-
+-void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color)
+-{
+- doodle_session *ds = wb->proto_data;
+- ds->brush_size = size;
+- ds->brush_color = color;
+-
+- /* Notify the core about the changes */
+- purple_whiteboard_set_brush(wb, size, color);
+-}
+-
+-void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
+- const char *command, const char *message, const char *imv_key)
+-{
+- if(!command)
+- return;
+-
+- /* Now check to see what sort of Doodle message it is */
+- switch(atoi(command))
+- {
+- case DOODLE_CMD_REQUEST:
+- yahoo_doodle_command_got_request(gc, from, imv_key);
+- break;
+-
+- case DOODLE_CMD_READY:
+- yahoo_doodle_command_got_ready(gc, from, imv_key);
+- break;
+-
+- case DOODLE_CMD_CLEAR:
+- yahoo_doodle_command_got_clear(gc, from);
+- break;
+-
+- case DOODLE_CMD_DRAW:
+- yahoo_doodle_command_got_draw(gc, from, message);
+- break;
+-
+- case DOODLE_CMD_EXTRA:
+- yahoo_doodle_command_got_extra(gc, from, message, imv_key);
+- break;
+-
+- case DOODLE_CMD_CONFIRM:
+- yahoo_doodle_command_got_confirm(gc, from);
+- break;
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_doodle.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_doodle.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,131 +0,0 @@
+-/**
+- * @file yahoo_doodle.h The Yahoo! protocol plugin Doodle IMVironment object
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _YAHOO_DOODLE_H_
+-#define _YAHOO_DOODLE_H_
+-
+-/******************************************************************************
+- * Includes
+- *****************************************************************************/
+-#include "whiteboard.h"
+-#include "cmds.h"
+-
+-#define DOODLE_IMV_KEY "doodle;106"
+-
+-/******************************************************************************
+- * Defines
+- *****************************************************************************/
+-/* Doodle communication commands */
+-/* TODO: Should be an enum. */
+-#define DOODLE_CMD_REQUEST 0
+-#define DOODLE_CMD_CLEAR 1
+-#define DOODLE_CMD_DRAW 2
+-#define DOODLE_CMD_EXTRA 3
+-#define DOODLE_CMD_READY 4
+-#define DOODLE_CMD_CONFIRM 5
+-/* Doodle communication command for shutting down (also 0) */
+-#define DOODLE_CMD_SHUTDOWN 0
+-
+-#define DOODLE_EXTRA_NONE "\"1\""
+-#define DOODLE_EXTRA_TICTACTOE "\"3\""
+-#define DOODLE_EXTRA_DOTS "\"2\""
+-
+-/* Doodle session states */
+-/* TODO: Should be an enum. */
+-#define DOODLE_STATE_REQUESTING 0
+-#define DOODLE_STATE_REQUESTED 1
+-#define DOODLE_STATE_ESTABLISHED 2
+-#define DOODLE_STATE_CANCELLED 3
+-
+-/* Doodle canvas dimensions */
+-#define DOODLE_CANVAS_WIDTH 368
+-#define DOODLE_CANVAS_HEIGHT 256
+-
+-/* Doodle color codes (most likely RGB) */
+-/* TODO: Should be an enum and sorted by color name. */
+-#define DOODLE_COLOR_RED 13369344
+-#define DOODLE_COLOR_ORANGE 16737792
+-#define DOODLE_COLOR_YELLOW 15658496
+-#define DOODLE_COLOR_GREEN 52224
+-#define DOODLE_COLOR_CYAN 52428
+-#define DOODLE_COLOR_BLUE 204
+-#define DOODLE_COLOR_VIOLET 5381277
+-#define DOODLE_COLOR_PURPLE 13369548
+-#define DOODLE_COLOR_TAN 12093547
+-#define DOODLE_COLOR_BROWN 5256485
+-#define DOODLE_COLOR_BLACK 0
+-#define DOODLE_COLOR_GREY 11184810
+-#define DOODLE_COLOR_WHITE 16777215
+-
+-#define PALETTE_NUM_OF_COLORS 12
+-
+-/* Doodle brush sizes (most likely variable) */
+-#define DOODLE_BRUSH_SMALL 2
+-#define DOODLE_BRUSH_MEDIUM 5
+-#define DOODLE_BRUSH_LARGE 10
+-
+-#define DOODLE_MAX_BRUSH_MOTIONS 100
+-
+-/******************************************************************************
+- * Datatypes
+- *****************************************************************************/
+-typedef struct _doodle_session
+-{
+- int brush_size; /* Size of drawing brush */
+- int brush_color; /* Color of drawing brush */
+- gchar *imv_key;
+-} doodle_session;
+-
+-/******************************************************************************
+- * API
+- *****************************************************************************/
+-
+-PurpleCmdRet yahoo_doodle_purple_cmd_start(PurpleConversation *conv, const char *cmd, char **args,
+- char **error, void *data);
+-
+-void yahoo_doodle_process(PurpleConnection *gc, const char *me, const char *from,
+- const char *command, const char *message, const char *imv_key);
+-void yahoo_doodle_initiate(PurpleConnection *gc, const char *to);
+-
+-void yahoo_doodle_command_got_shutdown(PurpleConnection *gc, const char *from);
+-
+-void yahoo_doodle_command_send_request(PurpleConnection *gc, const char *to, const char *imv_key);
+-void yahoo_doodle_command_send_ready(PurpleConnection *gc, const char *to, const char *imv_key);
+-void yahoo_doodle_command_send_draw(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
+-void yahoo_doodle_command_send_clear(PurpleConnection *gc, const char *to, const char *imv_key);
+-void yahoo_doodle_command_send_extra(PurpleConnection *gc, const char *to, const char *message, const char *imv_key);
+-void yahoo_doodle_command_send_confirm(PurpleConnection *gc, const char *to, const char *imv_key);
+-void yahoo_doodle_command_send_shutdown(PurpleConnection *gc, const char *to);
+-
+-void yahoo_doodle_start(PurpleWhiteboard *wb);
+-void yahoo_doodle_end(PurpleWhiteboard *wb);
+-void yahoo_doodle_get_dimensions(const PurpleWhiteboard *wb, int *width, int *height);
+-void yahoo_doodle_send_draw_list(PurpleWhiteboard *wb, GList *draw_list);
+-void yahoo_doodle_clear(PurpleWhiteboard *wb);
+-
+-void yahoo_doodle_draw_stroke(PurpleWhiteboard *wb, GList *draw_list);
+-void yahoo_doodle_get_brush(const PurpleWhiteboard *wb, int *size, int *color);
+-void yahoo_doodle_set_brush(PurpleWhiteboard *wb, int size, int color);
+-
+-#endif /* _YAHOO_DOODLE_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1951 +0,0 @@
+-/*
+- * @file yahoo_filexfer.c Yahoo Filetransfer
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "dnsquery.h"
+-
+-#include "prpl.h"
+-#include "util.h"
+-#include "debug.h"
+-#include "network.h"
+-#include "notify.h"
+-#include "proxy.h"
+-#include "ft.h"
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-#include "yahoo_filexfer.h"
+-#include "yahoo_doodle.h"
+-#include "yahoo_friend.h"
+-
+-struct yahoo_xfer_data {
+- gchar *host;
+- gchar *path;
+- int port;
+- PurpleConnection *gc;
+- long expires;
+- gboolean started;
+- gchar *txbuf;
+- gsize txbuflen;
+- gsize txbuf_written;
+- guint tx_handler;
+- gchar *rxqueue;
+- guint rxlen;
+- gchar *xfer_peer_idstring;
+- gchar *xfer_idstring_for_relay;
+- int version; /* 0 for old, 15 for Y7(YMSG 15) */
+- int info_val_249;
+-
+- enum {
+- STARTED = 0,
+- HEAD_REQUESTED,
+- HEAD_REPLY_RECEIVED,
+- TRANSFER_PHASE,
+- ACCEPTED,
+- P2P_HEAD_REQUESTED,
+- P2P_HEAD_REPLIED,
+- P2P_GET_REQUESTED
+- } status_15;
+-
+- /* contains all filenames, in case of multiple transfers, with the first
+- * one in the list being the current file's name (ymsg15) */
+- GSList *filename_list;
+- GSList *size_list; /* corresponds to filename_list, with size as **STRING** */
+- gboolean firstoflist;
+- gchar *xfer_url; /* url of the file, used when we are p2p server */
+- int yahoo_local_p2p_ft_server_fd;
+- int yahoo_local_p2p_ft_server_port;
+- int yahoo_p2p_ft_server_watcher;
+- int input_event;
+-};
+-
+-static void yahoo_xfer_data_free(struct yahoo_xfer_data *xd)
+-{
+- PurpleConnection *gc;
+- YahooData *yd;
+- PurpleXfer *xfer;
+- GSList *l;
+-
+- gc = xd->gc;
+- yd = gc->proto_data;
+-
+- /* remove entry from map */
+- if(xd->xfer_peer_idstring) {
+- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
+- if(xfer)
+- g_hash_table_remove(yd->xfer_peer_idstring_map, xd->xfer_peer_idstring);
+- }
+-
+- /* empty file & filesize list */
+- for (l = xd->filename_list; l; l = l->next) {
+- g_free(l->data);
+- l->data=NULL;
+- }
+- for (l = xd->size_list; l; l = l->next) {
+- g_free(l->data);
+- l->data=NULL;
+- }
+- g_slist_free(xd->filename_list);
+- g_slist_free(xd->size_list);
+-
+- g_free(xd->host);
+- g_free(xd->path);
+- g_free(xd->txbuf);
+- g_free(xd->xfer_peer_idstring);
+- g_free(xd->xfer_idstring_for_relay);
+- if (xd->tx_handler)
+- purple_input_remove(xd->tx_handler);
+- g_free(xd);
+-}
+-
+-static void yahoo_receivefile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- int remaining, written;
+-
+- xfer = data;
+- xd = xfer->data;
+-
+- remaining = xd->txbuflen - xd->txbuf_written;
+- written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0) {
+- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- if (written < remaining) {
+- xd->txbuf_written += written;
+- return;
+- }
+-
+- purple_input_remove(xd->tx_handler);
+- xd->tx_handler = 0;
+- g_free(xd->txbuf);
+- xd->txbuf = NULL;
+- xd->txbuflen = 0;
+-
+- purple_xfer_start(xfer, source, NULL, 0);
+-
+-}
+-
+-static void yahoo_receivefile_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+-
+- purple_debug_info("yahoo", "in yahoo_receivefile_connected\n");
+-
+- if (!(xfer = data))
+- return;
+- if (!(xd = xfer->data))
+- return;
+- if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
+- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
+- xfer->who, _("Unable to connect."));
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- xfer->fd = source;
+-
+- /* The first time we get here, assemble the tx buffer */
+- if (xd->txbuflen == 0) {
+- xd->txbuf = g_strdup_printf("GET /%s HTTP/1.0\r\nHost: %s\r\n\r\n",
+- xd->path, xd->host);
+- xd->txbuflen = strlen(xd->txbuf);
+- xd->txbuf_written = 0;
+- }
+-
+- if (!xd->tx_handler)
+- {
+- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
+- yahoo_receivefile_send_cb, xfer);
+- yahoo_receivefile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
+- }
+-}
+-
+-static void yahoo_sendfile_send_cb(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- int written, remaining;
+-
+- xfer = data;
+- xd = xfer->data;
+-
+- remaining = xd->txbuflen - xd->txbuf_written;
+- written = write(xfer->fd, xd->txbuf + xd->txbuf_written, remaining);
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0) {
+- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- if (written < remaining) {
+- xd->txbuf_written += written;
+- return;
+- }
+-
+- purple_input_remove(xd->tx_handler);
+- xd->tx_handler = 0;
+- g_free(xd->txbuf);
+- xd->txbuf = NULL;
+- xd->txbuflen = 0;
+-
+- purple_xfer_start(xfer, source, NULL, 0);
+-}
+-
+-static void yahoo_sendfile_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- struct yahoo_packet *pkt;
+- gchar *size, *filename, *encoded_filename, *header;
+- guchar *pkt_buf;
+- const char *host;
+- int port;
+- size_t content_length, header_len, pkt_buf_len;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+-
+- purple_debug_info("yahoo", "in yahoo_sendfile_connected\n");
+-
+- if (!(xfer = data))
+- return;
+- if (!(xd = xfer->data))
+- return;
+-
+- if (source < 0) {
+- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
+- xfer->who, _("Unable to connect."));
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- xfer->fd = source;
+-
+- /* Assemble the tx buffer */
+- gc = xd->gc;
+- account = purple_connection_get_account(gc);
+- yd = gc->proto_data;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANSFER,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- size = g_strdup_printf("%" G_GSIZE_FORMAT, purple_xfer_get_size(xfer));
+- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
+- encoded_filename = yahoo_string_encode(gc, filename, NULL);
+-
+- yahoo_packet_hash(pkt, "sssss", 0, purple_connection_get_display_name(gc),
+- 5, xfer->who, 14, "", 27, encoded_filename, 28, size);
+- g_free(size);
+- g_free(encoded_filename);
+- g_free(filename);
+-
+- content_length = YAHOO_PACKET_HDRLEN + yahoo_packet_length(pkt);
+-
+- pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
+- yahoo_packet_free(pkt);
+-
+- host = purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST);
+- port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
+- header = g_strdup_printf(
+- "POST http://%s:%d/notifyft HTTP/1.0\r\n"
+- "Content-length: %" G_GSIZE_FORMAT "\r\n"
+- "Host: %s:%d\r\n"
+- "Cookie: Y=%s; T=%s\r\n"
+- "\r\n",
+- host, port, content_length + 4 + purple_xfer_get_size(xfer),
+- host, port, yd->cookie_y, yd->cookie_t);
+-
+- header_len = strlen(header);
+-
+- xd->txbuflen = header_len + pkt_buf_len + 4;
+- xd->txbuf = g_malloc(xd->txbuflen);
+-
+- memcpy(xd->txbuf, header, header_len);
+- g_free(header);
+- memcpy(xd->txbuf + header_len, pkt_buf, pkt_buf_len);
+- g_free(pkt_buf);
+- memcpy(xd->txbuf + header_len + pkt_buf_len, "29\xc0\x80", 4);
+-
+- xd->txbuf_written = 0;
+-
+- if (xd->tx_handler == 0)
+- {
+- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
+- yahoo_sendfile_send_cb, xfer);
+- yahoo_sendfile_send_cb(xfer, source, PURPLE_INPUT_WRITE);
+- }
+-}
+-
+-static void yahoo_xfer_init(PurpleXfer *xfer)
+-{
+- struct yahoo_xfer_data *xfer_data;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+-
+- xfer_data = xfer->data;
+- gc = xfer_data->gc;
+- yd = gc->proto_data;
+- account = purple_connection_get_account(gc);
+-
+- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
+- if (yd->jp) {
+- if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xferjp_host", YAHOOJP_XFER_HOST),
+- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
+- yahoo_sendfile_connected, xfer) == NULL)
+- {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),
+- _("Unable to establish file descriptor."));
+- purple_xfer_cancel_remote(xfer);
+- }
+- } else {
+- if (purple_proxy_connect(gc, account, purple_account_get_string(account, "xfer_host", YAHOO_XFER_HOST),
+- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
+- yahoo_sendfile_connected, xfer) == NULL)
+- {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),
+- _("Unable to establish file descriptor."));
+- purple_xfer_cancel_remote(xfer);
+- }
+- }
+- } else {
+- xfer->fd = -1;
+- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
+- yahoo_receivefile_connected, xfer) == NULL) {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),
+- _("Unable to establish file descriptor."));
+- purple_xfer_cancel_remote(xfer);
+- }
+- }
+-}
+-
+-static void yahoo_xfer_init_15(PurpleXfer *xfer)
+-{
+- struct yahoo_xfer_data *xfer_data;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- xfer_data = xfer->data;
+- gc = xfer_data->gc;
+- yd = gc->proto_data;
+- account = purple_connection_get_account(gc);
+-
+- if (purple_xfer_get_type(xfer) == PURPLE_XFER_SEND) {
+- gchar *filename;
+- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
+- YAHOO_STATUS_AVAILABLE,
+- yd->session_id);
+- yahoo_packet_hash(pkt, "sssiiiisiii",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 222, 1,
+- 266, 1,
+- 302, 268,
+- 300, 268,
+- 27, filename,
+- 28, xfer->size,
+- 301, 268,
+- 303, 268);
+- g_free(filename);
+- } else {
+- if(xfer_data->firstoflist == TRUE) {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 222, 3);
+- } else {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 271, 1);
+- }
+- }
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-static void yahoo_xfer_start(PurpleXfer *xfer)
+-{
+- /* We don't need to do anything here, do we? */
+-}
+-
+-static guint calculate_length(const gchar *l, size_t len)
+-{
+- int i;
+-
+- for (i = 0; i < len; i++) {
+- if (!g_ascii_isdigit(l[i]))
+- continue;
+- return strtol(l + i, NULL, 10);
+- }
+- return 0;
+-}
+-
+-static gssize yahoo_xfer_read(guchar **buffer, PurpleXfer *xfer)
+-{
+- gchar buf[4096];
+- gssize len;
+- gchar *start = NULL;
+- gchar *length;
+- gchar *end;
+- int filelen;
+- struct yahoo_xfer_data *xd = xfer->data;
+-
+- if (purple_xfer_get_type(xfer) != PURPLE_XFER_RECEIVE) {
+- return 0;
+- }
+-
+- len = read(xfer->fd, buf, sizeof(buf));
+-
+- if (len <= 0) {
+- if ((purple_xfer_get_size(xfer) > 0) &&
+- (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))) {
+- purple_xfer_set_completed(xfer, TRUE);
+- return 0;
+- } else
+- return -1;
+- }
+-
+- if (!xd->started) {
+- xd->rxqueue = g_realloc(xd->rxqueue, len + xd->rxlen);
+- memcpy(xd->rxqueue + xd->rxlen, buf, len);
+- xd->rxlen += len;
+-
+- length = g_strstr_len(xd->rxqueue, len, "Content-length:");
+- /* some proxies re-write this header, changing the capitalization :(
+- * technically that's allowed since headers are case-insensitive
+- * [RFC 2616, section 4.2] */
+- if (length == NULL)
+- length = g_strstr_len(xd->rxqueue, len, "Content-Length:");
+- if (length) {
+- end = g_strstr_len(length, length - xd->rxqueue, "\r\n");
+- if (!end)
+- return 0;
+- if ((filelen = calculate_length(length, len - (length - xd->rxqueue))))
+- purple_xfer_set_size(xfer, filelen);
+- }
+- start = g_strstr_len(xd->rxqueue, len, "\r\n\r\n");
+- if (start)
+- start += 4;
+- if (!start || start > (xd->rxqueue + len))
+- return 0;
+- xd->started = TRUE;
+-
+- len -= (start - xd->rxqueue);
+-
+- *buffer = g_malloc(len);
+- memcpy(*buffer, start, len);
+- g_free(xd->rxqueue);
+- xd->rxqueue = NULL;
+- xd->rxlen = 0;
+- } else {
+- *buffer = g_malloc(len);
+- memcpy(*buffer, buf, len);
+- }
+-
+- return len;
+-}
+-
+-static gssize yahoo_xfer_write(const guchar *buffer, size_t size, PurpleXfer *xfer)
+-{
+- gssize len;
+- struct yahoo_xfer_data *xd = xfer->data;
+-
+- if (!xd)
+- return -1;
+-
+- if (purple_xfer_get_type(xfer) != PURPLE_XFER_SEND) {
+- return -1;
+- }
+-
+- len = write(xfer->fd, buffer, size);
+-
+- if (len == -1) {
+- if (purple_xfer_get_bytes_sent(xfer) >= purple_xfer_get_size(xfer))
+- purple_xfer_set_completed(xfer, TRUE);
+- if ((errno != EAGAIN) && (errno != EINTR))
+- return -1;
+- return 0;
+- }
+-
+- return len;
+-}
+-
+-static void yahoo_xfer_cancel_send(PurpleXfer *xfer)
+-{
+- struct yahoo_xfer_data *xfer_data;
+-
+- xfer_data = xfer->data;
+-
+- if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
+- {
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- gc = xfer_data->gc;
+- yd = gc->proto_data;
+- account = purple_connection_get_account(gc);
+- if(xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
+- {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15,
+- YAHOO_STATUS_DISCONNECTED,
+- yd->session_id);
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 66, -1);
+- }
+- else
+- {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
+- YAHOO_STATUS_AVAILABLE,
+- yd->session_id);
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 222, 2);
+- }
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-
+-
+- if (xfer_data)
+- yahoo_xfer_data_free(xfer_data);
+- xfer->data = NULL;
+-}
+-
+-static void yahoo_xfer_cancel_recv(PurpleXfer *xfer)
+-{
+- struct yahoo_xfer_data *xfer_data;
+-
+- xfer_data = xfer->data;
+-
+- if(purple_xfer_get_status(xfer) == PURPLE_XFER_STATUS_CANCEL_LOCAL && xfer_data->version == 15)
+- {
+-
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+- struct yahoo_packet *pkt;
+-
+- gc = xfer_data->gc;
+- yd = gc->proto_data;
+- account = purple_connection_get_account(gc);
+- if(!xfer_data->xfer_idstring_for_relay) /* hack to see if file trans acc/info packet has been received */
+- {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
+- YAHOO_STATUS_AVAILABLE,
+- yd->session_id);
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 222, 4);
+- }
+- else
+- {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_15,
+- YAHOO_STATUS_DISCONNECTED,
+- yd->session_id);
+- yahoo_packet_hash(pkt, "sssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 66, -1);
+- }
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-
+- if (xfer_data)
+- yahoo_xfer_data_free(xfer_data);
+- xfer->data = NULL;
+-}
+-
+-/* Send HTTP OK after receiving file */
+-static void yahoo_p2p_ft_server_send_OK(PurpleXfer *xfer)
+-{
+- char *tx = NULL;
+- int written;
+-
+- tx = g_strdup_printf("HTTP/1.1 200 OK\r\nContent-Length: 0\r\nContent-Type: application/octet-stream\r\nConnection: close\r\n\r\n");
+- written = write(xfer->fd, tx, strlen(tx));
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0)
+- purple_debug_info("yahoo", "p2p filetransfer: Unable to write HTTP OK");
+-
+- /* close connection */
+- close(xfer->fd);
+- xfer->fd = -1;
+- g_free(tx);
+-}
+-
+-static void yahoo_xfer_end(PurpleXfer *xfer_old)
+-{
+- struct yahoo_xfer_data *xfer_data;
+- PurpleXfer *xfer = NULL;
+- PurpleConnection *gc;
+- YahooData *yd;
+-
+- xfer_data = xfer_old->data;
+- if(xfer_data && xfer_data->version == 15
+- && purple_xfer_get_type(xfer_old) == PURPLE_XFER_RECEIVE
+- && xfer_data->filename_list) {
+-
+- /* Send HTTP OK in case of p2p transfer, when we act as server */
+- if((xfer_data->xfer_url != NULL) && (xfer_old->fd >=0) && (purple_xfer_get_status(xfer_old) == PURPLE_XFER_STATUS_DONE))
+- yahoo_p2p_ft_server_send_OK(xfer_old);
+-
+- /* removing top of filename & size list completely */
+- g_free( xfer_data->filename_list->data );
+- g_free( xfer_data->size_list->data );
+-
+- xfer_data->filename_list->data = NULL;
+- xfer_data->size_list->data = NULL;
+-
+- xfer_data->filename_list = g_slist_delete_link(xfer_data->filename_list, xfer_data->filename_list);
+- xfer_data->size_list = g_slist_delete_link(xfer_data->size_list, xfer_data->size_list);
+-
+- /* if there are still more files */
+- if(xfer_data->filename_list)
+- {
+- gchar* filename;
+- long filesize;
+-
+- filename = xfer_data->filename_list->data;
+- filesize = atol( xfer_data->size_list->data );
+-
+- gc = xfer_data->gc;
+- yd = gc->proto_data;
+-
+- /* setting up xfer_data for next file's tranfer */
+- g_free(xfer_data->host);
+- g_free(xfer_data->path);
+- g_free(xfer_data->txbuf);
+- g_free(xfer_data->rxqueue);
+- g_free(xfer_data->xfer_idstring_for_relay);
+- if (xfer_data->tx_handler)
+- purple_input_remove(xfer_data->tx_handler);
+- xfer_data->host = NULL;
+- xfer_data->host = NULL;
+- xfer_data->port = 0;
+- xfer_data->expires = 0;
+- xfer_data->started = FALSE;
+- xfer_data->txbuf = NULL;
+- xfer_data->txbuflen = 0;
+- xfer_data->txbuf_written = 0;
+- xfer_data->tx_handler = 0;
+- xfer_data->rxqueue = NULL;
+- xfer_data->rxlen = 0;
+- xfer_data->xfer_idstring_for_relay = NULL;
+- xfer_data->info_val_249 = 0;
+- xfer_data->status_15 = STARTED;
+- xfer_data->firstoflist = FALSE;
+-
+- /* Dereference xfer_data from old xfer */
+- xfer_old->data = NULL;
+-
+- /* Build the file transfer handle. */
+- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, xfer_old->who);
+-
+-
+- if (xfer) {
+- /* Set the info about the incoming file. */
+- char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
+- purple_xfer_set_filename(xfer, utf8_filename);
+- g_free(utf8_filename);
+- purple_xfer_set_size(xfer, filesize);
+-
+- xfer->data = xfer_data;
+-
+- /* Setup our I/O op functions */
+- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
+- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
+- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
+- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
+- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
+- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
+- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
+- purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
+-
+- /* update map to current xfer */
+- g_hash_table_remove(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring);
+- g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
+-
+- /* Now perform the request */
+- purple_xfer_request(xfer);
+- }
+- return;
+- }
+- }
+- if (xfer_data)
+- yahoo_xfer_data_free(xfer_data);
+- xfer_old->data = NULL;
+-
+-}
+-
+-void yahoo_process_p2pfilexfer(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+-
+- char *me = NULL;
+- char *from = NULL;
+- char *service = NULL;
+- char *message = NULL;
+- char *command = NULL;
+- char *imv = NULL;
+- char *unknown = NULL;
+-
+- /* Get all the necessary values from this new packet */
+- while(l != NULL)
+- {
+- struct yahoo_pair *pair = l->data;
+-
+- switch(pair->key) {
+- case 5: /* Get who the packet is for */
+- me = pair->value;
+- break;
+- case 4: /* Get who the packet is from */
+- from = pair->value;
+- break;
+- case 49: /* Get the type of service */
+- service = pair->value;
+- break;
+- case 14: /* Get the 'message' of the packet */
+- message = pair->value;
+- break;
+- case 13: /* Get the command associated with this packet */
+- command = pair->value;
+- break;
+- case 63: /* IMVironment name and version */
+- imv = pair->value;
+- break;
+- case 64: /* Not sure, but it does vary with initialization of Doodle */
+- unknown = pair->value; /* So, I'll keep it (for a little while atleast) */
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- /* If this packet is an IMVIRONMENT, handle it accordingly */
+- if(service != NULL && imv != NULL && !strcmp(service, "IMVIRONMENT"))
+- {
+- /* Check for a Doodle packet and handle it accordingly */
+- if(strstr(imv, "doodle;") != NULL)
+- yahoo_doodle_process(gc, me, from, command, message, imv);
+-
+- /* If an IMVIRONMENT packet comes without a specific imviroment name */
+- if(!strcmp(imv, ";0"))
+- {
+- /* It is unfortunately time to close all IMVironments with the remote client */
+- yahoo_doodle_command_got_shutdown(gc, from);
+- }
+- }
+-}
+-
+-void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *from = NULL;
+- char *to = NULL;
+- char *msg = NULL;
+- char *url = NULL;
+- char *imv = NULL;
+- long expires = 0;
+- PurpleXfer *xfer;
+- YahooData *yd;
+- struct yahoo_xfer_data *xfer_data;
+- char *service = NULL;
+- char *filename = NULL;
+- unsigned long filesize = 0L;
+- GSList *l;
+-
+- yd = gc->proto_data;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- from = pair->value;
+- break;
+- case 5:
+- to = pair->value;
+- break;
+- case 14:
+- msg = pair->value;
+- break;
+- case 20:
+- url = pair->value;
+- break;
+- case 38:
+- expires = strtol(pair->value, NULL, 10);
+- break;
+- case 27:
+- filename = pair->value;
+- break;
+- case 28:
+- filesize = atol(pair->value);
+- break;
+- case 49:
+- service = pair->value;
+- break;
+- case 63:
+- imv = pair->value;
+- break;
+- }
+- }
+-
+- /*
+- * The remote user has changed their IMVironment. We
+- * record it for later use.
+- */
+- if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
+- g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
+- return;
+- }
+-
+- if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
+- if (service && (strcmp("FILEXFER", service) != 0)) {
+- purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
+- return;
+- }
+- }
+-
+- if (msg) {
+- char *tmp;
+- tmp = strchr(msg, '\006');
+- if (tmp)
+- *tmp = '\0';
+- }
+-
+- if (!url || !from)
+- return;
+-
+- /* Setup the Yahoo-specific file transfer data */
+- xfer_data = g_new0(struct yahoo_xfer_data, 1);
+- xfer_data->gc = gc;
+- if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
+- g_free(xfer_data);
+- return;
+- }
+-
+- purple_debug_misc("yahoo_filexfer", "Host is %s, port is %d, path is %s, and the full url was %s.\n",
+- xfer_data->host, xfer_data->port, xfer_data->path, url);
+-
+- /* Build the file transfer handle. */
+- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
+- if (xfer == NULL) {
+- g_free(xfer_data);
+- g_return_if_reached();
+- }
+-
+- xfer->data = xfer_data;
+-
+- /* Set the info about the incoming file. */
+- if (filename) {
+- char *utf8_filename = yahoo_string_decode(gc, filename, TRUE);
+- purple_xfer_set_filename(xfer, utf8_filename);
+- g_free(utf8_filename);
+- } else {
+- gchar *start, *end;
+- start = g_strrstr(xfer_data->path, "/");
+- if (start)
+- start++;
+- end = g_strrstr(xfer_data->path, "?");
+- if (start && *start && end) {
+- char *utf8_filename;
+- filename = g_strndup(start, end - start);
+- utf8_filename = yahoo_string_decode(gc, filename, TRUE);
+- g_free(filename);
+- purple_xfer_set_filename(xfer, utf8_filename);
+- g_free(utf8_filename);
+- filename = NULL;
+- }
+- }
+-
+- purple_xfer_set_size(xfer, filesize);
+-
+- /* Setup our I/O op functions */
+- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init);
+- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
+- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
+- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
+- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
+- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
+- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
+-
+- /* Now perform the request */
+- purple_xfer_request(xfer);
+-}
+-
+-PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xfer_data;
+-
+- g_return_val_if_fail(who != NULL, NULL);
+-
+- xfer_data = g_new0(struct yahoo_xfer_data, 1);
+- xfer_data->gc = gc;
+-
+- /* Build the file transfer handle. */
+- xfer = purple_xfer_new(gc->account, PURPLE_XFER_SEND, who);
+- if (xfer == NULL)
+- {
+- g_free(xfer_data);
+- g_return_val_if_reached(NULL);
+- }
+-
+- xfer->data = xfer_data;
+-
+- /* Setup our I/O op functions */
+- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init);
+- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
+- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
+- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
+- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
+- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
+- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
+-
+- return xfer;
+-}
+-
+-static gchar* yahoo_xfer_new_xfer_id(void)
+-{
+- gchar *ans;
+- int i,j;
+- ans = g_strnfill(24, ' ');
+- ans[23] = '$';
+- ans[22] = '$';
+- for(i = 0; i < 22; i++)
+- {
+- j = g_random_int_range (0,61);
+- if(j < 26)
+- ans[i] = j + 'a';
+- else if(j < 52)
+- ans[i] = j - 26 + 'A';
+- else
+- ans[i] = j - 52 + '0';
+- }
+- return ans;
+-}
+-
+-static void yahoo_xfer_dns_connected_15(GSList *hosts, gpointer data, const char *error_message)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- struct sockaddr_in *addr;
+- struct yahoo_packet *pkt;
+- unsigned long actaddr;
+- unsigned char a,b,c,d;
+- PurpleConnection *gc;
+- PurpleAccount *account;
+- YahooData *yd;
+- gchar *url;
+- gchar *filename;
+-
+- if (!(xfer = data))
+- return;
+- if (!(xd = xfer->data))
+- return;
+- gc = xd->gc;
+- account = purple_connection_get_account(gc);
+- yd = gc->proto_data;
+-
+- if(!hosts)
+- {
+- purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- /* Discard the length... */
+- hosts = g_slist_remove(hosts, hosts->data);
+- if(!hosts)
+- {
+- purple_debug_error("yahoo", "Unable to find an IP address for relay.msg.yahoo.com\n");
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- /* TODO:actually, u must try with addr no.1 , if its not working addr no.2 ..... */
+- addr = hosts->data;
+- actaddr = addr->sin_addr.s_addr;
+- d = actaddr & 0xff;
+- actaddr >>= 8;
+- c = actaddr & 0xff;
+- actaddr >>= 8;
+- b = actaddr & 0xff;
+- actaddr >>= 8;
+- a = actaddr & 0xff;
+- if(yd->jp)
+- xd->port = YAHOOJP_XFER_RELAY_PORT;
+- else
+- xd->port = YAHOO_XFER_RELAY_PORT;
+-
+- url = g_strdup_printf("%u.%u.%u.%u", d, c, b, a);
+-
+- /* Free the address... */
+- g_free(hosts->data);
+- hosts = g_slist_remove(hosts, hosts->data);
+- addr = NULL;
+- while (hosts != NULL)
+- {
+- /* Discard the length... */
+- hosts = g_slist_remove(hosts, hosts->data);
+- /* Free the address... */
+- g_free(hosts->data);
+- hosts = g_slist_remove(hosts, hosts->data);
+- }
+-
+- if (!purple_url_parse(url, &(xd->host), &(xd->port), &(xd->path), NULL, NULL)) {
+- purple_xfer_cancel_remote(xfer);
+- g_free(url);
+- return;
+- }
+- g_free(url);
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
+-
+- yahoo_packet_hash(pkt, "ssssis",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xd->xfer_peer_idstring,
+- 27, filename,
+- 249, 3,
+- 250, xd->host);
+-
+- g_free(filename);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who)
+-{
+- if (!who || yahoo_get_federation_from_name(who) != YAHOO_FEDERATION_NONE)
+- return FALSE;
+- return TRUE;
+-}
+-
+-void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file)
+-{
+- struct yahoo_xfer_data *xfer_data;
+- YahooData *yd = gc->proto_data;
+- PurpleXfer *xfer = yahoo_new_xfer(gc, who);
+-
+- g_return_if_fail(xfer != NULL);
+-
+- /* if we don't have a p2p connection, try establishing it now */
+- if( !g_hash_table_lookup(yd->peers, who) )
+- yahoo_send_p2p_pkt(gc, who, 0);
+-
+- xfer_data = xfer->data;
+- xfer_data->status_15 = STARTED;
+- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
+- xfer_data->version = 15;
+- xfer_data->xfer_peer_idstring = yahoo_xfer_new_xfer_id();
+- g_hash_table_insert(yd->xfer_peer_idstring_map, xfer_data->xfer_peer_idstring, xfer);
+-
+- /* Now perform the request */
+- if (file)
+- purple_xfer_request_accepted(xfer, file);
+- else
+- purple_xfer_request(xfer);
+-}
+-
+-static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data); /* using this in yahoo_xfer_send_cb_15 */
+-static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message);/* using this in recv_cb */
+-
+-static void yahoo_xfer_recv_cb_15(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- int did;
+- gchar* buf;
+- gchar* t;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+-
+- xfer = data;
+- xd = xfer->data;
+- account = purple_connection_get_account(xd->gc);
+- gc = xd->gc;
+-
+- buf=g_strnfill(1000, 0);
+- while((did = read(source, buf, 998)) > 0)
+- {
+- xd->txbuflen += did;
+- buf[did] = '\0';
+- t = xd->txbuf;
+- xd->txbuf = g_strconcat(t,buf,NULL);
+- g_free(t);
+- }
+- g_free(buf);
+-
+- if (did < 0 && errno == EAGAIN)
+- return;
+- else if (did < 0) {
+- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- purple_input_remove(xd->tx_handler);
+- xd->tx_handler = 0;
+- xd->txbuflen = 0;
+-
+- if(xd->status_15 == HEAD_REQUESTED) {
+- xd->status_15 = HEAD_REPLY_RECEIVED;
+- close(source);/* Is this required? */
+- g_free(xd->txbuf);
+- xd->txbuf = NULL;
+- if (purple_proxy_connect(gc, account, xd->host, xd->port, yahoo_xfer_connected_15, xfer) == NULL)
+- {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),
+- _("Unable to establish file descriptor."));
+- purple_xfer_cancel_remote(xfer);
+- }
+- } else {
+- purple_debug_error("yahoo","Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n",
+- purple_xfer_get_type(xfer),
+- xd->status_15);
+- return;
+- }
+-}
+-
+-static void yahoo_xfer_send_cb_15(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- int remaining, written;
+-
+- xfer = data;
+- xd = xfer->data;
+- remaining = xd->txbuflen - xd->txbuf_written;
+- written = write(source, xd->txbuf + xd->txbuf_written, remaining);
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0) {
+- purple_debug_error("yahoo", "Unable to write in order to start ft errno = %d\n", errno);
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- if (written < remaining) {
+- xd->txbuf_written += written;
+- return;
+- }
+-
+- purple_input_remove(xd->tx_handler);
+- xd->tx_handler = 0;
+- g_free(xd->txbuf);
+- xd->txbuf = NULL;
+- xd->txbuflen = 0;
+- xd->txbuf_written = 0;
+-
+- if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
+- {
+- xd->status_15 = HEAD_REQUESTED;
+- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_READ, yahoo_xfer_recv_cb_15, xfer);
+- yahoo_xfer_recv_cb_15(xfer, source, PURPLE_INPUT_READ);
+- }
+- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
+- {
+- xd->status_15 = TRANSFER_PHASE;
+- xfer->fd = source;
+- purple_xfer_start(xfer, source, NULL, 0);
+- }
+- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && (xd->status_15 == ACCEPTED || xd->status_15 == P2P_GET_REQUESTED) )
+- {
+- xd->status_15 = TRANSFER_PHASE;
+- xfer->fd = source;
+- /* Remove Read event */
+- purple_input_remove(xd->input_event);
+- xd->input_event = 0;
+- purple_xfer_start(xfer, source, NULL, 0);
+- }
+- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == P2P_HEAD_REQUESTED)
+- {
+- xd->status_15 = P2P_HEAD_REPLIED;
+- /* Remove Read event and close descriptor */
+- purple_input_remove(xd->input_event);
+- xd->input_event = 0;
+- close(source);
+- xfer->fd = -1;
+- /* start local server, listen for connections */
+- purple_network_listen(xd->yahoo_local_p2p_ft_server_port, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer);
+- }
+- else
+- {
+- purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
+- return;
+- }
+-}
+-
+-static void yahoo_xfer_connected_15(gpointer data, gint source, const gchar *error_message)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- PurpleAccount *account;
+- PurpleConnection *gc;
+-
+- if (!(xfer = data))
+- return;
+- if (!(xd = xfer->data))
+- return;
+- gc = xd->gc;
+- account = purple_connection_get_account(gc);
+- if ((source < 0) || (xd->path == NULL) || (xd->host == NULL)) {
+- purple_xfer_error(PURPLE_XFER_RECEIVE, purple_xfer_get_account(xfer),
+- xfer->who, _("Unable to connect."));
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+- /* The first time we get here, assemble the tx buffer */
+- if (xd->txbuflen == 0)
+- {
+- gchar* cookies;
+- YahooData *yd = gc->proto_data;
+-
+- /* cookies = yahoo_get_cookies(gc);
+- * This doesn't seem to be working. The function is returning NULL, which yahoo servers don't like
+- * For now let us not use this function */
+-
+- cookies = g_strdup_printf("Y=%s; T=%s", yd->cookie_y, yd->cookie_t);
+-
+- if(purple_xfer_get_type(xfer) == PURPLE_XFER_SEND && xd->status_15 == ACCEPTED)
+- {
+- if(xd->info_val_249 == 2)
+- {
+- /* sending file via p2p, we are connected as client */
+- xd->txbuf = g_strdup_printf("POST /%s HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %ld\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- xd->path,
+- xd->host,
+- (long int)xfer->size); /* to do, add Referer */
+- }
+- else
+- {
+- /* sending file via relaying */
+- xd->txbuf = g_strdup_printf("POST /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+- "Cookie:%s\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %ld\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- purple_url_encode(xd->xfer_idstring_for_relay),
+- purple_normalize(account, purple_account_get_username(account)),
+- xfer->who,
+- cookies,
+- xd->host,
+- (long int)xfer->size);
+- }
+- }
+- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == STARTED)
+- {
+- if(xd->info_val_249 == 1)
+- {
+- /* receiving file via p2p, connected as client */
+- xd->txbuf = g_strdup_printf("HEAD /%s HTTP/1.1\r\n"
+- "Accept: */*\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Content-Length: 0\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- xd->path,xd->host);
+- }
+- else
+- {
+- /* receiving file via relaying */
+- xd->txbuf = g_strdup_printf("HEAD /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+- "Accept: */*\r\n"
+- "Cookie: %s\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Content-Length: 0\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- purple_url_encode(xd->xfer_idstring_for_relay),
+- purple_normalize(account, purple_account_get_username(account)),
+- xfer->who,
+- cookies,
+- xd->host);
+- }
+- }
+- else if(purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE && xd->status_15 == HEAD_REPLY_RECEIVED)
+- {
+- if(xd->info_val_249 == 1)
+- {
+- /* receiving file via p2p, connected as client */
+- xd->txbuf = g_strdup_printf("GET /%s HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Connection: Keep-Alive\r\n\r\n",
+- xd->path, xd->host);
+- }
+- else
+- {
+- /* receiving file via relaying */
+- xd->txbuf = g_strdup_printf("GET /relay?token=%s&sender=%s&recver=%s HTTP/1.1\r\n"
+- "Cookie: %s\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Host: %s\r\n"
+- "Connection: Keep-Alive\r\n\r\n",
+- purple_url_encode(xd->xfer_idstring_for_relay),
+- purple_normalize(account, purple_account_get_username(account)),
+- xfer->who,
+- cookies,
+- xd->host);
+- }
+- }
+- else
+- {
+- purple_debug_error("yahoo", "Unrecognized yahoo file transfer mode and stage (ymsg15):%d,%d\n", purple_xfer_get_type(xfer), xd->status_15);
+- g_free(cookies);
+- return;
+- }
+- xd->txbuflen = strlen(xd->txbuf);
+- xd->txbuf_written = 0;
+- g_free(cookies);
+- }
+-
+- if (!xd->tx_handler)
+- {
+- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE,
+- yahoo_xfer_send_cb_15, xfer);
+- yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
+- }
+-}
+-
+-static void yahoo_p2p_ft_POST_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+-
+- xfer = data;
+- if (!(xd = xfer->data)) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- purple_input_remove(xd->input_event);
+- xd->status_15 = TRANSFER_PHASE;
+- xfer->fd = source;
+- purple_xfer_start(xfer, source, NULL, 0);
+-}
+-
+-static void yahoo_p2p_ft_HEAD_GET_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- guchar buf[1024];
+- int len;
+- char *url_head;
+- char *url_get;
+- time_t unix_time;
+- char *time_str;
+-
+- xfer = data;
+- if (!(xd = xfer->data)) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- len = read(source, buf, sizeof(buf));
+- if ((len < 0) && ((errno == EAGAIN) || (errno == EWOULDBLOCK)))
+- return ; /* No Worries*/
+- else if (len <= 0) {
+- purple_debug_warning("yahoo","p2p-ft: Error in connection, or host disconnected\n");
+- purple_input_remove(xd->input_event);
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- url_head = g_strdup_printf("HEAD %s", xd->xfer_url);
+- url_get = g_strdup_printf("GET %s", xd->xfer_url);
+-
+- if( strncmp(url_head, (char *)buf, strlen(url_head)) == 0 )
+- xd->status_15 = P2P_HEAD_REQUESTED;
+- else if( strncmp(url_get, (char *)buf, strlen(url_get)) == 0 )
+- xd->status_15 = P2P_GET_REQUESTED;
+- else {
+- purple_debug_warning("yahoo","p2p-ft: Wrong HEAD/GET request from peer, disconnecting host\n");
+- purple_input_remove(xd->input_event);
+- purple_xfer_cancel_remote(xfer);
+- g_free(url_head);
+- return;
+- }
+-
+- unix_time = time(NULL);
+- time_str = ctime(&unix_time);
+- time_str[strlen(time_str) - 1] = '\0';
+-
+- if (xd->txbuflen == 0) {
+- xd->txbuf = g_strdup_printf("HTTP/1.0 200 OK\r\n"
+- "Date: %s GMT\r\n"
+- "Server: Y!/1.0\r\n"
+- "MIME-version: 1.0\r\n"
+- "Last-modified: %s GMT\r\n"
+- "Content-length: %" G_GSIZE_FORMAT "\r\n\r\n",
+- time_str, time_str, xfer->size);
+- xd->txbuflen = strlen(xd->txbuf);
+- xd->txbuf_written = 0;
+- }
+-
+- if (!xd->tx_handler) {
+- xd->tx_handler = purple_input_add(source, PURPLE_INPUT_WRITE, yahoo_xfer_send_cb_15, xfer);
+- yahoo_xfer_send_cb_15(xfer, source, PURPLE_INPUT_WRITE);
+- }
+-
+- g_free(url_head);
+- g_free(url_get);
+-}
+-
+-static void yahoo_p2p_ft_server_send_connected_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- int acceptfd;
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+-
+- xfer = data;
+- if (!(xd = xfer->data)) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- acceptfd = accept(source, NULL, 0);
+- if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
+- return;
+- else if(acceptfd == -1) {
+- purple_debug_warning("yahoo","yahoo_p2p_server_send_connected_cb: accept: %s\n", g_strerror(errno));
+- purple_xfer_cancel_remote(xfer);
+- /* remove watcher and close p2p ft server */
+- purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
+- close(xd->yahoo_local_p2p_ft_server_fd);
+- return;
+- }
+-
+- /* remove watcher and close p2p ft server */
+- purple_input_remove(xd->yahoo_p2p_ft_server_watcher);
+- close(xd->yahoo_local_p2p_ft_server_fd);
+-
+- /* Add an Input Read event to the file descriptor */
+- xfer->fd = acceptfd;
+- if(xfer->type == PURPLE_XFER_RECEIVE)
+- xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_POST_cb, data);
+- else
+- xd->input_event = purple_input_add(acceptfd, PURPLE_INPUT_READ, yahoo_p2p_ft_HEAD_GET_cb, data);
+-}
+-
+-static void yahoo_p2p_ft_server_listen_cb(int listenfd, gpointer data)
+-{
+- PurpleXfer *xfer;
+- struct yahoo_xfer_data *xd;
+- struct yahoo_packet *pkt;
+- PurpleAccount *account;
+- YahooData *yd;
+- gchar *filename;
+- const char *local_ip;
+- gchar *url_to_send = NULL;
+- char *filename_without_spaces = NULL;
+-
+- xfer = data;
+- if (!(xd = xfer->data) || (listenfd == -1)) {
+- purple_debug_warning("yahoo","p2p: error starting server for p2p file transfer\n");
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- if( (xfer->type == PURPLE_XFER_RECEIVE) || (xd->status_15 != P2P_HEAD_REPLIED) ) {
+- yd = xd->gc->proto_data;
+- account = purple_connection_get_account(xd->gc);
+- local_ip = purple_network_get_my_ip(listenfd);
+- xd->yahoo_local_p2p_ft_server_port = purple_network_get_port_from_fd(listenfd);
+-
+- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
+- filename_without_spaces = g_strdup(filename);
+- purple_util_chrreplace(filename_without_spaces, ' ', '+');
+- xd->xfer_url = g_strdup_printf("/Messenger.%s.%d000%s?AppID=Messenger&UserID=%s&K=lc9lu2u89gz1llmplwksajkjx", xfer->who, (int)time(NULL), filename_without_spaces, xfer->who);
+- url_to_send = g_strdup_printf("http://%s:%d%s", local_ip, xd->yahoo_local_p2p_ft_server_port, xd->xfer_url);
+-
+- if(xfer->type == PURPLE_XFER_RECEIVE) {
+- xd->info_val_249 = 2; /* 249=2: we are p2p server, and receiving file */
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "ssssis",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xd->xfer_peer_idstring,
+- 27, xfer->filename,
+- 249, 2,
+- 250, url_to_send);
+- }
+- else {
+- xd->info_val_249 = 1; /* 249=1: we are p2p server, and sending file */
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "ssssis",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xd->xfer_peer_idstring,
+- 27, filename,
+- 249, 1,
+- 250, url_to_send);
+- }
+-
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(filename);
+- g_free(url_to_send);
+- g_free(filename_without_spaces);
+- }
+-
+- /* Add an Input Read event to the file descriptor */
+- xd->yahoo_local_p2p_ft_server_fd = listenfd;
+- xd->yahoo_p2p_ft_server_watcher = purple_input_add(listenfd, PURPLE_INPUT_READ, yahoo_p2p_ft_server_send_connected_cb, data);
+-}
+-
+-/* send (p2p) file transfer information */
+-static void yahoo_p2p_client_send_ft_info(PurpleConnection *gc, PurpleXfer *xfer)
+-{
+- struct yahoo_xfer_data *xd;
+- struct yahoo_packet *pkt;
+- PurpleAccount *account;
+- YahooData *yd;
+- gchar *filename;
+- struct yahoo_p2p_data *p2p_data;
+-
+- if (!(xd = xfer->data))
+- return;
+-
+- account = purple_connection_get_account(gc);
+- yd = gc->proto_data;
+-
+- p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
+- if( p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER )
+- if(purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer))
+- return;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_INFO_15, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- filename = g_path_get_basename(purple_xfer_get_local_filename(xfer));
+-
+- yahoo_packet_hash(pkt, "ssssi",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xd->xfer_peer_idstring,
+- 27, filename,
+- 249, 2); /* 249=2: we are p2p client */
+- xd->info_val_249 = 2;
+- yahoo_packet_send_and_free(pkt, yd);
+-
+- g_free(filename);
+-}
+-
+-void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *from = NULL;
+- char *to = NULL;
+- char *imv = NULL;
+- long val_222 = 0L;
+- PurpleXfer *xfer;
+- YahooData *yd;
+- struct yahoo_xfer_data *xfer_data;
+- char *service = NULL;
+- char *filename = NULL;
+- char *xfer_peer_idstring = NULL;
+- char *utf8_filename;
+- unsigned long filesize = 0L;
+- GSList *l;
+- GSList *filename_list = NULL;
+- GSList *size_list = NULL;
+- int nooffiles = 0;
+-
+- yd = gc->proto_data;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- from = pair->value;
+- break;
+- case 5:
+- to = pair->value;
+- break;
+- case 265:
+- xfer_peer_idstring = pair->value;
+- break;
+- case 27:
+- filename_list = g_slist_prepend(filename_list, g_strdup(pair->value));
+- nooffiles++;
+- break;
+- case 28:
+- size_list = g_slist_prepend(size_list, g_strdup(pair->value));
+- break;
+- case 222:
+- val_222 = atol(pair->value);
+- /* 1=send, 2=cancel, 3=accept, 4=reject */
+- break;
+-
+- /* check for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
+- case 49:
+- service = pair->value;
+- break;
+- case 63:
+- imv = pair->value;
+- break;
+- /* end check */
+-
+- }
+- }
+- if(!xfer_peer_idstring)
+- return;
+-
+- if(val_222 == 2 || val_222 == 4)
+- {
+- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
+- xfer_peer_idstring);
+- if(!xfer) return;
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+- if(val_222 == 3)
+- {
+- PurpleAccount *account;
+- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map,
+- xfer_peer_idstring);
+- if(!xfer)
+- return;
+- /*
+- * In the file trans info packet that we must reply with, we are
+- * supposed to mention the ip address...
+- * purple connect does not give me a way of finding the ip address...
+- * so, purple dnsquery is used... but retries, trying with next ip
+- * address etc. is not implemented..TODO
+- */
+-
+- /* To send through p2p */
+- if( g_hash_table_lookup(yd->peers, from) ) {
+- /* send p2p file transfer information */
+- yahoo_p2p_client_send_ft_info(gc, xfer);
+- return;
+- }
+-
+- account = purple_connection_get_account(gc);
+- if (yd->jp)
+- {
+- purple_dnsquery_a_account(account, YAHOOJP_XFER_RELAY_HOST,
+- YAHOOJP_XFER_RELAY_PORT,
+- yahoo_xfer_dns_connected_15, xfer);
+- }
+- else
+- {
+- purple_dnsquery_a_account(account, YAHOO_XFER_RELAY_HOST,
+- YAHOO_XFER_RELAY_PORT,
+- yahoo_xfer_dns_connected_15, xfer);
+- }
+- return;
+- }
+-
+- /* processing for p2p and imviron .... not sure it comes by this service packet. Since it was bundled with filexfer in old ymsg version, still keeping it. */
+- /*
+- * The remote user has changed their IMVironment. We
+- * record it for later use.
+- */
+- if (from && imv && service && (strcmp("IMVIRONMENT", service) == 0)) {
+- g_hash_table_replace(yd->imvironments, g_strdup(from), g_strdup(imv));
+- return;
+- }
+-
+- if (pkt->service == YAHOO_SERVICE_P2PFILEXFER) {
+- if (service && (strcmp("FILEXFER", service) != 0)) {
+- purple_debug_misc("yahoo", "unhandled service 0x%02x\n", pkt->service);
+- return;
+- }
+- }
+- /* end processing */
+-
+- if(!filename_list)
+- return;
+- /* have to change list into order in which client at other end sends */
+- filename_list = g_slist_reverse(filename_list);
+- size_list = g_slist_reverse(size_list);
+- filename = filename_list->data;
+- filesize = atol(size_list->data);
+-
+- if(!from) return;
+- xfer_data = g_new0(struct yahoo_xfer_data, 1);
+- xfer_data->version = 15;
+- xfer_data->firstoflist = TRUE;
+- xfer_data->gc = gc;
+- xfer_data->xfer_peer_idstring = g_strdup(xfer_peer_idstring);
+- xfer_data->filename_list = filename_list;
+- xfer_data->size_list = size_list;
+-
+- /* Build the file transfer handle. */
+- xfer = purple_xfer_new(gc->account, PURPLE_XFER_RECEIVE, from);
+- if (xfer == NULL)
+- {
+- g_free(xfer_data);
+- g_return_if_reached();
+- }
+-
+- xfer->message = NULL;
+-
+- /* Set the info about the incoming file. */
+- utf8_filename = yahoo_string_decode(gc, filename, TRUE);
+- purple_xfer_set_filename(xfer, utf8_filename);
+- g_free(utf8_filename);
+- purple_xfer_set_size(xfer, filesize);
+-
+- xfer->data = xfer_data;
+-
+- /* Setup our I/O op functions */
+- purple_xfer_set_init_fnc(xfer, yahoo_xfer_init_15);
+- purple_xfer_set_start_fnc(xfer, yahoo_xfer_start);
+- purple_xfer_set_end_fnc(xfer, yahoo_xfer_end);
+- purple_xfer_set_cancel_send_fnc(xfer, yahoo_xfer_cancel_send);
+- purple_xfer_set_cancel_recv_fnc(xfer, yahoo_xfer_cancel_recv);
+- purple_xfer_set_read_fnc(xfer, yahoo_xfer_read);
+- purple_xfer_set_write_fnc(xfer, yahoo_xfer_write);
+- purple_xfer_set_request_denied_fnc(xfer,yahoo_xfer_cancel_recv);
+-
+- g_hash_table_insert(yd->xfer_peer_idstring_map,
+- xfer_data->xfer_peer_idstring,
+- xfer);
+-
+- if(nooffiles > 1) {
+- gchar* message;
+- message = g_strdup_printf(_("%s is trying to send you a group of %d files.\n"), xfer->who, nooffiles);
+- purple_xfer_conversation_write(xfer, message, FALSE);
+- g_free(message);
+- }
+- /* Now perform the request */
+- purple_xfer_request(xfer);
+-}
+-
+-void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- char *from = NULL;
+- char *to = NULL;
+- char *url = NULL;
+- long val_249 = 0;
+- long val_66 = 0;
+- PurpleXfer *xfer;
+- YahooData *yd;
+- struct yahoo_xfer_data *xfer_data;
+- char *filename = NULL;
+- char *xfer_peer_idstring = NULL;
+- char *xfer_idstring_for_relay = NULL;
+- GSList *l;
+- struct yahoo_packet *pkt_to_send;
+- struct yahoo_p2p_data *p2p_data;
+-
+- yd = gc->proto_data;
+-
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- from = pair->value;
+- break;
+- case 5:
+- to = pair->value;
+- break;
+- case 265:
+- xfer_peer_idstring = pair->value;
+- break;
+- case 27:
+- filename = pair->value;
+- break;
+- case 66:
+- val_66 = strtol(pair->value, NULL, 10);
+- break;
+- case 249:
+- val_249 = strtol(pair->value, NULL, 10);
+- /* 249 has value 1 or 2 when doing p2p transfer and value 3 when relaying through yahoo server */
+- break;
+- case 250:
+- url = pair->value;
+- break;
+- case 251:
+- xfer_idstring_for_relay = pair->value;
+- break;
+- }
+- }
+-
+- if(!xfer_peer_idstring)
+- return;
+-
+- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
+-
+- if(!xfer) return;
+-
+- if(val_66==-1)
+- {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- xfer_data = xfer->data;
+-
+- xfer_data->info_val_249 = val_249;
+- xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
+- if(val_249 == 1 || val_249 == 3) {
+- PurpleAccount *account;
+- if (!purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL)) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- account = purple_connection_get_account(xfer_data->gc);
+-
+- pkt_to_send = yahoo_packet_new(YAHOO_SERVICE_FILETRANS_ACC_15,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt_to_send, "ssssis",
+- 1, purple_normalize(account, purple_account_get_username(account)),
+- 5, xfer->who,
+- 265, xfer_data->xfer_peer_idstring,
+- 27, xfer->filename,
+- 249, xfer_data->info_val_249,
+- 251, xfer_data->xfer_idstring_for_relay);
+-
+- yahoo_packet_send_and_free(pkt_to_send, yd);
+-
+- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
+- yahoo_xfer_connected_15, xfer) == NULL) {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),
+- _("Unable to establish file descriptor."));
+- purple_xfer_cancel_remote(xfer);
+- }
+- }
+- else if(val_249 == 2) {
+- p2p_data = g_hash_table_lookup(yd->peers, xfer->who);
+- if( !( p2p_data && (p2p_data->connection_type == YAHOO_P2P_WE_ARE_SERVER) ) ) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+- if(!purple_network_listen_range(0, 0, SOCK_STREAM, yahoo_p2p_ft_server_listen_cb, xfer)) {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+- }
+-}
+-
+-/* TODO: Check filename etc. No probs till some hacker comes in the way */
+-void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- gchar *xfer_peer_idstring = NULL;
+- gchar *xfer_idstring_for_relay = NULL;
+- PurpleXfer *xfer;
+- YahooData *yd;
+- struct yahoo_xfer_data *xfer_data;
+- GSList *l;
+- PurpleAccount *account;
+- long val_66 = 0;
+- gchar *url = NULL;
+- int val_249 = 0;
+-
+- yd = gc->proto_data;
+- for (l = pkt->hash; l; l = l->next) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 251:
+- xfer_idstring_for_relay = pair->value;
+- break;
+- case 265:
+- xfer_peer_idstring = pair->value;
+- break;
+- case 66:
+- val_66 = atol(pair->value);
+- break;
+- case 249:
+- val_249 = atol(pair->value);
+- break;
+- case 250:
+- url = pair->value; /* we get a p2p url here when sending file, connected as client */
+- break;
+- }
+- }
+-
+- xfer = g_hash_table_lookup(yd->xfer_peer_idstring_map, xfer_peer_idstring);
+- if(!xfer) return;
+-
+- if(val_66 == -1 || ( (!(xfer_idstring_for_relay)) && (val_249 != 2) ))
+- {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- if( (val_249 == 2) && (!(url)) )
+- {
+- purple_xfer_cancel_remote(xfer);
+- return;
+- }
+-
+- xfer_data = xfer->data;
+- if(url)
+- purple_url_parse(url, &(xfer_data->host), &(xfer_data->port), &(xfer_data->path), NULL, NULL);
+-
+- xfer_data->xfer_idstring_for_relay = g_strdup(xfer_idstring_for_relay);
+- xfer_data->status_15 = ACCEPTED;
+- account = purple_connection_get_account(gc);
+-
+- if (purple_proxy_connect(gc, account, xfer_data->host, xfer_data->port,
+- yahoo_xfer_connected_15, xfer) == NULL)
+- {
+- purple_notify_error(gc, NULL, _("File Transfer Failed"),_("Unable to connect"));
+- purple_xfer_cancel_remote(xfer);
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_filexfer.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_filexfer.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,70 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef _YAHOO_FILEXFER_H_
+-#define _YAHOO_FILEXFER_H_
+-
+-#include "ft.h"
+-
+-/**
+- * Process ymsg events, particular IMViroments like Doodle
+- */
+-void yahoo_process_p2pfilexfer( PurpleConnection *gc, struct yahoo_packet *pkt );
+-
+-/**
+- * Process ymsg file receive invites.
+- */
+-void yahoo_process_filetransfer(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-/**
+- * Create a new PurpleXfer
+- *
+- * @param gc The PurpleConnection handle.
+- * @param who Who will we be sending it to?
+- */
+-PurpleXfer *yahoo_new_xfer(PurpleConnection *gc, const char *who);
+-
+-/**
+- * Returns TRUE if the buddy can receive file, FALSE otherwise.
+- * Federated users cannot receive files. So this will return FALSE only
+- * for them.
+- *
+- * @param gc The connection
+- * @param who The name of the remote user
+- *
+- * @return TRUE or FALSE
+- */
+-gboolean yahoo_can_receive_file(PurpleConnection *gc, const char *who);
+-
+-/**
+- * Send a file.
+- *
+- * @param gc The PurpleConnection handle.
+- * @param who Who are we sending it to?
+- * @param file What file? If NULL, user will choose after this call.
+- */
+-void yahoo_send_file(PurpleConnection *gc, const char *who, const char *file);
+-
+-void yahoo_process_filetrans_15(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_filetrans_info_15(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_filetrans_acc_15(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-#endif
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,325 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-#include "prpl.h"
+-#include "util.h"
+-#include "debug.h"
+-
+-#include "yahoo_friend.h"
+-#include "yahoo_aliases.h"
+-
+-static YahooFriend *yahoo_friend_new(void)
+-{
+- YahooFriend *ret;
+-
+- ret = g_new0(YahooFriend, 1);
+- ret->status = YAHOO_STATUS_OFFLINE;
+- ret->presence = YAHOO_PRESENCE_DEFAULT;
+-
+- return ret;
+-}
+-
+-YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name)
+-{
+- YahooData *yd;
+- const char *norm;
+-
+- g_return_val_if_fail(gc != NULL, NULL);
+- g_return_val_if_fail(gc->proto_data != NULL, NULL);
+-
+- yd = gc->proto_data;
+- norm = purple_normalize(purple_connection_get_account(gc), name);
+-
+- return g_hash_table_lookup(yd->friends, norm);
+-}
+-
+-YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name)
+-{
+- YahooFriend *f;
+- YahooData *yd;
+- const char *norm;
+-
+- g_return_val_if_fail(gc != NULL, NULL);
+- g_return_val_if_fail(gc->proto_data != NULL, NULL);
+-
+- yd = gc->proto_data;
+- norm = purple_normalize(purple_connection_get_account(gc), name);
+-
+- f = g_hash_table_lookup(yd->friends, norm);
+- if (!f) {
+- f = yahoo_friend_new();
+- g_hash_table_insert(yd->friends, g_strdup(norm), f);
+- }
+-
+- return f;
+-}
+-
+-void yahoo_friend_set_ip(YahooFriend *f, const char *ip)
+-{
+- g_free(f->ip);
+- f->ip = g_strdup(ip);
+-}
+-
+-const char *yahoo_friend_get_ip(YahooFriend *f)
+-{
+- return f->ip;
+-}
+-
+-void yahoo_friend_set_game(YahooFriend *f, const char *game)
+-{
+- g_free(f->game);
+-
+- if (game)
+- f->game = g_strdup(game);
+- else
+- f->game = NULL;
+-}
+-
+-const char *yahoo_friend_get_game(YahooFriend *f)
+-{
+- return f->game;
+-}
+-
+-void yahoo_friend_set_status_message(YahooFriend *f, char *msg)
+-{
+- g_free(f->msg);
+-
+- f->msg = msg;
+-}
+-
+-const char *yahoo_friend_get_status_message(YahooFriend *f)
+-{
+- return f->msg;
+-}
+-
+-void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs)
+-{
+- f->bicon_sent_request = !needs;
+-}
+-
+-gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f)
+-{
+- return !f->bicon_sent_request;
+-}
+-
+-void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id)
+-{
+- g_free(f->ypd.id);
+- f->ypd.id = g_strdup(alias_id);
+-}
+-
+-const char *yahoo_friend_get_alias_id(YahooFriend *f)
+-{
+- return f->ypd.id;
+-}
+-
+-void yahoo_friend_free(gpointer p)
+-{
+- YahooFriend *f = p;
+- g_free(f->msg);
+- g_free(f->game);
+- g_free(f->ip);
+- yahoo_personal_details_reset(&f->ypd, TRUE);
+- g_free(f);
+-}
+-
+-void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- YahooFriend *f;
+- char *temp = NULL;
+- char *who = NULL;
+- int value = 0;
+- YahooFederation fed = YAHOO_FEDERATION_NONE;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 7:
+- temp = pair->value;
+- break;
+- case 31:
+- value = strtol(pair->value, NULL, 10);
+- break;
+- case 241:
+- fed = strtol(pair->value, NULL, 10);
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- if (value != 1 && value != 2) {
+- purple_debug_error("yahoo", "Received unknown value for presence key: %d\n", value);
+- return;
+- }
+-
+- switch (fed) {
+- case YAHOO_FEDERATION_MSN:
+- who = g_strconcat("msn/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_OCS:
+- who = g_strconcat("ocs/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_IBM:
+- who = g_strconcat("ibm/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_PBX:
+- who = g_strconcat("pbx/", temp, NULL);
+- break;
+- case YAHOO_FEDERATION_NONE:
+- who = g_strdup(temp);
+- break;
+- }
+- g_return_if_fail(who != NULL);
+-
+- f = yahoo_friend_find(gc, who);
+- if (!f) {
+- g_free(who);
+- return;
+- }
+-
+- if (pkt->service == YAHOO_SERVICE_PRESENCE_PERM) {
+- purple_debug_info("yahoo", "Setting permanent presence for %s to %d.\n", who, (value == 1));
+- /* If setting from perm offline to online when in invisible status,
+- * this has already been taken care of (when the temp status changed) */
+- if (value == 2 && f->presence == YAHOO_PRESENCE_ONLINE) {
+- } else {
+- if (value == 1) /* Setting Perm offline */
+- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
+- else
+- f->presence = YAHOO_PRESENCE_DEFAULT;
+- }
+- } else {
+- purple_debug_info("yahoo", "Setting session presence for %s to %d.\n", who, (value == 1));
+- if (value == 1)
+- f->presence = YAHOO_PRESENCE_ONLINE;
+- else
+- f->presence = YAHOO_PRESENCE_DEFAULT;
+- }
+- g_free(who);
+-}
+-
+-void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
+- YahooPresenceVisibility presence)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt = NULL;
+- YahooFriend *f;
+- const char *thirtyone, *thirteen;
+- int service = -1;
+- const char *temp = NULL;
+-
+- if (!yd->logged_in)
+- return;
+-
+- f = yahoo_friend_find(gc, name);
+- if (!f)
+- return;
+-
+- if(f->fed != YAHOO_FEDERATION_NONE)
+- temp = name+4;
+- else
+- temp = name;
+-
+- /* No need to change the value if it is already correct */
+- if (f->presence == presence) {
+- purple_debug_info("yahoo", "Not setting presence because there are no changes.\n");
+- return;
+- }
+-
+- if (presence == YAHOO_PRESENCE_PERM_OFFLINE) {
+- service = YAHOO_SERVICE_PRESENCE_PERM;
+- thirtyone = "1";
+- thirteen = "2";
+- } else if (presence == YAHOO_PRESENCE_DEFAULT) {
+- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
+- service = YAHOO_SERVICE_PRESENCE_PERM;
+- thirtyone = "2";
+- thirteen = "2";
+- } else if (yd->current_status == YAHOO_STATUS_INVISIBLE) {
+- service = YAHOO_SERVICE_PRESENCE_SESSION;
+- thirtyone = "2";
+- thirteen = "1";
+- }
+- } else if (presence == YAHOO_PRESENCE_ONLINE) {
+- if (f->presence == YAHOO_PRESENCE_PERM_OFFLINE) {
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PRESENCE_PERM,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+- if(f->fed)
+- yahoo_packet_hash(pkt, "ssssssiss",
+- 1, purple_connection_get_display_name(gc),
+- 31, "2", 13, "2",
+- 302, "319", 300, "319",
+- 7, temp, 241, f->fed,
+- 301, "319", 303, "319");
+- else
+- yahoo_packet_hash(pkt, "ssssssss",
+- 1, purple_connection_get_display_name(gc),
+- 31, "2", 13, "2",
+- 302, "319", 300, "319",
+- 7, temp,
+- 301, "319", 303, "319");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-
+- service = YAHOO_SERVICE_PRESENCE_SESSION;
+- thirtyone = "1";
+- thirteen = "1";
+- }
+-
+- if (service > 0) {
+- pkt = yahoo_packet_new(service,
+- YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- if(f->fed)
+- yahoo_packet_hash(pkt, "ssssssiss",
+- 1, purple_connection_get_display_name(gc),
+- 31, thirtyone, 13, thirteen,
+- 302, "319", 300, "319",
+- 7, temp, 241, f->fed,
+- 301, "319", 303, "319");
+- else
+- yahoo_packet_hash(pkt, "ssssssss",
+- 1, purple_connection_get_display_name(gc),
+- 31, thirtyone, 13, thirteen,
+- 302, "319", 300, "319",
+- 7, temp,
+- 301, "319", 303, "319");
+-
+- yahoo_packet_send_and_free(pkt, yd);
+- }
+-}
+-
+-void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status)
+-{
+- f->p2p_status = p2p_status;
+-}
+-
+-YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f)
+-{
+- return f->p2p_status;
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_friend.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_friend.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,93 +0,0 @@
+-/**
+- * @file yahoo_friend.h The Yahoo! protocol plugin YahooFriend object
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _YAHOO_FRIEND_H_
+-#define _YAHOO_FRIEND_H_
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-
+-typedef enum {
+- YAHOO_PRESENCE_DEFAULT = 0,
+- YAHOO_PRESENCE_ONLINE,
+- YAHOO_PRESENCE_PERM_OFFLINE
+-} YahooPresenceVisibility;
+-
+-typedef enum {
+- YAHOO_P2PSTATUS_NOT_CONNECTED = 0,
+- YAHOO_P2PSTATUS_DO_NOT_CONNECT,
+- YAHOO_P2PSTATUS_WE_ARE_SERVER,
+- YAHOO_P2PSTATUS_WE_ARE_CLIENT
+-} YahooP2PStatus;
+-
+-
+-/* these are called friends instead of buddies mainly so I can use variables
+- * named f and not confuse them with variables named b
+- */
+-typedef struct _YahooFriend {
+- enum yahoo_status status;
+- gchar *msg;
+- gchar *game;
+- int idle;
+- int away;
+- gboolean sms;
+- gchar *ip;
+- gboolean bicon_sent_request;
+- YahooPresenceVisibility presence;
+- YahooFederation fed;
+- long int version_id;
+- YahooPersonalDetails ypd;
+- YahooP2PStatus p2p_status;
+- gboolean p2p_packet_sent; /* 0:not sent, 1=sent */
+- gint session_id; /* session id of friend */
+-} YahooFriend;
+-
+-YahooFriend *yahoo_friend_find(PurpleConnection *gc, const char *name);
+-YahooFriend *yahoo_friend_find_or_new(PurpleConnection *gc, const char *name);
+-
+-void yahoo_friend_set_ip(YahooFriend *f, const char *ip);
+-const char *yahoo_friend_get_ip(YahooFriend *f);
+-
+-void yahoo_friend_set_game(YahooFriend *f, const char *game);
+-const char *yahoo_friend_get_game(YahooFriend *f);
+-
+-void yahoo_friend_set_status_message(YahooFriend *f, char *msg);
+-const char *yahoo_friend_get_status_message(YahooFriend *f);
+-
+-void yahoo_friend_set_alias_id(YahooFriend *f, const char *alias_id);
+-const char *yahoo_friend_get_alias_id(YahooFriend *f);
+-
+-void yahoo_friend_set_buddy_icon_need_request(YahooFriend *f, gboolean needs);
+-gboolean yahoo_friend_get_buddy_icon_need_request(YahooFriend *f);
+-
+-void yahoo_friend_free(gpointer p);
+-
+-void yahoo_process_presence(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_friend_update_presence(PurpleConnection *gc, const char *name,
+- YahooPresenceVisibility presence);
+-
+-void yahoo_friend_set_p2p_status(YahooFriend *f, YahooP2PStatus p2p_status);
+-YahooP2PStatus yahoo_friend_get_p2p_status(YahooFriend *f);
+-
+-#endif /* _YAHOO_FRIEND_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,403 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-#include "debug.h"
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-
+-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service, enum yahoo_status status, int id)
+-{
+- struct yahoo_packet *pkt = g_new0(struct yahoo_packet, 1);
+-
+- pkt->service = service;
+- pkt->status = status;
+- pkt->id = id;
+-
+- return pkt;
+-}
+-
+-void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value)
+-{
+- struct yahoo_pair *pair;
+-
+- g_return_if_fail(value != NULL);
+-
+- pair = g_new0(struct yahoo_pair, 1);
+- pair->key = key;
+- pair->value = g_strdup(value);
+- pkt->hash = g_slist_prepend(pkt->hash, pair);
+-}
+-
+-void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value)
+-{
+- struct yahoo_pair *pair;
+-
+- pair = g_new0(struct yahoo_pair, 1);
+- pair->key = key;
+- pair->value = g_strdup_printf("%d", value);
+- pkt->hash = g_slist_prepend(pkt->hash, pair);
+-}
+-
+-void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...)
+-{
+- char *strval;
+- int key, intval;
+- const char *cur;
+- va_list ap;
+-
+- va_start(ap, fmt);
+- for (cur = fmt; *cur; cur++) {
+- key = va_arg(ap, int);
+- switch (*cur) {
+- case 'i':
+- intval = va_arg(ap, int);
+- yahoo_packet_hash_int(pkt, key, intval);
+- break;
+- case 's':
+- strval = va_arg(ap, char *);
+- yahoo_packet_hash_str(pkt, key, strval);
+- break;
+- default:
+- purple_debug_error("yahoo", "Invalid format character '%c'\n", *cur);
+- break;
+- }
+- }
+- va_end(ap);
+-}
+-
+-size_t yahoo_packet_length(struct yahoo_packet *pkt)
+-{
+- GSList *l;
+-
+- size_t len = 0;
+-
+- l = pkt->hash;
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- int tmp = pair->key;
+- do {
+- tmp /= 10;
+- len++;
+- } while (tmp);
+- len += 2;
+- len += strlen(pair->value);
+- len += 2;
+- l = l->next;
+- }
+-
+- 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;
+- char key[64];
+- const guchar *delimiter;
+- gboolean accept;
+- int x;
+- struct yahoo_pair *pair;
+-
+- while (pos + 1 < len)
+- {
+- if (data[pos] == '\0')
+- break;
+-
+- pair = g_new0(struct yahoo_pair, 1);
+-
+- x = 0;
+- while (pos + 1 < len) {
+- if (data[pos] == 0xc0 && data[pos + 1] == 0x80)
+- break;
+- if (x >= sizeof(key)-1) {
+- x++;
+- pos++;
+- continue;
+- }
+- key[x++] = data[pos++];
+- }
+- if (x >= sizeof(key)-1) {
+- x = 0;
+- }
+- key[x] = 0;
+- pos += 2;
+- pair->key = strtol(key, NULL, 10);
+- accept = x; /* if x is 0 there was no key, so don't accept it */
+-
+- if (pos + 1 > len) {
+- /* Malformed packet! (Truncated--garbage or something) */
+- accept = FALSE;
+- }
+-
+- if (accept) {
+- delimiter = (const guchar *)g_strstr_len((const char *)&data[pos], len - pos, "\xc0\x80");
+- if (delimiter == NULL)
+- {
+- /* Malformed packet! (It doesn't end in 0xc0 0x80) */
+- g_free(pair);
+- pos = len;
+- continue;
+- }
+- x = delimiter - data;
+- pair->value = g_strndup((const gchar *)&data[pos], x - pos);
+- pos = x;
+- pkt->hash = g_slist_prepend(pkt->hash, pair);
+-
+- if (purple_debug_is_verbose() || g_getenv("PURPLE_YAHOO_DEBUG")) {
+- char *esc;
+- esc = g_strescape(pair->value, NULL);
+- purple_debug_misc("yahoo", "Key: %d \tValue: %s\n", pair->key, esc);
+- g_free(esc);
+- }
+- } else {
+- g_free(pair);
+- }
+- pos += 2;
+-
+- if (pos + 1 > len) break;
+-
+- /* Skip over garbage we've noticed in the mail notifications */
+- if (data[0] == '9' && data[pos] == 0x01)
+- pos++;
+- }
+-
+- /*
+- * Originally this function used g_slist_append(). I changed
+- * it to use g_slist_prepend() for improved performance.
+- * Ideally the Yahoo! PRPL code would be indifferent to the
+- * order of the key/value pairs, but I don't know if this is
+- * the case for all incoming messages. To be on the safe side
+- * we reverse the list.
+- */
+- pkt->hash = g_slist_reverse(pkt->hash);
+-}
+-
+-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data)
+-{
+- GSList *l;
+- int pos = 0;
+-
+- /* This is only called from one place, and the list is
+- * always backwards */
+-
+- l = pkt->hash = g_slist_reverse(pkt->hash);
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+- gchar buf[100];
+-
+- g_snprintf(buf, sizeof(buf), "%d", pair->key);
+- strcpy((char *)&data[pos], buf);
+- pos += strlen(buf);
+- data[pos++] = 0xc0;
+- data[pos++] = 0x80;
+-
+- strcpy((char *)&data[pos], pair->value);
+- pos += strlen(pair->value);
+- data[pos++] = 0xc0;
+- data[pos++] = 0x80;
+-
+- l = l->next;
+- }
+-}
+-
+-void yahoo_packet_dump(guchar *data, int len)
+-{
+-#ifdef YAHOO_DEBUG
+- int i;
+-
+- purple_debug_misc("yahoo", "");
+-
+- for (i = 0; i + 1 < len; i += 2) {
+- if ((i % 16 == 0) && i) {
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+- }
+-
+- purple_debug_misc(NULL, "%02x%02x ", data[i], data[i + 1]);
+- }
+- if (i < len)
+- purple_debug_misc(NULL, "%02x", data[i]);
+-
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+-
+- for (i = 0; i < len; i++) {
+- if ((i % 16 == 0) && i) {
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+- }
+-
+- if (g_ascii_isprint(data[i]))
+- purple_debug_misc(NULL, "%c ", data[i]);
+- else
+- purple_debug_misc(NULL, ". ");
+- }
+-
+- purple_debug_misc(NULL, "\n");
+-#endif /* YAHOO_DEBUG */
+-}
+-
+-static void
+-yahoo_packet_send_can_write(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- YahooData *yd = data;
+- int ret, writelen;
+-
+- writelen = purple_circ_buffer_get_max_read(yd->txbuf);
+-
+- if (writelen == 0) {
+- purple_input_remove(yd->txhandler);
+- yd->txhandler = 0;
+- return;
+- }
+-
+- ret = write(yd->fd, yd->txbuf->outptr, writelen);
+-
+- if (ret < 0 && errno == EAGAIN)
+- return;
+- else if (ret < 0) {
+- /* TODO: what to do here - do we really have to disconnect? */
+- purple_connection_error_reason(yd->gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
+- _("Write Error"));
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(yd->txbuf, ret);
+-}
+-
+-
+-size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm,
+- gboolean jp, guchar **buf)
+-{
+- size_t pktlen = yahoo_packet_length(pkt);
+- size_t len = YAHOO_PACKET_HDRLEN + pktlen;
+- guchar *data;
+- int pos = 0;
+-
+- data = g_malloc0(len + 1);
+-
+- memcpy(data + pos, "YMSG", 4); pos += 4;
+-
+- if (wm)
+- pos += yahoo_put16(data + pos, YAHOO_WEBMESSENGER_PROTO_VER);
+- else if (jp)
+- pos += yahoo_put16(data + pos, YAHOO_PROTO_VER_JAPAN);
+- else
+- pos += yahoo_put16(data + pos, YAHOO_PROTO_VER);
+- pos += yahoo_put16(data + pos, 0x0000);
+- pos += yahoo_put16(data + pos, pktlen + pad);
+- pos += yahoo_put16(data + pos, pkt->service);
+- pos += yahoo_put32(data + pos, pkt->status);
+- pos += yahoo_put32(data + pos, pkt->id);
+-
+- yahoo_packet_write(pkt, data + pos);
+-
+- *buf = data;
+-
+- return len;
+-}
+-
+-int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd)
+-{
+- size_t len;
+- gssize ret;
+- guchar *data;
+-
+- if (yd->fd < 0)
+- return -1;
+-
+- len = yahoo_packet_build(pkt, 0, yd->wm, yd->jp, &data);
+-
+- yahoo_packet_dump(data, len);
+- if (yd->txhandler == 0)
+- ret = write(yd->fd, data, len);
+- else {
+- ret = -1;
+- errno = EAGAIN;
+- }
+-
+- if (ret < 0 && errno == EAGAIN)
+- ret = 0;
+- else if (ret <= 0) {
+- purple_debug_warning("yahoo", "Only wrote %" G_GSSIZE_FORMAT
+- " of %" G_GSIZE_FORMAT " bytes!\n", ret, len);
+- g_free(data);
+- return ret;
+- }
+-
+- if (ret < len) {
+- if (yd->txhandler == 0)
+- yd->txhandler = purple_input_add(yd->fd, PURPLE_INPUT_WRITE,
+- yahoo_packet_send_can_write, yd);
+- purple_circ_buffer_append(yd->txbuf, data + ret, len - ret);
+- }
+-
+- g_free(data);
+-
+- return ret;
+-}
+-
+-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd)
+-{
+- int ret;
+-
+- ret = yahoo_packet_send(pkt, yd);
+- yahoo_packet_free(pkt);
+- return ret;
+-}
+-
+-void yahoo_packet_free(struct yahoo_packet *pkt)
+-{
+- while (pkt->hash) {
+- struct yahoo_pair *pair = pkt->hash->data;
+- g_free(pair->value);
+- g_free(pair);
+- pkt->hash = g_slist_delete_link(pkt->hash, pkt->hash);
+- }
+- g_free(pkt);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_packet.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_packet.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,150 +0,0 @@
+-/**
+- * @file yahoo_packet.h The Yahoo! protocol plugin
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _YAHOO_PACKET_H_
+-#define _YAHOO_PACKET_H_
+-
+-enum yahoo_service { /* these are easier to see in hex */
+- YAHOO_SERVICE_LOGON = 1,
+- YAHOO_SERVICE_LOGOFF,
+- YAHOO_SERVICE_ISAWAY,
+- YAHOO_SERVICE_ISBACK,
+- YAHOO_SERVICE_IDLE, /* 5 (placemarker) */
+- YAHOO_SERVICE_MESSAGE,
+- YAHOO_SERVICE_IDACT,
+- YAHOO_SERVICE_IDDEACT,
+- YAHOO_SERVICE_MAILSTAT,
+- YAHOO_SERVICE_USERSTAT, /* 0xa */
+- YAHOO_SERVICE_NEWMAIL,
+- YAHOO_SERVICE_CHATINVITE,
+- YAHOO_SERVICE_CALENDAR,
+- YAHOO_SERVICE_NEWPERSONALMAIL,
+- YAHOO_SERVICE_NEWCONTACT,
+- YAHOO_SERVICE_ADDIDENT, /* 0x10 */
+- YAHOO_SERVICE_ADDIGNORE,
+- YAHOO_SERVICE_PING,
+- YAHOO_SERVICE_GOTGROUPRENAME,
+- YAHOO_SERVICE_SYSMESSAGE = 0x14,
+- YAHOO_SERVICE_SKINNAME = 0x15,
+- YAHOO_SERVICE_PASSTHROUGH2 = 0x16,
+- YAHOO_SERVICE_CONFINVITE = 0x18,
+- YAHOO_SERVICE_CONFLOGON,
+- YAHOO_SERVICE_CONFDECLINE,
+- YAHOO_SERVICE_CONFLOGOFF,
+- YAHOO_SERVICE_CONFADDINVITE,
+- YAHOO_SERVICE_CONFMSG,
+- YAHOO_SERVICE_CHATLOGON,
+- YAHOO_SERVICE_CHATLOGOFF,
+- YAHOO_SERVICE_CHATMSG = 0x20,
+- YAHOO_SERVICE_GAMELOGON = 0x28,
+- YAHOO_SERVICE_GAMELOGOFF,
+- YAHOO_SERVICE_GAMEMSG = 0x2a,
+- YAHOO_SERVICE_FILETRANSFER = 0x46,
+- YAHOO_SERVICE_VOICECHAT = 0x4A,
+- YAHOO_SERVICE_NOTIFY = 0x4B,
+- YAHOO_SERVICE_VERIFY,
+- YAHOO_SERVICE_P2PFILEXFER,
+- YAHOO_SERVICE_PEERTOPEER = 0x4F,
+- YAHOO_SERVICE_WEBCAM,
+- YAHOO_SERVICE_AUTHRESP = 0x54,
+- YAHOO_SERVICE_LIST = 0x55,
+- YAHOO_SERVICE_AUTH = 0x57,
+- YAHOO_SERVICE_AUTHBUDDY = 0x6d,
+- YAHOO_SERVICE_ADDBUDDY = 0x83,
+- YAHOO_SERVICE_REMBUDDY = 0x84,
+- YAHOO_SERVICE_IGNORECONTACT, /* > 1, 7, 13 < 1, 66, 13, 0*/
+- YAHOO_SERVICE_REJECTCONTACT,
+- YAHOO_SERVICE_GROUPRENAME = 0x89, /* > 1, 65(new), 66(0), 67(old) */
+- YAHOO_SERVICE_KEEPALIVE = 0x8A,
+- YAHOO_SERVICE_CHATONLINE = 0x96, /* > 109(id), 1, 6(abcde) < 0,1*/
+- YAHOO_SERVICE_CHATGOTO,
+- YAHOO_SERVICE_CHATJOIN, /* > 1 104-room 129-1600326591 62-2 */
+- YAHOO_SERVICE_CHATLEAVE,
+- YAHOO_SERVICE_CHATEXIT = 0x9b,
+- YAHOO_SERVICE_CHATADDINVITE = 0x9d,
+- YAHOO_SERVICE_CHATLOGOUT = 0xa0,
+- YAHOO_SERVICE_CHATPING,
+- YAHOO_SERVICE_COMMENT = 0xa8,
+- YAHOO_SERVICE_PRESENCE_PERM = 0xb9,
+- YAHOO_SERVICE_PRESENCE_SESSION = 0xba,
+- YAHOO_SERVICE_AVATAR = 0xbc,
+- YAHOO_SERVICE_PICTURE_CHECKSUM = 0xbd,
+- YAHOO_SERVICE_PICTURE = 0xbe,
+- YAHOO_SERVICE_PICTURE_UPDATE = 0xc1,
+- YAHOO_SERVICE_PICTURE_UPLOAD = 0xc2,
+- YAHOO_SERVICE_Y6_VISIBLE_TOGGLE = 0xc5,
+- YAHOO_SERVICE_Y6_STATUS_UPDATE = 0xc6,
+- YAHOO_SERVICE_AVATAR_UPDATE = 0xc7,
+- YAHOO_SERVICE_VERIFY_ID_EXISTS = 0xc8,
+- YAHOO_SERVICE_AUDIBLE = 0xd0,
+- YAHOO_SERVICE_CONTACT_DETAILS = 0xd3,
+- /* YAHOO_SERVICE_CHAT_SESSION = 0xd4,?? Reports start of chat session, gets an id from server */
+- YAHOO_SERVICE_AUTH_REQ_15 = 0xd6,
+- YAHOO_SERVICE_FILETRANS_15 = 0xdc,
+- YAHOO_SERVICE_FILETRANS_INFO_15 = 0xdd,
+- YAHOO_SERVICE_FILETRANS_ACC_15 = 0xde,
+- /* photo sharing services ?? - 0xd2, 0xd7, 0xd8, 0xda */
+- YAHOO_SERVICE_CHGRP_15 = 0xe7,
+- YAHOO_SERVICE_STATUS_15 = 0xf0,
+- YAHOO_SERVICE_LIST_15 = 0xf1,
+- YAHOO_SERVICE_MESSAGE_ACK = 0xfb,
+- YAHOO_SERVICE_WEBLOGIN = 0x0226,
+- YAHOO_SERVICE_SMS_MSG = 0x02ea
+- /* YAHOO_SERVICE_DISCONNECT = 0x07d1 Server forces us to disconnect. Is sent with TCP FIN flag set */
+-};
+-
+-struct yahoo_pair {
+- int key;
+- char *value;
+-};
+-
+-struct yahoo_packet {
+- guint16 service;
+- guint32 status;
+- guint32 id;
+- GSList *hash;
+-};
+-
+-#define YAHOO_WEBMESSENGER_PROTO_VER 0x0065
+-#define YAHOO_PROTO_VER 0x0010
+-#define YAHOO_PROTO_VER_JAPAN 0x0010
+-
+-#define YAHOO_PACKET_HDRLEN (4 + 2 + 2 + 2 + 2 + 4 + 4)
+-
+-struct yahoo_packet *yahoo_packet_new(enum yahoo_service service,
+- enum yahoo_status status, int id);
+-void yahoo_packet_hash(struct yahoo_packet *pkt, const char *fmt, ...);
+-void yahoo_packet_hash_str(struct yahoo_packet *pkt, int key, const char *value);
+-void yahoo_packet_hash_int(struct yahoo_packet *pkt, int key, int value);
+-int yahoo_packet_send(struct yahoo_packet *pkt, YahooData *yd);
+-int yahoo_packet_send_and_free(struct yahoo_packet *pkt, YahooData *yd);
+-size_t yahoo_packet_build(struct yahoo_packet *pkt, int pad, gboolean wm, gboolean jp,
+-guchar **buf);
+-void yahoo_packet_read(struct yahoo_packet *pkt, const guchar *data, int len);
+-void yahoo_packet_write(struct yahoo_packet *pkt, guchar *data);
+-void yahoo_packet_dump(guchar *data, int len);
+-size_t yahoo_packet_length(struct yahoo_packet *pkt);
+-void yahoo_packet_free(struct yahoo_packet *pkt);
+-
+-#endif /* _YAHOO_PACKET_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,587 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#include "internal.h"
+-
+-#include "account.h"
+-#include "accountopt.h"
+-#include "blist.h"
+-#include "debug.h"
+-#include "privacy.h"
+-#include "prpl.h"
+-#include "proxy.h"
+-#include "util.h"
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-#include "yahoo_friend.h"
+-#include "yahoo_picture.h"
+-
+-
+-struct yahoo_fetch_picture_data {
+- PurpleConnection *gc;
+- char *who;
+- int checksum;
+-};
+-
+-static void
+-yahoo_fetch_picture_cb(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *pic_data, size_t len, const gchar *error_message)
+-{
+- struct yahoo_fetch_picture_data *d;
+- YahooData *yd;
+-
+- d = user_data;
+- yd = d->gc->proto_data;
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- if (error_message != NULL) {
+- purple_debug_error("yahoo", "Fetching buddy icon failed: %s\n", error_message);
+- } else if (len == 0) {
+- purple_debug_error("yahoo", "Fetched an icon with length 0. Strange.\n");
+- } else {
+- char *checksum = g_strdup_printf("%i", d->checksum);
+- purple_buddy_icons_set_for_user(purple_connection_get_account(d->gc), d->who, g_memdup(pic_data, len), len, checksum);
+- g_free(checksum);
+- }
+-
+- g_free(d->who);
+- g_free(d);
+-}
+-
+-void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- YahooData *yd;
+- GSList *l = pkt->hash;
+- char *who = NULL, *us = NULL;
+- gboolean got_icon_info = FALSE, send_icon_info = FALSE;
+- char *url = NULL;
+- int checksum = 0;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 1:
+- case 4:
+- who = pair->value;
+- break;
+- case 5:
+- us = pair->value;
+- break;
+- case 13: {
+- int tmp;
+- tmp = strtol(pair->value, NULL, 10);
+- if (tmp == 1) {
+- send_icon_info = TRUE;
+- } else if (tmp == 2) {
+- got_icon_info = TRUE;
+- }
+- break;
+- }
+- case 20:
+- url = pair->value;
+- break;
+- case 192:
+- checksum = strtol(pair->value, NULL, 10);
+- break;
+- }
+-
+- l = l->next;
+- }
+-
+- if (!who)
+- return;
+-
+- if (!purple_privacy_check(purple_connection_get_account(gc), who)) {
+- purple_debug_info("yahoo", "Picture packet from %s dropped.\n", who);
+- return;
+- }
+-
+- /* Yahoo IM 6 spits out 0.png as the URL if the buddy icon is not set */
+- if (who && got_icon_info && url && !g_ascii_strncasecmp(url, "http://", 7)) {
+- /* TODO: make this work p2p, try p2p before the url */
+- PurpleUtilFetchUrlData *url_data;
+- struct yahoo_fetch_picture_data *data;
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+-
+- data = g_new0(struct yahoo_fetch_picture_data, 1);
+- data->gc = gc;
+- data->who = g_strdup(who);
+- data->checksum = checksum;
+- /* TODO: Does this need to be MSIE 5.0? */
+- url_data = purple_util_fetch_url(url, use_whole_url,
+- "Mozilla/4.0 (compatible; MSIE 5.5)", FALSE,
+- yahoo_fetch_picture_cb, data);
+- if (url_data != NULL) {
+- yd = gc->proto_data;
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- }
+- } else if (who && send_icon_info) {
+- yahoo_send_picture_info(gc, who);
+- }
+-}
+-
+-void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- char *who = NULL;
+- int checksum = 0;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- who = pair->value;
+- break;
+- case 5:
+- /* us */
+- break;
+- case 192:
+- checksum = strtol(pair->value, NULL, 10);
+- break;
+- }
+- l = l->next;
+- }
+-
+- if (who) {
+- PurpleBuddy *b = purple_find_buddy(gc->account, who);
+- const char *locksum = NULL;
+-
+- /* FIXME: Cleanup this strtol() stuff if possible. */
+- if (b) {
+- locksum = purple_buddy_icons_get_checksum_for_user(b);
+- if (!locksum || (checksum != strtol(locksum, NULL, 10)))
+- yahoo_send_picture_request(gc, who);
+- }
+- }
+-}
+-
+-void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+- GSList *l = pkt->hash;
+- char *url = NULL;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 5:
+- /* us */
+- break;
+- case 27:
+- /* filename on our computer. */
+- break;
+- case 20: /* url at yahoo */
+- url = pair->value;
+- case 38: /* timestamp */
+- break;
+- }
+- l = l->next;
+- }
+-
+- if (url) {
+- g_free(yd->picture_url);
+- yd->picture_url = g_strdup(url);
+- purple_account_set_string(account, YAHOO_PICURL_SETTING, url);
+- purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, yd->picture_checksum);
+- yahoo_send_picture_checksum(gc);
+- yahoo_send_picture_update(gc, 2);
+- }
+-}
+-
+-void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt)
+-{
+- GSList *l = pkt->hash;
+- char *who = NULL;
+- int avatar = 0;
+-
+- while (l) {
+- struct yahoo_pair *pair = l->data;
+-
+- switch (pair->key) {
+- case 4:
+- who = pair->value;
+- break;
+- case 5:
+- /* us */
+- break;
+- case 206: /* Older versions. Still needed? */
+- case 213: /* Newer versions */
+- /*
+- * 0 - No icon or avatar
+- * 1 - Using an avatar
+- * 2 - Using an icon
+- */
+- avatar = strtol(pair->value, NULL, 10);
+- break;
+- }
+- l = l->next;
+- }
+-
+- if (who) {
+- if (avatar == 2)
+- yahoo_send_picture_request(gc, who);
+- else if ((avatar == 0) || (avatar == 1)) {
+- YahooFriend *f;
+- purple_buddy_icons_set_for_user(gc->account, who, NULL, 0, NULL);
+- if ((f = yahoo_friend_find(gc, who)))
+- yahoo_friend_set_buddy_icon_need_request(f, TRUE);
+- purple_debug_misc("yahoo", "Setting user %s's icon to NULL.\n", who);
+- }
+- }
+-}
+-
+-void yahoo_send_picture_info(PurpleConnection *gc, const char *who)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+-
+- if (!yd->picture_url) {
+- purple_debug_warning("yahoo", "Attempted to send picture info without a picture\n");
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "ssssi", 1, purple_connection_get_display_name(gc),
+- 5, who,
+- 13, "2", 20, yd->picture_url, 192, yd->picture_checksum);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_send_picture_request(PurpleConnection *gc, const char *who)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc)); /* me */
+- yahoo_packet_hash_str(pkt, 5, who); /* the other guy */
+- yahoo_packet_hash_str(pkt, 13, "1"); /* 1 = request, 2 = reply */
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_send_picture_checksum(PurpleConnection *gc)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_CHECKSUM, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "ssi", 1, purple_connection_get_display_name(gc),
+- 212, "1", 192, yd->picture_checksum);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yahoo_packet *pkt;
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_AVATAR_UPDATE, YAHOO_STATUS_AVAILABLE, yd->session_id);
+- yahoo_packet_hash(pkt, "si", 3, who, 213, type);
+- yahoo_packet_send_and_free(pkt, yd);
+-}
+-
+-struct yspufe {
+- PurpleConnection *gc;
+- int type;
+-};
+-
+-static void yahoo_send_picture_update_foreach(gpointer key, gpointer value, gpointer data)
+-{
+- const char *who = key;
+- YahooFriend *f = value;
+- struct yspufe *d = data;
+-
+- if (f->status != YAHOO_STATUS_OFFLINE)
+- yahoo_send_picture_update_to_user(d->gc, who, d->type);
+-}
+-
+-void yahoo_send_picture_update(PurpleConnection *gc, int type)
+-{
+- YahooData *yd = gc->proto_data;
+- struct yspufe data;
+-
+- data.gc = gc;
+- data.type = type;
+-
+- g_hash_table_foreach(yd->friends, yahoo_send_picture_update_foreach, &data);
+-}
+-
+-void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d)
+-{
+- purple_debug_misc("yahoo", "In yahoo_buddy_icon_upload_data_free()\n");
+-
+- if (d->str)
+- g_string_free(d->str, TRUE);
+- g_free(d->filename);
+- if (d->watcher)
+- purple_input_remove(d->watcher);
+- if (d->fd != -1)
+- close(d->fd);
+- g_free(d);
+-}
+-
+-/* we couldn't care less about the server's response, but yahoo gets grumpy if we close before it sends it */
+-static void yahoo_buddy_icon_upload_reading(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- struct yahoo_buddy_icon_upload_data *d = data;
+- PurpleConnection *gc = d->gc;
+- char buf[1024];
+- int ret;
+-
+- if (!PURPLE_CONNECTION_IS_VALID(gc)) {
+- yahoo_buddy_icon_upload_data_free(d);
+- return;
+- }
+-
+- ret = read(d->fd, buf, sizeof(buf));
+-
+- if (ret < 0 && errno == EAGAIN)
+- return;
+- else if (ret <= 0) {
+- /* There are other problems if d->str->len overflows, so shut up the
+- * warning on 64-bit. */
+- purple_debug_info("yahoo", "Buddy icon upload response (%" G_GSIZE_FORMAT ") bytes (> ~400 indicates failure):\n%.*s\n",
+- d->str->len, (guint)d->str->len, d->str->str);
+-
+- yahoo_buddy_icon_upload_data_free(d);
+- return;
+- }
+-
+- g_string_append_len(d->str, buf, ret);
+-}
+-
+-static void yahoo_buddy_icon_upload_pending(gpointer data, gint source, PurpleInputCondition condition)
+-{
+- struct yahoo_buddy_icon_upload_data *d = data;
+- PurpleConnection *gc = d->gc;
+- gssize wrote;
+-
+- if (!PURPLE_CONNECTION_IS_VALID(gc)) {
+- yahoo_buddy_icon_upload_data_free(d);
+- return;
+- }
+-
+- wrote = write(d->fd, d->str->str + d->pos, d->str->len - d->pos);
+- if (wrote < 0 && errno == EAGAIN)
+- return;
+- if (wrote <= 0) {
+- purple_debug_info("yahoo", "Error uploading buddy icon.\n");
+- yahoo_buddy_icon_upload_data_free(d);
+- return;
+- }
+- d->pos += wrote;
+- if (d->pos >= d->str->len) {
+- purple_debug_misc("yahoo", "Finished uploading buddy icon.\n");
+- purple_input_remove(d->watcher);
+- /* Clean out the sent buffer and reuse it to read the result */
+- g_string_free(d->str, TRUE);
+- d->str = g_string_new("");
+- d->watcher = purple_input_add(d->fd, PURPLE_INPUT_READ, yahoo_buddy_icon_upload_reading, d);
+- }
+-}
+-
+-static void yahoo_buddy_icon_upload_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- struct yahoo_buddy_icon_upload_data *d = data;
+- struct yahoo_packet *pkt;
+- gchar *tmp, *header;
+- guchar *pkt_buf;
+- const char *host;
+- int port;
+- gsize pkt_buf_len;
+- PurpleConnection *gc = d->gc;
+- PurpleAccount *account;
+- YahooData *yd;
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(gc);
+-
+- account = purple_connection_get_account(gc);
+- yd = gc->proto_data;
+-
+- /* Buddy icon connect is now complete; clear the PurpleProxyConnectData */
+- yd->buddy_icon_connect_data = NULL;
+-
+- if (source < 0) {
+- purple_debug_error("yahoo", "Buddy icon upload failed: %s\n", error_message);
+- yahoo_buddy_icon_upload_data_free(d);
+- return;
+- }
+-
+- pkt = yahoo_packet_new(YAHOO_SERVICE_PICTURE_UPLOAD, YAHOO_STATUS_AVAILABLE, yd->session_id);
+-
+- tmp = g_strdup_printf("%" G_GSIZE_FORMAT, d->str->len);
+- /* 1 = me, 38 = expire time(?), 0 = me, 28 = size, 27 = filename, 14 = NULL, 29 = data */
+- yahoo_packet_hash_str(pkt, 1, purple_connection_get_display_name(gc));
+- yahoo_packet_hash_str(pkt, 38, "604800"); /* time til expire */
+- purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, time(NULL) + 604800);
+- yahoo_packet_hash_str(pkt, 0, purple_connection_get_display_name(gc));
+- yahoo_packet_hash_str(pkt, 28, tmp);
+- g_free(tmp);
+- yahoo_packet_hash_str(pkt, 27, d->filename);
+- yahoo_packet_hash_str(pkt, 14, "");
+- /* 4 padding for the 29 key name */
+- pkt_buf_len = yahoo_packet_build(pkt, 4, FALSE, yd->jp, &pkt_buf);
+- yahoo_packet_free(pkt);
+-
+- /* header + packet + "29" + 0xc0 + 0x80) + pictureblob */
+-
+- host = purple_account_get_string(account, "xfer_host", yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST);
+- port = purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT);
+- tmp = g_strdup_printf("%s:%d", host, port);
+- header = g_strdup_printf("POST %s%s/notifyft HTTP/1.1\r\n"
+- "User-Agent: " YAHOO_CLIENT_USERAGENT "\r\n"
+- "Cookie: T=%s; Y=%s\r\n"
+- "Host: %s\r\n"
+- "Content-Length: %" G_GSIZE_FORMAT "\r\n"
+- "Cache-Control: no-cache\r\n\r\n",
+- use_whole_url ? "http://" : "", use_whole_url ? tmp : "",
+- yd->cookie_t, yd->cookie_y,
+- tmp,
+- pkt_buf_len + 4 + d->str->len);
+- g_free(tmp);
+-
+- /* There's no magic here, we just need to prepend in reverse order */
+- g_string_prepend(d->str, "29\xc0\x80");
+-
+- g_string_prepend_len(d->str, (char *)pkt_buf, pkt_buf_len);
+- g_free(pkt_buf);
+-
+- g_string_prepend(d->str, header);
+- g_free(header);
+-
+- /* There are other problems if we're uploading over 4GB of data */
+- purple_debug_info("yahoo", "Buddy icon upload data:\n%.*s\n", (guint)d->str->len, d->str->str);
+-
+- d->fd = source;
+- d->watcher = purple_input_add(d->fd, PURPLE_INPUT_WRITE, yahoo_buddy_icon_upload_pending, d);
+-
+- yahoo_buddy_icon_upload_pending(d, d->fd, PURPLE_INPUT_WRITE);
+-}
+-
+-void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d)
+-{
+- PurpleAccount *account = purple_connection_get_account(gc);
+- YahooData *yd = gc->proto_data;
+-
+- if (yd->buddy_icon_connect_data != NULL) {
+- /* Cancel any in-progress buddy icon upload */
+- purple_proxy_connect_cancel(yd->buddy_icon_connect_data);
+- yd->buddy_icon_connect_data = NULL;
+- }
+-
+- yd->buddy_icon_connect_data = purple_proxy_connect(NULL, account,
+- purple_account_get_string(account, "xfer_host",
+- yd->jp? YAHOOJP_XFER_HOST : YAHOO_XFER_HOST),
+- purple_account_get_int(account, "xfer_port", YAHOO_XFER_PORT),
+- yahoo_buddy_icon_upload_connected, d);
+-
+- if (yd->buddy_icon_connect_data == NULL)
+- {
+- purple_debug_error("yahoo", "Uploading our buddy icon failed to connect.\n");
+- yahoo_buddy_icon_upload_data_free(d);
+- }
+-}
+-
+-static int yahoo_buddy_icon_calculate_checksum(const guchar *data, gsize len)
+-{
+- /* This code is borrowed from Kopete, which seems to be managing to calculate
+- checksums in such a manner that Yahoo!'s servers are happy */
+-
+- const guchar *p = data;
+- int checksum = 0, g, i = len;
+-
+- while(i--) {
+- checksum = (checksum << 4) + *p++;
+-
+- if((g = (checksum & 0xf0000000)) != 0)
+- checksum ^= g >> 23;
+-
+- checksum &= ~g;
+- }
+-
+- purple_debug_misc("yahoo", "Calculated buddy icon checksum: %d\n", checksum);
+-
+- return checksum;
+-}
+-
+-void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
+-{
+- YahooData *yd = gc->proto_data;
+- PurpleAccount *account = gc->account;
+-
+- if (img == NULL) {
+- g_free(yd->picture_url);
+- yd->picture_url = NULL;
+-
+- /* TODO: don't we have to clear it on the server too?! */
+-
+- purple_account_set_string(account, YAHOO_PICURL_SETTING, NULL);
+- purple_account_set_int(account, YAHOO_PICCKSUM_SETTING, 0);
+- purple_account_set_int(account, YAHOO_PICEXPIRE_SETTING, 0);
+- if (yd->logged_in)
+- /* Tell everyone we ain't got one no more */
+- yahoo_send_picture_update(gc, 0);
+-
+- } else {
+- gconstpointer data = purple_imgstore_get_data(img);
+- size_t len = purple_imgstore_get_size(img);
+- GString *s = g_string_new_len(data, len);
+- struct yahoo_buddy_icon_upload_data *d;
+- int oldcksum = purple_account_get_int(account, YAHOO_PICCKSUM_SETTING, 0);
+- int expire = purple_account_get_int(account, YAHOO_PICEXPIRE_SETTING, 0);
+- const char *oldurl = purple_account_get_string(account, YAHOO_PICURL_SETTING, NULL);
+-
+- yd->picture_checksum = yahoo_buddy_icon_calculate_checksum(data, len);
+-
+- if ((yd->picture_checksum == oldcksum) &&
+- (expire > (time(NULL) + 60*60*24)) && oldurl)
+- {
+- purple_debug_misc("yahoo", "buddy icon is up to date. Not reuploading.\n");
+- g_string_free(s, TRUE);
+- g_free(yd->picture_url);
+- yd->picture_url = g_strdup(oldurl);
+- return;
+- }
+-
+- /* We use this solely for sending a filename to the server */
+- d = g_new0(struct yahoo_buddy_icon_upload_data, 1);
+- d->gc = gc;
+- d->str = s;
+- d->fd = -1;
+- d->filename = g_strdup(purple_imgstore_get_filename(img));
+-
+- if (!yd->logged_in) {
+- yd->picture_upload_todo = d;
+- return;
+- }
+-
+- yahoo_buddy_icon_upload(gc, d);
+-
+- }
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_picture.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_picture.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,43 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifndef _YAHOO_PICTURE_H_
+-#define _YAHOO_PICTURE_H_
+-
+-void yahoo_send_picture_request(PurpleConnection *gc, const char *who);
+-void yahoo_send_picture_info(PurpleConnection *gc, const char *who);
+-void yahoo_send_picture_checksum(PurpleConnection *gc);
+-void yahoo_send_picture_update(PurpleConnection *gc, int type);
+-void yahoo_send_picture_update_to_user(PurpleConnection *gc, const char *who, int type);
+-
+-void yahoo_process_picture(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_picture_checksum(PurpleConnection *gc, struct yahoo_packet *pkt);
+-void yahoo_process_picture_upload(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-void yahoo_process_avatar_update(PurpleConnection *gc, struct yahoo_packet *pkt);
+-
+-void yahoo_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img);
+-void yahoo_buddy_icon_upload(PurpleConnection *gc, struct yahoo_buddy_icon_upload_data *d);
+-void yahoo_buddy_icon_upload_data_free(struct yahoo_buddy_icon_upload_data *d);
+-
+-#endif /* _YAHOO_PICTURE_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_profile.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_profile.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/yahoo_profile.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/yahoo_profile.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1282 +0,0 @@
+-/*
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#define PHOTO_SUPPORT 1
+-
+-#include "internal.h"
+-#include "debug.h"
+-#include "notify.h"
+-#include "util.h"
+-#if PHOTO_SUPPORT
+-#include "imgstore.h"
+-#endif /* PHOTO_SUPPORT */
+-
+-#include "libymsg.h"
+-#include "yahoo_friend.h"
+-
+-typedef struct {
+- PurpleConnection *gc;
+- char *name;
+-} YahooGetInfoData;
+-
+-typedef enum profile_lang_id {
+- XX, DA, DE, EL,
+- EN, EN_GB,
+- ES_AR, ES_ES, ES_MX, ES_US,
+- FR_CA, FR_FR,
+- IT, JA, KO, NO, PT, SV,
+- ZH_CN, ZH_HK, ZH_TW, ZH_US, PT_BR
+-} profile_lang_id_t;
+-
+-typedef struct profile_lang_node {
+- profile_lang_id_t lang;
+- char *last_updated_string;
+- char *det;
+-} profile_lang_node_t;
+-
+-typedef struct profile_strings_node {
+- profile_lang_id_t lang;
+- char *lang_string; /* Only to make debugging output saner */
+- char *charset;
+- char *yahoo_id_string;
+- char *private_string;
+- char *no_answer_string;
+- char *my_email_string;
+- char *realname_string;
+- char *location_string;
+- char *age_string;
+- char *maritalstatus_string;
+- char *gender_string;
+- char *occupation_string;
+- char *hobbies_string;
+- char *latest_news_string;
+- char *favorite_quote_string;
+- char *links_string;
+- char *no_home_page_specified_string;
+- char *home_page_string;
+- char *no_cool_link_specified_string;
+- char *cool_link_1_string;
+- char *cool_link_2_string;
+- char *cool_link_3_string;
+- char *dummy;
+-} profile_strings_node_t;
+-
+-typedef enum profile_state {
+- PROFILE_STATE_DEFAULT,
+- PROFILE_STATE_NOT_FOUND,
+- PROFILE_STATE_UNKNOWN_LANGUAGE
+-} profile_state_t;
+-
+-typedef struct {
+- YahooGetInfoData *info_data;
+- PurpleNotifyUserInfo *user_info;
+- char *url_buffer;
+- char *photo_url_text;
+- char *profile_url_text;
+- const profile_strings_node_t *strings;
+- const char *last_updated_string;
+- const char *title;
+- profile_state_t profile_state;
+-} YahooGetInfoStepTwoData;
+-
+-/* Strings to determine the profile "language" (more accurately "locale").
+- * Strings in this list must be in the original charset in the profile.
+- * The "Last Updated" string is used, but sometimes is not sufficient to
+- * distinguish 2 locales with this (e.g., ES_ES from ES_US, or FR_CA from
+- * FR_FR, or EL from EN_GB), in which case a second string is added and
+- * such special cases must be placed before the more general case.
+- */
+-static const profile_lang_node_t profile_langs[] = {
+- { DA, "Opdateret sidste gang&nbsp;", NULL },
+- { DE, "Letzter Update&nbsp;", NULL },
+- { EL, "Last Updated:", "http://gr.profiles.yahoo.com" },
+- { EN_GB, "Last Update&nbsp;", "Favourite Quote" },
+- { EN, "Last Update:", NULL },
+- { EN, "Last Update&nbsp;", NULL },
+- { ES_AR, "\332ltima actualizaci\363n&nbsp;", NULL },
+- { ES_ES, "Actualizada el&nbsp;", "http://es.profiles.yahoo.com" },
+- { ES_MX, "Actualizada el &nbsp;", "http://mx.profiles.yahoo.com" },
+- { ES_US, "Actualizada el &nbsp;", NULL },
+- { FR_CA, "Derni\xe8re mise \xe0 jour", "http://cf.profiles.yahoo.com" },
+- { FR_FR, "Derni\xe8re mise \xe0 jour", NULL },
+- { IT, "Ultimo aggiornamento:", NULL },
+- { JA, "\xba\xc7\xbd\xaa\xb9\xb9\xbf\xb7\xc6\xfc\xa1\xa7", NULL },
+- { KO, "\xb0\xbb\xbd\xc5\x20\xb3\xaf\xc2\xa5&nbsp;", NULL },
+- { NO, "Sist oppdatert&nbsp;", NULL },
+- { PT, "\332ltima atualiza\347\343o&nbsp;", NULL },
+- { PT_BR, "\332ltima atualiza\347\343o:", NULL },
+- { SV, "Senast uppdaterad&nbsp;", NULL },
+- { ZH_CN, "\xd7\xee\xba\xf3\xd0\xde\xb8\xc4\xc8\xd5\xc6\xda", NULL },
+- { ZH_HK, "\xb3\xcc\xaa\xf1\xa7\xf3\xb7\x73\xae\xc9\xb6\xa1", NULL },
+- { ZH_US, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1", "http://chinese.profiles.yahoo.com" },
+- { ZH_TW, "\xb3\xcc\xab\xe1\xad\xd7\xa7\xef\xa4\xe9\xb4\xc1", NULL },
+- { XX, NULL, NULL }
+-};
+-
+-/* Strings in this list must be in UTF-8; &nbsp;'s should be specified as spaces. */
+-static const profile_strings_node_t profile_strings[] = {
+- { DA, "da", "ISO-8859-1",
+- "Yahoo! ID:",
+- "Privat",
+- "Intet svar",
+- "Min Email",
+- "Rigtige navn:",
+- "Opholdssted:",
+- "Alder:",
+- "Ægteskabelig status:",
+- "Køn:",
+- "Erhverv:",
+- "Hobbyer:",
+- "Sidste nyt:",
+- "Favoritcitat",
+- "Links",
+- "Ingen hjemmeside specificeret",
+- "Forside:",
+- "Intet cool link specificeret",
+- "Cool link 1:",
+- "Cool link 2:",
+- "Cool link 3:",
+- NULL
+- },
+- { DE, "de", "ISO-8859-1",
+- "Yahoo!-ID:",
+- "Privat",
+- "Keine Antwort",
+- "Meine E-Mail",
+- "Realer Name:",
+- "Ort:",
+- "Alter:",
+- "Familienstand:",
+- "Geschlecht:",
+- "Beruf:",
+- "Hobbys:",
+- "Neuste Nachrichten:",
+- "Mein Lieblingsspruch",
+- "Links",
+- "Keine Homepage angegeben",
+- "Homepage:",
+- "Keinen coolen Link angegeben",
+- "Cooler Link 1:",
+- "Cooler Link 2:",
+- "Cooler Link 3:",
+- NULL
+- },
+- { EL, "el", "ISO-8859-7", /* EL is identical to EN, except no_answer_string */
+- "Yahoo! ID:",
+- "Private",
+- "Καμία απάντηση",
+- "My Email",
+- "Real Name:",
+- "Location:",
+- "Age:",
+- "Marital Status:",
+- "Gender:",
+- "Occupation:",
+- "Hobbies:",
+- "Latest News",
+- "Favorite Quote",
+- "Links",
+- "No home page specified",
+- "Home Page:",
+- "No cool link specified",
+- "Cool Link 1:",
+- "Cool Link 2:",
+- "Cool Link 3:",
+- NULL
+- },
+- { EN, "en", "ISO-8859-1",
+- "Yahoo! ID:",
+- "Private",
+- "No Answer",
+- "My Email:",
+- "Real Name:",
+- "Location:",
+- "Age:",
+- "Marital Status:",
+- "Sex:",
+- "Occupation:",
+- "Hobbies",
+- "Latest News",
+- "Favorite Quote",
+- "Links",
+- "No home page specified",
+- "Home Page:",
+- "No cool link specified",
+- "Cool Link 1",
+- "Cool Link 2",
+- "Cool Link 3",
+- NULL
+- },
+- { EN_GB, "en_GB", "ISO-8859-1", /* Same as EN except spelling of "Favourite" */
+- "Yahoo! ID:",
+- "Private",
+- "No Answer",
+- "My Email:",
+- "Real Name:",
+- "Location:",
+- "Age:",
+- "Marital Status:",
+- "Sex:",
+- "Occupation:",
+- "Hobbies",
+- "Latest News",
+- "Favourite Quote",
+- "Links",
+- "No home page specified",
+- "Home Page:",
+- "No cool link specified",
+- "Cool Link 1",
+- "Cool Link 2",
+- "Cool Link 3",
+- NULL
+- },
+- { ES_AR, "es_AR", "ISO-8859-1",
+- "Usuario de Yahoo!:",
+- "Privado",
+- "No introdujiste una respuesta",
+- "Mi dirección de correo electrónico",
+- "Nombre real:",
+- "Ubicación:",
+- "Edad:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupación:",
+- "Pasatiempos:",
+- "Últimas noticias:",
+- "Tu cita favorita",
+- "Enlaces",
+- "Ninguna página de inicio especificada",
+- "Página de inicio:",
+- "Ningún enlace preferido",
+- "Enlace genial 1:",
+- "Enlace genial 2:",
+- "Enlace genial 3:",
+- NULL
+- },
+- { ES_ES, "es_ES", "ISO-8859-1",
+- "ID de Yahoo!:",
+- "Privado",
+- "Sin respuesta",
+- "Mi correo-e",
+- "Nombre verdadero:",
+- "Lugar:",
+- "Edad:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupación:",
+- "Aficiones:",
+- "Ultimas Noticias:",
+- "Tu cita Favorita",
+- "Enlace",
+- "Ninguna página personal especificada",
+- "Página de Inicio:",
+- "Ningún enlace preferido",
+- "Enlaces Preferidos 1:",
+- "Enlaces Preferidos 2:",
+- "Enlaces Preferidos 3:",
+- NULL
+- },
+- { ES_MX, "es_MX", "ISO-8859-1",
+- "ID de Yahoo!:",
+- "Privado",
+- "Sin responder",
+- "Mi Dirección de correo-e",
+- "Nombre real:",
+- "Ubicación:",
+- "Edad:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupación:",
+- "Pasatiempos:",
+- "Ultimas Noticias:",
+- "Su cita favorita",
+- "Enlaces",
+- "Ninguna Página predefinida",
+- "Página web:",
+- "Ningún Enlace preferido",
+- "Enlaces Preferidos 1:",
+- "Enlaces Preferidos 2:",
+- "Enlaces Preferidos 3:",
+- NULL
+- },
+- { ES_US, "es_US", "ISO-8859-1",
+- "ID de Yahoo!:",
+- "Privado",
+- "No introdujo una respuesta",
+- "Mi Dirección de correo-e",
+- "Nombre real:",
+- "Localidad:",
+- "Edad:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupación:",
+- "Pasatiempos:",
+- "Ultimas Noticias:",
+- "Su cita Favorita",
+- "Enlaces",
+- "Ninguna Página de inicio predefinida",
+- "Página de inicio:",
+- "Ningún Enlace preferido",
+- "Enlaces Preferidos 1:",
+- "Enlaces Preferidos 2:",
+- "Enlaces Preferidos 3:",
+- NULL
+- },
+- { FR_CA, "fr_CA", "ISO-8859-1",
+- "Compte Yahoo!:",
+- "Privé",
+- "Sans réponse",
+- "Mon courriel",
+- "Nom réel:",
+- "Lieu:",
+- "Âge:",
+- "État civil:",
+- "Sexe:",
+- "Profession:",
+- "Passe-temps:",
+- "Actualités:",
+- "Citation préférée",
+- "Liens",
+- "Pas de mention d'une page personnelle",
+- "Page personnelle:",
+- "Pas de mention d'un lien favori",
+- "Lien préféré 1:",
+- "Lien préféré 2:",
+- "Lien préféré 3:",
+- NULL
+- },
+- { FR_FR, "fr_FR", "ISO-8859-1",
+- "Compte Yahoo!:",
+- "Privé",
+- "Sans réponse",
+- "Mon E-mail",
+- "Nom réel:",
+- "Lieu:",
+- "Âge:",
+- "Situation de famille:",
+- "Sexe:",
+- "Profession:",
+- "Centres d'intérêts:",
+- "Actualités:",
+- "Citation préférée",
+- "Liens",
+- "Pas de mention d'une page perso",
+- "Page perso:",
+- "Pas de mention d'un lien favori",
+- "Lien préféré 1:",
+- "Lien préféré 2:",
+- "Lien préféré 3:",
+- NULL
+- },
+- { IT, "it", "ISO-8859-1",
+- "Yahoo! ID:",
+- "Non pubblica",
+- "Nessuna risposta",
+- "La mia e-mail:",
+- "Nome vero:",
+- "Località:",
+- "Età:",
+- "Stato civile:",
+- "Sesso:",
+- "Occupazione:",
+- "Hobby",
+- "Ultime notizie",
+- "Citazione preferita",
+- "Link",
+- "Nessuna home page specificata",
+- "Inizio:",
+- "Nessun link specificato",
+- "Cool Link 1",
+- "Cool Link 2",
+- "Cool Link 3",
+- NULL
+- },
+- { JA, "ja", "EUC-JP",
+- "Yahoo! JAPAN ID:",
+- "非公開",
+- "無回答",
+- "メール:",
+- "名前:",
+- "住所:",
+- "年齢:",
+- "未婚/既婚:",
+- "性別:",
+- "職業:",
+- "趣味:",
+- "最近の出来事:",
+- NULL,
+-#if 0
+- "おすすめサイト",
+-#else
+- "自己PR", /* "Self description" comes before "Links" for yahoo.co.jp */
+-#endif
+- NULL,
+- NULL,
+- NULL,
+- "おすすめサイト1:",
+- "おすすめサイト2:",
+- "おすすめサイト3:",
+- NULL
+- },
+- { KO, "ko", "EUC-KR",
+- "야후! ID:",
+- "비공개",
+- "비공개",
+- "My Email",
+- "실명:",
+- "거주지:",
+- "나이:",
+- "결혼 여부:",
+- "성별:",
+- "직업:",
+- "취미:",
+- "자기 소개:",
+- "좋아하는 명언",
+- "링크",
+- "홈페이지를 지정하지 않았습니다.",
+- "홈페이지:",
+- "추천 사이트가 없습니다.",
+- "추천 사이트 1:",
+- "추천 사이트 2:",
+- "추천 사이트 3:",
+- NULL
+- },
+- { NO, "no", "ISO-8859-1",
+- "Yahoo! ID:",
+- "Privat",
+- "Ikke noe svar",
+- "Min e-post",
+- "Virkelig navn:",
+- "Sted:",
+- "Alder:",
+- "Sivilstatus:",
+- "Kjønn:",
+- "Yrke:",
+- "Hobbyer:",
+- "Siste nytt:",
+- "Yndlingssitat",
+- "Lenker",
+- "Ingen hjemmeside angitt",
+- "Hjemmeside:",
+- "No cool link specified",
+- "Bra lenke 1:",
+- "Bra lenke 2:",
+- "Bra lenke 3:",
+- NULL
+- },
+- { PT, "pt", "ISO-8859-1",
+- "ID Yahoo!:",
+- "Particular",
+- "Sem resposta",
+- "Meu e-mail",
+- "Nome verdadeiro:",
+- "Local:",
+- "Idade:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupação:",
+- "Hobbies:",
+- "Últimas notícias:",
+- "Frase favorita",
+- "Links",
+- "Nenhuma página pessoal especificada",
+- "Página pessoal:",
+- "Nenhum site legal especificado",
+- "Site legal 1:",
+- "Site legal 2:",
+- "Site legal 3:",
+- NULL
+- },
+- { PT_BR, "pt_br", "ISO-8859-1",
+- "ID Yahoo!:",
+- "Particular",
+- "Sem resposta",
+- "Meu e-mail",
+- "Nome verdadeiro:",
+- "Localização:",
+- "Idade:",
+- "Estado civil:",
+- "Sexo:",
+- "Ocupação:",
+- "Pasatiempos:",
+- "Últimas novidades:",
+- "Frase preferida:",
+- "Links",
+- "Nenhuma home page especificada",
+- "Página Web:",
+- "Nenhum site legal especificado",
+- "Link legal 1",
+- "Link legal 2",
+- "Link legal 3",
+- NULL
+- },
+- { SV, "sv", "ISO-8859-1",
+- "Yahoo!-ID:",
+- "Privat",
+- "Inget svar",
+- "Min mail",
+- "Riktigt namn:",
+- "Plats:",
+- "Ålder:",
+- "Civilstånd:",
+- "Kön:",
+- "Yrke:",
+- "Hobby:",
+- "Senaste nytt:",
+- "Favoritcitat",
+- "Länkar",
+- "Ingen hemsida specificerad",
+- "Hemsida:",
+- "Ingen cool länk specificerad",
+- "Coola länkar 1:",
+- "Coola länkar 2:",
+- "Coola länkar 3:",
+- NULL
+- },
+- { ZH_CN, "zh_CN", "GB2312",
+- "Yahoo! ID:",
+- "没有提供",
+- "没有回答",
+- "个人电邮地址",
+- "真实姓名:",
+- "所在地点:",
+- "年龄:",
+- "婚姻状况:",
+- "性别:",
+- "职业:",
+- "业余爱好:",
+- "个人近况:",
+- "喜欢的引言",
+- "链接",
+- "没有个人主页",
+- "个人主页:",
+- "没有推荐网站链接",
+- "推荐网站链接 1:",
+- "推荐网站链接 2:",
+- "推荐网站链接 3:",
+- NULL
+- },
+- { ZH_HK, "zh_HK", "Big5",
+- "Yahoo! ID:",
+- "私人的",
+- "沒有回答",
+- "電子信箱",
+- "真實姓名:",
+- "地點:",
+- "年齡:",
+- "婚姻狀況:",
+- "性別:",
+- "職業:",
+- "嗜好:",
+- "最新消息:",
+- "最喜愛的股票叫價", /* [sic] Yahoo!'s translators don't check context */
+- "連結",
+- "沒有注明個人網頁", /* [sic] */
+- "個人網頁:",
+- "沒有注明 Cool 連結", /* [sic] */
+- "Cool 連結 1:", /* TODO */
+- "Cool 連結 2:", /* TODO */
+- "Cool 連結 3:", /* TODO */
+- NULL
+- },
+- { ZH_TW, "zh_TW", "Big5",
+- "帳 號:",
+- "沒有提供",
+- "沒有回應",
+- "電子信箱",
+- "姓名:",
+- "地點:",
+- "年齡:",
+- "婚姻狀態:",
+- "性別:",
+- "職業:",
+- "興趣:",
+- "個人近況:",
+- "喜歡的名句",
+- "連結",
+- "沒有個人網頁",
+- "個人網頁:",
+- "沒有推薦網站連結",
+- "推薦網站連結 1:",
+- "推薦網站連結 2:",
+- "推薦網站連結 3:",
+- NULL
+- },
+- { ZH_US, "zh_US", "Big5", /* ZH_US is like ZH_TW, but also a bit like ZH_HK */
+- "Yahoo! ID:",
+- "沒有提供",
+- "沒有回答",
+- "個人Email地址",
+- "真實姓名:",
+- "地點:",
+- "年齡:",
+- "婚姻狀態:",
+- "性別:",
+- "職業:",
+- "嗜好:",
+- "個人近況:",
+- "喜歡的名句",
+- "連結",
+- "沒有個人網頁",
+- "個人網頁:",
+- "沒有推薦網站連結",
+- "推薦網站連結 1:", /* TODO */
+- "推薦網站連結 2:", /* TODO */
+- "推薦網站連結 3:", /* TODO */
+- NULL
+- },
+- { XX, NULL, NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL,
+- NULL
+- },
+-};
+-
+-static char *yahoo_info_date_reformat(const char *field, size_t len)
+-{
+- char *tmp = g_strndup(field, len);
+- time_t t = purple_str_to_time(tmp, FALSE, NULL, NULL, NULL);
+-
+- g_free(tmp);
+- return g_strdup(purple_date_format_short(localtime(&t)));
+-}
+-
+-static char *yahoo_remove_nonbreaking_spaces(char *str)
+-{
+- char *p;
+- while ((p = strstr(str, "&nbsp;")) != NULL) {
+- *p = ' '; /* Turn &nbsp;'s into ordinary blanks */
+- p += 1;
+- memmove(p, p + 5, strlen(p + 5));
+- str[strlen(str) - 5] = '\0';
+- }
+- return str;
+-}
+-
+-static void yahoo_extract_user_info_text(PurpleNotifyUserInfo *user_info, YahooGetInfoData *info_data) {
+- PurpleBuddy *b;
+- YahooFriend *f;
+-
+- b = purple_find_buddy(purple_connection_get_account(info_data->gc),
+- info_data->name);
+-
+- if (b) {
+- const char *balias = purple_buddy_get_local_buddy_alias(b);
+- if(balias && balias[0]) {
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Alias"), balias);
+- }
+- #if 0
+- if (b->idle > 0) {
+- char *idletime = purple_str_seconds_to_string(time(NULL) - b->idle);
+- purple_notify_user_info_add_pair_plaintext(user_info, _("Idle"), idletime);
+- g_free(idletime);
+- }
+- #endif
+-
+- /* Add the normal tooltip pairs */
+- yahoo_tooltip_text(b, user_info, TRUE);
+-
+- if ((f = yahoo_friend_find(info_data->gc, purple_buddy_get_name(b)))) {
+- const char *ip;
+- if ((ip = yahoo_friend_get_ip(f)))
+- purple_notify_user_info_add_pair_plaintext(user_info, _("IP Address"), ip);
+- }
+- }
+-}
+-
+-#if PHOTO_SUPPORT
+-
+-static char *yahoo_get_photo_url(const char *url_text, const char *name) {
+- GString *s = g_string_sized_new(strlen(name) + 8);
+- char *p;
+- char *it = NULL;
+-
+- /*g_string_printf(s, " alt=\"%s\">", name);*/
+- /* Y! newformat */
+- g_string_printf(s, " alt=%s>", name);
+- p = strstr(url_text, s->str);
+-
+- if (p) {
+- /* Search backwards for "http://". This is stupid, but it works. */
+- for (; !it && p > url_text; p -= 1) {
+- /*if (strncmp(p, "\"http://", 8) == 0) {*/
+- /* Y! newformat*/
+- if (strncmp(p, "=http://", 8) == 0) {
+- char *q;
+- p += 1; /* skip only the ' ' */
+- q = strchr(p, ' ');
+- if (q) {
+- g_free(it);
+- it = g_strndup(p, q - p);
+- }
+- }
+- }
+- }
+-
+- g_string_free(s, TRUE);
+- return it;
+-}
+-
+-static void
+-yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
+- const gchar *url_text, size_t len, const gchar *error_message);
+-
+-#endif /* PHOTO_SUPPORT */
+-
+-static void yahoo_got_info(PurpleUtilFetchUrlData *url_data, gpointer user_data,
+- const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- YahooGetInfoData *info_data = (YahooGetInfoData *)user_data;
+- PurpleNotifyUserInfo *user_info;
+- char *p;
+-#if PHOTO_SUPPORT
+- YahooGetInfoStepTwoData *info2_data;
+- char *photo_url_text = NULL;
+-#else
+- gboolean found = FALSE;
+- char *stripped;
+- int stripped_len;
+- char *last_updated_utf8_string = NULL;
+-#endif /* !PHOTO_SUPPORT */
+- const char *last_updated_string = NULL;
+- char *url_buffer;
+- GString *s;
+- char *tmp;
+- char *profile_url_text = NULL;
+- int lang, strid;
+- YahooData *yd;
+- const profile_strings_node_t *strings = NULL;
+- const char *title;
+- profile_state_t profile_state = PROFILE_STATE_DEFAULT;
+-
+- purple_debug_info("yahoo", "In yahoo_got_info\n");
+-
+- yd = info_data->gc->proto_data;
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- user_info = purple_notify_user_info_new();
+-
+- title = yd->jp ? _("Yahoo! Japan Profile") :
+- _("Yahoo! Profile");
+-
+- /* Get the tooltip info string */
+- yahoo_extract_user_info_text(user_info, info_data);
+-
+- /* We failed to grab the profile URL. This is not expected to actually
+- * happen except under unusual error conditions, as Yahoo is observed
+- * to send back HTML, with a 200 status code.
+- */
+- if (error_message != NULL || url_text == NULL || strcmp(url_text, "") == 0) {
+- purple_notify_user_info_add_pair(user_info, _("Error retrieving profile"), NULL);
+- purple_notify_userinfo(info_data->gc, info_data->name,
+- user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+- g_free(profile_url_text);
+- g_free(info_data->name);
+- g_free(info_data);
+- return;
+- }
+-
+- /* Construct the correct profile URL */
+- s = g_string_sized_new(80); /* wild guess */
+- g_string_printf(s, "%s%s", (yd->jp? YAHOOJP_PROFILE_URL: YAHOO_PROFILE_URL),
+- info_data->name);
+- profile_url_text = g_string_free(s, FALSE);
+- s = NULL;
+-
+- /* We don't yet support the multiple link level of the warning page for
+- * 'adult' profiles, not to mention the fact that yahoo wants you to be
+- * logged in (on the website) to be able to view an 'adult' profile. For
+- * now, just tell them that we can't help them, and provide a link to the
+- * profile if they want to do the web browser thing.
+- */
+- p = strstr(url_text, "Adult Profiles Warning Message");
+- if (!p) {
+- p = strstr(url_text, "Adult Content Warning"); /* TITLE element */
+- }
+- if (p) {
+- tmp = g_strdup_printf("<b>%s</b><br><br>"
+- "%s<br><a href=\"%s\">%s</a>",
+- _("Sorry, profiles marked as containing adult content "
+- "are not supported at this time."),
+- _("If you wish to view this profile, "
+- "you will need to visit this link in your web browser:"),
+- profile_url_text, profile_url_text);
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+-
+- purple_notify_userinfo(info_data->gc, info_data->name,
+- user_info, NULL, NULL);
+-
+- g_free(profile_url_text);
+- purple_notify_user_info_destroy(user_info);
+- g_free(info_data->name);
+- g_free(info_data);
+- return;
+- }
+-
+- /* Check whether the profile is written in a supported language */
+- for (lang = 0;; lang += 1) {
+- last_updated_string = profile_langs[lang].last_updated_string;
+- if (!last_updated_string)
+- break;
+-
+- p = strstr(url_text, last_updated_string);
+-
+- if (p) {
+- if (profile_langs[lang].det && !strstr(url_text, profile_langs[lang].det))
+- p = NULL;
+- else
+- break;
+- }
+- }
+-
+- if (p) {
+- for (strid = 0; profile_strings[strid].lang != XX; strid += 1) {
+- if (profile_strings[strid].lang == profile_langs[lang].lang) break;
+- }
+- strings = profile_strings + strid;
+- purple_debug_info("yahoo", "detected profile lang = %s (%d)\n", profile_strings[strid].lang_string, lang);
+- }
+-
+- /* Every user may choose his/her own profile language, and this language
+- * has nothing to do with the preferences of the user which looks at the
+- * profile. We try to support all languages, but nothing is guaranteed.
+- * If we cannot determine the language, it means either (1) the profile
+- * is written in an unsupported language, (2) our language support is
+- * out of date, or (3) the user is not found, or (4) Y! have changed their
+- * webpage layout
+- */
+- if (!p || strings->lang == XX) {
+- if (!strstr(url_text, "Yahoo! Member Directory - User not found")
+- && !strstr(url_text, "was not found on this server.")
+- && !strstr(url_text, "\xb8\xf8\xb3\xab\xa5\xd7\xa5\xed\xa5\xd5\xa5\xa3\xa1\xbc\xa5\xeb\xa4\xac\xb8\xab\xa4\xc4\xa4\xab\xa4\xea\xa4\xde\xa4\xbb\xa4\xf3")) {
+- profile_state = PROFILE_STATE_UNKNOWN_LANGUAGE;
+- } else {
+- profile_state = PROFILE_STATE_NOT_FOUND;
+- }
+- }
+-
+-#if PHOTO_SUPPORT
+- photo_url_text = yahoo_get_photo_url(url_text, info_data->name);
+-#endif /* PHOTO_SUPPORT */
+-
+- url_buffer = g_strdup(url_text);
+-
+- /*
+- * purple_markup_strip_html() doesn't strip out character entities like &nbsp;
+- * and &#183;
+- */
+- yahoo_remove_nonbreaking_spaces(url_buffer);
+-#if 1
+- while ((p = strstr(url_buffer, "&#183;")) != NULL) {
+- memmove(p, p + 6, strlen(p + 6));
+- url_buffer[strlen(url_buffer) - 6] = '\0';
+- }
+-#endif
+-
+- /* nuke the nasty \r's */
+- purple_str_strip_char(url_buffer, '\r');
+-
+-#if PHOTO_SUPPORT
+- /* Marshall the existing state */
+- info2_data = g_malloc(sizeof(YahooGetInfoStepTwoData));
+- info2_data->info_data = info_data;
+- info2_data->url_buffer = url_buffer;
+- info2_data->photo_url_text = photo_url_text;
+- info2_data->profile_url_text = profile_url_text;
+- info2_data->strings = strings;
+- info2_data->last_updated_string = last_updated_string;
+- info2_data->title = title;
+- info2_data->profile_state = profile_state;
+- info2_data->user_info = user_info;
+-
+- /* Try to put the photo in there too, if there's one */
+- if (photo_url_text) {
+- PurpleUtilFetchUrlData *url_data;
+- /* use whole URL if using HTTP Proxy */
+- gboolean use_whole_url = yahoo_account_use_http_proxy(info_data->gc);
+-
+- /* User-uploaded photos use a different server that requires the Host
+- * header, but Yahoo Japan will use the "chunked" content encoding if
+- * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url
+- */
+- url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL,
+- FALSE, yahoo_got_photo, info2_data);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+- } else {
+- /* Emulate a callback */
+- yahoo_got_photo(NULL, info2_data, NULL, 0, NULL);
+- }
+-}
+-
+-static void
+-yahoo_got_photo(PurpleUtilFetchUrlData *url_data, gpointer data,
+- const gchar *url_text, size_t len, const gchar *error_message)
+-{
+- YahooGetInfoStepTwoData *info2_data = (YahooGetInfoStepTwoData *)data;
+- YahooData *yd;
+- gboolean found = FALSE;
+- int id = -1;
+-
+- /* Temporary variables */
+- char *p = NULL;
+- char *stripped;
+- int stripped_len;
+- char *last_updated_utf8_string = NULL;
+- char *tmp;
+-
+- /* Unmarshall the saved state */
+- YahooGetInfoData *info_data = info2_data->info_data;
+- char *url_buffer = info2_data->url_buffer;
+- PurpleNotifyUserInfo *user_info = info2_data->user_info;
+- char *photo_url_text = info2_data->photo_url_text;
+- char *profile_url_text = info2_data->profile_url_text;
+- const profile_strings_node_t *strings = info2_data->strings;
+- const char *last_updated_string = info2_data->last_updated_string;
+- profile_state_t profile_state = info2_data->profile_state;
+-
+- /* We continue here from yahoo_got_info, as if nothing has happened */
+-#endif /* PHOTO_SUPPORT */
+-
+- /* Jun 29 05 Bleeter: Y! changed their profile pages. Terminators now seem to be */
+- /* </dd> and not \n. The prpl's need to be audited before it can be moved */
+- /* in to purple_markup_strip_html*/
+- char *fudged_buffer;
+-
+- yd = info_data->gc->proto_data;
+- yd->url_datas = g_slist_remove(yd->url_datas, url_data);
+-
+- fudged_buffer = purple_strcasereplace(url_buffer, "</dd>", "</dd><br>");
+- /* nuke the html, it's easier than trying to parse the horrid stuff */
+- stripped = purple_markup_strip_html(fudged_buffer);
+- stripped_len = strlen(stripped);
+-
+- purple_debug_misc("yahoo", "stripped = %p\n", stripped);
+- purple_debug_misc("yahoo", "url_buffer = %p\n", url_buffer);
+-
+- /* convert to utf8 */
+- if (strings && strings->charset) {
+- p = g_convert(stripped, -1, "utf-8", strings->charset,
+- NULL, NULL, NULL);
+- if (!p) {
+- p = g_locale_to_utf8(stripped, -1, NULL, NULL, NULL);
+- if (!p) {
+- p = g_convert(stripped, -1, "utf-8", "windows-1252",
+- NULL, NULL, NULL);
+- }
+- }
+- if (p) {
+- g_free(stripped);
+- stripped = purple_utf8_ncr_decode(p);
+- stripped_len = strlen(stripped);
+- g_free(p);
+- }
+- }
+- p = NULL;
+-
+- /* "Last updated" should also be converted to utf8 and with &nbsp; killed */
+- if (strings && strings->charset) {
+- last_updated_utf8_string = g_convert(last_updated_string, -1, "utf-8",
+- strings->charset, NULL, NULL, NULL);
+- yahoo_remove_nonbreaking_spaces(last_updated_utf8_string);
+-
+- purple_debug_misc("yahoo", "after utf8 conversion: stripped = (%s)\n", stripped);
+- }
+-
+- if (profile_state == PROFILE_STATE_DEFAULT) {
+-#if 0
+- /* extract their Yahoo! ID and put it in. Don't bother marking has_info as
+- * true, since the Yahoo! ID will always be there */
+- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->yahoo_id_string, (yd->jp ? 2 : 10), "\n", 0,
+- NULL, _("Yahoo! ID"), 0, NULL, NULL))
+- ;
+-#endif
+-
+-#if PHOTO_SUPPORT
+- /* Try to put the photo in there too, if there's one and is readable */
+- if (data && url_text && len != 0) {
+- if (strstr(url_text, "400 Bad Request")
+- || strstr(url_text, "403 Forbidden")
+- || strstr(url_text, "404 Not Found")) {
+-
+- purple_debug_info("yahoo", "Error getting %s: %s\n",
+- photo_url_text, url_text);
+- } else {
+- purple_debug_info("yahoo", "%s is %" G_GSIZE_FORMAT
+- " bytes\n", photo_url_text, len);
+- id = purple_imgstore_add_with_id(g_memdup(url_text, len), len, NULL);
+-
+- tmp = g_strdup_printf("<img id=\"%d\"><br>", id);
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+- }
+- }
+-#endif /* PHOTO_SUPPORT */
+-
+- /* extract their Email address and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->my_email_string, (yd->jp ? 4 : 1), " ", 0,
+- strings->private_string, _("Email"), 0, NULL, NULL);
+-
+- /* extract the Nickname if it exists */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- "Nickname:", 1, "\n", '\n',
+- NULL, _("Nickname"), 0, NULL, NULL);
+-
+- /* extract their RealName and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->realname_string, (yd->jp ? 3 : 1), "\n", '\n',
+- NULL, _("Real Name"), 0, NULL, NULL);
+-
+- /* extract their Location and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->location_string, (yd->jp ? 4 : 2), "\n", '\n',
+- NULL, _("Location"), 0, NULL, NULL);
+-
+- /* extract their Age and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->age_string, (yd->jp ? 2 : 3), "\n", '\n',
+- NULL, _("Age"), 0, NULL, NULL);
+-
+- /* extract their MaritalStatus and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->maritalstatus_string, (yd->jp ? 2 : 3), "\n", '\n',
+- strings->no_answer_string, _("Marital Status"), 0, NULL, NULL);
+-
+- /* extract their Gender and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->gender_string, (yd->jp ? 2 : 3), "\n", '\n',
+- strings->no_answer_string, _("Gender"), 0, NULL, NULL);
+-
+- /* extract their Occupation and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->occupation_string, 2, "\n", '\n',
+- NULL, _("Occupation"), 0, NULL, NULL);
+-
+- /* Hobbies, Latest News, and Favorite Quote are a bit different, since
+- * the values can contain embedded newlines... but any or all of them
+- * can also not appear. The way we delimit them is to successively
+- * look for the next one that _could_ appear, and if all else fails,
+- * we end the section by looking for the 'Links' heading, which is the
+- * next thing to follow this bunch. (For Yahoo Japan, we check for
+- * the "Description" ("Self PR") heading instead of "Links".)
+- */
+-
+- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->hobbies_string, (yd->jp ? 3 : 1), strings->latest_news_string,
+- '\n', "\n", _("Hobbies"), 0, NULL, NULL))
+- {
+- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->hobbies_string, 1, strings->favorite_quote_string,
+- '\n', "\n", _("Hobbies"), 0, NULL, NULL))
+- {
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->hobbies_string, 1, strings->links_string,
+- '\n', "\n", _("Hobbies"), 0, NULL, NULL);
+- }
+- else
+- found = TRUE;
+- }
+- else
+- found = TRUE;
+-
+- if (!purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->latest_news_string, 1, strings->favorite_quote_string,
+- '\n', "\n", _("Latest News"), 0, NULL, NULL))
+- {
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->latest_news_string, (yd->jp ? 2 : 1), strings->links_string,
+- '\n', "\n", _("Latest News"), 0, NULL, NULL);
+- }
+- else
+- found = TRUE;
+-
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->favorite_quote_string, 1, strings->links_string,
+- '\n', "\n", _("Favorite Quote"), 0, NULL, NULL);
+-
+- /* Home Page will either be "No home page specified",
+- * or "Home Page: " and a link.
+- * For Yahoo! Japan, if there is no home page specified,
+- * neither "No home page specified" nor "Home Page:" is shown.
+- */
+- if (strings->home_page_string) {
+- p = !strings->no_home_page_specified_string? NULL:
+- strstr(stripped, strings->no_home_page_specified_string);
+- if(!p)
+- {
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->home_page_string, 1, "\n", 0, NULL,
+- _("Home Page"), 1, NULL, NULL);
+- }
+- }
+-
+- /* Cool Link {1,2,3} is also different. If "No cool link specified"
+- * exists, then we have none. If we have one however, we'll need to
+- * check and see if we have a second one. If we have a second one,
+- * we have to check to see if we have a third one.
+- */
+- p = !strings->no_cool_link_specified_string? NULL:
+- strstr(stripped,strings->no_cool_link_specified_string);
+- if (!p)
+- {
+- if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->cool_link_1_string, 1, "\n", 0, NULL,
+- _("Cool Link 1"), 1, NULL, NULL))
+- {
+- found = TRUE;
+- if (purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->cool_link_2_string, 1, "\n", 0, NULL,
+- _("Cool Link 2"), 1, NULL, NULL))
+- {
+- purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- strings->cool_link_3_string, 1, "\n", 0, NULL,
+- _("Cool Link 3"), 1, NULL, NULL);
+- }
+- }
+- }
+-
+- if (last_updated_utf8_string != NULL) {
+- /* see if Member Since is there, and if so, extract it. */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- "Member Since:", 1, last_updated_utf8_string,
+- '\n', NULL, _("Member Since"), 0, NULL, yahoo_info_date_reformat);
+-
+- /* extract the Last Updated date and put it in */
+- found |= purple_markup_extract_info_field(stripped, stripped_len, user_info,
+- last_updated_utf8_string, (yd->jp ? 2 : 1), (yd->jp ? "\n" : " "), (yd->jp ? 0 : '\n'), NULL,
+- _("Last Update"), 0, NULL, (yd->jp ? NULL : yahoo_info_date_reformat));
+- }
+- } /* if (profile_state == PROFILE_STATE_DEFAULT) */
+-
+- if(!found)
+- {
+- const gchar *str;
+-
+- purple_notify_user_info_add_section_break(user_info);
+- purple_notify_user_info_add_pair(user_info,
+- _("Error retrieving profile"), NULL);
+-
+- if (profile_state == PROFILE_STATE_UNKNOWN_LANGUAGE) {
+- str = _("This profile is in a language "
+- "or format that is not supported at this time.");
+-
+- } else if (profile_state == PROFILE_STATE_NOT_FOUND) {
+- PurpleBuddy *b = purple_find_buddy
+- (purple_connection_get_account(info_data->gc),
+- info_data->name);
+- YahooFriend *f = NULL;
+- if (b) {
+- /* Someone on the buddy list can be "not on server list",
+- * in which case the user may or may not actually exist.
+- * Hence this extra step.
+- */
+- PurpleAccount *account = purple_buddy_get_account(b);
+- f = yahoo_friend_find(purple_account_get_connection(account),
+- purple_buddy_get_name(b));
+- }
+- str = f ? _("Could not retrieve the user's profile. "
+- "This most likely is a temporary server-side problem. "
+- "Please try again later.") :
+- _("Could not retrieve the user's profile. "
+- "This most likely means that the user does not exist; "
+- "however, Yahoo! sometimes does fail to find a user's "
+- "profile. If you know that the user exists, "
+- "please try again later.");
+- } else {
+- str = _("The user's profile is empty.");
+- }
+-
+- purple_notify_user_info_add_pair(user_info, NULL, str);
+- }
+-
+- /* put a link to the actual profile URL */
+- purple_notify_user_info_add_section_break(user_info);
+- tmp = g_strdup_printf("<a href=\"%s\">%s</a>",
+- profile_url_text, _("View web profile"));
+- purple_notify_user_info_add_pair(user_info, NULL, tmp);
+- g_free(tmp);
+-
+- g_free(stripped);
+-
+- /* show it to the user */
+- purple_notify_userinfo(info_data->gc, info_data->name,
+- user_info, NULL, NULL);
+- purple_notify_user_info_destroy(user_info);
+-
+- g_free(last_updated_utf8_string);
+- g_free(url_buffer);
+- g_free(fudged_buffer);
+- g_free(profile_url_text);
+- g_free(info_data->name);
+- g_free(info_data);
+-
+-#if PHOTO_SUPPORT
+- g_free(photo_url_text);
+- g_free(info2_data);
+- if (id != -1)
+- purple_imgstore_unref_by_id(id);
+-#endif /* PHOTO_SUPPORT */
+-}
+-
+-void yahoo_get_info(PurpleConnection *gc, const char *name)
+-{
+- YahooData *yd = gc->proto_data;
+- YahooGetInfoData *data;
+- char *url;
+- PurpleUtilFetchUrlData *url_data;
+-
+- data = g_new0(YahooGetInfoData, 1);
+- data->gc = gc;
+- data->name = g_strdup(name);
+-
+- url = g_strdup_printf("%s%s",
+- (yd->jp ? YAHOOJP_PROFILE_URL : YAHOO_PROFILE_URL), name);
+-
+- url_data = purple_util_fetch_url(url, TRUE, NULL, FALSE, yahoo_got_info, data);
+- if (url_data != NULL)
+- yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
+-
+- g_free(url);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/ycht.c pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.c
+--- pidgin-2.10.7/libpurple/protocols/yahoo/ycht.c 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,658 +0,0 @@
+-/**
+- * @file ycht.c The Yahoo! protocol plugin, YCHT protocol stuff.
+- *
+- * purple
+- *
+- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
+- * Liberal amounts of code borrowed from the rest of the Yahoo! prpl.
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#include "internal.h"
+-#include "prpl.h"
+-#include "notify.h"
+-#include "account.h"
+-#include "proxy.h"
+-#include "debug.h"
+-#include "conversation.h"
+-#include "util.h"
+-
+-#include "libymsg.h"
+-#include "yahoo_packet.h"
+-#include "ycht.h"
+-#include "yahoochat.h"
+-
+-/*
+- * dword: YCHT
+- * dword: 0x000000AE
+- * dword: service
+- * word: status
+- * word: size
+- */
+-#define YAHOO_CHAT_ID (1)
+-/************************************************************************************
+- * Functions to process various kinds of packets.
+- ************************************************************************************/
+-static void ycht_process_login(YchtConn *ycht, YchtPkt *pkt)
+-{
+- PurpleConnection *gc = ycht->gc;
+- YahooData *yd = gc->proto_data;
+-
+- if (ycht->logged_in)
+- return;
+-
+- yd->chat_online = TRUE;
+- ycht->logged_in = TRUE;
+-
+- if (ycht->room)
+- ycht_chat_join(ycht, ycht->room);
+-}
+-
+-static void ycht_process_logout(YchtConn *ycht, YchtPkt *pkt)
+-{
+- PurpleConnection *gc = ycht->gc;
+- YahooData *yd = gc->proto_data;
+-
+- yd->chat_online = FALSE;
+- ycht->logged_in = FALSE;
+-}
+-
+-static void ycht_process_chatjoin(YchtConn *ycht, YchtPkt *pkt)
+-{
+- char *room, *topic;
+- PurpleConnection *gc = ycht->gc;
+- PurpleConversation *c = NULL;
+- gboolean new_room = FALSE;
+- char **members;
+- int i;
+-
+- room = g_list_nth_data(pkt->data, 0);
+- topic = g_list_nth_data(pkt->data, 1);
+- if (!g_list_nth_data(pkt->data, 4))
+- return;
+- if (!room)
+- return;
+-
+- members = g_strsplit(g_list_nth_data(pkt->data, 4), "\001", 0);
+- for (i = 0; members[i]; i++) {
+- char *tmp = strchr(members[i], '\002');
+- if (tmp)
+- *tmp = '\0';
+- }
+-
+- if (g_list_length(pkt->data) > 5)
+- new_room = TRUE;
+-
+- if (new_room && ycht->changing_rooms) {
+- serv_got_chat_left(gc, YAHOO_CHAT_ID);
+- ycht->changing_rooms = FALSE;
+- c = serv_got_joined_chat(gc, YAHOO_CHAT_ID, room);
+- } else {
+- c = purple_find_chat(gc, YAHOO_CHAT_ID);
+- }
+-
+- if (topic)
+- purple_conv_chat_set_topic(PURPLE_CONV_CHAT(c), NULL, topic);
+-
+- for (i = 0; members[i]; i++) {
+- if (new_room) {
+- /*if (!strcmp(members[i], purple_connection_get_display_name(ycht->gc)))
+- continue;*/
+- purple_conv_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL, PURPLE_CBFLAGS_NONE, TRUE);
+- } else {
+- yahoo_chat_add_user(PURPLE_CONV_CHAT(c), members[i], NULL);
+- }
+- }
+-
+- g_strfreev(members);
+-}
+-
+-static void ycht_process_chatpart(YchtConn *ycht, YchtPkt *pkt)
+-{
+- char *room, *who;
+-
+- room = g_list_nth_data(pkt->data, 0);
+- who = g_list_nth_data(pkt->data, 1);
+-
+- if (who && room) {
+- PurpleConversation *c = purple_find_chat(ycht->gc, YAHOO_CHAT_ID);
+- if (c && !purple_utf8_strcasecmp(purple_conversation_get_name(c), room))
+- purple_conv_chat_remove_user(PURPLE_CONV_CHAT(c), who, NULL);
+-
+- }
+-}
+-
+-static void ycht_progress_chatmsg(YchtConn *ycht, YchtPkt *pkt)
+-{
+- char *who, *what, *msg;
+- PurpleConversation *c;
+- PurpleConnection *gc = ycht->gc;
+-
+- who = g_list_nth_data(pkt->data, 1);
+- what = g_list_nth_data(pkt->data, 2);
+-
+- if (!who || !what)
+- return;
+-
+- c = purple_find_chat(gc, YAHOO_CHAT_ID);
+- if (!c)
+- return;
+-
+- msg = yahoo_string_decode(gc, what, 1);
+- what = yahoo_codes_to_html(msg);
+- g_free(msg);
+-
+- if (pkt->service == YCHT_SERVICE_CHATMSG_EMOTE) {
+- char *tmp = g_strdup_printf("/me %s", what);
+- g_free(what);
+- what = tmp;
+- }
+-
+- serv_got_chat_in(gc, YAHOO_CHAT_ID, who, 0, what, time(NULL));
+- g_free(what);
+-}
+-
+-static void ycht_progress_online_friends(YchtConn *ycht, YchtPkt *pkt)
+-{
+-#if 0
+- PurpleConnection *gc = ycht->gc;
+- YahooData *yd = gc->proto_data;
+-
+- if (ycht->logged_in)
+- return;
+-
+- yd->chat_online = TRUE;
+- ycht->logged_in = TRUE;
+-
+- if (ycht->room)
+- ycht_chat_join(ycht, ycht->room);
+-#endif
+-}
+-
+-/*****************************************************************************
+- * Functions dealing with YCHT packets and their contents directly.
+- *****************************************************************************/
+-static void ycht_packet_dump(const guchar *data, int len)
+-{
+-#ifdef YAHOO_YCHT_DEBUG
+- int i;
+-
+- purple_debug_misc("yahoo", "");
+-
+- for (i = 0; i + 1 < len; i += 2) {
+- if ((i % 16 == 0) && i) {
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+- }
+-
+- purple_debug_misc(NULL, "%02hhx%02hhx ", data[i], data[i + 1]);
+- }
+- if (i < len)
+- purple_debug_misc(NULL, "%02hhx", data[i]);
+-
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+-
+- for (i = 0; i < len; i++) {
+- if ((i % 16 == 0) && i) {
+- purple_debug_misc(NULL, "\n");
+- purple_debug_misc("yahoo", "");
+- }
+-
+- if (g_ascii_isprint(data[i]))
+- purple_debug_misc(NULL, "%c ", data[i]);
+- else
+- purple_debug_misc(NULL, ". ");
+- }
+-
+- purple_debug_misc(NULL, "\n");
+-#endif /* YAHOO_YCHT_DEBUG */
+-}
+-
+-static YchtPkt *ycht_packet_new(guint version, guint service, int status)
+-{
+- YchtPkt *ret;
+-
+- ret = g_new0(YchtPkt, 1);
+-
+- ret->version = version;
+- ret->service = service;
+- ret->status = status;
+-
+- return ret;
+-}
+-
+-static void ycht_packet_append(YchtPkt *pkt, const char *str)
+-{
+- g_return_if_fail(pkt != NULL);
+- g_return_if_fail(str != NULL);
+-
+- pkt->data = g_list_append(pkt->data, g_strdup(str));
+-}
+-
+-static int ycht_packet_length(YchtPkt *pkt)
+-{
+- int ret;
+- GList *l;
+-
+- ret = YCHT_HEADER_LEN;
+-
+- for (l = pkt->data; l; l = l->next) {
+- ret += strlen(l->data);
+- if (l->next)
+- ret += strlen(YCHT_SEP);
+- }
+-
+- return ret;
+-}
+-
+-static void ycht_packet_send_write_cb(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- YchtConn *ycht = data;
+- int ret, writelen;
+-
+- writelen = purple_circ_buffer_get_max_read(ycht->txbuf);
+-
+- if (writelen == 0) {
+- purple_input_remove(ycht->tx_handler);
+- ycht->tx_handler = 0;
+- return;
+- }
+-
+- ret = write(ycht->fd, ycht->txbuf->outptr, writelen);
+-
+- if (ret < 0 && errno == EAGAIN)
+- return;
+- else if (ret <= 0) {
+- /* TODO: error handling */
+-/*
+- gchar *tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- purple_connection_error_reason(purple_account_get_connection(irc->account),
+- PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
+- g_free(tmp);
+-*/
+- return;
+- }
+-
+- purple_circ_buffer_mark_read(ycht->txbuf, ret);
+-
+-}
+-
+-static void ycht_packet_send(YchtConn *ycht, YchtPkt *pkt)
+-{
+- int len, pos, written;
+- char *buf;
+- GList *l;
+-
+- g_return_if_fail(ycht != NULL);
+- g_return_if_fail(pkt != NULL);
+- g_return_if_fail(ycht->fd != -1);
+-
+- pos = 0;
+- len = ycht_packet_length(pkt);
+- buf = g_malloc(len);
+-
+- memcpy(buf + pos, "YCHT", 4); pos += 4;
+- pos += yahoo_put32(buf + pos, pkt->version);
+- pos += yahoo_put32(buf + pos, pkt->service);
+- pos += yahoo_put16(buf + pos, pkt->status);
+- pos += yahoo_put16(buf + pos, len - YCHT_HEADER_LEN);
+-
+- for (l = pkt->data; l; l = l->next) {
+- int slen = strlen(l->data);
+- memcpy(buf + pos, l->data, slen); pos += slen;
+-
+- if (l->next) {
+- memcpy(buf + pos, YCHT_SEP, strlen(YCHT_SEP));
+- pos += strlen(YCHT_SEP);
+- }
+- }
+-
+- if (!ycht->tx_handler)
+- written = write(ycht->fd, buf, len);
+- else {
+- written = -1;
+- errno = EAGAIN;
+- }
+-
+- if (written < 0 && errno == EAGAIN)
+- written = 0;
+- else if (written <= 0) {
+- /* TODO: Error handling (was none before NBIO changes) */
+- written = 0;
+- }
+-
+- if (written < len) {
+- if (!ycht->tx_handler)
+- ycht->tx_handler = purple_input_add(ycht->fd,
+- PURPLE_INPUT_WRITE, ycht_packet_send_write_cb,
+- ycht);
+- purple_circ_buffer_append(ycht->txbuf, buf + written,
+- len - written);
+- }
+-
+- g_free(buf);
+-}
+-
+-static void ycht_packet_read(YchtPkt *pkt, const char *buf, int len)
+-{
+- const char *pos = buf;
+- const char *needle;
+- char *tmp, *tmp2;
+- int i = 0;
+-
+- while (len > 0 && (needle = g_strstr_len(pos, len, YCHT_SEP))) {
+- tmp = g_strndup(pos, needle - pos);
+- pkt->data = g_list_append(pkt->data, tmp);
+- len -= needle - pos + strlen(YCHT_SEP);
+- pos = needle + strlen(YCHT_SEP);
+- tmp2 = g_strescape(tmp, NULL);
+- purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i++, tmp2);
+- g_free(tmp2);
+- }
+-
+- if (len) {
+- tmp = g_strndup(pos, len);
+- pkt->data = g_list_append(pkt->data, tmp);
+- tmp2 = g_strescape(tmp, NULL);
+- purple_debug_misc("yahoo", "Data[%d]:\t%s\n", i, tmp2);
+- g_free(tmp2);
+- };
+-
+- purple_debug_misc("yahoo", "--==End of incoming YCHT packet==--\n");
+-}
+-
+-static void ycht_packet_process(YchtConn *ycht, YchtPkt *pkt)
+-{
+- if (pkt->data && !strncmp(pkt->data->data, "*** Danger Will Robinson!!!", strlen("*** Danger Will Robinson!!!")))
+- return;
+-
+- switch (pkt->service) {
+- case YCHT_SERVICE_LOGIN:
+- ycht_process_login(ycht, pkt);
+- break;
+- case YCHT_SERVICE_LOGOUT:
+- ycht_process_logout(ycht, pkt);
+- break;
+- case YCHT_SERVICE_CHATJOIN:
+- ycht_process_chatjoin(ycht, pkt);
+- break;
+- case YCHT_SERVICE_CHATPART:
+- ycht_process_chatpart(ycht, pkt);
+- break;
+- case YCHT_SERVICE_CHATMSG:
+- case YCHT_SERVICE_CHATMSG_EMOTE:
+- ycht_progress_chatmsg(ycht, pkt);
+- break;
+- case YCHT_SERVICE_ONLINE_FRIENDS:
+- ycht_progress_online_friends(ycht, pkt);
+- break;
+- default:
+- purple_debug_warning("yahoo", "YCHT: warning, unhandled service 0x%02x\n", pkt->service);
+- }
+-}
+-
+-static void ycht_packet_free(YchtPkt *pkt)
+-{
+- GList *l;
+-
+- g_return_if_fail(pkt != NULL);
+-
+- for (l = pkt->data; l; l = l->next)
+- g_free(l->data);
+- g_list_free(pkt->data);
+- g_free(pkt);
+-}
+-
+-/************************************************************************************
+- * Functions dealing with connecting and disconnecting and reading data into YchtPkt
+- * structs, and all that stuff.
+- ************************************************************************************/
+-
+-void ycht_connection_close(YchtConn *ycht)
+-{
+- YahooData *yd = ycht->gc->proto_data;
+-
+- if (yd) {
+- yd->ycht = NULL;
+- yd->chat_online = FALSE;
+- }
+-
+- if (ycht->fd > 0)
+- close(ycht->fd);
+- if (ycht->inpa)
+- purple_input_remove(ycht->inpa);
+-
+- if (ycht->tx_handler)
+- purple_input_remove(ycht->tx_handler);
+-
+- purple_circ_buffer_destroy(ycht->txbuf);
+-
+- g_free(ycht->rxqueue);
+-
+- g_free(ycht);
+-}
+-
+-static void ycht_connection_error(YchtConn *ycht, const gchar *error)
+-{
+-
+- purple_notify_info(ycht->gc, NULL, _("Connection problem with the YCHT server"), error);
+- ycht_connection_close(ycht);
+-}
+-
+-static void ycht_pending(gpointer data, gint source, PurpleInputCondition cond)
+-{
+- YchtConn *ycht = data;
+- char buf[1024];
+- int len;
+-
+- len = read(ycht->fd, buf, sizeof(buf));
+-
+- if (len < 0) {
+- gchar *tmp;
+-
+- if (errno == EAGAIN)
+- /* No worries */
+- return;
+-
+- tmp = g_strdup_printf(_("Lost connection with server: %s"),
+- g_strerror(errno));
+- ycht_connection_error(ycht, tmp);
+- g_free(tmp);
+- return;
+- } else if (len == 0) {
+- ycht_connection_error(ycht, _("Server closed the connection"));
+- return;
+- }
+-
+- ycht->rxqueue = g_realloc(ycht->rxqueue, len + ycht->rxlen);
+- memcpy(ycht->rxqueue + ycht->rxlen, buf, len);
+- ycht->rxlen += len;
+-
+- while (1) {
+- YchtPkt *pkt;
+- int pos = 0;
+- int pktlen;
+- guint service;
+- guint version;
+- gint status;
+-
+- if (ycht->rxlen < YCHT_HEADER_LEN)
+- return;
+-
+- if (strncmp("YCHT", (char *)ycht->rxqueue, 4) != 0)
+- purple_debug_error("yahoo", "YCHT: protocol error.\n");
+-
+- pos += 4; /* YCHT */
+-
+- version = yahoo_get32(ycht->rxqueue + pos); pos += 4;
+- service = yahoo_get32(ycht->rxqueue + pos); pos += 4;
+- status = yahoo_get16(ycht->rxqueue + pos); pos += 2;
+- pktlen = yahoo_get16(ycht->rxqueue + pos); pos += 2;
+- purple_debug_misc("yahoo", "ycht: %d bytes to read, rxlen is %d\n",
+- pktlen, ycht->rxlen);
+-
+- if (ycht->rxlen < (YCHT_HEADER_LEN + pktlen))
+- return;
+-
+- purple_debug_misc("yahoo", "--==Incoming YCHT packet==--\n");
+- purple_debug_misc("yahoo", "YCHT Service: 0x%02x Version: 0x%02x Status: 0x%02x\n",
+- service, version, status);
+- ycht_packet_dump(ycht->rxqueue, YCHT_HEADER_LEN + pktlen);
+-
+- pkt = ycht_packet_new(version, service, status);
+- ycht_packet_read(pkt, (char *)ycht->rxqueue + pos, pktlen);
+-
+- ycht->rxlen -= YCHT_HEADER_LEN + pktlen;
+- if (ycht->rxlen) {
+- guchar *tmp = g_memdup(ycht->rxqueue + YCHT_HEADER_LEN + pktlen, ycht->rxlen);
+- g_free(ycht->rxqueue);
+- ycht->rxqueue = tmp;
+- } else {
+- g_free(ycht->rxqueue);
+- ycht->rxqueue = NULL;
+- }
+-
+- ycht_packet_process(ycht, pkt);
+-
+- ycht_packet_free(pkt);
+- }
+-}
+-
+-static void ycht_got_connected(gpointer data, gint source, const gchar *error_message)
+-{
+- YchtConn *ycht = data;
+- PurpleConnection *gc = ycht->gc;
+- YahooData *yd = gc->proto_data;
+- YchtPkt *pkt;
+- char *buf;
+-
+- if (source < 0) {
+- ycht_connection_error(ycht, _("Unable to connect"));
+- return;
+- }
+-
+- ycht->fd = source;
+-
+- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_LOGIN, 0);
+-
+- buf = g_strdup_printf("%s\001Y=%s; T=%s", purple_connection_get_display_name(gc), yd->cookie_y, yd->cookie_t);
+- ycht_packet_append(pkt, buf);
+- g_free(buf);
+-
+- ycht_packet_send(ycht, pkt);
+-
+- ycht_packet_free(pkt);
+-
+- ycht->inpa = purple_input_add(ycht->fd, PURPLE_INPUT_READ, ycht_pending, ycht);
+-}
+-
+-void ycht_connection_open(PurpleConnection *gc)
+-{
+- YchtConn *ycht;
+- YahooData *yd = gc->proto_data;
+- PurpleAccount *account = purple_connection_get_account(gc);
+-
+- ycht = g_new0(YchtConn, 1);
+- ycht->gc = gc;
+- ycht->fd = -1;
+-
+- yd->ycht = ycht;
+-
+- if (purple_proxy_connect(gc, account,
+- purple_account_get_string(account, "ycht-server", YAHOO_YCHT_HOST),
+- purple_account_get_int(account, "ycht-port", YAHOO_YCHT_PORT),
+- ycht_got_connected, ycht) == NULL)
+- {
+- ycht_connection_error(ycht, _("Unable to connect"));
+- return;
+- }
+-}
+-
+-/*******************************************************************************************
+- * These are functions called because the user did something.
+- *******************************************************************************************/
+-
+-void ycht_chat_join(YchtConn *ycht, const char *room)
+-{
+- YchtPkt *pkt;
+- char *tmp;
+-
+- tmp = g_strdup(room);
+- g_free(ycht->room);
+- ycht->room = tmp;
+-
+- if (!ycht->logged_in)
+- return;
+-
+- ycht->changing_rooms = TRUE;
+- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATJOIN, 0);
+- ycht_packet_append(pkt, ycht->room);
+- ycht_packet_send(ycht, pkt);
+- ycht_packet_free(pkt);
+-}
+-
+-int ycht_chat_send(YchtConn *ycht, const char *room, const char *what)
+-{
+- YchtPkt *pkt;
+- char *msg1, *msg2, *buf;
+-
+- if (strcmp(room, ycht->room))
+- purple_debug_warning("yahoo", "uhoh, sending to the wrong room!\n");
+-
+- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_CHATMSG, 0);
+-
+- msg1 = yahoo_html_to_codes(what);
+- msg2 = yahoo_string_encode(ycht->gc, msg1, NULL);
+- g_free(msg1);
+-
+- buf = g_strdup_printf("%s\001%s", ycht->room, msg2);
+- ycht_packet_append(pkt, buf);
+- g_free(msg2);
+- g_free(buf);
+-
+- ycht_packet_send(ycht, pkt);
+- ycht_packet_free(pkt);
+- return 1;
+-}
+-
+-void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout)
+-{
+- if (logout)
+- ycht_connection_close(ycht);
+-}
+-
+-void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg)
+-{
+-}
+-
+-void ycht_chat_goto_user(YchtConn *ycht, const char *name)
+-{
+-}
+-
+-void ycht_chat_send_keepalive(YchtConn *ycht)
+-{
+- YchtPkt *pkt;
+-
+- pkt = ycht_packet_new(YCHT_VERSION, YCHT_SERVICE_PING, 0);
+- ycht_packet_send(ycht, pkt);
+- ycht_packet_free(pkt);
+-}
+diff -Nur pidgin-2.10.7/libpurple/protocols/yahoo/ycht.h pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.h
+--- pidgin-2.10.7/libpurple/protocols/yahoo/ycht.h 2013-02-11 07:16:52.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/yahoo/ycht.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,97 +0,0 @@
+-/**
+- * @file ycht.h The Yahoo! protocol plugin, YCHT protocol stuff.
+- *
+- * purple
+- *
+- * Copyright (C) 2004 Timothy Ringenbach <omarvo@hotmail.com>
+- *
+- * 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-
+-#ifndef _PURPLE_YCHT_H_
+-#define _PURPLE_YCHT_H_
+-
+-/* #define YAHOO_YCHT_DEBUG */
+-
+-#define YAHOO_YCHT_HOST "jcs3.chat.dcn.yahoo.com"
+-#define YAHOO_YCHT_PORT 8002
+-
+-#define YCHT_VERSION (0xae)
+-#define YCHT_HEADER_LEN (0x10)
+-
+-typedef enum {
+- YCHT_SERVICE_LOGIN = 0x01,
+- YCHT_SERVICE_LOGOUT = 0x02,
+- YCHT_SERVICE_CHATJOIN = 0x11,
+- YCHT_SERVICE_CHATPART = 0x12,
+- YCHT_SERVICE_CHATMSG = 0x41,
+- YCHT_SERVICE_CHATMSG_EMOTE = 0x43,
+- YCHT_SERVICE_PING = 0x62,
+- YCHT_SERVICE_ONLINE_FRIENDS = 0x68
+-} ycht_service;
+-/*
+-yahoo: YCHT Service: 0x11 Version: 0x100
+-yahoo: Data[0]: Linux, FreeBSD, Solaris:1
+-yahoo: Data[1]: Questions, problems and discussions about all flavors of Unix.
+-yahoo: Data[2]:
+-yahoo: Data[3]: 0
+-yahoo: Data[4]: sgooki888\0020\002 \0022769036\00258936\002
+-yahoo: --==End of incoming YCHT packet==--
+-
+-yahoo: --==Incoming YCHT packet==--
+-yahoo: YCHT Service: 0x12 Version: 0x100
+-yahoo: Data[0]: Linux, FreeBSD, Solaris:1
+-yahoo: Data[1]: cccc4cccc
+-yahoo: --==End of incoming YCHT packet==--
+-
+-*/
+-#define YCHT_SEP "\xc0\x80"
+-
+-typedef struct _YchtConn {
+- PurpleConnection *gc;
+- gchar *room;
+- int room_id;
+- gint fd;
+- gint inpa;
+- gboolean logged_in;
+- gboolean changing_rooms;
+- guchar *rxqueue;
+- guint rxlen;
+- PurpleCircBuffer *txbuf;
+- guint tx_handler;
+-} YchtConn;
+-
+-typedef struct {
+- guint version;
+- guint service;
+- gint status;
+- GList *data;
+-} YchtPkt;
+-
+-void ycht_connection_open(PurpleConnection *gc);
+-void ycht_connection_close(YchtConn *ycht);
+-
+-void ycht_chat_join(YchtConn *ycht, const char *room);
+-int ycht_chat_send(YchtConn *ycht, const char *room, const char *what);
+-void ycht_chat_leave(YchtConn *ycht, const char *room, gboolean logout);
+-void ycht_chat_send_invite(YchtConn *ycht, const char *room, const char *buddy, const char *msg);
+-void ycht_chat_goto_user(YchtConn *ycht, const char *name);
+-void ycht_chat_send_keepalive(YchtConn *ycht);
+-
+-#endif /* _PURPLE_YCHT_H_ */
+diff -Nur pidgin-2.10.7/libpurple/protocols/zephyr/Makefile.in pidgin-2.10.7-nonprism/libpurple/protocols/zephyr/Makefile.in
+--- pidgin-2.10.7/libpurple/protocols/zephyr/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/protocols/zephyr/Makefile.in 2013-08-16 23:51:52.870438890 -0300
+@@ -233,8 +233,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -296,8 +294,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/libpurple/prpl.h pidgin-2.10.7-nonprism/libpurple/prpl.h
+--- pidgin-2.10.7/libpurple/prpl.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/prpl.h 2013-08-16 22:29:46.145754932 -0300
+@@ -161,15 +161,11 @@
+
+ /**
+ * Notify on new mail.
+- *
+- * MSN and Yahoo notify you when you have new mail.
+ */
+ OPT_PROTO_MAIL_CHECK = 0x00000020,
+
+ /**
+ * Images in IMs.
+- *
+- * Oscar lets you send images in direct IMs.
+ */
+ OPT_PROTO_IM_IMAGE = 0x00000040,
+
+@@ -184,16 +180,13 @@
+ /**
+ * Allows font size to be specified in sane point size
+ *
+- * Probably just XMPP and Y!M
++ * Probably just XMPP
+ */
+ OPT_PROTO_USE_POINTSIZE = 0x00000100,
+
+ /**
+ * Set the Register button active even when the username has not
+ * been specified.
+- *
+- * Gadu-Gadu doesn't need a username to register new account (because
+- * usernames are assigned by the server).
+ */
+ OPT_PROTO_REGISTER_NOSCREENNAME = 0x00000200,
+
+@@ -467,9 +460,7 @@
+ void (*convo_closed)(PurpleConnection *, const char *who);
+
+ /**
+- * Convert the username @a who to its canonical form. (For example,
+- * AIM treats "fOo BaR" and "foobar" as the same user; this function
+- * should return the same normalized string for both of those.)
++ * Convert the username @a who to its canonical form.
+ */
+ const char *(*normalize)(const PurpleAccount *, const char *who);
+
+@@ -923,7 +914,7 @@
+ * @param who Whose attention to request.
+ * @param type_code An index into the prpl's attention_types list determining the type
+ * of the attention request command to send. 0 if prpl only defines one
+- * (for example, Yahoo and MSN), but some protocols define more (MySpaceIM).
++ * , but some protocols define more.
+ *
+ * Note that you can't send arbitrary PurpleAttentionType's, because there is
+ * only a fixed set of attention commands.
+diff -Nur pidgin-2.10.7/libpurple/purple-url-handler pidgin-2.10.7-nonprism/libpurple/purple-url-handler
+--- pidgin-2.10.7/libpurple/purple-url-handler 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/purple-url-handler 2013-08-16 21:16:42.951304560 -0300
+@@ -117,70 +117,6 @@
+ def addbuddy(account, screenname, group="", alias=""):
+ cpurple.PurpleBlistRequestAddBuddy(account, screenname, group, alias)
+
+-
+-def aim(uri):
+- protocol = "prpl-aim"
+- match = re.match(r"^aim:([^?]*)(\?(.*))", uri)
+- if not match:
+- print "Invalid aim URI: %s" % uri
+- return
+-
+- command = urllib.unquote_plus(match.group(1))
+- paramstring = match.group(3)
+- params = {}
+- if paramstring:
+- for param in paramstring.split("&"):
+- key, value = extendlist(param.split("=", 1), 2, "")
+- params[key] = urllib.unquote_plus(value)
+- accountname = params.get("account", "")
+- screenname = params.get("screenname", "")
+-
+- account = findaccount(protocol, accountname)
+-
+- if command.lower() == "goim":
+- goim(account, screenname, params.get("message"))
+- elif command.lower() == "gochat":
+- gochat(account, params)
+- elif command.lower() == "addbuddy":
+- addbuddy(account, screenname, params.get("group", ""))
+-
+-def gg(uri):
+- protocol = "prpl-gg"
+- match = re.match(r"^gg:(.*)", uri)
+- if not match:
+- print "Invalid gg URI: %s" % uri
+- return
+-
+- screenname = urllib.unquote_plus(match.group(1))
+- account = findaccount(protocol)
+- goim(account, screenname)
+-
+-def icq(uri):
+- protocol = "prpl-icq"
+- match = re.match(r"^icq:([^?]*)(\?(.*))", uri)
+- if not match:
+- print "Invalid icq URI: %s" % uri
+- return
+-
+- command = urllib.unquote_plus(match.group(1))
+- paramstring = match.group(3)
+- params = {}
+- if paramstring:
+- for param in paramstring.split("&"):
+- key, value = extendlist(param.split("=", 1), 2, "")
+- params[key] = urllib.unquote_plus(value)
+- accountname = params.get("account", "")
+- screenname = params.get("screenname", "")
+-
+- account = findaccount(protocol, accountname)
+-
+- if command.lower() == "goim":
+- goim(account, screenname, params.get("message"))
+- elif command.lower() == "gochat":
+- gochat(account, params)
+- elif command.lower() == "addbuddy":
+- addbuddy(account, screenname, params.get("group", ""))
+-
+ def irc(uri):
+ protocol = "prpl-irc"
+ match = re.match(r"^irc:(//([^/]*))?/?([^?]*)(\?(.*))?", uri)
+@@ -221,34 +157,6 @@
+ channel = "#" + channel
+ gochat(account, {"server": server, "channel": channel, "password": params.get("key", "")}, params.get("msg"))
+
+-def msnim(uri):
+- protocol = "prpl-msn"
+- match = re.match(r"^msnim:([^?]*)(\?(.*))", uri)
+- if not match:
+- print "Invalid msnim URI: %s" % uri
+- return
+-
+- command = urllib.unquote_plus(match.group(1))
+- paramstring = match.group(3)
+- params = {}
+- if paramstring:
+- for param in paramstring.split("&"):
+- key, value = extendlist(param.split("=", 1), 2, "")
+- params[key] = urllib.unquote_plus(value)
+- screenname = params.get("contact", "")
+-
+- account = findaccount(protocol)
+-
+- if command.lower() == "chat":
+- goim(account, screenname)
+- elif command.lower() == "add":
+- addbuddy(account, screenname)
+-
+-def myim(uri):
+- protocol = "prpl-myspace"
+- print "TODO: send uri: ", uri
+- assert False, "Not implemented"
+-
+ def sip(uri):
+ protocol = "prpl-simple"
+ match = re.match(r"^sip:(.*)", uri)
+@@ -300,57 +208,6 @@
+ else:
+ goim(account, screenname)
+
+-def gtalk(uri):
+- protocol = "prpl-jabber"
+- match = re.match(r"^gtalk:([^?]*)(\?(.*))", uri)
+- if not match:
+- print "Invalid gtalk URI: %s" % uri
+- return
+-
+- command = urllib.unquote_plus(match.group(1))
+- paramstring = match.group(3)
+- params = {}
+- if paramstring:
+- for param in paramstring.split("&"):
+- key, value = extendlist(param.split("=", 1), 2, "")
+- params[key] = urllib.unquote_plus(value)
+- accountname = params.get("from_jid", "")
+- jid = params.get("jid", "")
+-
+- account = findaccount(protocol, accountname)
+-
+- if command.lower() == "chat":
+- goim(account, jid)
+- elif command.lower() == "call":
+- # XXX V&V prompt to establish call
+- goim(account, jid)
+-
+-def ymsgr(uri):
+- protocol = "prpl-yahoo"
+- match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri)
+- if not match:
+- print "Invalid ymsgr URI: %s" % uri
+- return
+-
+- command = urllib.unquote_plus(match.group(1))
+- screenname = urllib.unquote_plus(match.group(3))
+- paramstring = match.group(5)
+- params = {}
+- if paramstring:
+- for param in paramstring.split("&"):
+- key, value = extendlist(param.split("=", 1), 2, "")
+- params[key] = urllib.unquote_plus(value)
+-
+- account = findaccount(protocol)
+-
+- if command.lower() == "sendim":
+- goim(account, screenname, params.get("m"))
+- elif command.lower() == "chat":
+- gochat(account, {"room": screenname})
+- elif command.lower() == "addfriend":
+- addbuddy(account, screenname)
+-
+-
+ def main(argv=sys.argv):
+ if len(argv) != 2 or argv[1] == "--help" or argv[1] == "-h":
+ print "Usage: %s URI" % argv[0]
+diff -Nur pidgin-2.10.7/libpurple/savedstatuses.c pidgin-2.10.7-nonprism/libpurple/savedstatuses.c
+--- pidgin-2.10.7/libpurple/savedstatuses.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/savedstatuses.c 2013-08-16 22:52:44.582754543 -0300
+@@ -387,7 +387,6 @@
+ const char *protocol;
+ acct_name = xmlnode_get_data(node);
+ protocol = xmlnode_get_attrib(node, "protocol");
+- protocol = _purple_oscar_convert(acct_name, protocol); /* XXX: Remove */
+ if ((acct_name != NULL) && (protocol != NULL))
+ ret->account = purple_accounts_find(acct_name, protocol);
+ g_free(acct_name);
+diff -Nur pidgin-2.10.7/libpurple/server.h pidgin-2.10.7-nonprism/libpurple/server.h
+--- pidgin-2.10.7/libpurple/server.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/server.h 2013-08-16 23:30:04.149920853 -0300
+@@ -69,7 +69,7 @@
+ * @param who Whose attention to request.
+ * @param type_code An index into the prpl's attention_types list determining the type
+ * of the attention request command to send. 0 if prpl only defines one
+- * (for example, Yahoo and MSN), but some protocols define more (MySpaceIM).
++ * , but some protocols define more.
+ *
+ * Note that you can't send arbitrary PurpleAttentionType's, because there is
+ * only a fixed set of attention commands.
+diff -Nur pidgin-2.10.7/libpurple/status.h pidgin-2.10.7-nonprism/libpurple/status.h
+--- pidgin-2.10.7/libpurple/status.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/status.h 2013-08-16 22:52:22.542054119 -0300
+@@ -43,8 +43,7 @@
+ * one of your AIM buddies has set himself as "away." You have a
+ * PurpleBuddy node for this person in your buddy list. Purple wants
+ * to mark this buddy as "away," so it creates a new PurpleStatus.
+- * The PurpleStatus has its PurpleStatusType set to the "away" state
+- * for the oscar PRPL. The PurpleStatus also contains the buddy's
++ * The PurpleStatus also contains the buddy's
+ * away message. PurpleStatuses are sometimes saved, depending on
+ * the context. The current PurpleStatuses associated with each of
+ * your accounts are saved so that the next time you start Purple,
+diff -Nur pidgin-2.10.7/libpurple/tests/check_libpurple.c pidgin-2.10.7-nonprism/libpurple/tests/check_libpurple.c
+--- pidgin-2.10.7/libpurple/tests/check_libpurple.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/check_libpurple.c 2013-08-16 22:55:33.731462302 -0300
+@@ -88,8 +88,6 @@
+ srunner_add_suite(sr, jabber_digest_md5_suite());
+ srunner_add_suite(sr, jabber_jutil_suite());
+ srunner_add_suite(sr, jabber_scram_suite());
+- srunner_add_suite(sr, oscar_util_suite());
+- srunner_add_suite(sr, yahoo_util_suite());
+ srunner_add_suite(sr, util_suite());
+ srunner_add_suite(sr, xmlnode_suite());
+
+diff -Nur pidgin-2.10.7/libpurple/tests/Makefile.am pidgin-2.10.7-nonprism/libpurple/tests/Makefile.am
+--- pidgin-2.10.7/libpurple/tests/Makefile.am 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/Makefile.am 2013-08-16 22:56:03.189064778 -0300
+@@ -14,8 +14,6 @@
+ test_jabber_digest_md5.c \
+ test_jabber_jutil.c \
+ test_jabber_scram.c \
+- test_oscar_util.c \
+- test_yahoo_util.c \
+ test_util.c \
+ test_xmlnode.c \
+ $(top_builddir)/libpurple/util.h
+@@ -31,8 +29,6 @@
+
+ check_libpurple_LDADD=\
+ $(top_builddir)/libpurple/protocols/jabber/libjabber.la \
+- $(top_builddir)/libpurple/protocols/oscar/liboscar.la \
+- $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
+ $(top_builddir)/libpurple/libpurple.la \
+ @CHECK_LIBS@ \
+ $(GLIB_LIBS)
+diff -Nur pidgin-2.10.7/libpurple/tests/Makefile.in pidgin-2.10.7-nonprism/libpurple/tests/Makefile.in
+--- pidgin-2.10.7/libpurple/tests/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/Makefile.in 2013-08-16 23:53:20.713146759 -0300
+@@ -65,8 +65,8 @@
+ CONFIG_CLEAN_VPATH_FILES =
+ am__check_libpurple_SOURCES_DIST = check_libpurple.c tests.h \
+ test_cipher.c test_jabber_caps.c test_jabber_digest_md5.c \
+- test_jabber_jutil.c test_jabber_scram.c test_oscar_util.c \
+- test_yahoo_util.c test_util.c test_xmlnode.c \
++ test_jabber_jutil.c test_jabber_scram.c \
++ test_util.c test_xmlnode.c \
+ $(top_builddir)/libpurple/util.h
+ @HAVE_CHECK_TRUE@am_check_libpurple_OBJECTS = \
+ @HAVE_CHECK_TRUE@ check_libpurple-check_libpurple.$(OBJEXT) \
+@@ -75,15 +75,11 @@
+ @HAVE_CHECK_TRUE@ check_libpurple-test_jabber_digest_md5.$(OBJEXT) \
+ @HAVE_CHECK_TRUE@ check_libpurple-test_jabber_jutil.$(OBJEXT) \
+ @HAVE_CHECK_TRUE@ check_libpurple-test_jabber_scram.$(OBJEXT) \
+-@HAVE_CHECK_TRUE@ check_libpurple-test_oscar_util.$(OBJEXT) \
+-@HAVE_CHECK_TRUE@ check_libpurple-test_yahoo_util.$(OBJEXT) \
+ @HAVE_CHECK_TRUE@ check_libpurple-test_util.$(OBJEXT) \
+ @HAVE_CHECK_TRUE@ check_libpurple-test_xmlnode.$(OBJEXT)
+ check_libpurple_OBJECTS = $(am_check_libpurple_OBJECTS)
+ am__DEPENDENCIES_1 =
+ @HAVE_CHECK_TRUE@check_libpurple_DEPENDENCIES = $(top_builddir)/libpurple/protocols/jabber/libjabber.la \
+-@HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/protocols/oscar/liboscar.la \
+-@HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
+ @HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/libpurple.la \
+ @HAVE_CHECK_TRUE@ $(am__DEPENDENCIES_1)
+ AM_V_lt = $(am__v_lt_@AM_V@)
+@@ -177,8 +173,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -240,8 +234,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+@@ -389,8 +381,6 @@
+ @HAVE_CHECK_TRUE@ test_jabber_digest_md5.c \
+ @HAVE_CHECK_TRUE@ test_jabber_jutil.c \
+ @HAVE_CHECK_TRUE@ test_jabber_scram.c \
+-@HAVE_CHECK_TRUE@ test_oscar_util.c \
+-@HAVE_CHECK_TRUE@ test_yahoo_util.c \
+ @HAVE_CHECK_TRUE@ test_util.c \
+ @HAVE_CHECK_TRUE@ test_xmlnode.c \
+ @HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/util.h
+@@ -406,8 +396,6 @@
+
+ @HAVE_CHECK_TRUE@check_libpurple_LDADD = \
+ @HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/protocols/jabber/libjabber.la \
+-@HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/protocols/oscar/liboscar.la \
+-@HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/protocols/yahoo/libymsg.la \
+ @HAVE_CHECK_TRUE@ $(top_builddir)/libpurple/libpurple.la \
+ @HAVE_CHECK_TRUE@ @CHECK_LIBS@ \
+ @HAVE_CHECK_TRUE@ $(GLIB_LIBS)
+@@ -471,10 +459,8 @@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_jabber_digest_md5.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_jabber_jutil.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_jabber_scram.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_oscar_util.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_util.Po@am__quote@
+ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_xmlnode.Po@am__quote@
+-@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/check_libpurple-test_yahoo_util.Po@am__quote@
+
+ .c.o:
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $<
+@@ -581,34 +567,6 @@
+ @AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+ @am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -c -o check_libpurple-test_jabber_scram.obj `if test -f 'test_jabber_scram.c'; then $(CYGPATH_W) 'test_jabber_scram.c'; else $(CYGPATH_W) '$(srcdir)/test_jabber_scram.c'; fi`
+
+-check_libpurple-test_oscar_util.o: test_oscar_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -MT check_libpurple-test_oscar_util.o -MD -MP -MF $(DEPDIR)/check_libpurple-test_oscar_util.Tpo -c -o check_libpurple-test_oscar_util.o `test -f 'test_oscar_util.c' || echo '$(srcdir)/'`test_oscar_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_libpurple-test_oscar_util.Tpo $(DEPDIR)/check_libpurple-test_oscar_util.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_oscar_util.c' object='check_libpurple-test_oscar_util.o' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -c -o check_libpurple-test_oscar_util.o `test -f 'test_oscar_util.c' || echo '$(srcdir)/'`test_oscar_util.c
+-
+-check_libpurple-test_oscar_util.obj: test_oscar_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -MT check_libpurple-test_oscar_util.obj -MD -MP -MF $(DEPDIR)/check_libpurple-test_oscar_util.Tpo -c -o check_libpurple-test_oscar_util.obj `if test -f 'test_oscar_util.c'; then $(CYGPATH_W) 'test_oscar_util.c'; else $(CYGPATH_W) '$(srcdir)/test_oscar_util.c'; fi`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_libpurple-test_oscar_util.Tpo $(DEPDIR)/check_libpurple-test_oscar_util.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_oscar_util.c' object='check_libpurple-test_oscar_util.obj' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -c -o check_libpurple-test_oscar_util.obj `if test -f 'test_oscar_util.c'; then $(CYGPATH_W) 'test_oscar_util.c'; else $(CYGPATH_W) '$(srcdir)/test_oscar_util.c'; fi`
+-
+-check_libpurple-test_yahoo_util.o: test_yahoo_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -MT check_libpurple-test_yahoo_util.o -MD -MP -MF $(DEPDIR)/check_libpurple-test_yahoo_util.Tpo -c -o check_libpurple-test_yahoo_util.o `test -f 'test_yahoo_util.c' || echo '$(srcdir)/'`test_yahoo_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_libpurple-test_yahoo_util.Tpo $(DEPDIR)/check_libpurple-test_yahoo_util.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_yahoo_util.c' object='check_libpurple-test_yahoo_util.o' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -c -o check_libpurple-test_yahoo_util.o `test -f 'test_yahoo_util.c' || echo '$(srcdir)/'`test_yahoo_util.c
+-
+-check_libpurple-test_yahoo_util.obj: test_yahoo_util.c
+-@am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -MT check_libpurple-test_yahoo_util.obj -MD -MP -MF $(DEPDIR)/check_libpurple-test_yahoo_util.Tpo -c -o check_libpurple-test_yahoo_util.obj `if test -f 'test_yahoo_util.c'; then $(CYGPATH_W) 'test_yahoo_util.c'; else $(CYGPATH_W) '$(srcdir)/test_yahoo_util.c'; fi`
+-@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_libpurple-test_yahoo_util.Tpo $(DEPDIR)/check_libpurple-test_yahoo_util.Po
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ $(AM_V_CC)source='test_yahoo_util.c' object='check_libpurple-test_yahoo_util.obj' libtool=no @AMDEPBACKSLASH@
+-@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+-@am__fastdepCC_FALSE@ $(AM_V_CC@am__nodep@)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -c -o check_libpurple-test_yahoo_util.obj `if test -f 'test_yahoo_util.c'; then $(CYGPATH_W) 'test_yahoo_util.c'; else $(CYGPATH_W) '$(srcdir)/test_yahoo_util.c'; fi`
+-
+ check_libpurple-test_util.o: test_util.c
+ @am__fastdepCC_TRUE@ $(AM_V_CC)$(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(check_libpurple_CFLAGS) $(CFLAGS) -MT check_libpurple-test_util.o -MD -MP -MF $(DEPDIR)/check_libpurple-test_util.Tpo -c -o check_libpurple-test_util.o `test -f 'test_util.c' || echo '$(srcdir)/'`test_util.c
+ @am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/check_libpurple-test_util.Tpo $(DEPDIR)/check_libpurple-test_util.Po
+diff -Nur pidgin-2.10.7/libpurple/tests/test_jabber_caps.c pidgin-2.10.7-nonprism/libpurple/tests/test_jabber_caps.c
+--- pidgin-2.10.7/libpurple/tests/test_jabber_caps.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/test_jabber_caps.c 2013-08-17 00:25:08.235128437 -0300
+@@ -33,7 +33,7 @@
+ START_TEST(test_calculate_caps)
+ {
+ assert_caps_calculate_match("sha1", "GNjxthSckUNvAIoCCJFttjl6VL8=",
+- "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>");
++ "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>");
+ }
+ END_TEST
+
+diff -Nur pidgin-2.10.7/libpurple/tests/test_jabber_jutil.c pidgin-2.10.7-nonprism/libpurple/tests/test_jabber_jutil.c
+--- pidgin-2.10.7/libpurple/tests/test_jabber_jutil.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/test_jabber_jutil.c 2013-08-27 22:53:21.524229291 -0300
+@@ -99,19 +99,19 @@
+
+ START_TEST(test_jabber_id_new)
+ {
+- assert_valid_jid("gmail.com");
+- assert_valid_jid("gmail.com/Test");
+- assert_valid_jid("gmail.com/Test@");
+- assert_valid_jid("gmail.com/@");
+- assert_valid_jid("gmail.com/Test@alkjaweflkj");
+- assert_valid_jid("mark.doliner@gmail.com");
+- assert_valid_jid("mark.doliner@gmail.com/Test12345");
+- assert_valid_jid("mark.doliner@gmail.com/Test@12345");
+- assert_valid_jid("mark.doliner@gmail.com/Te/st@12@//345");
++ assert_valid_jid("mail.com");
++ assert_valid_jid("mail.com/Test");
++ assert_valid_jid("mail.com/Test@");
++ assert_valid_jid("mail.com/@");
++ assert_valid_jid("mail.com/Test@alkjaweflkj");
++ assert_valid_jid("mark.doliner@mail.com");
++ assert_valid_jid("mark.doliner@mail.com/Test12345");
++ assert_valid_jid("mark.doliner@mail.com/Test@12345");
++ assert_valid_jid("mark.doliner@mail.com/Te/st@12@//345");
+ assert_valid_jid("わいど@conference.jabber.org");
+ assert_valid_jid("まりるーむ@conference.jabber.org");
+- assert_valid_jid("mark.doliner@gmail.com/まりるーむ");
+- assert_valid_jid("mark.doliner@gmail/stuff.org");
++ assert_valid_jid("mark.doliner@mail.com/まりるーむ");
++ assert_valid_jid("mark.doliner@mail/stuff.org");
+ assert_valid_jid("stuart@nödåtXäYZ.se");
+ assert_valid_jid("stuart@nödåtXäYZ.se/まりるーむ");
+ assert_valid_jid("mark.doliner@わいど.org");
+@@ -123,17 +123,17 @@
+ assert_valid_jid("pa=ul@10.0.42.230");
+ assert_valid_jid("pa,ul@10.0.42.230");
+
+- assert_invalid_jid("@gmail.com");
+- assert_invalid_jid("@@gmail.com");
+- assert_invalid_jid("mark.doliner@@gmail.com/Test12345");
+- assert_invalid_jid("mark@doliner@gmail.com/Test12345");
+- assert_invalid_jid("@gmail.com/Test@12345");
++ assert_invalid_jid("@mail.com");
++ assert_invalid_jid("@@mail.com");
++ assert_invalid_jid("mark.doliner@@mail.com/Test12345");
++ assert_invalid_jid("mark@doliner@mail.com/Test12345");
++ assert_invalid_jid("@mail.com/Test@12345");
+ assert_invalid_jid("/Test@12345");
+ assert_invalid_jid("mark.doliner@");
+ assert_invalid_jid("mark.doliner/");
+- assert_invalid_jid("mark.doliner@gmail_stuff.org");
+- assert_invalid_jid("mark.doliner@gmail[stuff.org");
+- assert_invalid_jid("mark.doliner@gmail\\stuff.org");
++ assert_invalid_jid("mark.doliner@mail_stuff.org");
++ assert_invalid_jid("mark.doliner@mail[stuff.org");
++ assert_invalid_jid("mark.doliner@mail\\stuff.org");
+ assert_invalid_jid("paul@[::1]124");
+ assert_invalid_jid("paul@2[::1]124/as");
+ assert_invalid_jid("paul@まつ.おおかみ/\x01");
+diff -Nur pidgin-2.10.7/libpurple/tests/test_oscar_util.c pidgin-2.10.7-nonprism/libpurple/tests/test_oscar_util.c
+--- pidgin-2.10.7/libpurple/tests/test_oscar_util.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/test_oscar_util.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,47 +0,0 @@
+-#include <string.h>
+-
+-#include "tests.h"
+-#include "../protocols/oscar/oscar.h"
+-
+-START_TEST(test_oscar_util_name_compare)
+-{
+- int i;
+- const char *good[] = {
+- "test",
+- "TEST",
+- "Test",
+- "teSt",
+- " TesT",
+- "test ",
+- " T E s T "
+- };
+- const char *bad[] = {
+- "toast",
+- "test@example.com",
+- "test@aim.com"
+- };
+-
+- for (i = 0; i < G_N_ELEMENTS(good); i++) {
+- ck_assert_int_eq(0, oscar_util_name_compare("test", good[i]));
+- ck_assert_int_eq(0, oscar_util_name_compare(good[i], "test"));
+- }
+- for (i = 0; i < G_N_ELEMENTS(bad); i++) {
+- ck_assert_int_ne(0, oscar_util_name_compare("test", bad[i]));
+- ck_assert_int_ne(0, oscar_util_name_compare(bad[i], "test"));
+- }
+-}
+-END_TEST
+-
+-Suite *oscar_util_suite(void)
+-{
+- Suite *s;
+- TCase *tc;
+-
+- s = suite_create("OSCAR Utility Functions");
+-
+- tc = tcase_create("Convert IM from network format to HTML");
+- tcase_add_test(tc, test_oscar_util_name_compare);
+- suite_add_tcase(s, tc);
+-
+- return s;
+-}
+diff -Nur pidgin-2.10.7/libpurple/tests/tests.h pidgin-2.10.7-nonprism/libpurple/tests/tests.h
+--- pidgin-2.10.7/libpurple/tests/tests.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/tests.h 2013-08-16 22:56:18.999567027 -0300
+@@ -13,8 +13,6 @@
+ Suite * jabber_digest_md5_suite(void);
+ Suite * jabber_jutil_suite(void);
+ Suite * jabber_scram_suite(void);
+-Suite * oscar_util_suite(void);
+-Suite * yahoo_util_suite(void);
+ Suite * util_suite(void);
+ Suite * xmlnode_suite(void);
+
+diff -Nur pidgin-2.10.7/libpurple/tests/test_yahoo_util.c pidgin-2.10.7-nonprism/libpurple/tests/test_yahoo_util.c
+--- pidgin-2.10.7/libpurple/tests/test_yahoo_util.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/tests/test_yahoo_util.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,214 +0,0 @@
+-#include <string.h>
+-
+-#include "tests.h"
+-#include "../protocols/yahoo/libymsg.h"
+-
+-static void setup_codes_to_html(void)
+-{
+- yahoo_init_colorht();
+-}
+-
+-static void teardown_codes_to_html(void)
+-{
+- yahoo_dest_colorht();
+-}
+-
+-START_TEST(test_codes_to_html)
+-{
+- assert_string_equal_free("",
+- yahoo_codes_to_html(""));
+- assert_string_equal_free("",
+- yahoo_codes_to_html("\x1B[12345m"));
+- assert_string_equal_free("plain",
+- yahoo_codes_to_html("plain"));
+- assert_string_equal_free("unknown ansi code",
+- yahoo_codes_to_html("unknown \x1B[12345m ansi code"));
+- assert_string_equal_free("plain &lt;peanut&gt;",
+- yahoo_codes_to_html("plain <peanut>"));
+- assert_string_equal_free("plain &lt;peanut",
+- yahoo_codes_to_html("plain <peanut"));
+- assert_string_equal_free("plain&gt; peanut",
+- yahoo_codes_to_html("plain> peanut"));
+- assert_string_equal_free("<font face='inva&gt;lid'>test</font>",
+- yahoo_codes_to_html("<font face='inva>lid'>test"));
+- assert_string_equal_free("&lt;font face=&apos;inva&gt;lid",
+- yahoo_codes_to_html("<font face='inva>lid"));
+-
+- /* bold/italic/underline */
+- assert_string_equal_free("<b>bold</b>",
+- yahoo_codes_to_html("\x1B[1mbold"));
+- assert_string_equal_free("<i>italic</i>",
+- yahoo_codes_to_html("\x1B[2mitalic"));
+- assert_string_equal_free("<u>underline</u>",
+- yahoo_codes_to_html("\x1B[4munderline"));
+- assert_string_equal_free("no markup",
+- yahoo_codes_to_html("no\x1B[x4m markup"));
+- assert_string_equal_free("<b>bold</b> <i>italic</i> <u>underline</u>",
+- yahoo_codes_to_html("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline"));
+- assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> italic</i>",
+- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m italic"));
+- assert_string_equal_free("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>",
+- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic\x1B[x1m \x1B[4mitalicunderline"));
+- assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i><u> boldunderline</u></b>",
+- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x2m boldunderline"));
+- assert_string_equal_free("<b>bold <i>bolditalic <u>bolditalicunderline</u></i></b><i><u> italicunderline</u></i>",
+- yahoo_codes_to_html("\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x1m italicunderline"));
+-
+- /* link */
+- assert_string_equal_free("http://pidgin.im/",
+- yahoo_codes_to_html("\x1B[lmhttp://pidgin.im/\x1B[xlm"));
+-
+-#ifdef USE_CSS_FORMATTING
+- /* font color */
+- assert_string_equal_free("<span style='color: #0000FF'>blue</span>",
+- yahoo_codes_to_html("\x1B[31mblue"));
+- assert_string_equal_free("<span style='color: #70ea15'>custom color</span>",
+- yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
+-
+- /* font face */
+- assert_string_equal_free("<font face='Georgia'>test</font>",
+- yahoo_codes_to_html("<font face='Georgia'>test</font>"));
+-
+- /* font size */
+- assert_string_equal_free("<font><span style='font-size: 15pt'>test</span></font>",
+- yahoo_codes_to_html("<font size='15'>test"));
+- assert_string_equal_free("<font><span style='font-size: 32pt'>size 32</span></font>",
+- yahoo_codes_to_html("<font size='32'>size 32"));
+-
+- /* combinations */
+- assert_string_equal_free("<font face='Georgia'><span style='font-size: 32pt'>test</span></font>",
+- yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
+- assert_string_equal_free("<span style='color: #FF0080'><font><span style='font-size: 15pt'>test</span></font></span>",
+- yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
+-#else
+- /* font color */
+- assert_string_equal_free("<font color='#0000FF'>blue</font>",
+- yahoo_codes_to_html("\x1B[31mblue"));
+- assert_string_equal_free("<font color='#70ea15'>custom color</font>",
+- yahoo_codes_to_html("\x1B[#70ea15mcustom color"));
+- assert_string_equal_free("test",
+- yahoo_codes_to_html("<ALT #ff0000,#00ff00,#0000ff>test</ALT>"));
+-
+- /* font face */
+- assert_string_equal_free("<font face='Georgia'>test</font>",
+- yahoo_codes_to_html("<font face='Georgia'>test"));
+-
+- /* font size */
+- assert_string_equal_free("<font size='4' absz='15'>test</font>",
+- yahoo_codes_to_html("<font size='15'>test"));
+- assert_string_equal_free("<font size='6' absz='32'>size 32</font>",
+- yahoo_codes_to_html("<font size='32'>size 32"));
+-
+- /* combinations */
+- assert_string_equal_free("<font face='Georgia' size='6' absz='32'>test</font>",
+- yahoo_codes_to_html("<font face='Georgia' size='32'>test"));
+- assert_string_equal_free("<font color='#FF0080'><font size='4' absz='15'>test</font></font>",
+- yahoo_codes_to_html("\x1B[35m<font size='15'>test"));
+- assert_string_equal_free(":&lt;",
+- yahoo_codes_to_html("<FADE #ff0000,#00ff00,#0000ff>:<</FADE>"));
+-#endif /* !USE_CSS_FORMATTING */
+-}
+-END_TEST
+-
+-START_TEST(test_html_to_codes)
+-{
+- assert_string_equal_free("plain",
+- yahoo_html_to_codes("plain"));
+- assert_string_equal_free("plain <peanut>",
+- yahoo_html_to_codes("plain &lt;peanut&gt;"));
+- assert_string_equal_free("plain <peanut",
+- yahoo_html_to_codes("plain &lt;peanut"));
+- assert_string_equal_free("plain> peanut",
+- yahoo_html_to_codes("plain&gt; peanut"));
+- assert_string_equal_free("plain >",
+- yahoo_html_to_codes("plain &gt;"));
+- assert_string_equal_free("plain > ",
+- yahoo_html_to_codes("plain &gt; "));
+- assert_string_equal_free("plain <",
+- yahoo_html_to_codes("plain &lt;"));
+- assert_string_equal_free("plain < ",
+- yahoo_html_to_codes("plain &lt; "));
+- assert_string_equal_free("plain &lt",
+- yahoo_html_to_codes("plain &lt"));
+- assert_string_equal_free("plain &",
+- yahoo_html_to_codes("plain &amp;"));
+-
+- /* bold/italic/underline */
+- assert_string_equal_free("\x1B[1mbold\x1B[x1m",
+- yahoo_html_to_codes("<b>bold</b>"));
+- assert_string_equal_free("\x1B[2mitalic\x1B[x2m",
+- yahoo_html_to_codes("<i>italic</i>"));
+- assert_string_equal_free("\x1B[4munderline\x1B[x4m",
+- yahoo_html_to_codes("<u>underline</u>"));
+- assert_string_equal_free("no markup",
+- yahoo_html_to_codes("no</u> markup"));
+- assert_string_equal_free("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m",
+- yahoo_html_to_codes("<b>bold</b> <i>italic</i> <u>underline</u>"));
+- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m",
+- yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> italic</i>"));
+- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m",
+- yahoo_html_to_codes("<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>"));
+-
+- /* link */
+- assert_string_equal_free("http://pidgin.im/",
+- yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">http://pidgin.im/</A>"));
+- assert_string_equal_free("mark@example.com",
+- yahoo_html_to_codes("<A HREF=\"mailto:mark@example.com\">mark@example.com</A>"));
+-#if 0
+- assert_string_equal_free("Pidgin (http://pidgin.im/)",
+- yahoo_html_to_codes("<A HREF=\"http://pidgin.im/\">Pidgin</A>"));
+-#endif
+-
+- /* font nothing */
+- assert_string_equal_free("nothing",
+- yahoo_html_to_codes("<font>nothing</font>"));
+-
+- /* font color */
+- assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m",
+- yahoo_html_to_codes("<font color=\"#E71414\">red</font>"));
+- assert_string_equal_free("\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black",
+- yahoo_html_to_codes("<font color=\"#FF0000\">red</font> <font color=\"#0000FF\">blue</font> black"));
+-
+- /* font size */
+- assert_string_equal_free("<font size=\"10\">test</font>",
+- yahoo_html_to_codes("<font size=\"2\">test</font>"));
+- assert_string_equal_free("<font size=\"30\">test</font>",
+- yahoo_html_to_codes("<font size=\"6\">test</font>"));
+-
+- /* combinations */
+- assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> rednormal\x1B[#000000m",
+- yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> rednormal</font>"));
+-
+- assert_string_equal_free("\x1B[#FF0000m<font size=\"8\">redsmall</font> \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m",
+- yahoo_html_to_codes("<font color=\"#FF0000\"><font size=\"1\">redsmall</font> <font color=\"#00FF00\">greennormal</font> rednormal</font>"));
+-
+- assert_string_equal_free("\x1B[1mbold \x1B[#FF0000mred <font face=\"Comic Sans MS\" size=\"20\">larger \x1B[#000000mbacktoblack <font size=\"12\">normalsize</font>\x1B[#FF0000m</font>\x1B[#000000m\x1B[x1m",
+- yahoo_html_to_codes("<b>bold <font color=\"#FF0000\">red <font face=\"Comic Sans MS\" size=\"5\">larger <font color=\"#000000\">backtoblack <font size=\"3\">normalsize</font></font></font></font></b>"));
+-
+- /* buzz/unknown tags */
+- assert_string_equal_free("<ding>",
+- yahoo_html_to_codes("<ding>"));
+- assert_string_equal_free("Unknown <tags>",
+- yahoo_html_to_codes("Unknown <tags>"));
+-}
+-END_TEST
+-
+-Suite *
+-yahoo_util_suite(void)
+-{
+- Suite *s;
+- TCase *tc;
+-
+- s = suite_create("Yahoo Utility Functions");
+-
+- tc = tcase_create("Convert IM from network format to HTML");
+- tcase_add_unchecked_fixture(tc, setup_codes_to_html, teardown_codes_to_html);
+- tcase_add_test(tc, test_codes_to_html);
+- suite_add_tcase(s, tc);
+-
+- tc = tcase_create("Convert IM from HTML to network format");
+- tcase_add_test(tc, test_html_to_codes);
+- suite_add_tcase(s, tc);
+-
+- return s;
+-}
+diff -Nur pidgin-2.10.7/libpurple/util.c pidgin-2.10.7-nonprism/libpurple/util.c
+--- pidgin-2.10.7/libpurple/util.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/util.c 2013-08-16 23:29:38.062434329 -0300
+@@ -3451,8 +3451,7 @@
+ * 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
++ * 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.
+@@ -4943,18 +4942,6 @@
+ return buf;
+ }
+
+-const char *_purple_oscar_convert(const char *act, const char *protocol)
+-{
+- if (act && purple_strequal(protocol, "prpl-oscar")) {
+- int i;
+- for (i = 0; act[i] != '\0'; i++)
+- if (!isdigit(act[i]))
+- return "prpl-aim";
+- return "prpl-icq";
+- }
+- return protocol;
+-}
+-
+ void purple_restore_default_signal_handlers(void)
+ {
+ #ifndef _WIN32
+diff -Nur pidgin-2.10.7/libpurple/util.h pidgin-2.10.7-nonprism/libpurple/util.h
+--- pidgin-2.10.7/libpurple/util.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/util.h 2013-08-16 23:31:12.535403448 -0300
+@@ -456,8 +456,7 @@
+ /**
+ * Extracts a field of data from HTML.
+ *
+- * This is a scary function. See protocols/msn/msn.c and
+- * protocols/yahoo/yahoo_profile.c for example usage.
++ * This is a scary function.
+ *
+ * @param str The string to parse.
+ * @param len The size of str.
+@@ -1450,16 +1449,6 @@
+ const char *purple_escape_filename(const char *str);
+
+ /**
+- * This is added temporarily to assist the split of oscar into aim and icq.
+- * This should not be used by plugins.
+- *
+- * @deprecated This function should not be used in new code and should be
+- * removed in 3.0.0. The aim/icq prpl split happened a long
+- * time ago, and we don't need to keep migrating old data.
+- */
+-const char *_purple_oscar_convert(const char *act, const char *protocol);
+-
+-/**
+ * Restore default signal handlers for signals which might reasonably have
+ * handlers. This should be called by a fork()'d child process, since child processes
+ * inherit the handlers of the parent.
+diff -Nur pidgin-2.10.7/libpurple/win32/giowin32.c pidgin-2.10.7-nonprism/libpurple/win32/giowin32.c
+--- pidgin-2.10.7/libpurple/win32/giowin32.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/giowin32.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,859 +0,0 @@
+-/* GLIB - Library of useful routines for C programming
+- * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
+- *
+- * giowin32.c: IO Channels for Win32.
+- * Copyright 1998 Owen Taylor and Tor Lillqvist
+- * Copyright 1999-2000 Tor Lillqvist and Craig Setera
+- * Copyright 2001-2003 Andrew Lanoix
+- *
+- * This library is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU Lesser General Public
+- * License as published by the Free Software Foundation; either
+- * version 2 of the License, or (at your option) any later version.
+- *
+- * This library is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * Lesser General Public License for more details.
+- *
+- * You should have received a copy of the GNU Lesser General Public
+- * License along with this library; if not, write to the
+- * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+- * Boston, MA 02111-1301, USA.
+- */
+-
+-/*
+- * Modified by the GLib Team and others 1997-2000. See the AUTHORS
+- * file for a list of people on the GLib Team. See the ChangeLog
+- * files for a list of changes. These files are distributed with
+- * GLib at ftp://ftp.gtk.org/pub/gtk/.
+- */
+-
+-/* Define this to get (very) verbose logging of all channels */
+-/* #define G_IO_WIN32_DEBUG */
+-
+-/* #include "config.h" */
+-
+-#include <glib.h>
+-
+-#include <stdlib.h>
+-#include <winsock2.h>
+-#include <windows.h>
+-#include <fcntl.h>
+-#include <io.h>
+-#include <process.h>
+-#include <errno.h>
+-#include <sys/stat.h>
+-
+-#include <glib/gstdio.h>
+-
+-typedef struct _GIOWin32Channel GIOWin32Channel;
+-typedef struct _GIOWin32Watch GIOWin32Watch;
+-
+-#define BUFFER_SIZE 4096
+-
+-GIOChannel *wpurple_g_io_channel_win32_new_socket (int socket);
+-
+-typedef enum {
+- G_IO_WIN32_WINDOWS_MESSAGES, /* Windows messages */
+- G_IO_WIN32_FILE_DESC, /* Unix-like file descriptors from
+- * _open() or _pipe(). Read with read().
+- * Have to create separate thread to read.
+- */
+- G_IO_WIN32_SOCKET /* Sockets. A separate thread is blocked
+- * in select() most of the time.
+- */
+-} GIOWin32ChannelType;
+-
+-struct _GIOWin32Channel {
+- GIOChannel channel;
+- gint fd; /* Either a Unix-like file handle as provided
+- * by the Microsoft C runtime, or a SOCKET
+- * as provided by WinSock.
+- */
+- GIOWin32ChannelType type;
+-
+- gboolean debug;
+-
+- CRITICAL_SECTION mutex;
+-
+- /* This is used by G_IO_WIN32_WINDOWS_MESSAGES channels */
+- HWND hwnd; /* handle of window, or NULL */
+-
+- /* Following fields are used by both fd and socket channels. */
+- gboolean running; /* Is reader thread running. FALSE if
+- * EOF has been reached.
+- */
+- gboolean needs_close; /* If the channel has been closed while
+- * the reader thread was still running.
+- */
+- guint thread_id; /* If non-NULL has a reader thread, or has
+- * had.*/
+- HANDLE data_avail_event;
+-
+- gushort revents;
+-
+- /* Following fields used by fd channels for input */
+-
+- /* Data is kept in a circular buffer. To be able to distinguish between
+- * empty and full buffer, we cannot fill it completely, but have to
+- * leave a one character gap.
+- *
+- * Data available is between indexes rdp and wrp-1 (modulo BUFFER_SIZE).
+- *
+- * Empty: wrp == rdp
+- * Full: (wrp + 1) % BUFFER_SIZE == rdp
+- * Partial: otherwise
+- */
+- guchar *buffer; /* (Circular) buffer */
+- gint wrp, rdp; /* Buffer indices for writing and reading */
+- HANDLE space_avail_event;
+-
+- /* Following fields used by socket channels */
+- GSList *watches;
+- HANDLE data_avail_noticed_event;
+- gint reset_send; /* socket used to send data so select_thread() can reset/re-loop */
+- gint reset_recv; /* socket used to recv data so select_thread() can reset/re-loop */
+-};
+-
+-#define LOCK(mutex) EnterCriticalSection (&mutex)
+-#define UNLOCK(mutex) LeaveCriticalSection (&mutex)
+-
+-struct _GIOWin32Watch {
+- GSource source;
+- GPollFD pollfd;
+- GIOChannel *channel;
+- GIOCondition condition;
+-};
+-
+-static void
+-g_win32_print_gioflags (GIOFlags flags)
+-{
+- char *bar = "";
+-
+- if (flags & G_IO_FLAG_APPEND)
+- bar = "|", g_print ("APPEND");
+- if (flags & G_IO_FLAG_NONBLOCK)
+- g_print ("%sNONBLOCK", bar), bar = "|";
+- if (flags & G_IO_FLAG_IS_READABLE)
+- g_print ("%sREADABLE", bar), bar = "|";
+- if (flags & G_IO_FLAG_IS_WRITEABLE)
+- g_print ("%sWRITEABLE", bar), bar = "|";
+- if (flags & G_IO_FLAG_IS_SEEKABLE)
+- g_print ("%sSEEKABLE", bar), bar = "|";
+-}
+-
+-static gboolean
+-g_io_win32_get_debug_flag (void)
+-{
+-#ifdef G_IO_WIN32_DEBUG
+- return TRUE;
+-#else
+- if (getenv ("G_IO_WIN32_DEBUG") != NULL)
+- return TRUE;
+- else
+- return FALSE;
+-#endif
+-}
+-
+-static void
+-g_io_channel_win32_init (GIOWin32Channel *channel)
+-{
+- channel->debug = g_io_win32_get_debug_flag ();
+- channel->buffer = NULL;
+- channel->running = FALSE;
+- channel->needs_close = FALSE;
+- channel->thread_id = 0;
+- channel->data_avail_event = NULL;
+- channel->revents = 0;
+- channel->space_avail_event = NULL;
+- channel->reset_send = INVALID_SOCKET;
+- channel->reset_recv = INVALID_SOCKET;
+- channel->data_avail_noticed_event = NULL;
+- channel->watches = NULL;
+- InitializeCriticalSection (&channel->mutex);
+-}
+-
+-static void
+-create_events (GIOWin32Channel *channel)
+-{
+- SECURITY_ATTRIBUTES sec_attrs;
+-
+- sec_attrs.nLength = sizeof (SECURITY_ATTRIBUTES);
+- sec_attrs.lpSecurityDescriptor = NULL;
+- sec_attrs.bInheritHandle = FALSE;
+-
+- /* The data available event is manual reset, the space available event
+- * is automatic reset.
+- */
+- if (!(channel->data_avail_event = CreateEvent (&sec_attrs, TRUE, FALSE, NULL))
+- || !(channel->space_avail_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL))
+- || !(channel->data_avail_noticed_event = CreateEvent (&sec_attrs, FALSE, FALSE, NULL)))
+- {
+- gchar *emsg = g_win32_error_message (GetLastError ());
+- g_error ("Error creating event: %s", emsg);
+- g_free (emsg);
+- }
+-}
+-
+-static void
+-create_thread (GIOWin32Channel *channel,
+- GIOCondition condition,
+- unsigned (__stdcall *thread) (void *parameter))
+-{
+- HANDLE thread_handle;
+-
+- thread_handle = (HANDLE) _beginthreadex (NULL, 0, thread, channel, 0,
+- &channel->thread_id);
+- if (thread_handle == 0)
+- g_warning (G_STRLOC ": Error creating reader thread: %s",
+- g_strerror (errno));
+- else if (!CloseHandle (thread_handle))
+- g_warning (G_STRLOC ": Error closing thread handle: %s\n",
+- g_win32_error_message (GetLastError ()));
+-
+- WaitForSingleObject (channel->space_avail_event, INFINITE);
+-}
+-
+-static void
+-init_reset_sockets (GIOWin32Channel *channel)
+-{
+- struct sockaddr_in local, local2, server;
+- int len;
+-
+- channel->reset_send = (gint) socket (AF_INET, SOCK_DGRAM, 0);
+- if (channel->reset_send == INVALID_SOCKET)
+- {
+- g_warning (G_STRLOC ": Error creating reset_send socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+- local.sin_family = AF_INET;
+- local.sin_port = 0;
+- local.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+-
+- if (bind (channel->reset_send, (struct sockaddr *)&local, sizeof (local)) == SOCKET_ERROR)
+- {
+- g_warning (G_STRLOC ": Error binding to reset_send socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+- local2.sin_family = AF_INET;
+- local2.sin_port = 0;
+- local2.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+-
+- channel->reset_recv = (gint) socket (AF_INET, SOCK_DGRAM, 0);
+- if (channel->reset_recv == INVALID_SOCKET)
+- {
+- g_warning (G_STRLOC ": Error creating reset_recv socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+- if (bind (channel->reset_recv, (struct sockaddr *)&local2, sizeof (local)) == SOCKET_ERROR)
+- {
+- g_warning (G_STRLOC ": Error binding to reset_recv socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+- len = sizeof (local2);
+- if (getsockname (channel->reset_recv, (struct sockaddr *)&local2, &len) == SOCKET_ERROR)
+- {
+- g_warning (G_STRLOC ": Error getsockname with reset_recv socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+- memset (&server, 0, sizeof (server));
+- server.sin_addr.s_addr = htonl (INADDR_LOOPBACK);
+- server.sin_family = AF_INET;
+- server.sin_port = local2.sin_port;
+-
+- if (connect (channel->reset_send, (struct sockaddr *)&server, sizeof (server)) == SOCKET_ERROR)
+- {
+- g_warning (G_STRLOC ": connect to reset_recv socket: %s\n",
+- g_win32_error_message (WSAGetLastError ()));
+- }
+-
+-}
+-
+-static unsigned __stdcall
+-select_thread (void *parameter)
+-{
+- GIOWin32Channel *channel = parameter;
+- fd_set read_fds, write_fds, except_fds;
+- GSList *tmp;
+- int n;
+- char buffer[8];
+-
+- g_io_channel_ref ((GIOChannel *)channel);
+-
+- if (channel->debug)
+- g_print ("select_thread %#x: start fd:%d data_avail:%#x data_avail_noticed:%#x\n",
+- channel->thread_id,
+- channel->fd,
+- (guint) channel->data_avail_event,
+- (guint) channel->data_avail_noticed_event);
+-
+- channel->rdp = channel->wrp = 0;
+- channel->running = TRUE;
+-
+- SetEvent (channel->space_avail_event);
+-
+- while (channel->running)
+- {
+- FD_ZERO (&read_fds);
+- FD_ZERO (&write_fds);
+- FD_ZERO (&except_fds);
+- FD_SET (channel->reset_recv, &read_fds);
+-
+- LOCK (channel->mutex);
+- tmp = channel->watches;
+- while (tmp)
+- {
+- GIOWin32Watch *watch = (GIOWin32Watch *)tmp->data;
+-
+- if (watch->condition & (G_IO_IN | G_IO_HUP))
+- FD_SET (channel->fd, &read_fds);
+- if (watch->condition & G_IO_OUT)
+- FD_SET (channel->fd, &write_fds);
+- if (watch->condition & G_IO_ERR)
+- FD_SET (channel->fd, &except_fds);
+-
+- tmp = tmp->next;
+- }
+- UNLOCK (channel->mutex);
+-
+- if (channel->debug)
+- g_print ("select_thread %#x: calling select() for%s%s%s\n",
+- channel->thread_id,
+- (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
+- (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
+- (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
+-
+- n = select (1, &read_fds, &write_fds, &except_fds, NULL);
+-
+- LOCK (channel->mutex);
+- if (channel->needs_close)
+- {
+- UNLOCK (channel->mutex);
+- break;
+- }
+- UNLOCK (channel->mutex);
+-
+- if (n == SOCKET_ERROR)
+- {
+- if (channel->debug)
+- g_print ("select_thread %#x: select returned SOCKET_ERROR\n",
+- channel->thread_id);
+- break;
+- }
+-
+- if (FD_ISSET (channel->reset_recv, &read_fds))
+- {
+- if (channel->debug)
+- g_print ("select_thread %#x: re-looping\n",
+- channel->thread_id);
+- recv (channel->reset_recv, (char *)&buffer, (int) sizeof (buffer), 0);
+- continue;
+- }
+-
+- if (channel->debug)
+- g_print ("select_thread %#x: got%s%s%s\n",
+- channel->thread_id,
+- (FD_ISSET (channel->fd, &read_fds) ? " IN" : ""),
+- (FD_ISSET (channel->fd, &write_fds) ? " OUT" : ""),
+- (FD_ISSET (channel->fd, &except_fds) ? " ERR" : ""));
+-
+- if (FD_ISSET (channel->fd, &read_fds))
+- channel->revents |= G_IO_IN;
+- if (FD_ISSET (channel->fd, &write_fds))
+- channel->revents |= G_IO_OUT;
+- if (FD_ISSET (channel->fd, &except_fds))
+- channel->revents |= G_IO_ERR;
+-
+- if (channel->debug)
+- g_print ("select_thread %#x: resetting data_avail_noticed, setting data_avail\n",
+- channel->thread_id);
+-
+- LOCK (channel->mutex);
+- ResetEvent (channel->data_avail_noticed_event);
+- SetEvent (channel->data_avail_event);
+- if (channel->needs_close)
+- {
+- UNLOCK (channel->mutex);
+- break;
+- }
+- UNLOCK (channel->mutex);
+-
+- if (channel->debug)
+- g_print ("select_thread %#x: waiting for data_avail_noticed\n",
+- channel->thread_id);
+-
+- WaitForSingleObject (channel->data_avail_noticed_event, INFINITE);
+- if (channel->debug)
+- g_print ("select_thread %#x: got data_avail_noticed\n",
+- channel->thread_id);
+- }
+-
+- LOCK (channel->mutex);
+- channel->running = FALSE;
+- if (channel->debug)
+- g_print ("select_thread %#x: got error, setting data_avail\n",
+- channel->thread_id);
+- SetEvent (channel->data_avail_event);
+- UNLOCK (channel->mutex);
+- g_io_channel_unref ((GIOChannel *)channel);
+-
+- /* No need to call _endthreadex(), the actual thread starter routine
+- * in MSVCRT (see crt/src/threadex.c:_threadstartex) calls
+- * _endthreadex() for us.
+- */
+-
+- return 0;
+-}
+-
+-static gboolean
+-g_io_win32_prepare (GSource *source,
+- gint *timeout)
+-{
+- GIOWin32Watch *watch = (GIOWin32Watch *)source;
+- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
+- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
+-
+- *timeout = -1;
+-
+- if (channel->debug)
+- g_print ("g_io_win32_prepare: for thread %#x buffer_condition:%#x\n"
+- " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
+- channel->thread_id, buffer_condition,
+- watch->pollfd.events, watch->pollfd.revents, channel->revents);
+-
+- if (channel->type == G_IO_WIN32_FILE_DESC)
+- {
+- LOCK (channel->mutex);
+- if (channel->running && channel->wrp == channel->rdp)
+- {
+- if (channel->debug)
+- g_print ("g_io_win32_prepare: for thread %#x, setting channel->revents = 0\n",
+- channel->thread_id);
+- channel->revents = 0;
+- }
+- UNLOCK (channel->mutex);
+- }
+- else if (channel->type == G_IO_WIN32_SOCKET)
+- {
+- LOCK (channel->mutex);
+- channel->revents = 0;
+- if (channel->debug)
+- g_print ("g_io_win32_prepare: for thread %#x, setting data_avail_noticed\n",
+- channel->thread_id);
+- SetEvent (channel->data_avail_noticed_event);
+- if (channel->debug)
+- g_print ("g_io_win32_prepare: thread %#x, there.\n",
+- channel->thread_id);
+- UNLOCK (channel->mutex);
+- }
+-
+- return ((watch->condition & buffer_condition) == watch->condition);
+-}
+-
+-static gboolean
+-g_io_win32_check (GSource *source)
+-{
+- MSG msg;
+- GIOWin32Watch *watch = (GIOWin32Watch *)source;
+- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
+- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
+-
+- if (channel->debug)
+- g_print ("g_io_win32_check: for thread %#x buffer_condition:%#x\n"
+- " watch->pollfd.events:%#x watch->pollfd.revents:%#x channel->revents:%#x\n",
+- channel->thread_id, buffer_condition,
+- watch->pollfd.events, watch->pollfd.revents, channel->revents);
+-
+- if (channel->type != G_IO_WIN32_WINDOWS_MESSAGES)
+- {
+- watch->pollfd.revents = (watch->pollfd.events & channel->revents);
+- }
+- else
+- {
+- return (PeekMessage (&msg, channel->hwnd, 0, 0, PM_NOREMOVE));
+- }
+-
+- if (channel->type == G_IO_WIN32_SOCKET)
+- {
+- LOCK (channel->mutex);
+- if (channel->debug)
+- g_print ("g_io_win32_check: thread %#x, resetting data_avail\n",
+- channel->thread_id);
+- ResetEvent (channel->data_avail_event);
+- if (channel->debug)
+- g_print ("g_io_win32_check: thread %#x, there.\n",
+- channel->thread_id);
+- UNLOCK (channel->mutex);
+- }
+-
+- return ((watch->pollfd.revents | buffer_condition) & watch->condition);
+-}
+-
+-static gboolean
+-g_io_win32_dispatch (GSource *source,
+- GSourceFunc callback,
+- gpointer user_data)
+-{
+- GIOFunc func = (GIOFunc)callback;
+- GIOWin32Watch *watch = (GIOWin32Watch *)source;
+- GIOCondition buffer_condition = g_io_channel_get_buffer_condition (watch->channel);
+-
+- if (!func)
+- {
+- g_warning (G_STRLOC ": GIOWin32Watch dispatched without callback\n"
+- "You must call g_source_connect().");
+- return FALSE;
+- }
+-
+- return (*func) (watch->channel,
+- (watch->pollfd.revents | buffer_condition) & watch->condition,
+- user_data);
+-}
+-
+-static void
+-g_io_win32_finalize (GSource *source)
+-{
+- GIOWin32Watch *watch = (GIOWin32Watch *)source;
+- GIOWin32Channel *channel = (GIOWin32Channel *)watch->channel;
+- char send_buffer[] = "f";
+-
+- LOCK (channel->mutex);
+- if (channel->debug)
+- g_print ("g_io_win32_finalize: channel with thread %#x\n",
+- channel->thread_id);
+-
+- channel->watches = g_slist_remove (channel->watches, watch);
+-
+- SetEvent (channel->data_avail_noticed_event);
+- if (channel->type == G_IO_WIN32_SOCKET)
+- {
+- /* Tell select_thread() to exit */
+- channel->needs_close = 1;
+- /* Wake up select_thread() from its blocking select() */
+- send (channel->reset_send, send_buffer, sizeof (send_buffer), 0);
+- }
+-
+- UNLOCK (channel->mutex);
+- g_io_channel_unref (watch->channel);
+-}
+-
+-static GSourceFuncs wp_g_io_watch_funcs = {
+- g_io_win32_prepare,
+- g_io_win32_check,
+- g_io_win32_dispatch,
+- g_io_win32_finalize,
+- NULL, NULL
+-};
+-
+-static GSource *
+-g_io_win32_create_watch (GIOChannel *channel,
+- GIOCondition condition,
+- unsigned (__stdcall *thread) (void *parameter))
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+- GIOWin32Watch *watch;
+- GSource *source;
+- char send_buffer[] = "c";
+-
+- source = g_source_new (&wp_g_io_watch_funcs, sizeof (GIOWin32Watch));
+- watch = (GIOWin32Watch *)source;
+-
+- watch->channel = channel;
+- g_io_channel_ref (channel);
+-
+- watch->condition = condition;
+-
+- if (win32_channel->data_avail_event == NULL)
+- create_events (win32_channel);
+-
+- watch->pollfd.fd = (gint) win32_channel->data_avail_event;
+- watch->pollfd.events = condition;
+-
+- if (win32_channel->debug)
+- g_print ("g_io_win32_create_watch: fd:%d condition:%#x handle:%#x\n",
+- win32_channel->fd, condition, watch->pollfd.fd);
+-
+- LOCK (win32_channel->mutex);
+- win32_channel->watches = g_slist_append (win32_channel->watches, watch);
+-
+- if (win32_channel->thread_id == 0)
+- create_thread (win32_channel, condition, thread);
+- else
+- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
+-
+- g_source_add_poll (source, &watch->pollfd);
+- UNLOCK (win32_channel->mutex);
+-
+- return source;
+-}
+-
+-static void
+-g_io_win32_free (GIOChannel *channel)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+-
+- if (win32_channel->debug)
+- g_print ("thread %#x: freeing channel, fd: %d\n",
+- win32_channel->thread_id,
+- win32_channel->fd);
+-
+- if (win32_channel->reset_send && win32_channel->reset_send != INVALID_SOCKET)
+- closesocket (win32_channel->reset_send);
+- if (win32_channel->reset_recv && win32_channel->reset_recv != INVALID_SOCKET)
+- closesocket (win32_channel->reset_recv);
+- if (win32_channel->data_avail_event)
+- CloseHandle (win32_channel->data_avail_event);
+- if (win32_channel->space_avail_event)
+- CloseHandle (win32_channel->space_avail_event);
+- if (win32_channel->data_avail_noticed_event)
+- CloseHandle (win32_channel->data_avail_noticed_event);
+- DeleteCriticalSection (&win32_channel->mutex);
+-
+- g_free (win32_channel->buffer);
+- g_slist_free (win32_channel->watches);
+- g_free (win32_channel);
+-}
+-
+-static GIOStatus
+-g_io_win32_sock_read (GIOChannel *channel,
+- gchar *buf,
+- gsize count,
+- gsize *bytes_read,
+- GError **err)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+- gint result;
+- GIOChannelError error = G_IO_STATUS_NORMAL;
+- GIOStatus internal_status = G_IO_STATUS_NORMAL;
+- char send_buffer[] = "sr";
+-
+- if (win32_channel->debug)
+- g_print ("g_io_win32_sock_read: sockfd:%d count:%d\n",
+- win32_channel->fd, count);
+-#ifdef WE_NEED_TO_HANDLE_WSAEINTR
+-repeat:
+-#endif
+- result = recv (win32_channel->fd, buf, count, 0);
+-
+- if (win32_channel->debug)
+- g_print ("g_io_win32_sock_read: recv:%d\n", result);
+-
+- if (result == SOCKET_ERROR)
+- {
+- *bytes_read = 0;
+-
+- switch (WSAGetLastError ())
+- {
+- case WSAEINVAL:
+- error = G_IO_CHANNEL_ERROR_INVAL;
+- break;
+- case WSAEWOULDBLOCK:
+- return G_IO_STATUS_AGAIN;
+-#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
+- case WSAEINTR:
+- goto repeat;
+-#endif
+- default:
+- error = G_IO_CHANNEL_ERROR_FAILED;
+- break;
+- }
+- g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket read error");
+- internal_status = G_IO_STATUS_ERROR;
+- /* FIXME get all errors, better error messages */
+- }
+- else
+- {
+- *bytes_read = result;
+- if (result == 0)
+- internal_status = G_IO_STATUS_EOF;
+- }
+-
+- if ((internal_status == G_IO_STATUS_EOF) ||
+- (internal_status == G_IO_STATUS_ERROR))
+- {
+- LOCK (win32_channel->mutex);
+- SetEvent (win32_channel->data_avail_noticed_event);
+- win32_channel->needs_close = 1;
+- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
+- UNLOCK (win32_channel->mutex);
+- }
+- return internal_status;
+-}
+-
+-static GIOStatus
+-g_io_win32_sock_write (GIOChannel *channel,
+- const gchar *buf,
+- gsize count,
+- gsize *bytes_written,
+- GError **err)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+- gint result;
+- GIOChannelError error = G_IO_STATUS_NORMAL;
+- char send_buffer[] = "sw";
+-
+- if (win32_channel->debug)
+- g_print ("g_io_win32_sock_write: sockfd:%d count:%d\n",
+- win32_channel->fd, count);
+-#ifdef WE_NEED_TO_HANDLE_WSAEINTR
+-repeat:
+-#endif
+- result = send (win32_channel->fd, buf, count, 0);
+-
+- if (win32_channel->debug)
+- g_print ("g_io_win32_sock_write: send:%d\n", result);
+-
+- if (result == SOCKET_ERROR)
+- {
+- *bytes_written = 0;
+-
+- switch (WSAGetLastError ())
+- {
+- case WSAEINVAL:
+- error = G_IO_CHANNEL_ERROR_INVAL;
+- break;
+- case WSAEWOULDBLOCK:
+- return G_IO_STATUS_AGAIN;
+-#ifdef WE_NEED_TO_HANDLE_WSAEINTR /* not anymore with wsock2 ? */
+- case WSAEINTR:
+- goto repeat;
+-#endif
+- default:
+- error = G_IO_CHANNEL_ERROR_FAILED;
+- break;
+- }
+- g_set_error (err, G_IO_CHANNEL_ERROR, error, "Socket write error");
+- LOCK (win32_channel->mutex);
+- SetEvent (win32_channel->data_avail_noticed_event);
+- win32_channel->needs_close = 1;
+- send (win32_channel->reset_send, send_buffer, sizeof (send_buffer), 0);
+- UNLOCK (win32_channel->mutex);
+- return G_IO_STATUS_ERROR;
+- /* FIXME get all errors, better error messages */
+- }
+- else
+- {
+- *bytes_written = result;
+-
+- return G_IO_STATUS_NORMAL;
+- }
+-}
+-
+-static GIOStatus
+-g_io_win32_sock_close (GIOChannel *channel,
+- GError **err)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+-
+- LOCK (win32_channel->mutex);
+- if (win32_channel->running)
+- {
+- if (win32_channel->debug)
+- g_print ("thread %#x: running, marking for later close\n",
+- win32_channel->thread_id);
+- win32_channel->running = FALSE;
+- win32_channel->needs_close = TRUE;
+- SetEvent(win32_channel->data_avail_noticed_event);
+- }
+- if (win32_channel->fd != -1)
+- {
+- if (win32_channel->debug)
+- g_print ("thread %#x: closing socket %d\n",
+- win32_channel->thread_id,
+- win32_channel->fd);
+-
+- closesocket (win32_channel->fd);
+- win32_channel->fd = -1;
+- }
+- UNLOCK (win32_channel->mutex);
+-
+- /* FIXME error detection? */
+-
+- return G_IO_STATUS_NORMAL;
+-}
+-
+-static GSource *
+-g_io_win32_sock_create_watch (GIOChannel *channel,
+- GIOCondition condition)
+-{
+- return g_io_win32_create_watch (channel, condition, select_thread);
+-}
+-
+-static GIOStatus
+-g_io_win32_set_flags (GIOChannel *channel,
+- GIOFlags flags,
+- GError **err)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+-
+- if (win32_channel->debug)
+- {
+- g_print ("g_io_win32_set_flags: ");
+- g_win32_print_gioflags (flags);
+- g_print ("\n");
+- }
+-
+- g_warning ("g_io_win32_set_flags () not implemented.\n");
+-
+- return G_IO_STATUS_NORMAL;
+-}
+-
+-static GIOFlags
+-g_io_win32_sock_get_flags (GIOChannel *channel)
+-{
+- /* XXX Could do something here. */
+- return 0;
+-}
+-
+-static GIOFuncs win32_channel_sock_funcs = {
+- g_io_win32_sock_read,
+- g_io_win32_sock_write,
+- NULL,
+- g_io_win32_sock_close,
+- g_io_win32_sock_create_watch,
+- g_io_win32_free,
+- g_io_win32_set_flags,
+- g_io_win32_sock_get_flags,
+-};
+-
+-GIOChannel *
+-wpurple_g_io_channel_win32_new_socket (int socket)
+-{
+- GIOWin32Channel *win32_channel = g_new (GIOWin32Channel, 1);
+- GIOChannel *channel = (GIOChannel *)win32_channel;
+-
+- g_io_channel_init (channel);
+- g_io_channel_win32_init (win32_channel);
+- init_reset_sockets (win32_channel);
+- if (win32_channel->debug)
+- g_print ("g_io_channel_win32_new_socket: sockfd:%d\n", socket);
+- channel->funcs = &win32_channel_sock_funcs;
+- win32_channel->type = G_IO_WIN32_SOCKET;
+- win32_channel->fd = socket;
+-
+- /* XXX: check this */
+- channel->is_readable = TRUE;
+- channel->is_writeable = TRUE;
+-
+- channel->is_seekable = FALSE;
+-
+- return channel;
+-}
+-
+-#if 0
+-void
+-g_io_channel_win32_set_debug (GIOChannel *channel,
+- gboolean flag)
+-{
+- GIOWin32Channel *win32_channel = (GIOWin32Channel *)channel;
+-
+- win32_channel->debug = flag;
+-}
+-#endif
+-
+diff -Nur pidgin-2.10.7/libpurple/win32/global.mak pidgin-2.10.7-nonprism/libpurple/win32/global.mak
+--- pidgin-2.10.7/libpurple/win32/global.mak 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/global.mak 1969-12-31 21:00:00.000000000 -0300
+@@ -1,120 +0,0 @@
+-#
+-# global.mak
+-#
+-# This file should be included by all Makefile.mingw files for project
+-# wide definitions (after correctly defining PIDGIN_TREE_TOP).
+-#
+-
+-#include optional $(PIDGIN_TREE_TOP)/local.mak to allow overriding of any definitions
+--include $(PIDGIN_TREE_TOP)/local.mak
+-
+-# Locations of our various dependencies
+-WIN32_DEV_TOP ?= $(PIDGIN_TREE_TOP)/../win32-dev
+-GTKSPELL_TOP ?= $(WIN32_DEV_TOP)/gtkspell-2.0.16
+-ENCHANT_TOP ?= $(WIN32_DEV_TOP)/enchant_1.6.0_win32
+-GTK_TOP ?= $(WIN32_DEV_TOP)/gtk_2_0-2.14
+-GTK_BIN ?= $(GTK_TOP)/bin
+-BONJOUR_TOP ?= $(WIN32_DEV_TOP)/Bonjour_SDK
+-LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.9.0
+-MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa3
+-NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.13.6-nspr-4.9.2
+-PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl-5.10.0
+-SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.10
+-TCL_LIB_TOP ?= $(WIN32_DEV_TOP)/tcl-8.4.5
+-GSTREAMER_TOP ?= $(WIN32_DEV_TOP)/gstreamer-0.10.13
+-GCC_SSP_TOP ?= $(WIN32_DEV_TOP)/gcc-core-4.4.0-mingw32-dll
+-CYRUS_SASL_TOP ?= $(WIN32_DEV_TOP)/cyrus-sasl-2.1.25
+-
+-# Where we installing this stuff to?
+-PIDGIN_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
+-PURPLE_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
+-PIDGIN_INSTALL_PLUGINS_DIR := $(PIDGIN_INSTALL_DIR)/plugins
+-PIDGIN_INSTALL_PERL_DIR := $(PIDGIN_INSTALL_PLUGINS_DIR)/perl
+-PURPLE_INSTALL_PLUGINS_DIR := $(PURPLE_INSTALL_DIR)/plugins
+-PURPLE_INSTALL_PERL_DIR := $(PURPLE_INSTALL_PLUGINS_DIR)/perl
+-PURPLE_INSTALL_PO_DIR := $(PURPLE_INSTALL_DIR)/locale
+-
+-# Important (enough) locations in our source code
+-PURPLE_TOP := $(PIDGIN_TREE_TOP)/libpurple
+-PURPLE_PLUGINS_TOP := $(PURPLE_TOP)/plugins
+-PURPLE_PERL_TOP := $(PURPLE_PLUGINS_TOP)/perl
+-PIDGIN_TOP := $(PIDGIN_TREE_TOP)/pidgin
+-PIDGIN_PIXMAPS_TOP := $(PIDGIN_TOP)/pixmaps
+-PIDGIN_PLUGINS_TOP := $(PIDGIN_TOP)/plugins
+-PURPLE_PO_TOP := $(PIDGIN_TREE_TOP)/po
+-PURPLE_PROTOS_TOP := $(PURPLE_TOP)/protocols
+-
+-# Locations of important (in-tree) build targets
+-PIDGIN_CONFIG_H := $(PIDGIN_TREE_TOP)/config.h
+-PURPLE_CONFIG_H := $(PIDGIN_TREE_TOP)/config.h
+-PIDGIN_REVISION_H := $(PIDGIN_TREE_TOP)/package_revision.h
+-PIDGIN_REVISION_RAW_TXT := $(PIDGIN_TREE_TOP)/package_revision_raw.txt
+-PURPLE_PURPLE_H := $(PURPLE_TOP)/purple.h
+-PURPLE_VERSION_H := $(PURPLE_TOP)/version.h
+-PURPLE_DLL := $(PURPLE_TOP)/libpurple.dll
+-PURPLE_PERL_DLL := $(PURPLE_PERL_TOP)/perl.dll
+-PIDGIN_DLL := $(PIDGIN_TOP)/pidgin.dll
+-PIDGIN_EXE := $(PIDGIN_TOP)/pidgin.exe
+-PIDGIN_PORTABLE_EXE := $(PIDGIN_TOP)/pidgin-portable.exe
+-
+-GCCWARNINGS ?= -Waggregate-return -Wcast-align -Wdeclaration-after-statement -Werror-implicit-function-declaration -Wextra -Wno-sign-compare -Wno-unused-parameter -Winit-self -Wmissing-declarations -Wmissing-prototypes -Wnested-externs -Wpointer-arith -Wundef
+-
+-CC_HARDENING_OPTIONS ?= -Wstack-protector -fwrapv -fno-strict-overflow -Wno-missing-field-initializers -Wformat-security -fstack-protector-all --param ssp-buffer-size=1
+-LD_HARDENING_OPTIONS ?= -Wl,--dynamicbase -Wl,--nxcompat
+-
+-
+-# parse the version number from the configure.ac file if it is newer
+-#m4_define([purple_major_version], [2])
+-#m4_define([purple_minor_version], [0])
+-#m4_define([purple_micro_version], [0])
+-#m4_define([purple_version_suffix], [devel])
+-PIDGIN_VERSION := $(shell \
+- if [ ! $(PIDGIN_TREE_TOP)/VERSION -nt $(PIDGIN_TREE_TOP)/configure.ac ]; then \
+- awk 'BEGIN {FS="[\\(\\)\\[\\]]"} /^m4_define..purple_(major|minor)_version/ {printf("%s.",$$5);} /^m4_define..purple_micro_version/ {printf("%s",$$5);} /^m4_define..purple_version_suffix/ {printf("%s",$$5); exit}' \
+- $(PIDGIN_TREE_TOP)/configure.ac > $(PIDGIN_TREE_TOP)/VERSION; \
+- fi; \
+- cat $(PIDGIN_TREE_TOP)/VERSION \
+-)
+-PURPLE_VERSION := $(PIDGIN_VERSION)
+-ifdef EXTRAVERSION
+-DISPLAY_VERSION := $(PIDGIN_VERSION)-$(EXTRAVERSION)
+-else
+-DISPLAY_VERSION := $(PIDGIN_VERSION)
+-endif
+-
+-CYRUS_SASL ?= 1
+-
+-ifeq ($(CYRUS_SASL), 1)
+-DEFINES += -DHAVE_CYRUS_SASL
+-endif
+-
+-DEFINES += -DHAVE_CONFIG_H -DWIN32_LEAN_AND_MEAN
+-
+-CFLAGS += -O2 -Wall $(GCCWARNINGS) $(CC_HARDENING_OPTIONS) -pipe -mms-bitfields -g
+-
+-# If not specified, dlls are built with the default base address of 0x10000000.
+-# When loaded into a process address space a dll will be rebased if its base
+-# address colides with the base address of an existing dll. To avoid rebasing
+-# we do the following. Rebasing can slow down the load time of dlls and it
+-# also renders debug info useless.
+-DLL_LD_FLAGS += -Wl,--enable-auto-image-base -Wl,--enable-auto-import $(LD_HARDENING_OPTIONS) -lssp
+-
+-# Build programs
+-ifeq "$(origin CC)" "default"
+- CC := gcc.exe
+-endif
+-GMSGFMT ?= $(WIN32_DEV_TOP)/gettext-0.17/bin/msgfmt
+-MAKENSIS ?= makensis.exe
+-PERL ?= perl
+-WINDRES ?= windres
+-STRIP ?= strip
+-INTLTOOL_MERGE ?= $(WIN32_DEV_TOP)/intltool_0.40.4-1_win32/bin/intltool-merge
+-MONO_SIGNCODE ?= signcode
+-GPG_SIGN ?= gpg
+-
+-PIDGIN_COMMON_RULES := $(PURPLE_TOP)/win32/rules.mak
+-PIDGIN_COMMON_TARGETS := $(PURPLE_TOP)/win32/targets.mak
+-MINGW_MAKEFILE := Makefile.mingw
+-
+-INSTALL_PIXMAPS ?= 1
+-INSTALL_SSL_CERTIFICATES ?= 1
+diff -Nur pidgin-2.10.7/libpurple/win32/libc_interface.c pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.c
+--- pidgin-2.10.7/libpurple/win32/libc_interface.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1105 +0,0 @@
+-/*
+- * purple
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#include <winsock2.h>
+-#include <ws2tcpip.h>
+-#include <io.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <errno.h>
+-#include <sys/timeb.h>
+-#include <sys/stat.h>
+-#include <time.h>
+-#include <glib.h>
+-#include "config.h"
+-#include "debug.h"
+-#include "libc_internal.h"
+-#include <glib/gstdio.h>
+-
+-/** This is redefined here because we can't include internal.h */
+-#ifdef ENABLE_NLS
+-# include <locale.h>
+-# include <libintl.h>
+-# define _(String) ((const char *)dgettext(PACKAGE, String))
+-# ifdef gettext_noop
+-# define N_(String) gettext_noop (String)
+-# else
+-# define N_(String) (String)
+-# endif
+-#else
+-# include <locale.h>
+-# define N_(String) (String)
+-# ifndef _
+-# define _(String) ((const char *)String)
+-# endif
+-# define ngettext(Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
+-# define dngettext(Domain, Singular, Plural, Number) ((Number == 1) ? ((const char *)Singular) : ((const char *)Plural))
+-#endif
+-
+-#ifndef S_ISDIR
+-# define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
+-#endif
+-
+-static char errbuf[1024];
+-
+-/* helpers */
+-static int wpurple_is_socket( int fd ) {
+- int optval;
+- int optlen = sizeof(int);
+-
+- if( (getsockopt(fd, SOL_SOCKET, SO_TYPE, (void*)&optval, &optlen)) == SOCKET_ERROR ) {
+- int error = WSAGetLastError();
+- if( error == WSAENOTSOCK )
+- return FALSE;
+- else {
+- purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_is_socket: getsockopt returned error: %d\n", error);
+- return FALSE;
+- }
+- }
+- return TRUE;
+-}
+-
+-/* socket.h */
+-int wpurple_socket (int namespace, int style, int protocol) {
+- int ret;
+-
+- ret = socket( namespace, style, protocol );
+-
+- if( ret == INVALID_SOCKET ) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return ret;
+-}
+-
+-int wpurple_connect(int socket, struct sockaddr *addr, u_long length) {
+- int ret;
+-
+- ret = connect( socket, addr, length );
+-
+- if( ret == SOCKET_ERROR ) {
+- errno = WSAGetLastError();
+- if( errno == WSAEWOULDBLOCK )
+- errno = WSAEINPROGRESS;
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr) {
+- if(getsockopt(socket, level, optname, optval, optlenptr) == SOCKET_ERROR ) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen) {
+- if(setsockopt(socket, level, optname, optval, optlen) == SOCKET_ERROR ) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_getsockname(int socket, struct sockaddr *addr, socklen_t *lenptr) {
+- if(getsockname(socket, addr, lenptr) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length) {
+- if(bind(socket, addr, length) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_listen(int socket, unsigned int n) {
+- if(listen(socket, n) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen) {
+- int ret;
+- if ((ret = sendto(socket, buf, len, flags, to, tolen)
+- ) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
+- errno = EAGAIN;
+- return -1;
+- }
+- return ret;
+-}
+-
+-/* fcntl.h */
+-/* This is not a full implementation of fcntl. Update as needed.. */
+-int wpurple_fcntl(int socket, int command, ...) {
+-
+- switch( command ) {
+- case F_GETFL:
+- return 0;
+-
+- case F_SETFL:
+- {
+- va_list args;
+- int val;
+- int ret=0;
+-
+- va_start(args, command);
+- val = va_arg(args, int);
+- va_end(args);
+-
+- switch( val ) {
+- case O_NONBLOCK:
+- {
+- u_long imode=1;
+- ret = ioctlsocket(socket, FIONBIO, &imode);
+- break;
+- }
+- case 0:
+- {
+- u_long imode=0;
+- ret = ioctlsocket(socket, FIONBIO, &imode);
+- break;
+- }
+- default:
+- errno = EINVAL;
+- return -1;
+- }/*end switch*/
+- if( ret == SOCKET_ERROR ) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+- }
+- default:
+- purple_debug(PURPLE_DEBUG_WARNING, "wpurple", "wpurple_fcntl: Unsupported command\n");
+- return -1;
+- }/*end switch*/
+-}
+-
+-/* sys/ioctl.h */
+-int wpurple_ioctl(int fd, int command, void* val) {
+- switch( command ) {
+- case FIONBIO:
+- {
+- if (ioctlsocket(fd, FIONBIO, (unsigned long *)val) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+- }
+- case SIOCGIFCONF:
+- {
+- INTERFACE_INFO InterfaceList[20];
+- unsigned long nBytesReturned;
+- if (WSAIoctl(fd, SIO_GET_INTERFACE_LIST,
+- 0, 0, &InterfaceList,
+- sizeof(InterfaceList), &nBytesReturned,
+- 0, 0) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- } else {
+- int i;
+- struct ifconf *ifc = val;
+- char *tmp = ifc->ifc_buf;
+- int nNumInterfaces =
+- nBytesReturned / sizeof(INTERFACE_INFO);
+- for (i = 0; i < nNumInterfaces; i++) {
+- INTERFACE_INFO ii = InterfaceList[i];
+- struct ifreq *ifr = (struct ifreq *) tmp;
+- struct sockaddr_in *sa = (struct sockaddr_in *) &ifr->ifr_addr;
+-
+- sa->sin_family = ii.iiAddress.AddressIn.sin_family;
+- sa->sin_port = ii.iiAddress.AddressIn.sin_port;
+- sa->sin_addr.s_addr = ii.iiAddress.AddressIn.sin_addr.s_addr;
+- tmp += sizeof(struct ifreq);
+-
+- /* Make sure that we can fit in the original buffer */
+- if (tmp >= (ifc->ifc_buf + ifc->ifc_len + sizeof(struct ifreq))) {
+- break;
+- }
+- }
+- /* Replace the length with the actually used length */
+- ifc->ifc_len = ifc->ifc_len - (ifc->ifc_buf - tmp);
+- return 0;
+- }
+- }
+- default:
+- errno = EINVAL;
+- return -1;
+- }/*end switch*/
+-}
+-
+-/* arpa/inet.h */
+-int wpurple_inet_aton(const char *name, struct in_addr *addr) {
+- if((addr->s_addr = inet_addr(name)) == INADDR_NONE)
+- return 0;
+- else
+- return 1;
+-}
+-
+-/* Thanks to GNU wget for this inet_ntop() implementation */
+-const char *
+-wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt)
+-{
+- /* struct sockaddr can't accomodate struct sockaddr_in6. */
+- union {
+- struct sockaddr_in6 sin6;
+- struct sockaddr_in sin;
+- } sa;
+- DWORD dstlen = cnt;
+- size_t srcsize;
+-
+- ZeroMemory(&sa, sizeof(sa));
+- switch (af)
+- {
+- case AF_INET:
+- sa.sin.sin_family = AF_INET;
+- sa.sin.sin_addr = *(struct in_addr *) src;
+- srcsize = sizeof (sa.sin);
+- break;
+- case AF_INET6:
+- sa.sin6.sin6_family = AF_INET6;
+- sa.sin6.sin6_addr = *(struct in6_addr *) src;
+- srcsize = sizeof (sa.sin6);
+- break;
+- default:
+- abort ();
+- }
+-
+- if (WSAAddressToString ((struct sockaddr *) &sa, srcsize, NULL, dst, &dstlen) != 0)
+- {
+- errno = WSAGetLastError();
+- return NULL;
+- }
+- return (const char *) dst;
+-}
+-
+-int
+-wpurple_inet_pton(int af, const char *src, void *dst)
+-{
+- /* struct sockaddr can't accomodate struct sockaddr_in6. */
+- union {
+- struct sockaddr_in6 sin6;
+- struct sockaddr_in sin;
+- } sa;
+- size_t srcsize;
+-
+- switch(af)
+- {
+- case AF_INET:
+- sa.sin.sin_family = AF_INET;
+- srcsize = sizeof (sa.sin);
+- break;
+- case AF_INET6:
+- sa.sin6.sin6_family = AF_INET6;
+- srcsize = sizeof (sa.sin6);
+- break;
+- default:
+- errno = WSAEPFNOSUPPORT;
+- return -1;
+- }
+-
+- if (WSAStringToAddress(src, af, NULL, (struct sockaddr *) &sa, &srcsize) != 0)
+- {
+- errno = WSAGetLastError();
+- return -1;
+- }
+-
+- switch(af)
+- {
+- case AF_INET:
+- memcpy(dst, &sa.sin.sin_addr, sizeof(sa.sin.sin_addr));
+- break;
+- case AF_INET6:
+- memcpy(dst, &sa.sin6.sin6_addr, sizeof(sa.sin6.sin6_addr));
+- break;
+- }
+-
+- return 1;
+-}
+-
+-
+-/* netdb.h */
+-struct hostent* wpurple_gethostbyname(const char *name) {
+- struct hostent *hp;
+-
+- if((hp = gethostbyname(name)) == NULL) {
+- errno = WSAGetLastError();
+- return NULL;
+- }
+- return hp;
+-}
+-
+-/* string.h */
+-char* wpurple_strerror(int errornum) {
+- if (errornum > WSABASEERR) {
+- switch(errornum) {
+- case WSAECONNABORTED: /* 10053 */
+- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection interrupted by other software on your computer."));
+- break;
+- case WSAECONNRESET: /* 10054 */
+- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Remote host closed connection."));
+- break;
+- case WSAETIMEDOUT: /* 10060 */
+- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection timed out."));
+- break;
+- case WSAECONNREFUSED: /* 10061 */
+- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Connection refused."));
+- break;
+- case WSAEADDRINUSE: /* 10048 */
+- g_snprintf(errbuf, sizeof(errbuf), "%s", _("Address already in use."));
+- break;
+- default:
+- g_snprintf(errbuf, sizeof(errbuf), "Windows socket error #%d", errornum);
+- }
+- } else {
+- const char *tmp = g_strerror(errornum);
+- g_snprintf(errbuf, sizeof(errbuf), "%s", tmp);
+- }
+- return errbuf;
+-}
+-
+-/* unistd.h */
+-
+-/*
+- * We need to figure out whether fd is a file or socket handle.
+- */
+-int wpurple_read(int fd, void *buf, unsigned int size) {
+- int ret;
+-
+- if (fd < 0) {
+- errno = EBADF;
+- g_return_val_if_reached(-1);
+- }
+-
+- if(wpurple_is_socket(fd)) {
+- if((ret = recv(fd, buf, size, 0)) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
+- errno = EAGAIN;
+- return -1;
+- }
+-#if 0
+- else if( ret == 0 ) {
+- /* connection has been gracefully closed */
+- errno = WSAENOTCONN;
+- return -1;
+- }
+-#endif
+- else {
+- /* success reading socket */
+- return ret;
+- }
+- } else {
+- /* fd is not a socket handle.. pass it off to read */
+- return _read(fd, buf, size);
+- }
+-}
+-
+-int wpurple_send(int fd, const void *buf, unsigned int size, int flags) {
+- int ret;
+-
+- ret = send(fd, buf, size, flags);
+-
+- if (ret == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
+- errno = EAGAIN;
+- return -1;
+- }
+- return ret;
+-}
+-
+-int wpurple_write(int fd, const void *buf, unsigned int size) {
+-
+- if (fd < 0) {
+- errno = EBADF;
+- g_return_val_if_reached(-1);
+- }
+-
+- if(wpurple_is_socket(fd))
+- return wpurple_send(fd, buf, size, 0);
+- else
+- return _write(fd, buf, size);
+-}
+-
+-int wpurple_recv(int fd, void *buf, size_t len, int flags) {
+- int ret;
+-
+- if((ret = recv(fd, buf, len, flags)) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- if(errno == WSAEWOULDBLOCK || errno == WSAEINPROGRESS)
+- errno = EAGAIN;
+- return -1;
+- } else {
+- return ret;
+- }
+-}
+-
+-int wpurple_close(int fd) {
+- int ret;
+-
+- if (fd < 0) {
+- errno = EBADF;
+- g_return_val_if_reached(-1);
+- }
+-
+- if( wpurple_is_socket(fd) ) {
+- if( (ret = closesocket(fd)) == SOCKET_ERROR ) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- else
+- return 0;
+- }
+- else
+- return _close(fd);
+-}
+-
+-int wpurple_gethostname(char *name, size_t size) {
+- if(gethostname(name, size) == SOCKET_ERROR) {
+- errno = WSAGetLastError();
+- return -1;
+- }
+- return 0;
+-}
+-
+-/* sys/time.h */
+-
+-int wpurple_gettimeofday(struct timeval *p, struct timezone *z) {
+- int res = 0;
+- struct _timeb timebuffer;
+-
+- if (z != 0) {
+- _tzset();
+- z->tz_minuteswest = _timezone/60;
+- z->tz_dsttime = _daylight;
+- }
+-
+- if (p != 0) {
+- _ftime(&timebuffer);
+- p->tv_sec = timebuffer.time; /* seconds since 1-1-1970 */
+- p->tv_usec = timebuffer.millitm*1000; /* microseconds */
+- }
+-
+- return res;
+-}
+-
+-/* stdio.h */
+-
+-int wpurple_rename (const char *oldname, const char *newname) {
+- return g_rename(oldname, newname);
+-}
+-
+-/* time.h */
+-
+-struct tm * wpurple_localtime_r (const time_t *time, struct tm *resultp) {
+- struct tm* tmptm;
+-
+- if(!time)
+- return NULL;
+- tmptm = localtime(time);
+- if(resultp && tmptm)
+- return memcpy(resultp, tmptm, sizeof(struct tm));
+- else
+- return NULL;
+-}
+-
+-/*
+- * Used by purple_utf8_strftime() by way of purple_internal_strftime()
+- * in src/util.c
+- *
+- * Code derived from PostgreSQL src/timezone/pgtz.c:
+- * http://developer.postgresql.org/cvsweb.cgi/pgsql/src/timezone/pgtz.c
+- */
+-
+-/*
+-PostgreSQL Database Management System
+-(formerly known as Postgres, then as Postgres95)
+-
+-Portions Copyright (c) 1996-2005, PostgreSQL Global Development Group
+-
+-Portions Copyright (c) 1994, The Regents of the University of California
+-
+-Permission to use, copy, modify, and distribute this software and its
+-documentation for any purpose, without fee, and without a written agreement
+-is hereby granted, provided that the above copyright notice and this
+-paragraph and the following two paragraphs appear in all copies.
+-
+-IN NO EVENT SHALL THE UNIVERSITY OF CALIFORNIA BE LIABLE TO ANY PARTY FOR
+-DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING
+-LOST PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS
+-DOCUMENTATION, EVEN IF THE UNIVERSITY OF CALIFORNIA HAS BEEN ADVISED OF THE
+-POSSIBILITY OF SUCH DAMAGE.
+-
+-THE UNIVERSITY OF CALIFORNIA SPECIFICALLY DISCLAIMS ANY WARRANTIES,
+-INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+-AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
+-ON AN "AS IS" BASIS, AND THE UNIVERSITY OF CALIFORNIA HAS NO OBLIGATIONS TO
+-PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS.
+-
+-*/
+-static struct
+-{
+- char *wstd; /* Windows name of standard timezone */
+- char *wdst; /* Windows name of daylight timezone */
+- char *ustd; /* Unix name of standard timezone */
+- char *udst; /* Unix name of daylight timezone */
+-} win32_tzmap[] =
+-{
+- {
+- "", "",
+- "", "",
+- },
+- /*
+- * This list was built from the contents of the registry at
+- * "HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Time Zones"
+- * on Windows XP Professional SP1
+- */
+- {
+- "Afghanistan Standard Time", "Afghanistan Daylight Time",
+- "AFT", "AFT"
+- },
+- {
+- "Alaskan Standard Time", "Alaskan Daylight Time",
+- "AKST", "AKDT"
+- },
+- {
+- "Arab Standard Time", "Arab Daylight Time",
+- "AST", "AST"
+- },
+- {
+- "Arabian Standard Time", "Arabian Daylight Time",
+- "GST", "GST"
+- },
+- {
+- "Arabic Standard Time", "Arabic Daylight Time",
+- "AST", "ADT"
+- },
+- {
+- "Atlantic Standard Time", "Atlantic Daylight Time",
+- "AST", "ADT"
+- },
+- {
+- "AUS Central Standard Time", "AUS Central Daylight Time",
+- "CST", "CST"
+- },
+- {
+- "AUS Eastern Standard Time", "AUS Eastern Daylight Time",
+- "EST", "EST"
+- },
+- {
+- "Azores Standard Time", "Azores Daylight Time",
+- "AZOT", "AZOST"
+- },
+- {
+- "Canada Central Standard Time", "Canada Central Daylight Time",
+- "CST", "MDT"
+- },
+- {
+- "Cape Verde Standard Time", "Cape Verde Daylight Time",
+- "CVT", "CVST"
+- },
+- {
+- "Caucasus Standard Time", "Caucasus Daylight Time",
+- "AZT", "AZST"
+- },
+- {
+- "Cen. Australia Standard Time", "Cen. Australia Daylight Time",
+- "CST", "CST"
+- },
+- {
+- "Central America Standard Time", "Central America Daylight Time",
+- "CST", "CDT"
+- },
+- {
+- "Central Asia Standard Time", "Central Asia Daylight Time",
+- "BDT", "BDT"
+- },
+- {
+- "Central Europe Standard Time", "Central Europe Daylight Time",
+- "CET", "CEST"
+- },
+- {
+- "Central European Standard Time", "Central European Daylight Time",
+- "CET", "CEST"
+- },
+- {
+- "Central Pacific Standard Time", "Central Pacific Daylight Time",
+- "NCT", "NCST"
+- },
+- {
+- "Central Standard Time", "Central Daylight Time",
+- "CST", "CDT"
+- },
+- {
+- "China Standard Time", "China Daylight Time",
+- "HKT", "HKST"
+- },
+- {
+- "Dateline Standard Time", "Dateline Daylight Time",
+- "GMT+12", "GMT+12"
+- },
+- {
+- "E. Africa Standard Time", "E. Africa Daylight Time",
+- "EAT", "EAT"
+- },
+- {
+- "E. Australia Standard Time", "E. Australia Daylight Time",
+- "EST", "EST"
+- },
+- {
+- "E. Europe Standard Time", "E. Europe Daylight Time",
+- "EET", "EEST"
+- },
+- {
+- "E. South America Standard Time", "E. South America Daylight Time",
+- "BRT", "BRST"
+- },
+- {
+- "Eastern Standard Time", "Eastern Daylight Time",
+- "EST", "EDT"
+- },
+- {
+- "Egypt Standard Time", "Egypt Daylight Time",
+- "EET", "EEST"
+- },
+- {
+- "Ekaterinburg Standard Time", "Ekaterinburg Daylight Time",
+- "YEKT", "YEKST"
+- },
+- {
+- "Fiji Standard Time", "Fiji Daylight Time",
+- "FJT", "FJST"
+- },
+- {
+- "FLE Standard Time", "FLE Daylight Time",
+- "EET", "EEST"
+- },
+- {
+- "GMT Standard Time", "GMT Daylight Time",
+- "GMT", "IST"
+- },
+- {
+- "Greenland Standard Time", "Greenland Daylight Time",
+- "WGT", "WGST"
+- },
+- {
+- "Greenwich Standard Time", "Greenwich Daylight Time",
+- "WET", "WEST"
+- },
+- {
+- "GTB Standard Time", "GTB Daylight Time",
+- "EET", "EEST"
+- },
+- {
+- "Hawaiian Standard Time", "Hawaiian Daylight Time",
+- "HST", "HPT"
+- },
+- {
+- "India Standard Time", "India Daylight Time",
+- "IST", "IST"
+- },
+- {
+- "Iran Standard Time", "Iran Daylight Time",
+- "IRST", "IRDT"
+- },
+- {
+- "Jerusalem Standard Time", "Jerusalem Daylight Time",
+- "IST", "IDT"
+- },
+- {
+- "Korea Standard Time", "Korea Daylight Time",
+- "KST", "KDT"
+- },
+- {
+- "Mexico Standard Time", "Mexico Daylight Time",
+- "CST", "CDT"
+- },
+- {
+- "Mexico Standard Time", "Mexico Daylight Time",
+- "BOT", "BOST"
+- },
+- {
+- "Mid-Atlantic Standard Time", "Mid-Atlantic Daylight Time",
+- "GST", "GST"
+- },
+- {
+- "Mountain Standard Time", "Mountain Daylight Time",
+- "MST", "MDT"
+- },
+- {
+- "Myanmar Standard Time", "Myanmar Daylight Time",
+- "MMT", "MMT"
+- },
+- {
+- "N. Central Asia Standard Time", "N. Central Asia Daylight Time",
+- "ALMT", "ALMST"
+- },
+- {
+- "Nepal Standard Time", "Nepal Daylight Time",
+- "NPT", "NPT"
+- },
+- {
+- "New Zealand Standard Time", "New Zealand Daylight Time",
+- "NZST", "NZDT"
+- },
+- {
+- "Newfoundland Standard Time", "Newfoundland Daylight Time",
+- "NST", "NDT"
+- },
+- {
+- "North Asia East Standard Time", "North Asia East Daylight Time",
+- "IRKT", "IRKST"
+- },
+- {
+- "North Asia Standard Time", "North Asia Daylight Time",
+- "KRAT", "KRAST"
+- },
+- {
+- "Pacific SA Standard Time", "Pacific SA Daylight Time",
+- "CLT", "CLST"
+- },
+- {
+- "Pacific Standard Time", "Pacific Daylight Time",
+- "PST", "PDT"
+- },
+- {
+- "Romance Standard Time", "Romance Daylight Time",
+- "CET", "CEST"
+- },
+- {
+- "Russian Standard Time", "Russian Daylight Time",
+- "MSK", "MSD"
+- },
+- {
+- "SA Eastern Standard Time", "SA Eastern Daylight Time",
+- "ART", "ARST"
+- },
+- {
+- "SA Pacific Standard Time", "SA Pacific Daylight Time",
+- "COT", "COST"
+- },
+- {
+- "SA Western Standard Time", "SA Western Daylight Time",
+- "VET", "VET"
+- },
+- {
+- "Samoa Standard Time", "Samoa Daylight Time",
+- "SST", "NDT"
+- },
+- {
+- "SE Asia Standard Time", "SE Asia Daylight Time",
+- "ICT", "ICT"
+- },
+- {
+- "Malay Peninsula Standard Time", "Malay Peninsula Daylight Time",
+- "MYT", "MALST"
+- },
+- {
+- "South Africa Standard Time", "South Africa Daylight Time",
+- "CAT", "CAT"
+- },
+- {
+- "Sri Lanka Standard Time", "Sri Lanka Daylight Time",
+- "LKT", "IST"
+- },
+- {
+- "Taipei Standard Time", "Taipei Daylight Time",
+- "CST", "CDT"
+- },
+- {
+- "Tasmania Standard Time", "Tasmania Daylight Time",
+- "EST", "EST"
+- },
+- {
+- "Tokyo Standard Time", "Tokyo Daylight Time",
+- "JST", "JDT"
+- },
+- {
+- "Tonga Standard Time", "Tonga Daylight Time",
+- "TOT", "TOST"
+- },
+- {
+- "US Eastern Standard Time", "US Eastern Daylight Time",
+- "EST", "EDT"
+- },
+- {
+- "US Mountain Standard Time", "US Mountain Daylight Time",
+- "MST", "MDT"
+- },
+- {
+- "Vladivostok Standard Time", "Vladivostok Daylight Time",
+- "VLAT", "VLAST"
+- },
+- {
+- "W. Australia Standard Time", "W. Australia Daylight Time",
+- "WST", "WST"
+- },
+-
+- /* Not mapped in PostgreSQL.
+- *
+- * I mapped this based on the following information... -- rlaager
+- * $ cd /usr/share/zoneinfo/Africa
+- * $ for i in * ; do echo `TZ=Africa/$i date +"%z %Z"` $i ; done | grep +0100
+- * +0100 CET Algiers
+- * +0100 WAT Bangui
+- * +0100 WAT Brazzaville
+- * +0100 CET Ceuta
+- * +0100 WAT Douala
+- * +0100 WAT Kinshasa
+- * +0100 WAT Lagos
+- * +0100 WAT Libreville
+- * +0100 WAT Luanda
+- * +0100 WAT Malabo
+- * +0100 WAT Ndjamena
+- * +0100 WAT Niamey
+- * +0100 WAT Porto-Novo
+- * +0100 CET Tunis
+- **/
+- {
+- "W. Central Africa Standard Time", "W. Central Africa Daylight Time",
+- "WAT", "WAT"
+- },
+-
+- {
+- "W. Europe Standard Time", "W. Europe Daylight Time",
+- "CET", "CEST"
+- },
+- {
+- "West Asia Standard Time", "West Asia Daylight Time",
+- "PKT", "PKST"
+- },
+- {
+- "West Pacific Standard Time", "West Pacific Daylight Time",
+- "ChST", "ChST"
+- },
+- {
+- "Yakutsk Standard Time", "Yakutsk Daylight Time",
+- "YAKT", "YAKST"
+- },
+- {
+- NULL, NULL,
+- NULL, NULL
+- }
+-};
+-
+-const char *
+-wpurple_get_timezone_abbreviation(const struct tm *tm)
+-{
+- int i;
+- char tzname[128];
+- char localtzname[256];
+- HKEY rootKey;
+- int idx;
+-
+- if (!tm)
+- {
+- purple_debug_warning("wpurple", "could not determine current date/time: localtime failed\n");
+- return "";
+- }
+-
+- if (strftime(tzname, sizeof(tzname) - 1, "%Z", tm) == 0)
+- {
+- purple_debug_error("wpurple", "timezone name is too long for the buffer\n");
+- return "";
+- }
+-
+- for (i = 0; win32_tzmap[i].wstd != NULL; i++)
+- {
+- if (strcmp(tzname, win32_tzmap[i].wstd) == 0)
+- {
+-#if 0
+- purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
+- win32_tzmap[i].ustd, tzname);
+-#endif
+- /* Cache the Result */
+- if (i > 0) {
+- if (win32_tzmap[0].wstd[0] != '\0')
+- g_free(win32_tzmap[0].wstd);
+- win32_tzmap[0].wstd = g_strdup(tzname);
+- win32_tzmap[0].ustd = win32_tzmap[i].ustd;
+- }
+-
+- return win32_tzmap[i].ustd;
+- }
+- if (strcmp(tzname, win32_tzmap[i].wdst) == 0)
+- {
+-#if 0
+- purple_debug_info("wpurple", "TZ \"%s\" matches Windows timezone \"%s\"\n",
+- win32_tzmap[i].udst, tzname);
+-#endif
+- /* Cache the Result */
+- if (i > 0) {
+- if (win32_tzmap[0].wdst[0] != '\0')
+- g_free(win32_tzmap[0].wdst);
+- win32_tzmap[0].wdst = g_strdup(tzname);
+- win32_tzmap[0].udst = win32_tzmap[i].udst;
+- }
+-
+- return win32_tzmap[i].udst;
+- }
+- }
+-
+- /*
+- * Localized Windows versions return localized names for the timezone.
+- * Scan the registry to find the English name, and then try matching
+- * against our table again.
+- */
+- memset(localtzname, 0, sizeof(localtzname));
+- if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+- "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones",
+- 0,
+- KEY_READ,
+- &rootKey) != ERROR_SUCCESS)
+- {
+- purple_debug_warning("wpurple", "could not open registry key to identify Windows timezone: %i\n", (int) GetLastError());
+- return "";
+- }
+-
+- for (idx = 0;; idx++)
+- {
+- char keyname[256];
+- char zonename[256];
+- DWORD namesize;
+- FILETIME lastwrite;
+- HKEY key;
+- LONG r;
+-
+- memset(keyname, 0, sizeof(keyname));
+- namesize = sizeof(keyname);
+- if ((r = RegEnumKeyEx(rootKey,
+- idx,
+- keyname,
+- &namesize,
+- NULL,
+- NULL,
+- NULL,
+- &lastwrite)) != ERROR_SUCCESS)
+- {
+- if (r == ERROR_NO_MORE_ITEMS)
+- break;
+- purple_debug_warning("wpurple", "could not enumerate registry subkeys to identify Windows timezone: %i\n", (int) r);
+- break;
+- }
+-
+- if ((r = RegOpenKeyEx(rootKey, keyname, 0, KEY_READ, &key)) != ERROR_SUCCESS)
+- {
+- purple_debug_warning("wpurple", "could not open registry subkey to identify Windows timezone: %i\n", (int) r);
+- break;
+- }
+-
+- memset(zonename, 0, sizeof(zonename));
+- namesize = sizeof(zonename);
+- if ((r = RegQueryValueEx(key, "Std", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
+- {
+- purple_debug_warning("wpurple", "could not query value for 'std' to identify Windows timezone: %i\n", (int) r);
+- RegCloseKey(key);
+- break;
+- }
+- if (strcmp(tzname, zonename) == 0)
+- {
+- /* Matched zone */
+- g_strlcpy(localtzname, keyname, sizeof(localtzname));
+- RegCloseKey(key);
+- break;
+- }
+- memset(zonename, 0, sizeof(zonename));
+- namesize = sizeof(zonename);
+- if ((r = RegQueryValueEx(key, "Dlt", NULL, NULL, (LPBYTE)zonename, &namesize)) != ERROR_SUCCESS)
+- {
+- purple_debug_warning("wpurple", "could not query value for 'dlt' to identify Windows timezone: %i\n", (int) r);
+- RegCloseKey(key);
+- break;
+- }
+- if (strcmp(tzname, zonename) == 0)
+- {
+- /* Matched DST zone */
+- g_strlcpy(localtzname, keyname, sizeof(localtzname));
+- RegCloseKey(key);
+- break;
+- }
+-
+- RegCloseKey(key);
+- }
+-
+- RegCloseKey(rootKey);
+-
+- if (localtzname[0])
+- {
+- /* Found a localized name, so scan for that one too */
+- for (i = 0; win32_tzmap[i].wstd != NULL; i++)
+- {
+- if (strcmp(localtzname, win32_tzmap[i].wstd) == 0)
+- {
+-#if 0
+- purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
+- win32_tzmap[i].ustd, tzname, localtzname);
+-#endif
+- /* Cache the Result */
+- if (win32_tzmap[0].wstd[0] != '\0')
+- g_free(win32_tzmap[0].wstd);
+- win32_tzmap[0].wstd = g_strdup(tzname);
+- win32_tzmap[0].ustd = win32_tzmap[i].ustd;
+-
+- return win32_tzmap[i].ustd;
+- }
+- if (strcmp(localtzname, win32_tzmap[i].wdst) == 0)
+- {
+-#if 0
+- purple_debug_info("wpurple", "TZ \"%s\" matches localized Windows timezone \"%s\" (\"%s\")\n",
+- win32_tzmap[i].udst, tzname, localtzname);
+-#endif
+- /* Cache the Result */
+- if (win32_tzmap[0].wdst[0] != '\0')
+- g_free(win32_tzmap[0].wdst);
+-
+- win32_tzmap[0].wdst = g_strdup(tzname);
+- win32_tzmap[0].udst = win32_tzmap[i].udst;
+-
+- return win32_tzmap[i].udst;
+- }
+- }
+- }
+-
+- purple_debug_warning("wpurple", "could not find a match for Windows timezone \"%s\"\n", tzname);
+- return "";
+-}
+-
+-int wpurple_g_access (const gchar *filename, int mode);
+-/**
+- * @deprecated - remove for 3.0.0
+- */
+-int
+-wpurple_g_access (const gchar *filename, int mode)
+-{
+- return g_access(filename, mode);
+-}
+-
+-
+diff -Nur pidgin-2.10.7/libpurple/win32/libc_interface.h pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.h
+--- pidgin-2.10.7/libpurple/win32/libc_interface.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/libc_interface.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,154 +0,0 @@
+-/*
+- * purple
+- *
+- * File: libc_interface.h
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _LIBC_INTERFACE_H_
+-#define _LIBC_INTERFACE_H_
+-#include <winsock2.h>
+-#include <ws2tcpip.h>
+-#include <io.h>
+-#include <errno.h>
+-#include "libc_internal.h"
+-#include <glib.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-#ifdef _MSC_VER
+-#define S_IRUSR S_IREAD
+-#define S_IWUSR S_IWRITE
+-#define S_IXUSR S_IEXEC
+-
+-#define S_ISDIR(m) (((m)&S_IFDIR)==S_IFDIR)
+-
+-#define F_OK 0
+-#endif
+-
+-/* sys/socket.h */
+-#define socket( domain, style, protocol ) \
+-wpurple_socket( domain, style, protocol )
+-
+-#define connect( socket, addr, length ) \
+-wpurple_connect( socket, addr, length )
+-
+-#define getsockopt( socket, level, optname, optval, optlenptr ) \
+-wpurple_getsockopt( socket, level, optname, optval, optlenptr )
+-
+-#define setsockopt( socket, level, optname, optval, optlen ) \
+-wpurple_setsockopt( socket, level, optname, optval, optlen )
+-
+-#define getsockname( socket, addr, lenptr ) \
+-wpurple_getsockname( socket, addr, lenptr )
+-
+-#define bind( socket, addr, length ) \
+-wpurple_bind( socket, addr, length )
+-
+-#define listen( socket, n ) \
+-wpurple_listen( socket, n )
+-
+-#define sendto(socket, buf, len, flags, to, tolen) \
+-wpurple_sendto(socket, buf, len, flags, to, tolen)
+-
+-#define recv(fd, buf, len, flags) \
+-wpurple_recv(fd, buf, len, flags)
+-
+-#define send(socket, buf, buflen, flags) \
+-wpurple_send(socket, buf, buflen, flags)
+-
+-/* sys/ioctl.h */
+-#define ioctl( fd, command, val ) \
+-wpurple_ioctl( fd, command, val )
+-
+-/* fcntl.h */
+-#define fcntl( fd, command, ... ) \
+-wpurple_fcntl( fd, command, ##__VA_ARGS__ )
+-
+-/* arpa/inet.h */
+-#define inet_aton( name, addr ) \
+-wpurple_inet_aton( name, addr )
+-
+-#define inet_ntop( af, src, dst, cnt ) \
+-wpurple_inet_ntop( af, src, dst, cnt )
+-
+-#define inet_pton( af, src, dst ) \
+-wpurple_inet_pton( af, src, dst )
+-
+-/* netdb.h */
+-#define gethostbyname( name ) \
+-wpurple_gethostbyname( name )
+-
+-/* netinet/in.h */
+-#define ntohl( netlong ) \
+-(unsigned int)ntohl( netlong )
+-
+-/* string.h */
+-#define hstrerror( herror ) \
+-wpurple_strerror( errno )
+-#define strerror( errornum ) \
+-wpurple_strerror( errornum )
+-#define g_strerror( errornum ) \
+-wpurple_strerror( errornum )
+-
+-/* unistd.h */
+-#define read( fd, buf, buflen ) \
+-wpurple_read( fd, buf, buflen )
+-
+-#define write( socket, buf, buflen ) \
+-wpurple_write( socket, buf, buflen )
+-
+-#define close( fd ) \
+-wpurple_close( fd )
+-
+-#ifndef sleep
+-#define sleep(x) Sleep((x)*1000)
+-#endif
+-
+-#define gethostname( name, size ) \
+-wpurple_gethostname( name, size )
+-
+-#define fsync(fd) _commit(fd)
+-
+-/* sys/time.h */
+-#define gettimeofday( timeval, timezone ) \
+-wpurple_gettimeofday( timeval, timezone )
+-
+-/* stdio.h */
+-#undef snprintf
+-#define snprintf _snprintf
+-#undef vsnprintf
+-#define vsnprintf _vsnprintf
+-
+-#define rename( oldname, newname ) \
+-wpurple_rename( oldname, newname )
+-
+-/* sys/stat.h */
+-#define fchmod(a,b)
+-
+-/* time.h */
+-#define localtime_r( time, resultp ) \
+-wpurple_localtime_r( time, resultp )
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* _LIBC_INTERFACE_H_ */
+diff -Nur pidgin-2.10.7/libpurple/win32/libc_internal.h pidgin-2.10.7-nonprism/libpurple/win32/libc_internal.h
+--- pidgin-2.10.7/libpurple/win32/libc_internal.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/libc_internal.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,152 +0,0 @@
+-/*
+- * purple
+- *
+- * File: libc_internal.h
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _LIBC_INTERNAL_
+-#define _LIBC_INTERNAL_
+-#include <glib.h>
+-
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* helper for purple_utf8_strftime() by way of purple_internal_strftime() in src/util.c */
+-const char *wpurple_get_timezone_abbreviation(const struct tm *tm);
+-
+-/* sys/socket.h */
+-int wpurple_socket(int domain, int style, int protocol);
+-int wpurple_connect(int socket, struct sockaddr *addr, u_long length);
+-int wpurple_getsockopt(int socket, int level, int optname, void *optval, socklen_t *optlenptr);
+-int wpurple_setsockopt(int socket, int level, int optname, const void *optval, socklen_t optlen);
+-int wpurple_getsockname (int socket, struct sockaddr *addr, socklen_t *lenptr);
+-int wpurple_bind(int socket, struct sockaddr *addr, socklen_t length);
+-int wpurple_listen(int socket, unsigned int n);
+-int wpurple_sendto(int socket, const void *buf, size_t len, int flags, const struct sockaddr *to, socklen_t tolen);
+-int wpurple_recv(int fd, void *buf, size_t len, int flags);
+-int wpurple_send(int fd, const void *buf, unsigned int size, int flags);
+-
+-/* arpa/inet.h */
+-int wpurple_inet_aton(const char *name, struct in_addr *addr);
+-const char *
+-wpurple_inet_ntop (int af, const void *src, char *dst, socklen_t cnt);
+-int wpurple_inet_pton(int af, const char *src, void *dst);
+-
+-/* netdb.h */
+-struct hostent* wpurple_gethostbyname(const char *name);
+-
+-/* string.h */
+-char* wpurple_strerror( int errornum );
+-
+-/* fcntl.h */
+-int wpurple_fcntl(int socket, int command, ...);
+-#define F_GETFL 3
+-#define F_SETFL 4
+-#define O_NONBLOCK 04000
+-
+-/* sys/ioctl.h */
+-#define SIOCGIFCONF 0x8912 /* get iface list */
+-int wpurple_ioctl(int fd, int command, void* opt);
+-
+-/* net/if.h */
+-struct ifreq
+-{
+- union
+- {
+- char ifrn_name[6]; /* Interface name, e.g. "en0". */
+- } ifr_ifrn;
+-
+- union
+- {
+- struct sockaddr ifru_addr;
+-#if 0
+- struct sockaddr ifru_dstaddr;
+- struct sockaddr ifru_broadaddr;
+- struct sockaddr ifru_netmask;
+- struct sockaddr ifru_hwaddr;
+- short int ifru_flags;
+- int ifru_ivalue;
+- int ifru_mtu;
+-#endif
+- char *ifru_data;
+- } ifr_ifru;
+-};
+-# define ifr_name ifr_ifrn.ifrn_name /* interface name */
+-# define ifr_addr ifr_ifru.ifru_addr /* address */
+-#if 0
+-# define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
+-# define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
+-# define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
+-# define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
+-# define ifr_flags ifr_ifru.ifru_flags /* flags */
+-# define ifr_metric ifr_ifru.ifru_ivalue /* metric */
+-# define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
+-#endif
+-# define ifr_data ifr_ifru.ifru_data /* for use by interface */
+-#if 0
+-# define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
+-# define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
+-# define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
+-#endif
+-
+-
+-struct ifconf
+-{
+- int ifc_len; /* Size of buffer. */
+- union
+- {
+- char *ifcu_buf;
+- struct ifreq *ifcu_req;
+- } ifc_ifcu;
+-};
+-# define ifc_buf ifc_ifcu.ifcu_buf /* Buffer address. */
+-# define ifc_req ifc_ifcu.ifcu_req /* Array of structures. */
+-
+-/* sys/time.h */
+-#if __MINGW32_MAJOR_VERSION < 3 || (__MINGW32_MAJOR_VERSION == 3 && __MINGW32_MINOR_VERSION < 10)
+-struct timezone {
+- int tz_minuteswest;
+- int tz_dsttime;
+-};
+-#else
+-# include <sys/time.h>
+-#endif
+-int wpurple_gettimeofday(struct timeval *p, struct timezone *z);
+-
+-/* time.h */
+-struct tm *wpurple_localtime_r(const time_t *time, struct tm *resultp);
+-
+-
+-/* unistd.h */
+-int wpurple_read(int fd, void *buf, unsigned int size);
+-int wpurple_write(int fd, const void *buf, unsigned int size);
+-int wpurple_close(int fd);
+-int wpurple_gethostname(char *name, size_t size);
+-
+-
+-/* stdio.h */
+-int wpurple_rename(const char *oldname, const char *newname);
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* _LIBC_INTERNAL_ */
+diff -Nur pidgin-2.10.7/libpurple/win32/libpurplerc.rc.in pidgin-2.10.7-nonprism/libpurple/win32/libpurplerc.rc.in
+--- pidgin-2.10.7/libpurple/win32/libpurplerc.rc.in 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/libpurplerc.rc.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,32 +0,0 @@
+-#include <winver.h>
+-#include "version.h"
+-
+-VS_VERSION_INFO VERSIONINFO
+- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- FILEFLAGSMASK 0
+- FILEFLAGS 0
+- FILEOS VOS__WINDOWS32
+- FILETYPE VFT_DLL
+- FILESUBTYPE VFT2_UNKNOWN
+- BEGIN
+- BLOCK "StringFileInfo"
+- BEGIN
+- BLOCK "040904B0"
+- BEGIN
+- VALUE "CompanyName", "The Pidgin developer community"
+- VALUE "FileDescription", "LibPurple Library"
+- VALUE "FileVersion", "@PURPLE_VERSION@"
+- VALUE "InternalName", "libpurple"
+- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
+- VALUE "OriginalFilename", "libpurple.dll"
+- VALUE "ProductName", "LibPurple"
+- VALUE "ProductVersion", "@PURPLE_VERSION@"
+- END
+- END
+- BLOCK "VarFileInfo"
+- BEGIN
+- VALUE "Translation", 0x409, 1200
+- END
+- END
+-
+diff -Nur pidgin-2.10.7/libpurple/win32/rules.mak pidgin-2.10.7-nonprism/libpurple/win32/rules.mak
+--- pidgin-2.10.7/libpurple/win32/rules.mak 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/rules.mak 1969-12-31 21:00:00.000000000 -0300
+@@ -1,13 +0,0 @@
+-# Rules on how to make object files from various sources
+-
+-%.o: %.c
+- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $<
+-
+-%.c: %.xs
+- $(PERL) -MExtUtils::ParseXS -e 'ExtUtils::ParseXS::process_file(filename => "$<", output => "$@", typemap => "$(PURPLE_PERL_TOP)/common/typemap");'
+-
+-%.o: %.rc
+- $(WINDRES) -I$(PURPLE_TOP) -i $< -o $@
+-
+-%.desktop: %.desktop.in $(wildcard $(PIDGIN_TREE_TOP)/po/*.po)
+- LC_ALL=C $(PERL) $(INTLTOOL_MERGE) -d -u -c $(PIDGIN_TREE_TOP)/po/.intltool-merge-cache $(PIDGIN_TREE_TOP)/po $< $@
+diff -Nur pidgin-2.10.7/libpurple/win32/targets.mak pidgin-2.10.7-nonprism/libpurple/win32/targets.mak
+--- pidgin-2.10.7/libpurple/win32/targets.mak 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/targets.mak 1969-12-31 21:00:00.000000000 -0300
+@@ -1,59 +0,0 @@
+-#
+-# targets.mak
+-#
+-# This file should be included at the end of all Makefile.mingw
+-# files for better handling of cross directory dependencies
+-#
+-
+-$(PIDGIN_CONFIG_H): $(PIDGIN_CONFIG_H).mingw $(PIDGIN_TREE_TOP)/configure.ac
+- sed -e 's/@VERSION@/$(PIDGIN_VERSION)/; s/@DISPLAY_VERSION@/$(DISPLAY_VERSION)/' $@.mingw > $@
+-
+-$(PURPLE_PURPLE_H): $(PURPLE_PURPLE_H).in
+- sed -e 's/@PLUGINS_DEFINE@/#define PURPLE_PLUGINS 1/' $@.in > $@
+-
+-$(PURPLE_VERSION_H): $(PURPLE_VERSION_H).in $(PIDGIN_TREE_TOP)/configure.ac
+- awk 'BEGIN {FS="[\\(\\)\\[\\]]"} \
+- /^m4_define..purple_major_version/ {system("sed -e s/@PURPLE_MAJOR_VERSION@/"$$5"/ $@.in > $@");} \
+- /^m4_define..purple_minor_version/ {system("sed -e s/@PURPLE_MINOR_VERSION@/"$$5"/ $@ > $@.tmp && mv $@.tmp $@");} \
+- /^m4_define..purple_micro_version/ {system("sed -e s/@PURPLE_MICRO_VERSION@/"$$5"/ $@ > $@.tmp && mv $@.tmp $@"); exit}' $(PIDGIN_TREE_TOP)/configure.ac
+-
+-$(PIDGIN_REVISION_RAW_TXT):
+- (hg --cwd $(PIDGIN_TREE_TOP) id -i --debug) 2>/dev/null >$@ \
+- || rm -f $@
+-
+-$(PIDGIN_REVISION_H): $(PIDGIN_REVISION_RAW_TXT)
+- if [ -f $< ]; then \
+- sed 's/^\(.\{1,\}\)$$/#define REVISION "\1"/' $< > $@; \
+- fi
+- [ -f $@ ] || echo "#define REVISION \"unknown\"" > $@
+-
+-$(PURPLE_DLL) $(PURPLE_DLL).a: $(PURPLE_VERSION_H)
+- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) libpurple.dll
+-
+-$(PURPLE_PERL_DLL) $(PURPLE_PERL_DLL).a:
+- $(MAKE) -C $(PURPLE_PERL_TOP) -f $(MINGW_MAKEFILE) perl.dll
+-
+-$(PIDGIN_DLL) $(PIDGIN_DLL).a:
+- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) pidgin.dll
+-
+-$(PIDGIN_EXE):
+- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) pidgin.exe
+-
+-# Installation Directories
+-$(PIDGIN_INSTALL_DIR):
+- mkdir -p $(PIDGIN_INSTALL_DIR)
+-
+-$(PIDGIN_INSTALL_PERL_DIR):
+- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
+-
+-$(PIDGIN_INSTALL_PLUGINS_DIR):
+- mkdir -p $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-$(PURPLE_INSTALL_PO_DIR):
+- mkdir -p $(PURPLE_INSTALL_PO_DIR)
+-
+-#$(PURPLE_INSTALL_PLUGINS_DIR):
+-# mkdir -p $(PURPLE_INSTALL_PLUGINS_DIR)
+-
+-#$(PURPLE_INSTALL_PERL_DIR):
+-# mkdir -p $(PURPLE_INSTALL_PERL_DIR)
+diff -Nur pidgin-2.10.7/libpurple/win32/win32dep.c pidgin-2.10.7-nonprism/libpurple/win32/win32dep.c
+--- pidgin-2.10.7/libpurple/win32/win32dep.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/win32dep.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,403 +0,0 @@
+-/*
+- * purple
+- *
+- * File: win32dep.c
+- * Date: June, 2002
+- * Description: Windows dependant code for Purple
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#define _WIN32_IE 0x501
+-#include "internal.h"
+-#include <winuser.h>
+-
+-#include "debug.h"
+-#include "notify.h"
+-
+-/*
+- * LOCALS
+- */
+-static char *app_data_dir = NULL, *install_dir = NULL,
+- *lib_dir = NULL, *locale_dir = NULL;
+-
+-static HINSTANCE libpurpledll_hInstance = NULL;
+-
+-/*
+- * PUBLIC CODE
+- */
+-
+-/* Escape windows dir separators. This is needed when paths are saved,
+- and on being read back have their '\' chars used as an escape char.
+- Returns an allocated string which needs to be freed.
+-*/
+-char *wpurple_escape_dirsep(const char *filename) {
+- int sepcount = 0;
+- const char *tmp = filename;
+- char *ret;
+- int cnt = 0;
+-
+- g_return_val_if_fail(filename != NULL, NULL);
+-
+- while(*tmp) {
+- if(*tmp == '\\')
+- sepcount++;
+- tmp++;
+- }
+- ret = g_malloc0(strlen(filename) + sepcount + 1);
+- while(*filename) {
+- ret[cnt] = *filename;
+- if(*filename == '\\')
+- ret[++cnt] = '\\';
+- filename++;
+- cnt++;
+- }
+- ret[cnt] = '\0';
+- return ret;
+-}
+-
+-/* Determine whether the specified dll contains the specified procedure.
+- If so, load it (if not already loaded). */
+-FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure) {
+- HMODULE hmod;
+- BOOL did_load = FALSE;
+- FARPROC proc = 0;
+-
+- wchar_t *wc_dllname = g_utf8_to_utf16(dllname, -1, NULL, NULL, NULL);
+-
+- if(!(hmod = GetModuleHandleW(wc_dllname))) {
+- purple_debug_warning("wpurple", "%s not already loaded; loading it...\n", dllname);
+- if(!(hmod = LoadLibraryW(wc_dllname))) {
+- purple_debug_error("wpurple", "Could not load: %s (%s)\n", dllname,
+- g_win32_error_message(GetLastError()));
+- g_free(wc_dllname);
+- return NULL;
+- }
+- else
+- did_load = TRUE;
+- }
+-
+- g_free(wc_dllname);
+- wc_dllname = NULL;
+-
+- if((proc = GetProcAddress(hmod, procedure))) {
+- purple_debug_info("wpurple", "This version of %s contains %s\n",
+- dllname, procedure);
+- return proc;
+- }
+- else {
+- purple_debug_warning("wpurple", "Function %s not found in dll %s\n",
+- procedure, dllname);
+- if(did_load) {
+- /* unload dll */
+- FreeLibrary(hmod);
+- }
+- return NULL;
+- }
+-}
+-
+-/* Determine Purple Paths during Runtime */
+-
+-/* Get paths to special Windows folders. */
+-gchar *wpurple_get_special_folder(int folder_type) {
+- gchar *retval = NULL;
+- wchar_t utf_16_dir[MAX_PATH + 1];
+-
+- if (SUCCEEDED(SHGetFolderPathW(NULL, folder_type, NULL,
+- SHGFP_TYPE_CURRENT, utf_16_dir))) {
+- retval = g_utf16_to_utf8(utf_16_dir, -1, NULL, NULL, NULL);
+- }
+-
+- return retval;
+-}
+-
+-const char *wpurple_install_dir(void) {
+- static gboolean initialized = FALSE;
+-
+- if (!initialized) {
+- char *tmp = NULL;
+- wchar_t winstall_dir[MAXPATHLEN];
+- if (GetModuleFileNameW(libpurpledll_hInstance, winstall_dir,
+- MAXPATHLEN) > 0) {
+- tmp = g_utf16_to_utf8(winstall_dir, -1,
+- NULL, NULL, NULL);
+- }
+-
+- if (tmp == NULL) {
+- tmp = g_win32_error_message(GetLastError());
+- purple_debug_error("wpurple",
+- "GetModuleFileName error: %s\n", tmp);
+- g_free(tmp);
+- return NULL;
+- } else {
+- install_dir = g_path_get_dirname(tmp);
+- g_free(tmp);
+- initialized = TRUE;
+- }
+- }
+-
+- return install_dir;
+-}
+-
+-const char *wpurple_lib_dir(void) {
+- static gboolean initialized = FALSE;
+-
+- if (!initialized) {
+- const char *inst_dir = wpurple_install_dir();
+- if (inst_dir != NULL) {
+- lib_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "plugins", inst_dir);
+- initialized = TRUE;
+- } else {
+- return NULL;
+- }
+- }
+-
+- return lib_dir;
+-}
+-
+-const char *wpurple_locale_dir(void) {
+- static gboolean initialized = FALSE;
+-
+- if (!initialized) {
+- const char *inst_dir = wpurple_install_dir();
+- if (inst_dir != NULL) {
+- locale_dir = g_strdup_printf("%s" G_DIR_SEPARATOR_S "locale", inst_dir);
+- initialized = TRUE;
+- } else {
+- return NULL;
+- }
+- }
+-
+- return locale_dir;
+-}
+-
+-const char *wpurple_data_dir(void) {
+-
+- if (!app_data_dir) {
+- /* Set app data dir, used by purple_home_dir */
+- const char *newenv = g_getenv("PURPLEHOME");
+- if (newenv)
+- app_data_dir = g_strdup(newenv);
+- else {
+- app_data_dir = wpurple_get_special_folder(CSIDL_APPDATA);
+- if (!app_data_dir)
+- app_data_dir = g_strdup("C:");
+- }
+- purple_debug_info("wpurple", "Purple settings dir: %s\n",
+- app_data_dir);
+- }
+-
+- return app_data_dir;
+-}
+-
+-/* Miscellaneous */
+-
+-gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname,
+- const char *value) {
+- HKEY reg_key;
+- gboolean success = FALSE;
+-
+- wchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL,
+- NULL, NULL);
+-
+- if(RegOpenKeyExW(rootkey, wc_subkey, 0,
+- KEY_SET_VALUE, &reg_key) == ERROR_SUCCESS) {
+- wchar_t *wc_valname = NULL;
+-
+- if (valname)
+- wc_valname = g_utf8_to_utf16(valname, -1,
+- NULL, NULL, NULL);
+-
+- if(value) {
+- wchar_t *wc_value = g_utf8_to_utf16(value, -1,
+- NULL, NULL, NULL);
+- int len = (wcslen(wc_value) * sizeof(wchar_t)) + 1;
+- if(RegSetValueExW(reg_key, wc_valname, 0, REG_SZ,
+- (LPBYTE)wc_value, len
+- ) == ERROR_SUCCESS)
+- success = TRUE;
+- g_free(wc_value);
+- } else
+- if(RegDeleteValueW(reg_key, wc_valname) == ERROR_SUCCESS)
+- success = TRUE;
+-
+- g_free(wc_valname);
+- }
+- g_free(wc_subkey);
+-
+- if(reg_key != NULL)
+- RegCloseKey(reg_key);
+-
+- return success;
+-}
+-
+-static HKEY _reg_open_key(HKEY rootkey, const char *subkey, REGSAM access) {
+- HKEY reg_key = NULL;
+- LONG rv;
+-
+- wchar_t *wc_subkey = g_utf8_to_utf16(subkey, -1, NULL,
+- NULL, NULL);
+- rv = RegOpenKeyExW(rootkey, wc_subkey, 0, access, &reg_key);
+-
+- g_free(wc_subkey);
+-
+- if (rv != ERROR_SUCCESS) {
+- char *errmsg = g_win32_error_message(rv);
+- purple_debug_error("wpurple", "Could not open reg key '%s' subkey '%s'.\nMessage: (%ld) %s\n",
+- ((rootkey == HKEY_LOCAL_MACHINE) ? "HKLM" :
+- (rootkey == HKEY_CURRENT_USER) ? "HKCU" :
+- (rootkey == HKEY_CLASSES_ROOT) ? "HKCR" : "???"),
+- subkey, rv, errmsg);
+- g_free(errmsg);
+- }
+-
+- return reg_key;
+-}
+-
+-static gboolean _reg_read(HKEY reg_key, const char *valname, LPDWORD type, LPBYTE data, LPDWORD data_len) {
+- LONG rv;
+-
+- wchar_t *wc_valname = NULL;
+- if (valname)
+- wc_valname = g_utf8_to_utf16(valname, -1, NULL, NULL, NULL);
+- rv = RegQueryValueExW(reg_key, wc_valname, 0, type, data, data_len);
+- g_free(wc_valname);
+-
+- if (rv != ERROR_SUCCESS) {
+- char *errmsg = g_win32_error_message(rv);
+- purple_debug_error("wpurple", "Could not read from reg key value '%s'.\nMessage: (%ld) %s\n",
+- valname, rv, errmsg);
+- g_free(errmsg);
+- }
+-
+- return (rv == ERROR_SUCCESS);
+-}
+-
+-gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result) {
+-
+- DWORD type;
+- DWORD nbytes;
+- HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE);
+- gboolean success = FALSE;
+-
+- if(reg_key) {
+- if(_reg_read(reg_key, valname, &type, (LPBYTE)result, &nbytes))
+- success = TRUE;
+- RegCloseKey(reg_key);
+- }
+-
+- return success;
+-}
+-
+-char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname) {
+-
+- DWORD type;
+- DWORD nbytes;
+- HKEY reg_key = _reg_open_key(rootkey, subkey, KEY_QUERY_VALUE);
+- char *result = NULL;
+-
+- if(reg_key) {
+- if(_reg_read(reg_key, valname, &type, NULL, &nbytes) && type == REG_SZ) {
+- LPBYTE data = (LPBYTE) g_new(wchar_t, ((nbytes + 1) / sizeof(wchar_t)) + 1);
+-
+- if(_reg_read(reg_key, valname, &type, data, &nbytes)) {
+- wchar_t *wc_temp = (wchar_t*) data;
+- wc_temp[nbytes / sizeof(wchar_t)] = '\0';
+- result = g_utf16_to_utf8(wc_temp, -1,
+- NULL, NULL, NULL);
+- }
+- g_free(data);
+- }
+- RegCloseKey(reg_key);
+- }
+-
+- return result;
+-}
+-
+-void wpurple_init(void) {
+- WORD wVersionRequested;
+- WSADATA wsaData;
+-
+- if (!g_thread_supported())
+- g_thread_init(NULL);
+-
+- purple_debug_info("wpurple", "wpurple_init start\n");
+- purple_debug_info("wpurple", "libpurple version: " DISPLAY_VERSION "\n");
+-
+- purple_debug_info("wpurple", "Glib:%u.%u.%u\n",
+- glib_major_version, glib_minor_version, glib_micro_version);
+-
+- /* Winsock init */
+- wVersionRequested = MAKEWORD(2, 2);
+- WSAStartup(wVersionRequested, &wsaData);
+-
+- /* Confirm that the winsock DLL supports 2.2 */
+- /* Note that if the DLL supports versions greater than
+- 2.2 in addition to 2.2, it will still return 2.2 in
+- wVersion since that is the version we requested. */
+- if(LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2) {
+- purple_debug_error("wpurple", "Could not find a usable WinSock DLL. Oh well.\n");
+- WSACleanup();
+- }
+-
+- purple_debug_info("wpurple", "wpurple_init end\n");
+-}
+-
+-/* Windows Cleanup */
+-
+-void wpurple_cleanup(void) {
+- purple_debug_info("wpurple", "wpurple_cleanup\n");
+-
+- /* winsock cleanup */
+- WSACleanup();
+-
+- g_free(app_data_dir);
+- g_free(install_dir);
+- g_free(lib_dir);
+- g_free(locale_dir);
+-
+- app_data_dir = NULL;
+- install_dir = NULL;
+- lib_dir = NULL;
+- locale_dir = NULL;
+-
+- libpurpledll_hInstance = NULL;
+-}
+-
+-long
+-wpurple_get_tz_offset() {
+- TIME_ZONE_INFORMATION tzi;
+- DWORD ret;
+- long off = -1;
+-
+- if ((ret = GetTimeZoneInformation(&tzi)) != TIME_ZONE_ID_INVALID)
+- {
+- off = -(tzi.Bias * 60);
+- if (ret == TIME_ZONE_ID_DAYLIGHT)
+- off -= tzi.DaylightBias * 60;
+- }
+-
+- return off;
+-}
+-
+-/* DLL initializer */
+-/* suppress gcc "no previous prototype" warning */
+-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+- libpurpledll_hInstance = hinstDLL;
+- return TRUE;
+-}
+diff -Nur pidgin-2.10.7/libpurple/win32/win32dep.h pidgin-2.10.7-nonprism/libpurple/win32/win32dep.h
+--- pidgin-2.10.7/libpurple/win32/win32dep.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/win32dep.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,92 +0,0 @@
+-/*
+- * purple
+- *
+- * File: win32dep.h
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _WIN32DEP_H_
+-#define _WIN32DEP_H_
+-#include <winsock2.h>
+-#include <windows.h>
+-#include <shlobj.h>
+-#include <process.h>
+-#include "wpurpleerror.h"
+-#include "libc_interface.h"
+-
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-/* the winapi headers don't yet have winhttp.h, so we use the struct from msdn directly */
+-typedef struct {
+- BOOL fAutoDetect;
+- LPWSTR lpszAutoConfigUrl;
+- LPWSTR lpszProxy;
+- LPWSTR lpszProxyBypass;
+-} WINHTTP_CURRENT_USER_IE_PROXY_CONFIG;
+-
+-/* rpcndr.h defines small as char, causing problems, so we need to undefine it */
+-#undef small
+-
+-/*
+- * PROTOS
+- */
+-
+-/**
+- ** win32dep.c
+- **/
+-/* Windows helper functions */
+-FARPROC wpurple_find_and_loadproc(const char *dllname, const char *procedure);
+-gboolean wpurple_read_reg_dword(HKEY rootkey, const char *subkey, const char *valname, LPDWORD result);
+-char *wpurple_read_reg_string(HKEY rootkey, const char *subkey, const char *valname); /* needs to be g_free'd */
+-gboolean wpurple_write_reg_string(HKEY rootkey, const char *subkey, const char *valname, const char *value);
+-char *wpurple_escape_dirsep(const char *filename); /* needs to be g_free'd */
+-GIOChannel *wpurple_g_io_channel_win32_new_socket(int socket); /* Until we get the post-2.8 glib win32 giochannel implementation working, use the thread-based one */
+-
+-/* Determine Purple paths */
+-gchar *wpurple_get_special_folder(int folder_type); /* needs to be g_free'd */
+-const char *wpurple_install_dir(void);
+-const char *wpurple_lib_dir(void);
+-const char *wpurple_locale_dir(void);
+-const char *wpurple_data_dir(void);
+-
+-/* init / cleanup */
+-void wpurple_init(void);
+-void wpurple_cleanup(void);
+-
+-long wpurple_get_tz_offset(void);
+-
+-/*
+- * MACROS
+- */
+-
+-/*
+- * Purple specific
+- */
+-#define DATADIR wpurple_install_dir()
+-#define LIBDIR wpurple_lib_dir()
+-#define LOCALEDIR wpurple_locale_dir()
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* _WIN32DEP_H_ */
+-
+diff -Nur pidgin-2.10.7/libpurple/win32/wpurpleerror.h pidgin-2.10.7-nonprism/libpurple/win32/wpurpleerror.h
+--- pidgin-2.10.7/libpurple/win32/wpurpleerror.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/libpurple/win32/wpurpleerror.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,58 +0,0 @@
+-/*
+- * purple
+- *
+- * File: wpurpleerror.h
+- * Date: October 14, 2002
+- * Description: Convert Winsock errors to Unix errors
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _WPURPLEERROR_H
+-#define _WPURPLEERROR_H
+-
+-/* Here we define unix socket errors as windows socket errors */
+-
+-#define ENETDOWN WSAENETDOWN
+-#define EAFNOSUPPORT WSAEAFNOSUPPORT
+-#define EINPROGRESS WSAEINPROGRESS
+-#define ENOBUFS WSAENOBUFS
+-#define EPROTONOSUPPORT WSAEPROTONOSUPPORT
+-#define EPROTOTYPE WSAEPROTOTYPE
+-#define ESOCKTNOSUPPORT WSAESOCKTNOSUPPORT
+-
+-#define EADDRINUSE WSAEADDRINUSE
+-#define EINPROGRESS WSAEINPROGRESS
+-#define EALREADY WSAEALREADY
+-#define EADDRNOTAVAIL WSAEADDRNOTAVAIL
+-#define ECONNREFUSED WSAECONNREFUSED
+-#define EISCONN WSAEISCONN
+-#define ENETUNREACH WSAENETUNREACH
+-#define ENOTSOCK WSAENOTSOCK
+-#define ETIMEDOUT WSAETIMEDOUT
+-#define EWOULDBLOCK WSAEWOULDBLOCK
+-
+-#define ENOTCONN WSAENOTCONN
+-#define ENETRESET WSAENETRESET
+-#define EOPNOTSUPP WSAEOPNOTSUPP
+-#define ESHUTDOWN WSAESHUTDOWN
+-#define EMSGSIZE WSAEMSGSIZE
+-#define ECONNABORTED WSAECONNABORTED
+-#define ECONNRESET WSAECONNRESET
+-#define EHOSTUNREACH WSAEHOSTUNREACH
+-
+-#endif /* end _WPURPLEERROR_H */
+diff -Nur pidgin-2.10.7/m4macros/Makefile.in pidgin-2.10.7-nonprism/m4macros/Makefile.in
+--- pidgin-2.10.7/m4macros/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/m4macros/Makefile.in 2013-08-17 00:04:19.720029689 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/Makefile.in pidgin-2.10.7-nonprism/Makefile.in
+--- pidgin-2.10.7/Makefile.in 2013-02-11 07:17:25.000000000 -0200
++++ pidgin-2.10.7-nonprism/Makefile.in 2013-08-17 00:05:38.535783624 -0300
+@@ -218,8 +218,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -281,8 +279,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/Makefile.mingw pidgin-2.10.7-nonprism/Makefile.mingw
+--- pidgin-2.10.7/Makefile.mingw 2013-02-11 07:16:50.000000000 -0200
++++ pidgin-2.10.7-nonprism/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,210 +0,0 @@
+-# Makefile.mingw
+-#
+-# Author: hermanator12002@yahoo.com
+-# Date 9/11/02
+-# Description: Top Makefile for win32 (mingw) port of Pidgin and libpurple
+-#
+-
+-PIDGIN_TREE_TOP := .
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-# Generate a X.X.X.X version for the installer file versioning header
+-# The last digit will be 99 for a final release, 0 for dev or unknown, or the beta number
+-PIDGIN_PRODUCT_VERSION = $(shell \
+-awk 'BEGIN {FS="."} { \
+- if (int($$3) == $$3) { \
+- $$4 = "99"; \
+- } else { \
+- $$5 = $$3; \
+- sub(int($$3), "", $$5); \
+- if ($$5 == "dev") { \
+- $$4 = "0"; \
+- } else { \
+- if (sub("beta", "", $$5) > 0) { \
+- $$4 = $$5; \
+- } else { \
+- $$4 = "0"; \
+- } \
+- } \
+- } \
+- printf("%s.%s.%s.%s", $$1, $$2, int($$3), $$4); \
+- exit; \
+-}' VERSION)
+-
+-GTK_INSTALL_VERSION = 2.16.6.1
+-
+-authenticode_sign = $(MONO_SIGNCODE) \
+- -spc "$(SIGNCODE_SPC)" -v "$(SIGNCODE_PVK)" \
+- -a sha1 -$$ commercial \
+- -n "$(2)" -i "https://pidgin.im" \
+- -t "http://timestamp.verisign.com/scripts/timstamp.dll" -tr 10 \
+- $(1)
+-
+-gpg_sign = $(GPG_SIGN) -ab $(1) && $(GPG_SIGN) --verify $(1).asc
+-
+-STRIPPED_RELEASE_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-win32bin
+-DEBUG_SYMBOLS_DIR = $(PIDGIN_TREE_TOP)/pidgin-$(PIDGIN_VERSION)-dbgsym
+-
+-PIDGIN_INST_DEP_DIR="$(WIN32_DEV_TOP)/pidgin-inst-deps-20120910"
+-
+-# Any *.dll or *.exe files included in win32-install-dir that we don't compile
+-# should be included in this list so they don't get stripped
+-EXTERNAL_DLLS = \
+- comerr32.dll \
+- exchndl.dll \
+- freebl3.dll \
+- gssapi32.dll \
+- k5sprt32.dll \
+- krb5_32.dll \
+- libenchant.dll \
+- libenchant_ispell.dll \
+- libenchant_myspell.dll \
+- libgtkspell-0.dll \
+- libmeanwhile-1.dll \
+- libnspr4.dll \
+- libplc4.dll \
+- libplds4.dll \
+- libsasl.dll \
+- libssp-0.dll \
+- libxml2-2.dll \
+- nss3.dll \
+- nssutil3.dll \
+- saslANONYMOUS.dll \
+- saslCRAMMD5.dll \
+- saslDIGESTMD5.dll \
+- saslGSSAPI.dll \
+- saslLOGIN.dll \
+- saslPLAIN.dll \
+- libsilc-1-1-2.dll \
+- libsilcclient-1-1-3.dll \
+- smime3.dll \
+- softokn3.dll \
+- sqlite3.dll \
+- ssl3.dll
+-
+-#build an expression for `find` to use to ignore the above files
+-EXTERNAL_DLLS_FIND_EXP = $(patsubst %,-o -name %,$(EXTERNAL_DLLS))
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-.PHONY: all docs install installer installer_offline installer_zip debug_symbols_zip installers clean uninstall create_release_install_dir generate_installer_includes $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) gtk_runtime_zip
+-
+-all: $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H)
+- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE)
+-ifndef DISABLE_NLS
+- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE)
+-endif
+-
+-install: all $(PIDGIN_INSTALL_DIR)
+- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) install
+-ifndef DISABLE_NLS
+- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) install
+-endif
+- $(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C share/sounds -f $(MINGW_MAKEFILE) install
+- mkdir -p $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
+- cp $(GTKSPELL_TOP)/bin/libgtkspell-0.dll $(PIDGIN_INSTALL_DIR)/spellcheck
+- cp $(ENCHANT_TOP)/bin/libenchant.dll $(PIDGIN_INSTALL_DIR)/spellcheck
+- cp -R $(ENCHANT_TOP)/lib/enchant/*.dll $(PIDGIN_INSTALL_DIR)/spellcheck/lib/enchant
+- cp $(PIDGIN_INST_DEP_DIR)/exchndl.dll $(PIDGIN_INSTALL_DIR)
+- cp $(GCC_SSP_TOP)/bin/libssp-0.dll $(PIDGIN_INSTALL_DIR)
+-
+-gtk_runtime_zip:
+- pidgin/win32/nsis/generate_gtk_zip.sh "`pwd`" "$(GPG_SIGN)"
+-
+-generate_installer_includes: create_release_install_dir gtk_runtime_zip debug_symbols_zip $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop
+- rm -f pidgin/win32/nsis/pidgin-translations.nsh pidgin/win32/nsis/pidgin-spellcheck.nsh pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
+- find $(STRIPPED_RELEASE_DIR)/locale -maxdepth 1 -mindepth 1 \
+- -exec basename {} ';' \
+- | LC_ALL=C sort | sed -e s/^/\!insertmacro\ LANG_SECTION\ \"/ -e s/$$/\"/ \
+- > pidgin/win32/nsis/pidgin-translations.nsh
+- #Convert the available.lst lines to "!insertmacro SPELLCHECK_SECTION lang lang_name lang_file"
+- sed -e "/^#/d" -e "s/^[^,]\{1,\},[^,]\{1,\},/\"/" \
+- -e "s/,/\"\ \"/" -e "s/,/\"\ \"/" -e "s/[\ \t]*$$/\"/" \
+- -e "s/^/\!insertmacro\ SPELLCHECK_SECTION\ /" \
+- pidgin/win32/nsis/available.lst \
+- > pidgin/win32/nsis/pidgin-spellcheck.nsh
+- #Convert the lines to "!insertmacro CHECK_SPELLCHECK_SECTION lang"
+- iconv -f latin1 -t utf-8 pidgin/win32/nsis/pidgin-spellcheck.nsh | \
+- sed -e "s/SPELLCHECK_SECTION/CHECK_SPELLCHECK_SECTION/" \
+- -e "s/ \"[^\"]*\"\ \"[^\"]*\"[\t\ ]*$$//" | \
+- iconv -f utf-8 -t latin1 \
+- > pidgin/win32/nsis/pidgin-spellcheck-preselect.nsh
+- #Generate the Installer translations
+- echo "!define GCOMPRIS_NSIS_INCLUDE_PATH \".\"" > $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
+- echo "@INSERT_TRANSLATIONS@" >> $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh
+- $(PERL) $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/create_nsis_translations.pl \
+- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/nsis_translations.desktop \
+- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/langmacros.nsh \
+- $(PIDGIN_TREE_TOP)/pidgin/win32/nsis/translations
+-
+-create_release_install_dir: install
+- rm -rf $(STRIPPED_RELEASE_DIR)
+- mkdir $(STRIPPED_RELEASE_DIR)
+- tar -cf - $(PIDGIN_INSTALL_DIR) --exclude=Gtk --exclude=spellcheck/share \
+- | tar --strip 2 -xC $(STRIPPED_RELEASE_DIR) -f -
+- find $(STRIPPED_RELEASE_DIR) \( -name '*.dll' -o -name '*.exe' \) \
+- -not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) \
+- -exec $(STRIP) --strip-unneeded {} ';'
+- $(call authenticode_sign, $(STRIPPED_RELEASE_DIR)/pidgin.exe, "Pidgin $(PIDGIN_VERSION)")
+-
+-installer: generate_installer_includes
+- $(eval $@_DEBUG_SYMBOLS_SHA1SUM := $(shell sha1sum $(DEBUG_SYMBOLS_DIR).zip | sed -e "s/\ .*$$//"))
+- $(eval $@_GTK_SHA1SUM := $(shell sha1sum pidgin/win32/nsis/gtk-runtime-$(GTK_INSTALL_VERSION).zip | sed -e "s/\ .*$$//"))
+- $(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
+- -DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
+- -DDEBUG_SYMBOLS_SHA1SUM="$($@_DEBUG_SYMBOLS_SHA1SUM)" -DGTK_SHA1SUM="$($@_GTK_SHA1SUM)"\
+- pidgin/win32/nsis/pidgin-installer.nsi
+- $(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe, "Pidgin Installer")
+- mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION).exe ./
+- $(call gpg_sign, pidgin-$(PIDGIN_VERSION).exe)
+-
+-installer_offline: generate_installer_includes
+- $(MAKENSIS) -V3 -DPIDGIN_VERSION="$(PIDGIN_VERSION)" -DPIDGIN_PRODUCT_VERSION="$(PIDGIN_PRODUCT_VERSION)" \
+- -DPIDGIN_INSTALL_DIR="$(STRIPPED_RELEASE_DIR)" -DGTK_INSTALL_VERSION="$(GTK_INSTALL_VERSION)" \
+- -DOFFLINE_INSTALLER \
+- pidgin/win32/nsis/pidgin-installer.nsi
+- $(call authenticode_sign, pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe, "Pidgin Installer")
+- mv pidgin/win32/nsis/pidgin-$(PIDGIN_VERSION)-offline.exe ./
+- $(call gpg_sign, pidgin-$(PIDGIN_VERSION)-offline.exe)
+-
+-installer_zip: create_release_install_dir
+- rm -f pidgin-$(PIDGIN_VERSION)-win32-bin.zip
+- zip -9 -r pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(STRIPPED_RELEASE_DIR)
+- $(call gpg_sign, pidgin-$(PIDGIN_VERSION)-win32-bin.zip)
+-
+-debug_symbols_zip: install
+- rm -rf $(DEBUG_SYMBOLS_DIR) $(DEBUG_SYMBOLS_DIR).zip
+- mkdir $(DEBUG_SYMBOLS_DIR)
+- tar -cf - `find $(PIDGIN_INSTALL_DIR) \( -name '*.dll' -o -name '*.exe' \) \
+- -not \( -false $(EXTERNAL_DLLS_FIND_EXP) \) -print` \
+- | tar --strip 2 --xform s/$$/.dbgsym/ -xC $(DEBUG_SYMBOLS_DIR) -f -
+- cp $(MEANWHILE_TOP)/bin/libmeanwhile-1.dll.unstripped $(DEBUG_SYMBOLS_DIR)/libmeanwhile-1.dll.dbgsym
+- zip -9 -r $(DEBUG_SYMBOLS_DIR).zip $(DEBUG_SYMBOLS_DIR)
+- $(call gpg_sign, $(DEBUG_SYMBOLS_DIR).zip)
+-
+-installers: installer installer_offline debug_symbols_zip installer_zip
+-
+-Doxyfile.mingw: Doxyfile.in
+- sed -e "s/@PACKAGE@/pidgin/" -e "s/@VERSION@/$(PIDGIN_VERSION)/" -e "s/@top_srcdir@/$(PIDGIN_TREE_TOP)/g" -e "s/@enable_dot@/NO/" $< > $@
+-
+-docs: Doxyfile.mingw
+- @echo "Running doxygen..."
+- @doxygen Doxyfile.mingw
+-
+-clean:
+- $(MAKE) -C $(PURPLE_PO_TOP) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(PURPLE_TOP) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C share/ca-certs -f $(MINGW_MAKEFILE) clean
+- rm -f $(PIDGIN_CONFIG_H) $(PIDGIN_REVISION_H) $(PIDGIN_REVISION_RAW_TXT) ./VERSION pidgin-$(PIDGIN_VERSION)*.exe pidgin-$(PIDGIN_VERSION)-win32-bin.zip $(DEBUG_SYMBOLS_DIR).zip
+- rm -rf doc/html Doxyfile.mingw
+-
+-uninstall:
+- rm -rf $(PURPLE_INSTALL_PERL_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(STRIPPED_RELEASE_DIR) $(DEBUG_SYMBOLS_DIR)
+- rm -f ./VERSION
+-
+-include $(PIDGIN_COMMON_TARGETS)
+-
+diff -Nur pidgin-2.10.7/NEWS pidgin-2.10.7-nonprism/NEWS
+--- pidgin-2.10.7/NEWS 2013-02-11 07:16:50.000000000 -0200
++++ pidgin-2.10.7-nonprism/NEWS 2013-08-16 22:35:02.839098729 -0300
+@@ -984,7 +984,7 @@
+ Luke: Not much to see here, some bug fixes that you all will enjoy as
+ the semester draws to a close and everyone still in school gets bogged
+ down with projects, papers, and exams. Enjoy! Oh, and if you are interested
+- in the perl or gadu-gadu functionality, please step up to help write
++ in the perl functionality, please step up to help write
+ patches, as both of these code blocks are currently unmaintained.
+
+ Tim: I fixed a couple bugs this time. In other news, Kim wants to get
+diff -Nur pidgin-2.10.7/pidgin/gtkaccount.c pidgin-2.10.7-nonprism/pidgin/gtkaccount.c
+--- pidgin-2.10.7/pidgin/gtkaccount.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkaccount.c 2013-08-27 22:45:35.495576079 -0300
+@@ -563,16 +563,11 @@
+ if (value == NULL)
+ value = purple_account_user_split_get_default_value(split);
+
+- /* Google Talk default domain hackery! */
+ menu = gtk_option_menu_get_menu(GTK_OPTION_MENU(dialog->protocol_menu));
+ item = gtk_menu_get_active(GTK_MENU(menu));
+- if (value == NULL && g_object_get_data(G_OBJECT(item), "fakegoogle") &&
++ if (value == NULL && g_object_get_data(G_OBJECT(item), "") &&
+ !strcmp(purple_account_user_split_get_text(split), _("Domain")))
+- value = "gmail.com";
+-
+- if (value == NULL && g_object_get_data(G_OBJECT(item), "fakefacebook") &&
+- !strcmp(purple_account_user_split_get_text(split), _("Domain")))
+- value = "chat.facebook.com";
++ value = "";
+
+ if (value != NULL)
+ gtk_entry_set_text(GTK_ENTRY(entry), value);
+@@ -925,10 +920,6 @@
+ model = gtk_list_store_new(2, G_TYPE_STRING, G_TYPE_POINTER);
+ opt_entry->widget = combo = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
+
+- if (g_object_get_data(G_OBJECT(item), "fakefacebook") &&
+- !strcmp(opt_entry->setting, "connection_security"))
+- str_value = "opportunistic_tls";
+-
+ /* Loop through list of PurpleKeyValuePair items */
+ for (node = list; node != NULL; node = node->next) {
+ if (node->data != NULL) {
+diff -Nur pidgin-2.10.7/pidgin/gtkblist.c pidgin-2.10.7-nonprism/pidgin/gtkblist.c
+--- pidgin-2.10.7/pidgin/gtkblist.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkblist.c 2013-08-16 23:10:16.549286879 -0300
+@@ -2126,10 +2126,6 @@
+ char *temp_vcard;
+ char *s, *c;
+ char *alias = NULL;
+- GList *aims = NULL;
+- GList *icqs = NULL;
+- GList *yahoos = NULL;
+- GList *msns = NULL;
+ GList *jabbers = NULL;
+
+ s = temp_vcard = g_strdup(vcard);
+@@ -2168,24 +2164,14 @@
+ /* We only want to worry about a few fields here. */
+ if (!strcmp(field, "FN"))
+ alias = g_strdup(value);
+- else if (!strcmp(field, "X-AIM") || !strcmp(field, "X-ICQ") ||
+- !strcmp(field, "X-YAHOO") || !strcmp(field, "X-MSN") ||
+- !strcmp(field, "X-JABBER"))
++ else if (!strcmp(field, "X-JABBER"))
+ {
+ char **values = g_strsplit(value, ":", 0);
+ char **im;
+
+ for (im = values; *im != NULL; im++)
+ {
+- if (!strcmp(field, "X-AIM"))
+- aims = g_list_append(aims, g_strdup(*im));
+- else if (!strcmp(field, "X-ICQ"))
+- icqs = g_list_append(icqs, g_strdup(*im));
+- else if (!strcmp(field, "X-YAHOO"))
+- yahoos = g_list_append(yahoos, g_strdup(*im));
+- else if (!strcmp(field, "X-MSN"))
+- msns = g_list_append(msns, g_strdup(*im));
+- else if (!strcmp(field, "X-JABBER"))
++ if (!strcmp(field, "X-JABBER"))
+ jabbers = g_list_append(jabbers, g_strdup(*im));
+ }
+
+@@ -2195,18 +2181,13 @@
+
+ g_free(temp_vcard);
+
+- if (aims == NULL && icqs == NULL && yahoos == NULL &&
+- msns == NULL && jabbers == NULL)
++ if (jabbers == NULL)
+ {
+ g_free(alias);
+
+ return FALSE;
+ }
+
+- add_buddies_from_vcard("prpl-aim", group, aims, alias);
+- add_buddies_from_vcard("prpl-icq", group, icqs, alias);
+- add_buddies_from_vcard("prpl-yahoo", group, yahoos, alias);
+- add_buddies_from_vcard("prpl-msn", group, msns, alias);
+ add_buddies_from_vcard("prpl-jabber", group, jabbers, alias);
+
+ g_free(alias);
+diff -Nur pidgin-2.10.7/pidgin/gtkdialogs.c pidgin-2.10.7-nonprism/pidgin/gtkdialogs.c
+--- pidgin-2.10.7/pidgin/gtkdialogs.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkdialogs.c 2013-08-16 21:37:21.863154130 -0300
+@@ -615,16 +615,6 @@
+ #endif
+ #endif
+
+-#if defined(_WIN32) || defined(USE_INTERNAL_LIBGADU)
+- g_string_append(str, " <b>Gadu-Gadu library (libgadu):</b> Internal<br/>");
+-#else
+-#ifdef HAVE_LIBGADU
+- g_string_append(str, " <b>Gadu-Gadu library (libgadu):</b> Enabled<br/>");
+-#else
+- g_string_append(str, " <b>Gadu-Gadu library (libgadu):</b> Disabled<br/>");
+-#endif
+-#endif
+-
+ #ifdef USE_GTKSPELL
+ g_string_append(str, " <b>GtkSpell:</b> Enabled<br/>");
+ #else
+diff -Nur pidgin-2.10.7/pidgin/gtkimhtml.c pidgin-2.10.7-nonprism/pidgin/gtkimhtml.c
+--- pidgin-2.10.7/pidgin/gtkimhtml.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkimhtml.c 2013-08-16 22:59:51.862994429 -0300
+@@ -2440,7 +2440,6 @@
+ static gboolean smooth_scroll_cb(gpointer data);
+
+ /*
+- <KingAnt> marv: The two IM image functions in oscar are purple_odc_send_im and purple_odc_incoming
+
+
+ [19:58] <Robot101> marv: images go into the imgstore, a refcounted... well.. hash. :)
+diff -Nur pidgin-2.10.7/pidgin/gtknotify.c pidgin-2.10.7-nonprism/pidgin/gtknotify.c
+--- pidgin-2.10.7/pidgin/gtknotify.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtknotify.c 2013-08-27 23:37:23.037593200 -0300
+@@ -1263,10 +1263,6 @@
+ command = g_strdup_printf("xdg-open %s", escaped);
+ g_free(tmp);
+ }
+- else if (purple_running_osx() == TRUE)
+- {
+- command = g_strdup_printf("open %s", escaped);
+- }
+ else if (!strcmp(web_browser, "epiphany") ||
+ !strcmp(web_browser, "galeon"))
+ {
+@@ -1289,30 +1285,31 @@
+ {
+ command = g_strdup_printf("kfmclient openURL %s", escaped);
+ /*
+- * Does Konqueror have options to open in new tab
++ * Does Konqueror-libre have options to open in new tab
+ * and/or current window?
+ */
+ }
+- else if (!strcmp(web_browser, "mozilla") ||
+- !strcmp(web_browser, "mozilla-firebird") ||
+- !strcmp(web_browser, "firefox") ||
+- !strcmp(web_browser, "seamonkey"))
++ else if (!strcmp(web_browser, "iceweasel") ||
++ !strcmp(web_browser, "icecat") ||
++ !strcmp(web_browser, "iceape"))
+ {
+ char *args = "";
+
+ command = g_strdup_printf("%s %s", web_browser, escaped);
+
+ /*
+- * Firefox 0.9 and higher require a "-a firefox" option when
++ * Iceweasel-libre 0.9 and higher require a "-a iceweasel" option when
+ * using -remote commands. This breaks older versions of
+ * mozilla. So we include this other handly little string
+- * when calling firefox. If the API for remote calls changes
+- * any more in firefox then firefox should probably be split
++ * when calling iceweasel. If the API for remote calls changes
++ * any more in iceweasel then iceweasel should probably be split
+ * apart from mozilla-firebird and mozilla... but this is good
+ * for now.
+ */
+- if (!strcmp(web_browser, "firefox"))
+- args = "-a firefox";
++ if (!strcmp(web_browser, "iceweasel"))
++ args = "-a iceweasel";
++ else if (!strcmp(web_browser, "icecat"))
++ args = "-a icecat";
+
+ if (place == PIDGIN_BROWSER_NEW_WINDOW)
+ remote_command = g_strdup_printf("%s %s -remote "
+@@ -1327,58 +1324,12 @@
+ "openURL(%s)",
+ web_browser, args, escaped);
+ }
+- else if (!strcmp(web_browser, "netscape"))
+- {
+- command = g_strdup_printf("netscape %s", escaped);
+-
+- if (place == PIDGIN_BROWSER_NEW_WINDOW)
+- {
+- remote_command = g_strdup_printf("netscape -remote "
+- "openURL(%s,new-window)",
+- escaped);
+- }
+- else if (place == PIDGIN_BROWSER_CURRENT)
+- {
+- remote_command = g_strdup_printf("netscape -remote "
+- "openURL(%s)", escaped);
+- }
+- }
+- else if (!strcmp(web_browser, "opera"))
+- {
+- if (place == PIDGIN_BROWSER_NEW_WINDOW)
+- command = g_strdup_printf("opera -newwindow %s", escaped);
+- else if (place == PIDGIN_BROWSER_NEW_TAB)
+- command = g_strdup_printf("opera -newpage %s", escaped);
+- else if (place == PIDGIN_BROWSER_CURRENT)
+- {
+- remote_command = g_strdup_printf("opera -remote "
+- "openURL(%s)", escaped);
+- command = g_strdup_printf("opera %s", escaped);
+- }
+- else
+- command = g_strdup_printf("opera %s", escaped);
+-
+- }
+- else if (!strcmp(web_browser, "google-chrome"))
+- {
+- /* Google Chrome doesn't have command-line arguments that control the
+- * opening of links from external calls. This is controlled solely from
+- * a preference within Google Chrome. */
+- command = g_strdup_printf("google-chrome %s", escaped);
+- }
+- else if (!strcmp(web_browser, "chrome"))
+- {
+- /* Chromium doesn't have command-line arguments that control the
+- * opening of links from external calls. This is controlled solely from
+- * a preference within Chromium. */
+- command = g_strdup_printf("chrome %s", escaped);
+- }
+- else if (!strcmp(web_browser, "chromium-browser"))
++ else if (!strcmp(web_browser, "chromium"))
+ {
+- /* Chromium doesn't have command-line arguments that control the
++ /* Chromium-libre doesn't have command-line arguments that control the
+ * opening of links from external calls. This is controlled solely from
+- * a preference within Chromium. */
+- command = g_strdup_printf("chromium-browser %s", escaped);
++ * a preference within Chromium-libre. */
++ command = g_strdup_printf("chromium %s", escaped);
+ }
+ else if (!strcmp(web_browser, "custom"))
+ {
+diff -Nur pidgin-2.10.7/pidgin/gtkprefs.c pidgin-2.10.7-nonprism/pidgin/gtkprefs.c
+--- pidgin-2.10.7/pidgin/gtkprefs.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkprefs.c 2013-08-27 22:55:58.523782666 -0300
+@@ -1851,24 +1851,15 @@
+
+ /* Sorted reverse alphabetically */
+ static const struct browser possible_browsers[] = {
+- {N_("Seamonkey"), "seamonkey"},
+- {N_("Opera"), "opera"},
+- {N_("Netscape"), "netscape"},
+- {N_("Mozilla"), "mozilla"},
+- {N_("Konqueror"), "kfmclient"},
+- {N_("Google Chrome"), "google-chrome"},
+- /* Do not move the line below. Code below expects gnome-open to be in
+- * this list immediately after xdg-open! */
++ {N_("Iceape-libre"), "iceape"},
++ {N_("Konqueror-libre"), "kfmclient"},
+ {N_("Desktop Default"), "xdg-open"},
+ {N_("GNOME Default"), "gnome-open"},
+- {N_("Galeon"), "galeon"},
+- {N_("Firefox"), "firefox"},
+- {N_("Firebird"), "mozilla-firebird"},
+- {N_("Epiphany"), "epiphany"},
+- /* Translators: please do not translate "chromium-browser" here! */
+- {N_("Chromium (chromium-browser)"), "chromium-browser"},
+- /* Translators: please do not translate "chrome" here! */
+- {N_("Chromium (chrome)"), "chrome"}
++ {N_("Iceweasel-libre"), "iceweasel"},
++ {N_("Icecat"), "icecat"},
++ {N_("Epiphany-libre"), "epiphany"},
++ /* Translators: please do not translate "chromium" here! */
++ {N_("Chromium-libre (chromium)"), "chromium"},
+ };
+ static const int num_possible_browsers = G_N_ELEMENTS(possible_browsers);
+
+diff -Nur pidgin-2.10.7/pidgin/gtkutils.c pidgin-2.10.7-nonprism/pidgin/gtkutils.c
+--- pidgin-2.10.7/pidgin/gtkutils.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkutils.c 2013-08-16 19:59:22.633298587 -0300
+@@ -677,7 +677,6 @@
+ GdkPixbuf *pixbuf = NULL;
+ GtkSizeGroup *sg;
+ GList *p;
+- const char *gtalk_name = NULL, *facebook_name = NULL;
+ int i;
+
+ aop_menu = g_malloc0(sizeof(AopMenu));
+@@ -686,55 +685,12 @@
+ 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");
+- facebook_name = _("Facebook (XMPP)");
+- }
+-
+ for (p = purple_plugins_get_protocols(), i = 0;
+ p != NULL;
+ p = p->next, i++) {
+
+ plugin = (PurplePlugin *)p->data;
+
+- if (gtalk_name && strcmp(gtalk_name, plugin->info->name) < 0) {
+- char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
+- "16", "google-talk.png", NULL);
+- GtkWidget *item;
+-
+- pixbuf = pidgin_pixbuf_new_from_file(filename);
+- g_free(filename);
+-
+- gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+- item = aop_menu_item_new(sg, pixbuf, gtalk_name, "prpl-jabber", "protocol"));
+- g_object_set_data(G_OBJECT(item), "fakegoogle", GINT_TO_POINTER(1));
+-
+- if (pixbuf)
+- g_object_unref(pixbuf);
+-
+- gtalk_name = NULL;
+- i++;
+- }
+-
+- if (facebook_name && strcmp(facebook_name, plugin->info->name) < 0) {
+- char *filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
+- "16", "facebook.png", NULL);
+- GtkWidget *item;
+-
+- pixbuf = pidgin_pixbuf_new_from_file(filename);
+- g_free(filename);
+-
+- gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+- item = aop_menu_item_new(sg, pixbuf, facebook_name, "prpl-jabber", "protocol"));
+- g_object_set_data(G_OBJECT(item), "fakefacebook", GINT_TO_POINTER(1));
+-
+- if (pixbuf)
+- g_object_unref(pixbuf);
+-
+- facebook_name = NULL;
+- i++;
+- }
+-
+ pixbuf = pidgin_create_prpl_icon_from_prpl(plugin, PIDGIN_PRPL_ICON_SMALL, NULL);
+
+ gtk_menu_shell_append(GTK_MENU_SHELL(aop_menu->menu),
+diff -Nur pidgin-2.10.7/pidgin/gtkwhiteboard.c pidgin-2.10.7-nonprism/pidgin/gtkwhiteboard.c
+--- pidgin-2.10.7/pidgin/gtkwhiteboard.c 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkwhiteboard.c 2013-08-16 23:25:21.614375960 -0300
+@@ -339,13 +339,10 @@
+ */
+ /* XXXX because otherwise gettext will see this string, even though it's
+ * in an #if 0 block. Remove the XXXX if you want to use this code.
+- * But, it really shouldn't be a Yahoo-specific string. ;) */
++ */
+ purple_conv_im_write(PURPLE_CONV_IM(conv), "", XXXX_("Sent Doodle request."),
+ PURPLE_MESSAGE_NICK | PURPLE_MESSAGE_RECV, time(NULL));
+
+- yahoo_doodle_command_send_request(gc, to);
+- yahoo_doodle_command_send_ready(gc, to);
+-
+ /* Insert this 'session' in the list. At this point, it's only a requested
+ * session.
+ */
+@@ -554,15 +551,13 @@
+ if(event->button == 1 && pixmap != NULL)
+ {
+ /* If the brush was never moved, express two sets of two deltas That's a
+- * 'point,' but not for Yahoo!
++ * 'point,'
+ */
+ /* if((event->x == LastX) && (event->y == LastY)) */
+ if(MotionCount == 0)
+ {
+ int index;
+
+- /* For Yahoo!, a (0 0) indicates the end of drawing */
+- /* FIXME: Yahoo Doodle specific! */
+ for(index = 0; index < 2; index++)
+ {
+ draw_list = g_list_append(draw_list, 0);
+diff -Nur pidgin-2.10.7/pidgin/gtkwhiteboard.h pidgin-2.10.7-nonprism/pidgin/gtkwhiteboard.h
+--- pidgin-2.10.7/pidgin/gtkwhiteboard.h 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/gtkwhiteboard.h 2013-08-27 23:28:41.018759351 -0300
+@@ -37,8 +37,7 @@
+ #define BRUSH_STATE_DOWN 1
+ #define BRUSH_STATE_MOTION 2
+
+-/* XXX: This seems duplicated with the Yahoo! Doodle prpl code.
+- * XXX: How should they work together? */
++/* XXX: How should they work together? */
+ #define PALETTE_NUM_COLORS 7
+
+ /**
+diff -Nur pidgin-2.10.7/pidgin/Makefile.am pidgin-2.10.7-nonprism/pidgin/Makefile.am
+--- pidgin-2.10.7/pidgin/Makefile.am 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/Makefile.am 2013-08-16 21:03:34.936610745 -0300
+@@ -160,10 +160,6 @@
+ $(GTK_LIBS) \
+ $(top_builddir)/libpurple/libpurple.la
+
+-if USE_INTERNAL_LIBGADU
+-INTGG_CFLAGS = -DUSE_INTERNAL_LIBGADU
+-endif
+-
+ AM_CPPFLAGS = \
+ -DDATADIR=\"$(datadir)\" \
+ -DLIBDIR=\"$(libdir)/pidgin/\" \
+@@ -179,6 +175,5 @@
+ $(GTK_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(GTKSPELL_CFLAGS) \
+- $(LIBXML_CFLAGS) \
+- $(INTGG_CFLAGS)
++ $(LIBXML_CFLAGS)
+ endif # ENABLE_GTK
+diff -Nur pidgin-2.10.7/pidgin/Makefile.in pidgin-2.10.7-nonprism/pidgin/Makefile.in
+--- pidgin-2.10.7/pidgin/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/Makefile.in 2013-08-16 23:56:44.729405978 -0300
+@@ -286,8 +286,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -349,8 +347,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+@@ -645,7 +641,6 @@
+ @ENABLE_GTK_TRUE@ $(GTK_LIBS) \
+ @ENABLE_GTK_TRUE@ $(top_builddir)/libpurple/libpurple.la
+
+-@ENABLE_GTK_TRUE@@USE_INTERNAL_LIBGADU_TRUE@INTGG_CFLAGS = -DUSE_INTERNAL_LIBGADU
+ @ENABLE_GTK_TRUE@AM_CPPFLAGS = \
+ @ENABLE_GTK_TRUE@ -DDATADIR=\"$(datadir)\" \
+ @ENABLE_GTK_TRUE@ -DLIBDIR=\"$(libdir)/pidgin/\" \
+diff -Nur pidgin-2.10.7/pidgin/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/Makefile.mingw
+--- pidgin-2.10.7/pidgin/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,175 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of Pidgin
+-#
+-
+-PIDGIN_TREE_TOP := ..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-##
+-## VARIABLE DEFINITIONS
+-##
+-EXE_TARGET := pidgin
+-PIDGIN_TARGET := pidgin
+-EXE_NAME := $(EXE_TARGET).exe
+-
+-WINAPP := -mwindows
+-
+-LDFLAGS := $(WINAPP) $(LD_HARDENING_OPTIONS) -Wl,--enable-auto-import -lssp
+-
+-##
+-## INCLUDE PATHS
+-##
+-PURPLE_INCLUDE_PATHS = \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include
+-
+-INCLUDE_PATHS += \
+- $(PURPLE_INCLUDE_PATHS) \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(GTKSPELL_TOP)/include/gtkspell-2.0
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-PIDGIN_C_SRC = \
+- gtkaccount.c \
+- gtkblist-theme-loader.c \
+- gtkblist-theme.c \
+- gtkblist.c \
+- gtkcellrendererexpander.c \
+- gtkcertmgr.c \
+- gtkconn.c \
+- gtkconv.c \
+- gtkdebug.c \
+- gtkdialogs.c \
+- gtkdnd-hints.c \
+- gtkdocklet.c \
+- gtkeventloop.c \
+- gtkft.c \
+- gtkicon-theme-loader.c \
+- gtkicon-theme.c \
+- gtkidle.c \
+- gtkimhtml.c \
+- gtkimhtmltoolbar.c \
+- gtklog.c \
+- gtkmain.c \
+- gtkmedia.c \
+- gtkmenutray.c \
+- gtknotify.c \
+- gtkplugin.c \
+- gtkpluginpref.c \
+- gtkpounce.c \
+- gtkprefs.c \
+- gtkprivacy.c \
+- gtkrequest.c \
+- gtkroomlist.c \
+- gtksavedstatuses.c \
+- gtkscrollbook.c \
+- gtksmiley.c \
+- gtksound.c \
+- gtksourceiter.c \
+- gtksourceundomanager.c \
+- gtkstatus-icon-theme.c \
+- gtkstatusbox.c \
+- gtkthemes.c \
+- gtkutils.c \
+- gtkwhiteboard.c \
+- minidialog.c \
+- pidginstock.c \
+- pidgintooltip.c \
+- win32/MinimizeToTray.c \
+- win32/gtkdocklet-win32.c \
+- win32/gtkwin32dep.c \
+- win32/untar.c \
+- win32/wspell.c
+-
+-PIDGIN_RC_SRC = win32/pidgin_dll_rc.rc
+-PIDGIN_OBJECTS = $(PIDGIN_C_SRC:%.c=%.o) $(PIDGIN_RC_SRC:%.rc=%.o)
+-
+-EXE_RC_SRC = win32/pidgin_exe_rc.rc
+-EXE_C_SRC = win32/winpidgin.c
+-EXE_OBJECTS = $(EXE_C_SRC:%.c=%.o) $(EXE_RC_SRC:%.rc=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-
+-PIDGIN_LIBS = \
+- -lintl \
+- -lglib-2.0 \
+- -lgobject-2.0 \
+- -lgthread-2.0 \
+- -lpurple \
+- -lz \
+- -lgtk-win32-2.0 \
+- -latk-1.0 \
+- -lcairo \
+- -lpango-1.0 \
+- -lgdk-win32-2.0 \
+- -lgdk_pixbuf-2.0 \
+- -lgdi32 \
+- -lwinmm
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install install_shallow clean
+-
+-all: $(EXE_TARGET).exe $(PIDGIN_TARGET).dll
+- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE)
+-
+-win32/pidgin_exe_rc.rc: win32/pidgin_exe_rc.rc.in $(PIDGIN_TREE_TOP)/VERSION
+- sed -e 's/@PIDGIN_VERSION@/$(PIDGIN_VERSION)/g' \
+- -e 's/@ORIGINAL_FILENAME@/$(EXE_NAME)/' \
+- $@.in > $@
+-
+-install_shallow: $(PIDGIN_INSTALL_DIR) $(EXE_TARGET).exe $(PIDGIN_TARGET).dll
+- cp $(EXE_TARGET).exe $(PIDGIN_TARGET).dll $(PIDGIN_INSTALL_DIR)
+-
+-install: install_shallow all
+- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(PIDGIN_PIXMAPS_TOP) -f $(MINGW_MAKEFILE) install
+-
+-win32/pidgin_dll_rc.rc: win32/pidgin_dll_rc.rc.in $(PIDGIN_TREE_TOP)/VERSION
+- sed -e 's/@PIDGIN_VERSION@/$(PIDGIN_VERSION)/g' \
+- $@.in > $@
+-
+-$(EXE_OBJECTS) $(PIDGIN_OBJECTS): $(PIDGIN_CONFIG_H)
+-
+-$(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a: $(PURPLE_DLL).a $(PIDGIN_OBJECTS)
+- $(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 $(EXE_OBJECTS) $(PIDGIN_TARGET).dll
+- $(CC) $(EXE_OBJECTS) $(LDFLAGS) -o $(EXE_TARGET).exe
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- $(MAKE) -C $(PIDGIN_PLUGINS_TOP) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(PIDGIN_PIXMAPS_TOP) -f $(MINGW_MAKEFILE) clean
+- rm -f $(PIDGIN_OBJECTS) $(PIDGIN_RC_SRC) $(EXE_OBJECTS) $(EXE_RC_SRC)
+- rm -f $(PIDGIN_TARGET).dll $(PIDGIN_TARGET).dll.a $(PIDGIN_TARGET).def
+- rm -f $(EXE_TARGET).exe
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/default.theme.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/default.theme.in
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/default.theme.in 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/default.theme.in 2013-08-16 23:13:41.759061988 -0300
+@@ -28,8 +28,7 @@
+
+
+ [XMPP]
+-# Following XEP-0038 + GTalk + our default set, in default set order
+-# The GTalk strings come from ticket #3307.
++# Following XEP-0038 + our default set, in default set order
+ happy.png :) :-) =)
+ excited.png :-D :-d :D :d =D =d
+ sad.png :-( :(
+@@ -47,7 +46,7 @@
+ foot-in-mouth.png :-!
+ shout.png >:o >:O
+
+-# Following XEP-0038 + GTalk
++# Following XEP-0038
+ angry.png >:-( >:( X-( x-(
+ good.png :yes:
+ bad.png :no:
+@@ -75,515 +74,3 @@
+ ! skywalker.png C:-) c:-) C:) c:)
+ ! monkey.png :-(|) :(|) 8-|)
+ ! cyclops.png O-) o-)
+-
+-
+-# Following AIM 6.1
+-[AIM]
+-happy.png :-) :)
+-wink.png ;-) ;)
+-sad.png :-( :(
+-tongue.png :P :p :-P :-p
+-shocked.png =-O
+-kiss.png :-*
+-shout.png >:o
+-excited.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 :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following Windows Live Messenger 8.1
+-[MSN]
+-happy.png :) :-)
+-excited.png :D :d :-D :-d
+-wink.png ;) ;-)
+-shocked.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)
+-in_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-)
+-sleepy.png |-)
+-bunny.png ('.')
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-# Hidden MSN emotes
+-cigarette.png (ci) (CI)
+-handcuffs.png (%)
+-console.png (xx) (XX)
+-fingers-crossed.png (yn) (YN)
+-
+-
+-# Following QQ 2006
+-[QQ]
+-shocked.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
+-sleeping.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
+-excited.png /:D /cy /toothy_smile
+-happy.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
+-sleepy.png /|-) /kun /sleepy
+-terror.png /:! /jk /terror
+-hot.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
+-afraid.png /shake /fad /shake
+-amorous.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
+-hungry.png /eat /fan /eat
+-pill.png /pill /yw /pill
+-rose.png /rose /mg /rose
+-wilt.png /fade /dx /wilt
+-kiss.png /kiss /wen /kiss
+-in_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 /<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 :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following ICQ 6.0
+-[ICQ]
+-happy.png :-) :)
+-neutral.png :-$
+-sad.png :-( :(
+-shocked.png =-O
+-wink.png ;-) ;)
+-tongue.png :-P :P :-p :p
+-music.png [:-}
+-laugh.png *JOKINGLY*
+-sleeping.png *TIRED*
+-crying.png :'( :'-(
+-sick.png :-!
+-kissed.png *KISSED*
+-stop.png *STOP*
+-kiss.png :-{} :-*
+-kissing.png *KISSING*
+-victory.png *YAHOO*
+-silly.png %)
+-embarrassed.png :-[
+-devil.png ]:->
+-angel.png O:-)
+-rose.png @}->--
+-shut-mouth.png :-X :X :-x :x
+-bomb.png @=
+-thinking.png :-\\ :-/
+-good.png *THUMBS\ UP*
+-shout.png >:o >:O :-@
+-beer.png *DRINK*
+-excited.png :-D :D
+-glasses-cool.png 8-)
+-amorous.png *IN\ LOVE*
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-hypnotized.png @-)
+-on-the-phone.png :)]
+-sad.png :( :-(
+-amorous.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.png ~x( ~X(
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.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
+-time-out.png :-t :-T
+-hug-left.png >:D< >:d<
+-love-over.png =((
+-hot.png #:-S #:-s
+-rotfl.png =)) :-j :-J
+-loser.png L-) l-)
+-party.png <:-P <:-p
+-nervous.png :-SS :-Ss :-sS :-ss
+-cowboy.png <):)
+-desire.png 8->
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-# 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 :-@
+-
+-# Only available after activating the Yahoo! Fighter IMVironment
+-male-fighter1.png o-> O->
+-male-fighter2.png o=> O=>
+-female-fighter.png o-+ O-+
+-yin-yang.png (%)
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo JAPAN]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-hypnotized.png @-)
+-on-the-phone.png :)]
+-sad.png :( :-(
+-amorous.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.png ~x( ~X(
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.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
+-time-out.png :-t :-T
+-hug-left.png >:D< >:d<
+-love-over.png =((
+-hot.png #:-S #:-s
+-rotfl.png =)) :-j :-J
+-loser.png L-) l-)
+-party.png <:-P <:-p
+-nervous.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 :-@
+-
+-# Only available after activating the Yahoo! Fighter IMVironment
+-male-fighter1.png o-> O->
+-male-fighter2.png o=> O=>
+-female-fighter.png o-+ O-+
+-yin-yang.png (%)
+-
+-
+-# Following MySpaceIM Beta 1.0.697.0
+-[MySpaceIM]
+-excited.png :D :-D
+-devil.png }:)
+-confused.png :Z
+-glasses-nerdy.png B)
+-bulgy-eyes.png %)
+-freaked-out.png :E
+-happy.png :) :-)
+-amorous.png :X
+-laugh.png :))
+-mohawk.png -:
+-mad-tongue.png X(
+-messed.png X)
+-glasses-nerdy.png Q)
+-doh.png :G
+-pirate.png P)
+-shocked.png :O
+-sidefrown.png :{
+-sinister.png :B
+-smirk.png :,
+-neutral.png :|
+-tongue.png :P :p
+-pissed-off.png B|
+-wink.png ;-) ;)
+-sad.png :[
+-kiss.png :x
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# MXit standard emoticons
+-[MXit]
+-happy.png :-) :)
+-sad.png :-( :(
+-wink.png ;-) ;)
+-excited.png :-D :D :-> :>
+-neutral.png :-| :|
+-shocked.png :-O :O
+-tongue.png :-P :P
+-embarrassed.png :-$ :$
+-glasses-cool.png 8-)
+-in_love.png (H)
+-rose.png (F)
+-### Added in v3.0
+-boy.png (m)
+-girl.png (f)
+-star.png (*)
+-chilli.png (c)
+-kiss.png (x)
+-lamp.png (i)
+-pissed-off.png :e :-e
+-shut-mouth.png :-x :x
+-thunder.png (z)
+-coffee.png (U)
+-mrgreen.png (G)
+-### Added in v5.0
+-sick.png :o(
+-excruciating.png :-{ :{
+-amorous.png :-} :}
+-eyeroll.png 8-o 8o
+-crying.png :'(
+-thinking.png :-? :?
+-drool.png :-~ :~
+-sleeping.png :-z :z
+-lying.png :L)
+-glasses-nerdy.png 8-| 8|
+-pirate.png P-)
+-### Added in v5.9.7
+-bored.png :-[ :[
+-cold.png :-< :<
+-confused.png :-, :,
+-hungry.png :-C :C
+-stressed.png :-s :s
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.in
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.in 2013-08-17 00:02:25.939870063 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.mingw
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-#
+-# 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.mingw
+-
+-.PHONY: install clean
+-
+-install: ./Makefile.am.mingw theme
+- if test '$(pidginsmileypix_DATA)'; then \
+- mkdir -p $(pidginsmileypixdir); \
+- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
+- fi;
+-
+-clean:
+- rm -f theme ./Makefile.am.mingw
+-
+-./Makefile.am.mingw: ./Makefile.am
+- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
+- include $@
+-
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/theme pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/theme
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/default/24/theme 2013-02-11 07:17:58.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/default/24/theme 2013-08-16 23:15:55.929941297 -0300
+@@ -28,8 +28,7 @@
+
+
+ [XMPP]
+-# Following XEP-0038 + GTalk + our default set, in default set order
+-# The GTalk strings come from ticket #3307.
++# Following XEP-0038 + our default set, in default set order
+ happy.png :) :-) =)
+ excited.png :-D :-d :D :d =D =d
+ sad.png :-( :(
+@@ -47,7 +46,7 @@
+ foot-in-mouth.png :-!
+ shout.png >:o >:O
+
+-# Following XEP-0038 + GTalk
++# Following XEP-0038
+ angry.png >:-( >:( X-( x-(
+ good.png :yes:
+ bad.png :no:
+@@ -75,515 +74,3 @@
+ ! skywalker.png C:-) c:-) C:) c:)
+ ! monkey.png :-(|) :(|) 8-|)
+ ! cyclops.png O-) o-)
+-
+-
+-# Following AIM 6.1
+-[AIM]
+-happy.png :-) :)
+-wink.png ;-) ;)
+-sad.png :-( :(
+-tongue.png :P :p :-P :-p
+-shocked.png =-O
+-kiss.png :-*
+-shout.png >:o
+-excited.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 :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following Windows Live Messenger 8.1
+-[MSN]
+-happy.png :) :-)
+-excited.png :D :d :-D :-d
+-wink.png ;) ;-)
+-shocked.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)
+-in_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-)
+-sleepy.png |-)
+-bunny.png ('.')
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-# Hidden MSN emotes
+-cigarette.png (ci) (CI)
+-handcuffs.png (%)
+-console.png (xx) (XX)
+-fingers-crossed.png (yn) (YN)
+-
+-
+-# Following QQ 2006
+-[QQ]
+-shocked.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
+-sleeping.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
+-excited.png /:D /cy /toothy_smile
+-happy.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
+-sleepy.png /|-) /kun /sleepy
+-terror.png /:! /jk /terror
+-hot.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
+-afraid.png /shake /fad /shake
+-amorous.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
+-hungry.png /eat /fan /eat
+-pill.png /pill /yw /pill
+-rose.png /rose /mg /rose
+-wilt.png /fade /dx /wilt
+-kiss.png /kiss /wen /kiss
+-in_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 /<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 :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following ICQ 6.0
+-[ICQ]
+-happy.png :-) :)
+-neutral.png :-$
+-sad.png :-( :(
+-shocked.png =-O
+-wink.png ;-) ;)
+-tongue.png :-P :P :-p :p
+-music.png [:-}
+-laugh.png *JOKINGLY*
+-sleeping.png *TIRED*
+-crying.png :'( :'-(
+-sick.png :-!
+-kissed.png *KISSED*
+-stop.png *STOP*
+-kiss.png :-{} :-*
+-kissing.png *KISSING*
+-victory.png *YAHOO*
+-silly.png %)
+-embarrassed.png :-[
+-devil.png ]:->
+-angel.png O:-)
+-rose.png @}->--
+-shut-mouth.png :-X :X :-x :x
+-bomb.png @=
+-thinking.png :-\\ :-/
+-good.png *THUMBS\ UP*
+-shout.png >:o >:O :-@
+-beer.png *DRINK*
+-excited.png :-D :D
+-glasses-cool.png 8-)
+-amorous.png *IN\ LOVE*
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-hypnotized.png @-)
+-on-the-phone.png :)]
+-sad.png :( :-(
+-amorous.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.png ~x( ~X(
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.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
+-time-out.png :-t :-T
+-hug-left.png >:D< >:d<
+-love-over.png =((
+-hot.png #:-S #:-s
+-rotfl.png =)) :-j :-J
+-loser.png L-) l-)
+-party.png <:-P <:-p
+-nervous.png :-SS :-Ss :-sS :-ss
+-cowboy.png <):)
+-desire.png 8->
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-# 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 :-@
+-
+-# Only available after activating the Yahoo! Fighter IMVironment
+-male-fighter1.png o-> O->
+-male-fighter2.png o=> O=>
+-female-fighter.png o-+ O-+
+-yin-yang.png (%)
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo JAPAN]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-hypnotized.png @-)
+-on-the-phone.png :)]
+-sad.png :( :-(
+-amorous.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.png ~x( ~X(
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.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
+-time-out.png :-t :-T
+-hug-left.png >:D< >:d<
+-love-over.png =((
+-hot.png #:-S #:-s
+-rotfl.png =)) :-j :-J
+-loser.png L-) l-)
+-party.png <:-P <:-p
+-nervous.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 :-@
+-
+-# Only available after activating the Yahoo! Fighter IMVironment
+-male-fighter1.png o-> O->
+-male-fighter2.png o=> O=>
+-female-fighter.png o-+ O-+
+-yin-yang.png (%)
+-
+-
+-# Following MySpaceIM Beta 1.0.697.0
+-[MySpaceIM]
+-excited.png :D :-D
+-devil.png }:)
+-confused.png :Z
+-glasses-nerdy.png B)
+-bulgy-eyes.png %)
+-freaked-out.png :E
+-happy.png :) :-)
+-amorous.png :X
+-laugh.png :))
+-mohawk.png -:
+-mad-tongue.png X(
+-messed.png X)
+-glasses-nerdy.png Q)
+-doh.png :G
+-pirate.png P)
+-shocked.png :O
+-sidefrown.png :{
+-sinister.png :B
+-smirk.png :,
+-neutral.png :|
+-tongue.png :P :p
+-pissed-off.png B|
+-wink.png ;-) ;)
+-sad.png :[
+-kiss.png :x
+-! skywalker.png C:-) c:-) C:) c:)
+-! monkey.png :-(|) :(|) 8-|)
+-! cyclops.png O-) o-)
+-
+-
+-# MXit standard emoticons
+-[MXit]
+-happy.png :-) :)
+-sad.png :-( :(
+-wink.png ;-) ;)
+-excited.png :-D :D :-> :>
+-neutral.png :-| :|
+-shocked.png :-O :O
+-tongue.png :-P :P
+-embarrassed.png :-$ :$
+-glasses-cool.png 8-)
+-in_love.png (H)
+-rose.png (F)
+-### Added in v3.0
+-boy.png (m)
+-girl.png (f)
+-star.png (*)
+-chilli.png (c)
+-kiss.png (x)
+-lamp.png (i)
+-pissed-off.png :e :-e
+-shut-mouth.png :-x :x
+-thunder.png (z)
+-coffee.png (U)
+-mrgreen.png (G)
+-### Added in v5.0
+-sick.png :o(
+-excruciating.png :-{ :{
+-amorous.png :-} :}
+-eyeroll.png 8-o 8o
+-crying.png :'(
+-thinking.png :-? :?
+-drool.png :-~ :~
+-sleeping.png :-z :z
+-lying.png :L)
+-glasses-nerdy.png 8-| 8|
+-pirate.png P-)
+-### Added in v5.9.7
+-bored.png :-[ :[
+-cold.png :-< :<
+-confused.png :-, :,
+-hungry.png :-C :C
+-stressed.png :-s :s
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.in
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.in 2013-08-17 00:01:20.721202021 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.mingw
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/none/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/none/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-#
+-# 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.mingw
+-
+-.PHONY: install clean
+-
+-install: ./Makefile.am.mingw theme
+- if test '$(pidginsmileypix_DATA)'; then \
+- mkdir -p $(pidginsmileypixdir); \
+- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
+- fi;
+-
+-clean:
+- rm -f theme ./Makefile.am.mingw
+-
+-./Makefile.am.mingw: ./Makefile.am
+- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
+- include $@
+-
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.in
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.in 2013-08-17 00:01:44.881943374 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.mingw
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-#
+-# 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.mingw
+-
+-.PHONY: install clean
+-
+-install: ./Makefile.am.mingw theme
+- if test '$(pidginsmileypix_DATA)'; then \
+- mkdir -p $(pidginsmileypixdir); \
+- cp $(pidginsmileypix_DATA) $(pidginsmileypixdir); \
+- fi;
+-
+-clean:
+- rm -f theme ./Makefile.am.mingw
+-
+-./Makefile.am.mingw: ./Makefile.am
+- sed -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' ./Makefile.am > $@
+- include $@
+-
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/small.theme.in pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/small.theme.in
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/small.theme.in 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/small.theme.in 2013-08-16 23:19:01.815778718 -0300
+@@ -22,8 +22,7 @@
+
+
+ [XMPP]
+-# Following XEP-0038 + GTalk + our default set, in default set order
+-# The GTalk strings come from ticket #3307.
++# Following XEP-0038 + our default set, in default set order
+ happy.png :) :-) =)
+ excited.png :-D :-d :D :d =D =d
+ sad.png :-( :(
+@@ -38,7 +37,7 @@
+ angel.png O:-) o:-)
+ shut-mouth.png :-X
+
+-# Following XEP-0038 + GTalk
++# Following XEP-0038
+ angry.png >:-( >:( X-( x-(
+ rose.png @->-- :rose:
+ phone.png :telephone:
+@@ -53,269 +52,3 @@
+ neutral.png :| :-|
+
+ # Hidden icons from the default set.
+-
+-
+-# Following AIM 6.1
+-[AIM]
+-happy.png :-) :)
+-wink.png ;-) ;)
+-sad.png :-( :(
+-tongue.png :P :p :-P :-p
+-shocked.png =-O
+-kiss.png :-*
+-excited.png :-D :D
+-embarrassed.png :-[
+-angel.png O:-)
+-thinking.png :-\\ :-/
+-crying.png :'(
+-shut-mouth.png :-X
+-glasses-cool.png 8-)
+-
+-
+-# Following Windows Live Messenger 8.1
+-[MSN]
+-happy.png :) :-)
+-excited.png :D :d :-D :-d
+-wink.png ;) ;-)
+-shocked.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)
+-in_love.png (L) (l)
+-star.png (*)
+-musical-note.png (8)
+-rose.png (F) (f)
+-kiss.png (K) (k)
+-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)
+-boy.png (Z) (z)
+-girl.png (X) (x)
+-sarcastic.png ^o)
+-sick.png +o(
+-plate.png (pl)
+-mobile.png (mp)
+-dont-know.png :^)
+-thinking.png *-)
+-thunder.png (li)
+-party.png <:o)
+-eyeroll.png 8-)
+-sleepy.png |-)
+-
+-# Hidden MSN emotes
+-cigarette.png (ci) (CI)
+-console.png (xx) (XX)
+-
+-
+-# Following QQ 2006
+-[QQ]
+-shocked.png /:O /jy /surprised
+-party.png /8-) /dy /revel
+-crying.png /:< /ll /cry
+-shut-mouth.png /:X /bz /shut_mouth
+-sleeping.png /:Z /shui /sleep
+-embarrassed.png /:-| /gg /embarassed
+-pissed-off.png /:@ /fn /pissed_off
+-excited.png /:D /cy /toothy_smile
+-happy.png /:) /wx /small_smile
+-sad.png /:( /ng /sad
+-glasses-cool.png /:+ /kuk /cool
+-sick.png /:T /tu /vomit
+-sleepy.png /|-) /kun /sleepy
+-hot.png /:L /sweat
+-question.png /? /yiw /question
+-excruciating.png /:8 /zhem /excrutiating
+-afraid.png /shake /fad /shake
+-amorous.png /love /aiq /love
+-search.png /find /zhao /search
+-hug-left.png /hug /yb /hug
+-lamp.png /! /dp /lightbulb
+-thunder.png /li /shd /lightning
+-musical-note.png /music /yy /music
+-coffee.png /coffee /kf /coffee
+-hungry.png /eat /fan /eat
+-rose.png /rose /mg /rose
+-kiss.png /kiss /wen /kiss
+-in_love.png /heart /xin /heart
+-meeting.png /meeting /hy /meeting
+-phone.png /phone /dh /phone
+-tv.png /TV /ds /TV
+-angry.png /<O> /oh /angry
+-girl.png /<00> /nv /woman
+-boy.png /<11> /nan /man
+-
+-
+-# Following ICQ 6.0
+-[ICQ]
+-happy.png :-) :)
+-neutral.png :-$
+-sad.png :-( :(
+-shocked.png =-O
+-wink.png ;-) ;)
+-tongue.png :-P :P :-p :p
+-music.png [:-}
+-sleeping.png *TIRED*
+-crying.png :'( :'-(
+-sick.png :-!
+-kiss.png :-{} :-*
+-embarrassed.png :-[
+-devil.png ]:->
+-angel.png O:-)
+-rose.png @}->--
+-shut-mouth.png :-X :X :-x :x
+-thinking.png :-\\ :-/
+-beer.png *DRINK*
+-excited.png :-D :D
+-glasses-cool.png 8-)
+-amorous.png *IN\ LOVE*
+-
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-sad.png :( :-(
+-amorous.png :x :-x :X :-X
+-angry.png X-( x-( X( x(
+-crying.png :((
+-drool.png =P~ =p~
+-lying.png :^O :^o
+-wink.png ;) ;-)
+-embarrassed.png :">
+-mean.png :-> :>
+-thinking.png :-?
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.png I-) i-) |-)
+-kiss.png :-* :*
+-confused.png :-S :-s
+-sarcastic.png /:)
+-eyeroll.png 8-|
+-hug-left.png >:D< >:d<
+-hot.png #:-S #:-s
+-party.png <:-P <:-p
+-nervous.png :-SS :-Ss :-sS :-ss
+-
+-# Hidden Yahoo emotes
+-coffee.png ~o) ~O)
+-rose.png @};-
+-dont-know.png :-L :-l
+-lamp.png *-:)
+-shame.png [-X [-x
+-musical-note.png :-"
+-star.png (*)
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo JAPAN]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-sad.png :( :-(
+-amorous.png :x :-x :X :-X
+-angry.png X-( x-( X( x(
+-crying.png :((
+-wink.png ;) ;-)
+-thinking.png :-?
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.png I-) i-) |-)
+-kiss.png :-* :*
+-confused.png :-S :-s
+-sarcastic.png /:)
+-eyeroll.png 8-|
+-hug-left.png >:D< >:d<
+-party.png <:-P <:-p
+-
+-# Hidden Yahoo emotes
+-coffee.png ~o) ~O)
+-rose.png @};-
+-dont-know.png :-L :-l
+-lamp.png *-:)
+-shame.png [-X [-x
+-musical-note.png :-"
+-star.png (*)
+-
+-
+-# Following MySpaceIM Beta 1.0.697.0
+-[MySpaceIM]
+-excited.png :D :-D
+-devil.png }:)
+-confused.png :Z
+-happy.png :) :-)
+-amorous.png :X
+-pirate.png P)
+-shocked.png :O
+-neutral.png :|
+-tongue.png :P :p
+-pissed-off.png B|
+-wink.png ;-) ;)
+-sad.png :[
+-kiss.png :x
+-
+-# MXit standard emoticons
+-[MXit]
+-happy.png :-) :)
+-sad.png :-( :(
+-wink.png ;-) ;)
+-excited.png :-D :D :-> :>
+-neutral.png :-| :|
+-shocked.png :-O :O
+-tongue.png :-P :P
+-embarrassed.png :-$ :$
+-glasses-cool.png 8-)
+-in_love.png (H)
+-rose.png (F)
+-### Added in v3.0
+-boy.png (m)
+-girl.png (f)
+-star.png (*)
+-chilli.png (c)
+-kiss.png (x)
+-lamp.png (i)
+-pissed-off.png :e :-e
+-shut-mouth.png :-x :x
+-thunder.png (z)
+-coffee.png (U)
+-mrgreen.png (G)
+-### Added in v5.0
+-sick.png :o(
+-excruciating.png :-{ :{
+-amorous.png :-} :}
+-eyeroll.png 8-o 8o
+-crying.png :'(
+-thinking.png :-? :?
+-drool.png :-~ :~
+-sleeping.png :-z :z
+-lying.png :L)
+-glasses-nerdy.png 8-| 8|
+-pirate.png P-)
+-### Added in v5.9.7
+-bored.png :-[ :[
+-cold.png :-< :<
+-confused.png :-, :,
+-hungry.png :-C :C
+-stressed.png :-s :s
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/theme pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/theme
+--- pidgin-2.10.7/pidgin/pixmaps/emotes/small/16/theme 2013-02-11 07:17:58.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/emotes/small/16/theme 2013-08-16 23:17:03.828740061 -0300
+@@ -22,8 +22,7 @@
+
+
+ [XMPP]
+-# Following XEP-0038 + GTalk + our default set, in default set order
+-# The GTalk strings come from ticket #3307.
++# Following XEP-0038 + our default set, in default set order
+ happy.png :) :-) =)
+ excited.png :-D :-d :D :d =D =d
+ sad.png :-( :(
+@@ -38,7 +37,7 @@
+ angel.png O:-) o:-)
+ shut-mouth.png :-X
+
+-# Following XEP-0038 + GTalk
++# Following XEP-0038
+ angry.png >:-( >:( X-( x-(
+ rose.png @->-- :rose:
+ phone.png :telephone:
+@@ -53,269 +52,3 @@
+ neutral.png :| :-|
+
+ # Hidden icons from the default set.
+-
+-
+-# Following AIM 6.1
+-[AIM]
+-happy.png :-) :)
+-wink.png ;-) ;)
+-sad.png :-( :(
+-tongue.png :P :p :-P :-p
+-shocked.png =-O
+-kiss.png :-*
+-excited.png :-D :D
+-embarrassed.png :-[
+-angel.png O:-)
+-thinking.png :-\\ :-/
+-crying.png :'(
+-shut-mouth.png :-X
+-glasses-cool.png 8-)
+-
+-
+-# Following Windows Live Messenger 8.1
+-[MSN]
+-happy.png :) :-)
+-excited.png :D :d :-D :-d
+-wink.png ;) ;-)
+-shocked.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)
+-in_love.png (L) (l)
+-star.png (*)
+-musical-note.png (8)
+-rose.png (F) (f)
+-kiss.png (K) (k)
+-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)
+-boy.png (Z) (z)
+-girl.png (X) (x)
+-sarcastic.png ^o)
+-sick.png +o(
+-plate.png (pl)
+-mobile.png (mp)
+-dont-know.png :^)
+-thinking.png *-)
+-thunder.png (li)
+-party.png <:o)
+-eyeroll.png 8-)
+-sleepy.png |-)
+-
+-# Hidden MSN emotes
+-cigarette.png (ci) (CI)
+-console.png (xx) (XX)
+-
+-
+-# Following QQ 2006
+-[QQ]
+-shocked.png /:O /jy /surprised
+-party.png /8-) /dy /revel
+-crying.png /:< /ll /cry
+-shut-mouth.png /:X /bz /shut_mouth
+-sleeping.png /:Z /shui /sleep
+-embarrassed.png /:-| /gg /embarassed
+-pissed-off.png /:@ /fn /pissed_off
+-excited.png /:D /cy /toothy_smile
+-happy.png /:) /wx /small_smile
+-sad.png /:( /ng /sad
+-glasses-cool.png /:+ /kuk /cool
+-sick.png /:T /tu /vomit
+-sleepy.png /|-) /kun /sleepy
+-hot.png /:L /sweat
+-question.png /? /yiw /question
+-excruciating.png /:8 /zhem /excrutiating
+-afraid.png /shake /fad /shake
+-amorous.png /love /aiq /love
+-search.png /find /zhao /search
+-hug-left.png /hug /yb /hug
+-lamp.png /! /dp /lightbulb
+-thunder.png /li /shd /lightning
+-musical-note.png /music /yy /music
+-coffee.png /coffee /kf /coffee
+-hungry.png /eat /fan /eat
+-rose.png /rose /mg /rose
+-kiss.png /kiss /wen /kiss
+-in_love.png /heart /xin /heart
+-meeting.png /meeting /hy /meeting
+-phone.png /phone /dh /phone
+-tv.png /TV /ds /TV
+-angry.png /<O> /oh /angry
+-girl.png /<00> /nv /woman
+-boy.png /<11> /nan /man
+-
+-
+-# Following ICQ 6.0
+-[ICQ]
+-happy.png :-) :)
+-neutral.png :-$
+-sad.png :-( :(
+-shocked.png =-O
+-wink.png ;-) ;)
+-tongue.png :-P :P :-p :p
+-music.png [:-}
+-sleeping.png *TIRED*
+-crying.png :'( :'-(
+-sick.png :-!
+-kiss.png :-{} :-*
+-embarrassed.png :-[
+-devil.png ]:->
+-angel.png O:-)
+-rose.png @}->--
+-shut-mouth.png :-X :X :-x :x
+-thinking.png :-\\ :-/
+-beer.png *DRINK*
+-excited.png :-D :D
+-glasses-cool.png 8-)
+-amorous.png *IN\ LOVE*
+-
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-sad.png :( :-(
+-amorous.png :x :-x :X :-X
+-angry.png X-( x-( X( x(
+-crying.png :((
+-drool.png =P~ =p~
+-lying.png :^O :^o
+-wink.png ;) ;-)
+-embarrassed.png :">
+-mean.png :-> :>
+-thinking.png :-?
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.png I-) i-) |-)
+-kiss.png :-* :*
+-confused.png :-S :-s
+-sarcastic.png /:)
+-eyeroll.png 8-|
+-hug-left.png >:D< >:d<
+-hot.png #:-S #:-s
+-party.png <:-P <:-p
+-nervous.png :-SS :-Ss :-sS :-ss
+-
+-# Hidden Yahoo emotes
+-coffee.png ~o) ~O)
+-rose.png @};-
+-dont-know.png :-L :-l
+-lamp.png *-:)
+-shame.png [-X [-x
+-musical-note.png :-"
+-star.png (*)
+-
+-# Following Yahoo! Messenger 8.1
+-[Yahoo JAPAN]
+-happy.png :) :-)
+-question.png :-/ :-\\
+-shocked.png :-O :O :-o :o
+-devil.png >:)
+-angel.png O:-) o:-) 0:-)
+-sick.png :-&
+-sleepy.png (:|
+-sad.png :( :-(
+-amorous.png :x :-x :X :-X
+-angry.png X-( x-( X( x(
+-crying.png :((
+-wink.png ;) ;-)
+-thinking.png :-?
+-excited.png :D :-D :d :-d
+-tongue.png :-P :P :-p :p
+-glasses-cool.png B-) b-)
+-neutral.png :| :-|
+-sleeping.png I-) i-) |-)
+-kiss.png :-* :*
+-confused.png :-S :-s
+-sarcastic.png /:)
+-eyeroll.png 8-|
+-hug-left.png >:D< >:d<
+-party.png <:-P <:-p
+-
+-# Hidden Yahoo emotes
+-coffee.png ~o) ~O)
+-rose.png @};-
+-dont-know.png :-L :-l
+-lamp.png *-:)
+-shame.png [-X [-x
+-musical-note.png :-"
+-star.png (*)
+-
+-
+-# Following MySpaceIM Beta 1.0.697.0
+-[MySpaceIM]
+-excited.png :D :-D
+-devil.png }:)
+-confused.png :Z
+-happy.png :) :-)
+-amorous.png :X
+-pirate.png P)
+-shocked.png :O
+-neutral.png :|
+-tongue.png :P :p
+-pissed-off.png B|
+-wink.png ;-) ;)
+-sad.png :[
+-kiss.png :x
+-
+-# MXit standard emoticons
+-[MXit]
+-happy.png :-) :)
+-sad.png :-( :(
+-wink.png ;-) ;)
+-excited.png :-D :D :-> :>
+-neutral.png :-| :|
+-shocked.png :-O :O
+-tongue.png :-P :P
+-embarrassed.png :-$ :$
+-glasses-cool.png 8-)
+-in_love.png (H)
+-rose.png (F)
+-### Added in v3.0
+-boy.png (m)
+-girl.png (f)
+-star.png (*)
+-chilli.png (c)
+-kiss.png (x)
+-lamp.png (i)
+-pissed-off.png :e :-e
+-shut-mouth.png :-x :x
+-thunder.png (z)
+-coffee.png (U)
+-mrgreen.png (G)
+-### Added in v5.0
+-sick.png :o(
+-excruciating.png :-{ :{
+-amorous.png :-} :}
+-eyeroll.png 8-o 8o
+-crying.png :'(
+-thinking.png :-? :?
+-drool.png :-~ :~
+-sleeping.png :-z :z
+-lying.png :L)
+-glasses-nerdy.png 8-| 8|
+-pirate.png P-)
+-### Added in v5.9.7
+-bored.png :-[ :[
+-cold.png :-< :<
+-confused.png :-, :,
+-hungry.png :-C :C
+-stressed.png :-s :s
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/Makefile.am pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.am
+--- pidgin-2.10.7/pidgin/pixmaps/Makefile.am 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.am 2013-08-17 00:00:17.335924146 -0300
+@@ -204,37 +204,19 @@
+ emotes/small/16/scalable/pidgin-emotes.svg
+
+ PROTOCOLS_16_SCALABLE = \
+- protocols/16/scalable/aim.svg \
+ protocols/16/scalable/bonjour.svg \
+- protocols/16/scalable/gadu-gadu.svg \
+- protocols/16/scalable/novell.svg \
+- protocols/16/scalable/icq.svg \
+ protocols/16/scalable/irc.svg \
+ protocols/16/scalable/jabber.svg \
+- protocols/16/scalable/meanwhile.svg \
+- protocols/16/scalable/msn.svg \
+ protocols/16/scalable/silc.svg \
+ protocols/16/scalable/simple.svg \
+- protocols/16/scalable/yahoo.svg \
+ protocols/16/scalable/zephyr.svg
+
+ PROTOCOLS_16 = \
+- protocols/16/aim.png \
+ protocols/16/bonjour.png \
+- protocols/16/facebook.png \
+- protocols/16/gadu-gadu.png \
+- protocols/16/google-talk.png \
+- protocols/16/novell.png \
+- protocols/16/icq.png \
+ protocols/16/irc.png \
+ protocols/16/jabber.png \
+- protocols/16/meanwhile.png \
+- protocols/16/msn.png \
+- protocols/16/mxit.png \
+- protocols/16/myspace.png \
+ protocols/16/silc.png \
+ protocols/16/simple.png \
+- protocols/16/yahoo.png \
+ protocols/16/zephyr.png
+
+ ICONS_16_SCALABLE = \
+@@ -259,72 +241,35 @@
+ ICONS_SCALABLE = icons/hicolor/scalable/apps/pidgin.svg
+
+ PROTOCOLS_22_SCALABLE = \
+- protocols/22/scalable/aim.svg \
+ protocols/22/scalable/bonjour.svg \
+- protocols/22/scalable/gadu-gadu.svg \
+- protocols/22/scalable/novell.svg \
+- protocols/22/scalable/icq.svg \
+ protocols/22/scalable/irc.svg \
+ protocols/22/scalable/jabber.svg \
+- protocols/22/scalable/meanwhile.svg \
+- protocols/22/scalable/msn.svg \
+ protocols/22/scalable/silc.svg \
+ protocols/22/scalable/simple.svg \
+- protocols/22/scalable/yahoo.svg \
+ protocols/22/scalable/zephyr.svg
+
+ PROTOCOLS_22 = \
+- protocols/22/aim.png \
+ protocols/22/bonjour.png \
+- protocols/22/facebook.png \
+- protocols/22/gadu-gadu.png \
+- protocols/22/google-talk.png \
+- protocols/22/novell.png \
+- protocols/22/icq.png \
+ protocols/22/irc.png \
+ protocols/22/jabber.png \
+- protocols/22/meanwhile.png \
+- protocols/22/msn.png \
+- protocols/22/mxit.png \
+- protocols/22/myspace.png \
+ protocols/22/silc.png \
+ protocols/22/simple.png \
+- protocols/22/yahoo.png \
+ protocols/22/zephyr.png
+
+ PROTOCOLS_48 = \
+- protocols/48/aim.png \
+ protocols/48/bonjour.png \
+- protocols/48/facebook.png \
+- protocols/48/gadu-gadu.png \
+- protocols/48/novell.png \
+- protocols/48/icq.png \
+ protocols/48/irc.png \
+ protocols/48/jabber.png \
+- protocols/48/meanwhile.png \
+- protocols/48/msn.png \
+- protocols/48/mxit.png \
+- protocols/48/myspace.png \
+ protocols/48/silc.png \
+ protocols/48/simple.png \
+- protocols/48/yahoo.png \
+ protocols/48/zephyr.png
+
+ PROTOCOLS_SCALABLE = \
+- protocols/scalable/aim.svg \
+ protocols/scalable/bonjour.svg \
+- protocols/scalable/gadu-gadu.svg \
+- protocols/scalable/google-talk.svg \
+- protocols/scalable/novell.svg \
+- protocols/scalable/icq.svg \
+ protocols/scalable/irc.svg \
+ protocols/scalable/jabber.svg \
+- protocols/scalable/meanwhile.svg \
+- protocols/scalable/msn.svg \
+- protocols/scalable/mxit.svg \
+ protocols/scalable/silc.svg \
+ protocols/scalable/simple.svg \
+- protocols/scalable/yahoo.svg \
+ protocols/scalable/zephyr.svg
+
+ STATUS_11 = \
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/Makefile.in pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.in
+--- pidgin-2.10.7/pidgin/pixmaps/Makefile.in 2013-02-11 07:17:23.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.in 2013-08-16 23:59:52.918508551 -0300
+@@ -240,40 +240,19 @@
+ emblems/scalable/male.svg emblems/scalable/not-authorized.svg \
+ emblems/scalable/secure.svg emblems/scalable/unavailable.svg \
+ emblems/scalable/video.svg emblems/scalable/voice.svg \
+- protocols/16/aim.png protocols/16/bonjour.png \
+- protocols/16/facebook.png protocols/16/gadu-gadu.png \
+- protocols/16/google-talk.png protocols/16/novell.png \
+- protocols/16/icq.png protocols/16/irc.png \
+- protocols/16/jabber.png protocols/16/meanwhile.png \
+- protocols/16/msn.png protocols/16/mxit.png \
+- protocols/16/myspace.png protocols/16/silc.png \
+- protocols/16/simple.png protocols/16/yahoo.png \
+- protocols/16/zephyr.png protocols/22/aim.png \
+- protocols/22/bonjour.png protocols/22/facebook.png \
+- protocols/22/gadu-gadu.png protocols/22/google-talk.png \
+- protocols/22/novell.png protocols/22/icq.png \
+- protocols/22/irc.png protocols/22/jabber.png \
+- protocols/22/meanwhile.png protocols/22/msn.png \
+- protocols/22/mxit.png protocols/22/myspace.png \
+- protocols/22/silc.png protocols/22/simple.png \
+- protocols/22/yahoo.png protocols/22/zephyr.png \
+- protocols/48/aim.png protocols/48/bonjour.png \
+- protocols/48/facebook.png protocols/48/gadu-gadu.png \
+- protocols/48/novell.png protocols/48/icq.png \
+- protocols/48/irc.png protocols/48/jabber.png \
+- protocols/48/meanwhile.png protocols/48/msn.png \
+- protocols/48/mxit.png protocols/48/myspace.png \
+- protocols/48/silc.png protocols/48/simple.png \
+- protocols/48/yahoo.png protocols/48/zephyr.png \
+- protocols/scalable/aim.svg protocols/scalable/bonjour.svg \
+- protocols/scalable/gadu-gadu.svg \
+- protocols/scalable/google-talk.svg \
+- protocols/scalable/novell.svg protocols/scalable/icq.svg \
+- protocols/scalable/irc.svg protocols/scalable/jabber.svg \
+- protocols/scalable/meanwhile.svg protocols/scalable/msn.svg \
+- protocols/scalable/mxit.svg protocols/scalable/silc.svg \
+- protocols/scalable/simple.svg protocols/scalable/yahoo.svg \
+- protocols/scalable/zephyr.svg status/11/available.png \
++ protocols/16/bonjour.png protocols/16/irc.png \
++ protocols/16/jabber.png protocols/16/silc.png \
++ protocols/16/simple.png protocols/16/zephyr.png \
++ protocols/22/bonjour.png protocols/22/irc.png \
++ protocols/22/jabber.png protocols/22/silc.png \
++ protocols/22/simple.png protocols/22/zephyr.png \
++ protocols/48/bonjour.png protocols/48/irc.png \
++ protocols/48/jabber.png protocols/48/silc.png \
++ protocols/48/simple.png protocols/48/zephyr.png \
++ protocols/scalable/bonjour.svg protocols/scalable/irc.svg \
++ protocols/scalable/jabber.svg protocols/scalable/silc.svg \
++ protocols/scalable/simple.svg protocols/scalable/zephyr.svg \
++ status/11/available.png \
+ status/11/away.png status/11/busy.png status/11/chat.png \
+ status/11/extended-away.png status/11/invisible.png \
+ status/11/log-in.png status/11/log-out.png \
+@@ -443,8 +422,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -506,8 +483,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+@@ -850,37 +825,19 @@
+ @INSTALL_PIXMAPS_TRUE@ emotes/small/16/scalable/pidgin-emotes.svg
+
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_16_SCALABLE = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/aim.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/bonjour.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/gadu-gadu.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/novell.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/icq.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/irc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/jabber.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/meanwhile.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/msn.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/silc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/simple.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/yahoo.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/scalable/zephyr.svg
+
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_16 = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/aim.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/bonjour.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/facebook.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/gadu-gadu.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/google-talk.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/novell.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/icq.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/irc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/jabber.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/meanwhile.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/msn.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/mxit.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/myspace.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/silc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/simple.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/16/yahoo.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/16/zephyr.png
+
+ @INSTALL_PIXMAPS_TRUE@ICONS_16_SCALABLE = \
+@@ -899,72 +856,35 @@
+ @INSTALL_PIXMAPS_TRUE@ICONS_48 = icons/hicolor/48x48/apps/pidgin.png
+ @INSTALL_PIXMAPS_TRUE@ICONS_SCALABLE = icons/hicolor/scalable/apps/pidgin.svg
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_22_SCALABLE = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/aim.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/bonjour.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/gadu-gadu.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/novell.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/icq.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/irc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/jabber.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/meanwhile.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/msn.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/silc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/simple.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/yahoo.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/scalable/zephyr.svg
+
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_22 = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/aim.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/bonjour.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/facebook.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/gadu-gadu.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/google-talk.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/novell.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/icq.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/irc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/jabber.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/meanwhile.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/msn.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/mxit.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/myspace.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/silc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/simple.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/22/yahoo.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/22/zephyr.png
+
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_48 = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/aim.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/bonjour.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/facebook.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/gadu-gadu.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/novell.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/icq.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/irc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/jabber.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/meanwhile.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/msn.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/mxit.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/myspace.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/silc.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/simple.png \
+-@INSTALL_PIXMAPS_TRUE@ protocols/48/yahoo.png \
+ @INSTALL_PIXMAPS_TRUE@ protocols/48/zephyr.png
+
+ @INSTALL_PIXMAPS_TRUE@PROTOCOLS_SCALABLE = \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/aim.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/bonjour.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/gadu-gadu.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/google-talk.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/novell.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/icq.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/irc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/jabber.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/meanwhile.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/msn.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/mxit.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/silc.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/simple.svg \
+-@INSTALL_PIXMAPS_TRUE@ protocols/scalable/yahoo.svg \
+ @INSTALL_PIXMAPS_TRUE@ protocols/scalable/zephyr.svg
+
+ @INSTALL_PIXMAPS_TRUE@STATUS_11 = \
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.mingw
+--- pidgin-2.10.7/pidgin/pixmaps/Makefile.mingw 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,51 +0,0 @@
+-#
+-# 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.mingw
+-
+-.PHONY: install clean
+-
+-install: ./Makefile.am.mingw
+- if test '$(SUBDIRS)'; then \
+- list='$(SUBDIRS)'; for subdir in $$list; do \
+- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) install || exit 1 ;\
+- done; \
+- fi;
+- if test '$(nobase_dist_pidginpixmap_DATA)'; then \
+- list='$(nobase_dist_pidginpixmap_DATA)'; for file in $$list; do \
+- dir=`dirname $$file`; \
+- mkdir -p $(pidginpixmapdir)/$$dir; \
+- cp $$file $(pidginpixmapdir)/$$dir/; \
+- done; \
+- fi;
+- if test '$(pidginbuttonpix_DATA)'; then \
+- mkdir -p $(pidginbuttonpixdir); \
+- cp $(pidginbuttonpix_DATA) $(pidginbuttonpixdir); \
+- fi;
+- if test '$(pidgindistpix_DATA)'; then \
+- mkdir -p $(pidgindistpixdir); \
+- cp $(pidgindistpix_DATA) $(pidgindistpixdir); \
+- fi;
+-
+-clean: ./Makefile.am.mingw
+- if test '$(SUBDIRS)'; then \
+- list='$(SUBDIRS)'; for subdir in $$list; do \
+- $(MAKE) -C $$subdir -f $(MINGW_MAKEFILE) clean;\
+- done; \
+- fi;
+- rm -f ./Makefile.am.mingw
+-
+-./Makefile.am.mingw: ./Makefile.am ./Makefile.mingw
+- sed \
+- -e 's/^if\ INSTALL_PIXMAPS/ifeq (\$$(INSTALL_PIXMAPS), 1)/' \
+- -e 's/^if\ ENABLE_TRAYCOMPAT/ifeq (\$$(ENABLE_TRAYCOMPAT), 1)/' \
+- $< > $@
+- include $@
+-
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/aim.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/facebook.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/gadu-gadu.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/google-talk.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/google-talk.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/icq.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/meanwhile.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/msn.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/mxit.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/myspace.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/novell.png differ
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/aim.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,265 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4248"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
+- sodipodi:docname="aim.svg"
+- inkscape:export-filename="/home/hbons/Bureaublad/aim.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4250">
+- <inkscape:perspective
+- sodipodi:type="inkscape:persp3d"
+- inkscape:vp_x="0 : 8 : 1"
+- inkscape:vp_y="0 : 1000 : 0"
+- inkscape:vp_z="16 : 8 : 1"
+- inkscape:persp3d-origin="8 : 5.3333333 : 1"
+- id="perspective40" />
+- <linearGradient
+- id="linearGradient8711"
+- inkscape:collect="always">
+- <stop
+- id="stop8713"
+- offset="0"
+- style="stop-color:#bb7e07;stop-opacity:1" />
+- <stop
+- id="stop8715"
+- offset="1"
+- style="stop-color:#926205;stop-opacity:1" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8703">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8705" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8707" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8686">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8688" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8690" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8784">
+- <stop
+- style="stop-color:#bb9007;stop-opacity:1;"
+- offset="0"
+- id="stop8786" />
+- <stop
+- style="stop-color:#927005;stop-opacity:1"
+- offset="1"
+- id="stop8788" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8776">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8778" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8780" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8653">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8655" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8657" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8637">
+- <stop
+- style="stop-color:#be7800;stop-opacity:1"
+- offset="0"
+- id="stop8639" />
+- <stop
+- style="stop-color:#906400;stop-opacity:1"
+- offset="1"
+- id="stop8641" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8637"
+- id="linearGradient8643"
+- x1="9.1367941"
+- y1="1.628371"
+- x2="16.636042"
+- y2="10.933484"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8653"
+- id="linearGradient8659"
+- x1="4.7796931"
+- y1="-4.2560463"
+- x2="14.475067"
+- y2="9.7333546"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8776"
+- id="linearGradient8782"
+- x1="9.4571943"
+- y1="4.418859"
+- x2="4.7050147"
+- y2="15.798837"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8711"
+- id="linearGradient8790"
+- x1="11.863748"
+- y1="8.6871567"
+- x2="1.8747424"
+- y2="13.60194"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="translate(1.2641541,-0.2145011)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8686"
+- id="linearGradient8692"
+- x1="8.3698959"
+- y1="-1.1186354"
+- x2="14.103671"
+- y2="8.6191578"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8784"
+- id="linearGradient8696"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="translate(1.2641541,-0.2145011)"
+- x1="5.2542644"
+- y1="8.9798889"
+- x2="8.4612246"
+- y2="14.318395" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8703"
+- id="linearGradient8709"
+- x1="4.9951673"
+- y1="8.807704"
+- x2="11.323474"
+- y2="13.381649"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="19.324309"
+- inkscape:cx="22.516951"
+- inkscape:cy="8.219724"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- inkscape:snap-bbox="true"
+- inkscape:snap-nodes="false"
+- objecttolerance="10"
+- gridtolerance="10">
+- <inkscape:grid
+- type="xygrid"
+- visible="true"
+- enabled="true"
+- id="grid7865" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4253">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- style="opacity:1;fill:#f8c766;fill-opacity:1;stroke:url(#linearGradient8790);stroke-width:1.00000024000000010;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 8.9039189,4.5121855 C 2.6129138,6.1978553 8.2398799,12.598865 1.5258742,12.598865 L 1.5342001,15.603027 C 7.5993543,15.603027 7.4985792,12.514605 7.4985792,12.514605 C 9.596051,12.514605 10.513648,13.498816 10.513648,15.520135 L 14.530663,15.541737 C 14.530663,9.8333244 9.0743771,9.4942293 9.0743771,9.4942293 C 9.0743771,9.4942293 14.495884,9.4837515 14.495884,9.4837515 C 14.495884,9.4837515 14.522789,6.4996057 14.522789,6.4996057 C 12.764013,6.4996057 9.6229595,6.7951443 8.9039189,4.5121855 z"
+- id="path4275"
+- sodipodi:nodetypes="cccccccccc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0049574"
+- inkscape:original="M 8.90625 4.5 C 2.6152446 6.1856697 8.2452557 12.59375 1.53125 12.59375 L 1.53125 15.59375 C 7.5964042 15.59375 7.5 12.5 7.5 12.5 C 9.597472 12.5 10.5 13.509931 10.5 15.53125 L 14.53125 15.53125 C 14.53125 9.8228378 9.0625 9.5 9.0625 9.5 C 9.0625 9.5 14.5 9.46875 14.5 9.46875 C 14.5 9.4687502 14.53125 6.5 14.53125 6.5 C 12.772474 6.5 9.6252906 6.7829588 8.90625 4.5 z "
+- style="opacity:1;fill:none;fill-opacity:1;stroke:url(#linearGradient8709);stroke-width:1.00000024000000010;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path8698"
+- d="M 8.59375,5.71875 C 7.7134558,6.0620005 7.2084274,6.4771924 6.9375,6.96875 C 6.6038545,7.5741002 6.4857642,8.3919875 6.375,9.3125 C 6.2642358,10.233013 6.1551074,11.306258 5.40625,12.21875 C 4.8173687,12.93631 3.7928472,13.277265 2.53125,13.4375 L 2.53125,14.46875 C 4.5119249,14.298403 5.6447647,13.783904 6.0625,13.34375 C 6.5586949,12.820926 6.5,12.53125 6.5,12.53125 C 6.4929534,12.261059 6.5950282,11.999416 6.7831848,11.80538 C 6.9713414,11.611343 7.2297197,11.501268 7.5,11.5 C 8.7100314,11.5 9.7708702,11.807465 10.5,12.5625 C 11.005067,13.085512 11.24875,13.784669 11.375,14.53125 L 13.28125,14.53125 C 12.990694,12.836887 12.221366,11.796156 11.28125,11.25 C 10.140118,10.587065 9,10.5 9,10.5 C 8.4861533,10.434579 8.1061894,9.9893393 8.1223688,9.4715975 C 8.1385483,8.9538556 8.5455711,8.5332097 9.0625,8.5 C 9.0625,8.5 12.168012,8.4764051 13.5,8.46875 C 13.504703,8.0219179 13.526621,7.9084884 13.53125,7.46875 C 12.783297,7.4790943 12.026654,7.5202371 11.125,7.34375 C 10.175282,7.157855 9.2606835,6.5802813 8.59375,5.71875 z" />
+- <path
+- sodipodi:type="arc"
+- style="fill:#f8c766;fill-opacity:1;stroke:url(#linearGradient8643);stroke-width:2.02997636999999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
+- transform="matrix(0.4926163,0,0,0.4926163,3.7999997,1.0105423)" />
+- <path
+- sodipodi:type="arc"
+- style="fill:none;fill-opacity:1;stroke:url(#linearGradient8692);stroke-width:3.38329338999999996;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path8682"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
+- transform="matrix(0.2955698,0,0,0.2955698,5.8799995,1.8063252)" />
+- <rect
+- style="opacity:0.11574074;fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8649"
+- width="1"
+- height="4"
+- x="1"
+- y="12" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,365 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg10335"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docname="emote-select.svg"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape"
+- inkscape:export-filename="/home/hbons/Bureaublad/gadu-gadu.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90">
+- <defs
+- id="defs10337">
+- <linearGradient
+- id="linearGradient8687"
+- inkscape:collect="always">
+- <stop
+- id="stop8689"
+- offset="0"
+- style="stop-color:#f57575;stop-opacity:1" />
+- <stop
+- id="stop8691"
+- offset="1"
+- style="stop-color:#fea523;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8653">
+- <stop
+- style="stop-color:#a40000;stop-opacity:1;"
+- offset="0"
+- id="stop8655" />
+- <stop
+- style="stop-color:#ef2929;stop-opacity:1"
+- offset="1"
+- id="stop8657" />
+- </linearGradient>
+- <inkscape:perspective
+- sodipodi:type="inkscape:persp3d"
+- inkscape:vp_x="0 : 8 : 1"
+- inkscape:vp_y="0 : 1000 : 0"
+- inkscape:vp_z="16 : 8 : 1"
+- inkscape:persp3d-origin="8 : 5.3333333 : 1"
+- id="perspective44" />
+- <linearGradient
+- id="linearGradient11170"
+- inkscape:collect="always">
+- <stop
+- id="stop11172"
+- offset="0"
+- style="stop-color:#000000;stop-opacity:1" />
+- <stop
+- id="stop11174"
+- offset="1"
+- style="stop-color:#2e3436;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient11164"
+- inkscape:collect="always">
+- <stop
+- id="stop11166"
+- offset="0"
+- style="stop-color:#000000;stop-opacity:1" />
+- <stop
+- id="stop11168"
+- offset="1"
+- style="stop-color:#2e3436;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient22870">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop22872" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop22874" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient22870"
+- id="linearGradient20933"
+- gradientUnits="userSpaceOnUse"
+- x1="-11.187567"
+- y1="-14.181667"
+- x2="31.90255"
+- y2="35.477989" />
+- <linearGradient
+- id="linearGradient11461"
+- inkscape:collect="always">
+- <stop
+- id="stop11463"
+- offset="0"
+- style="stop-color:#fbfeac;stop-opacity:1" />
+- <stop
+- id="stop11465"
+- offset="1"
+- style="stop-color:#eedb3c;stop-opacity:0;" />
+- </linearGradient>
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient11461"
+- id="radialGradient20931"
+- gradientUnits="userSpaceOnUse"
+- cx="11.806158"
+- cy="10.04414"
+- fx="11.88395"
+- fy="6.1128922"
+- r="10.561975"
+- gradientTransform="matrix(1.9034559,3.0329373e-8,-4.2282289e-8,2.6533656,-10.666343,-17.069444)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient22526"
+- id="linearGradient20942"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.8000001,0,0,0.8980646,-0.6999993,-2.2354831)"
+- x1="8.5062485"
+- y1="9.7487373"
+- x2="8.7451591"
+- y2="10.765122" />
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient22526">
+- <stop
+- style="stop-color:#f57575;stop-opacity:1"
+- offset="0"
+- id="stop22528" />
+- <stop
+- style="stop-color:#fea523;stop-opacity:0;"
+- offset="1"
+- id="stop22530" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8687"
+- id="linearGradient20915"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="translate(7.000002,1)"
+- x1="9.2937651"
+- y1="8.8493233"
+- x2="8.7171106"
+- y2="10" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient11164"
+- id="linearGradient11158"
+- gradientUnits="userSpaceOnUse"
+- x1="9.432662"
+- y1="9.6526775"
+- x2="10.732871"
+- y2="9.6526775" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient11170"
+- id="linearGradient11160"
+- gradientUnits="userSpaceOnUse"
+- x1="9.432662"
+- y1="9.6526775"
+- x2="10.732871"
+- y2="9.6526775" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8653"
+- id="linearGradient8659"
+- x1="14.605568"
+- y1="14.845765"
+- x2="9.3490162"
+- y2="3.9909718"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="31.392433"
+- inkscape:cx="15.513311"
+- inkscape:cy="8.506005"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:snap-nodes="false"
+- inkscape:snap-bbox="true"
+- objecttolerance="10"
+- gridtolerance="10"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0">
+- <inkscape:grid
+- type="xygrid"
+- id="grid10376"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata10340">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <rect
+- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8683"
+- width="2.0000002"
+- height="2"
+- x="12"
+- y="12"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8685"
+- width="2.0000002"
+- height="2"
+- x="2"
+- y="12"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8681"
+- width="2.0000002"
+- height="2"
+- x="12"
+- y="2"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8679"
+- width="2.0000002"
+- height="2"
+- x="1.9999998"
+- y="2"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8675"
+- width="2.0000002"
+- height="2"
+- x="14"
+- y="7"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8671"
+- width="2.0000002"
+- height="2"
+- x="-2.3841858e-07"
+- y="7"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#a40000;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8665"
+- width="2.0000002"
+- height="2"
+- x="7"
+- y="14"
+- rx="1"
+- ry="1" />
+- <rect
+- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:1;stroke-linecap:square;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;enable-background:accumulate"
+- id="rect8663"
+- width="2.0000002"
+- height="2"
+- x="7"
+- y="0"
+- rx="1"
+- ry="1" />
+- <rect
+- inkscape:label="22x22"
+- y="-0.90471238"
+- x="-0.90471238"
+- height="17.809425"
+- width="17.809425"
+- id="rect6749"
+- style="opacity:0;fill:#d3d7cf;fill-opacity:0;fill-rule:nonzero;stroke:none;stroke-width:2;marker:none;marker-start:none;marker-mid:none;marker-end:none;visibility:visible;display:inline;overflow:visible;enable-background:accumulate" />
+- <path
+- transform="matrix(0.651488,0,0,0.651488,0.30843,0.8446922)"
+- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
+- sodipodi:ry="9.975256"
+- sodipodi:rx="9.975256"
+- sodipodi:cy="10.983024"
+- sodipodi:cx="11.806158"
+- id="path17960"
+- style="opacity:1;fill:#fcaf3e;fill-opacity:1;stroke:url(#linearGradient8659);stroke-width:1.53875661000000008;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
+- sodipodi:type="arc" />
+- <path
+- transform="matrix(0.5513643,0,0,0.5513643,1.490506,1.944353)"
+- d="M 21.781414,10.983024 A 9.975256,9.975256 0 1 1 1.8309021,10.983024 A 9.975256,9.975256 0 1 1 21.781414,10.983024 z"
+- sodipodi:ry="9.975256"
+- sodipodi:rx="9.975256"
+- sodipodi:cy="10.983024"
+- sodipodi:cx="11.806158"
+- id="path17964"
+- style="opacity:1;fill:url(#radialGradient20931);fill-opacity:1;stroke:url(#linearGradient20933);stroke-width:1.81368327;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
+- sodipodi:type="arc" />
+- <path
+- id="path17966"
+- d="M 8.5000005,6.7451615 C 8.5000005,7.9844904 7.604002,8.9903231 6.500001,8.9903231 C 5.3959999,8.9903231 4.5000001,7.9844904 4.5000001,6.7451615 C 4.5000001,5.5058325 5.3959999,4.5000005 6.500001,4.5000005 C 7.604002,4.5000005 8.5000005,5.5058325 8.5000005,6.7451615 z"
+- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20942);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new" />
+- <path
+- sodipodi:nodetypes="cscsc"
+- id="path17974"
+- d="M 11,10 C 10.887023,11.226829 9.4422911,12 8.0000003,12 C 6.5577095,12 5.2085418,11.396721 5,10 C 5.6322481,10.739405 6.7426661,11.065616 8.0000003,11.065616 C 9.2573337,11.065616 10.367752,10.739405 11,10 z"
+- style="opacity:1;fill:#b40c0c;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new" />
+- <a
+- style="opacity:1;display:inline;enable-background:new"
+- id="a22276"
+- transform="matrix(0.8295523,0,0,0.9130993,-3.698956,-3.261344)">
+- <path
+- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:url(#linearGradient20915);stroke-width:1.14899766;stroke-miterlimit:4;stroke-opacity:1;display:inline;enable-background:new"
+- d="M 18.5,11 C 18.5,12.38 17.380001,13.5 16,13.5 C 14.62,13.5 13.5,12.38 13.5,11 C 13.5,9.62 14.62,8.5 16,8.5 C 17.380001,8.5 18.5,9.62 18.5,11 z"
+- id="path22835" />
+- </a>
+- <path
+- transform="matrix(0.9747196,0,0,0.5150957,-2.4615398,2.0279474)"
+- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
+- sodipodi:ry="1.9413869"
+- sodipodi:rx="1.0259361"
+- sodipodi:cy="9.6526775"
+- sodipodi:cx="9.7069349"
+- id="path17968"
+- style="opacity:1;fill:url(#linearGradient11160);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
+- sodipodi:type="arc" />
+- <path
+- transform="matrix(-0.9747196,0,0,0.5150957,18.46154,2.0279474)"
+- d="M 10.732871,9.6526775 A 1.0259361,1.9413869 0 1 1 8.6809988,9.6526775 A 1.0259361,1.9413869 0 1 1 10.732871,9.6526775 z"
+- sodipodi:ry="1.9413869"
+- sodipodi:rx="1.0259361"
+- sodipodi:cy="9.6526775"
+- sodipodi:cx="9.7069349"
+- id="path11156"
+- style="opacity:1;fill:url(#linearGradient11158);fill-opacity:1;stroke:none;stroke-width:0.98640186;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;display:inline;enable-background:new"
+- sodipodi:type="arc" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/icq.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,579 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4248"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16"
+- sodipodi:docname="icq.svg"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape"
+- inkscape:export-filename="/home/hbons/Bureaublad/icq.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90">
+- <defs
+- id="defs4250">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8780">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8782" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8784" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8772">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8774" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8776" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8764">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8766" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8768" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8756">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8758" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8760" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8748">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8750" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8752" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8740">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8742" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8744" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8732">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8734" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8736" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8724">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8726" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8728" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8716">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8718" />
+- <stop
+- style="stop-color:#2a5402;stop-opacity:1"
+- offset="1"
+- id="stop8720" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8708">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8710" />
+- <stop
+- style="stop-color:#346804;stop-opacity:1"
+- offset="1"
+- id="stop8712" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8700">
+- <stop
+- style="stop-color:#b90000;stop-opacity:1"
+- offset="0"
+- id="stop8702" />
+- <stop
+- style="stop-color:#6c0000;stop-opacity:1"
+- offset="1"
+- id="stop8704" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8692">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8694" />
+- <stop
+- style="stop-color:#3c7604;stop-opacity:1"
+- offset="1"
+- id="stop8696" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8684">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8686" />
+- <stop
+- style="stop-color:#356a04;stop-opacity:1"
+- offset="1"
+- id="stop8688" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8676">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8678" />
+- <stop
+- style="stop-color:#346803;stop-opacity:1"
+- offset="1"
+- id="stop8680" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8668">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8670" />
+- <stop
+- style="stop-color:#336603;stop-opacity:1"
+- offset="1"
+- id="stop8672" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8660">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8662" />
+- <stop
+- style="stop-color:#3a7404;stop-opacity:1"
+- offset="1"
+- id="stop8664" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8652">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8654" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8656" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8644">
+- <stop
+- style="stop-color:#c4a000;stop-opacity:1;"
+- offset="0"
+- id="stop8646" />
+- <stop
+- style="stop-color:#907600;stop-opacity:1"
+- offset="1"
+- id="stop8648" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2321">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2323" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0"
+- offset="1"
+- id="stop2325" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2361">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2363" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2365" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2321"
+- id="linearGradient4381"
+- gradientUnits="userSpaceOnUse"
+- x1="11.787398"
+- y1="11.115861"
+- x2="12.075002"
+- y2="12.360133" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2361"
+- id="linearGradient4383"
+- gradientUnits="userSpaceOnUse"
+- x1="6.3009863"
+- y1="8.3052416"
+- x2="6.3009863"
+- y2="17.320574"
+- gradientTransform="matrix(0.7516425,0,0,0.6729501,-0.8826506,1.4152198)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8644"
+- id="linearGradient8650"
+- x1="6.5158038"
+- y1="6.3653116"
+- x2="9.9300232"
+- y2="10.764107"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8652"
+- id="linearGradient8658"
+- x1="10.444659"
+- y1="12.360133"
+- x2="13.705344"
+- y2="12.360133"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8660"
+- id="linearGradient8666"
+- x1="9.8111737"
+- y1="4.9999985"
+- x2="17.188837"
+- y2="4.9999985"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.666684,0,0,0.8570726,0.499765,-0.7853612)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8668"
+- id="linearGradient8674"
+- x1="15.004629"
+- y1="16.519621"
+- x2="16.441046"
+- y2="19.245642"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8676"
+- id="linearGradient8682"
+- x1="11.152212"
+- y1="15.892158"
+- x2="9.9561481"
+- y2="19.775995"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8684"
+- id="linearGradient8690"
+- x1="13.906936"
+- y1="12.503142"
+- x2="22.096945"
+- y2="12.503142"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8692"
+- id="linearGradient8698"
+- x1="17.85483"
+- y1="7.9999962"
+- x2="19.682709"
+- y2="9.6703825"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8700"
+- id="linearGradient8706"
+- x1="5.3079047"
+- y1="14.33169"
+- x2="6.2636456"
+- y2="16.783527"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8708"
+- id="linearGradient8714"
+- x1="4.4860797"
+- y1="2.7814157"
+- x2="6.3950372"
+- y2="4.8916488"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8716"
+- id="linearGradient8722"
+- x1="6.2442408"
+- y1="8.825284"
+- x2="7.2848325"
+- y2="12.785048"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8724"
+- id="linearGradient8730"
+- x1="13.914243"
+- y1="3.5516012"
+- x2="12.632175"
+- y2="7.0243564"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.507229,0,0,0.7963119,2.6510069,-0.4796384)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8732"
+- id="linearGradient8738"
+- x1="8.2830858"
+- y1="4.66011"
+- x2="10.320723"
+- y2="6.5236211"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.658982,0,0,0.733665,-0.42174,-4.3113681e-2)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8740"
+- id="linearGradient8746"
+- x1="4.4425683"
+- y1="8.8338633"
+- x2="8.630022"
+- y2="10.278849"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.8000894,0,0,0.761045,-1.308226,-0.22823)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8748"
+- id="linearGradient8754"
+- x1="19.372143"
+- y1="6.7050757"
+- x2="15.963639"
+- y2="9.5312366"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.7538717,0,0,0.6730629,-1.1855766,0.1251422)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8756"
+- id="linearGradient8762"
+- x1="19.567648"
+- y1="13.050652"
+- x2="15.45147"
+- y2="12.219797"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8764"
+- id="linearGradient8770"
+- x1="16.516554"
+- y1="18.227236"
+- x2="14.661788"
+- y2="15.899495"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.6456695,0,0,0.740569,0.8060648,-0.220494)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8772"
+- id="linearGradient8778"
+- x1="10.093229"
+- y1="18.792187"
+- x2="10.940947"
+- y2="15.521823"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.7610362,0,0,0.799758,-0.9891698,-1.10256)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8780"
+- id="linearGradient8786"
+- x1="4.1927366"
+- y1="16.487579"
+- x2="6.7825565"
+- y2="14.544259"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.7516425,0,0,0.6729501,-0.8826506,1.4152198)" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="33.645576"
+- inkscape:cx="17.956733"
+- inkscape:cy="7.8216704"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- objecttolerance="10"
+- gridtolerance="10"
+- inkscape:snap-bbox="true"
+- inkscape:snap-nodes="false">
+- <inkscape:grid
+- type="xygrid"
+- id="grid7872"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4253">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8674);stroke-width:1.21922076000000001;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 12.963148,17.247339 C 12.171926,14.859179 12.454176,14.470485 13.497752,13.880864 C 14.541326,13.291244 15.108816,13.335817 16.744216,15.111033 C 17.767103,16.844843 17.750309,18.730526 16.706739,19.320144 C 15.663162,19.909767 13.986034,18.981148 12.963148,17.247339 z "
+- id="path2226"
+- transform="matrix(0.801314,0,0,0.839525,-1.523412,-1.868634)" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8770);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 10.228804,10.517757 C 10.129288,10.479606 10.118014,10.490039 9.8252606,10.679756 C 9.6724455,10.778787 9.5775476,10.848926 9.5427802,10.888041 C 9.5080129,10.927156 9.5107318,10.913111 9.5024259,10.957469 C 9.4869472,11.040134 9.5429901,11.490751 9.7445519,12.230322 C 10.019277,12.740003 10.386743,13.148547 10.692879,13.341176 C 11.011903,13.541914 11.205257,13.517117 11.298194,13.45689 C 11.392617,13.395699 11.497569,13.253133 11.499966,12.855177 C 11.502252,12.475722 11.370376,11.941058 11.1166,11.420325 C 10.645066,10.845418 10.310619,10.549121 10.228804,10.517757 z"
+- id="path2242" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8690);stroke-width:1.18385111999999992;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 16.771005,15.319703 C 14.33106,13.896777 14.27539,13.249081 14.702189,11.643547 C 15.128987,10.03802 15.633686,9.5050301 18.317374,9.5025628 C 20.461323,10.081613 21.854951,11.854605 21.428153,13.460133 C 21.001355,15.065667 18.914955,15.898753 16.771005,15.319703 z "
+- id="path2216"
+- transform="matrix(0.856389,0,0,0.833173,-2.916658,-1.417277)" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8762);stroke-width:1.30062020000000000;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.15625,10.5 C 17.064518,10.522558 16.402045,10.67233 16.1875,10.8125 C 15.955817,10.963867 15.820346,11.171396 15.625,11.90625 C 15.423716,12.663442 15.422318,12.879125 15.53125,13.09375 C 15.632536,13.29331 16.159381,13.76998 17.15625,14.375 C 17.98874,14.571156 18.819892,14.51269 19.40625,14.28125 C 20.02513,14.036974 20.378057,13.677476 20.5,13.21875 C 20.621263,12.762585 20.482161,12.251369 20.0625,11.71875 C 19.662743,11.211393 18.978208,10.748423 18.15625,10.5 z "
+- id="path2238"
+- transform="matrix(0.786923,0,0,0.751219,-1.665053,-0.387804)" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8698);stroke-width:1.22383844999999991;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.231066,10.043051 C 15.826638,10.834882 15.435297,10.552414 14.841659,9.5080341 C 14.248025,8.4636559 14.292902,7.895729 16.08021,6.2590696 C 17.825828,5.235395 19.724355,5.2521994 20.317989,6.2965763 C 20.911627,7.3409564 19.976685,9.0193762 18.231066,10.043051 z "
+- id="path2224"
+- transform="matrix(0.833845,0,0,0.800696,-2.590942,-0.905561)" />
+- <path
+- style="fill:#ef2929;fill-opacity:1;stroke:url(#linearGradient8706);stroke-width:1.22309434000000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.2295458,17.045044 C 4.8262841,17.837501 4.435133,17.554808 3.8417836,16.509603 C 3.2484366,15.464398 3.2932918,14.896022 5.0797326,13.258068 C 6.8245041,12.233585 8.7221095,12.250402 9.3154554,13.295606 C 9.9088085,14.34081 8.9743169,16.020559 7.2295458,17.045044 z "
+- id="path2228"
+- transform="matrix(0.835521,0,0,0.800063,-1.432383,-0.501236)" />
+- <path
+- style="opacity:0.75;fill:url(#linearGradient4383);fill-opacity:1;stroke:url(#linearGradient8786);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 4.8486235,10.500046 C 4.4564782,10.496935 3.9190242,10.637124 3.3923161,10.899611 C 2.8449198,11.364365 2.5603453,11.685808 2.5232295,11.782857 C 2.4833052,11.88725 2.475064,11.884191 2.6641625,12.182421 C 2.765801,12.342716 2.8393005,12.443491 2.8755619,12.476837 C 2.9118233,12.510183 2.8851423,12.490643 2.9225396,12.497866 C 2.9909999,12.51109 3.4626384,12.466271 4.1909363,12.26654 C 4.7259059,11.978527 5.1414644,11.620122 5.3418889,11.299174 C 5.5465286,10.971477 5.5126093,10.773335 5.4593331,10.689313 C 5.4086116,10.60932 5.2638969,10.503341 4.8486235,10.500046 z"
+- id="path2244" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8682);stroke-width:1.18253027999999993;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.6891342,15.77365 C 9.1118334,13.334726 9.7586709,13.278647 11.361671,13.703963 C 12.964665,14.129276 13.496553,14.633183 13.497097,17.314646 C 12.917316,19.457228 11.145785,20.850948 9.5427895,20.425634 C 7.93979,20.000318 7.109353,17.916231 7.6891342,15.77365 z "
+- id="path2218"
+- transform="matrix(0.834348,0,0,0.857095,-1.761273,-2.072186)" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8778);stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 6.5498451,10.543916 C 6.4093043,10.616602 6.0575323,11.02735 5.5985498,11.81853 C 5.4505732,12.478908 5.4715025,13.128474 5.6461146,13.592993 C 5.8305566,14.083663 6.1144425,14.372852 6.4547155,14.467729 C 6.7934078,14.562164 7.1943156,14.450544 7.5962698,14.117834 C 7.9788085,13.801196 8.3117436,13.270312 8.5000003,12.618288 C 8.4834797,11.748172 8.3825717,11.225309 8.2859589,11.068757 C 8.1814922,10.899479 8.0370643,10.799946 7.4773579,10.643886 C 6.8871683,10.479326 6.6912608,10.470777 6.5498451,10.543916 z"
+- id="path2240" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8714);stroke-width:1.00000142999999997;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.1358685,3.3890634 C 7.7698834,5.3939828 7.5437147,5.7203005 6.707483,6.2153016 C 5.8712512,6.7103014 5.4165141,6.6728807 4.1060474,5.1825438 C 3.2863948,3.7269694 3.29985,2.1438938 4.1360794,1.6488936 C 4.9723098,1.1538927 6.3162154,1.933489 7.1358685,3.3890634 z"
+- id="path2222" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8738);stroke-width:0.99999988;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 4.9118956,2.5017868 C 4.8344656,2.4933075 4.7351802,2.5160688 4.6853705,2.5476409 C 4.5947769,2.6050638 4.5024975,2.7622504 4.5000318,3.1666707 C 4.4976449,3.5581659 4.6240111,4.1063439 4.8913024,4.6340007 C 5.3464159,5.169468 5.6802006,5.4473321 5.7768094,5.4823009 C 5.8806263,5.5198786 5.8903157,5.5109256 6.1886732,5.3218116 C 6.3467933,5.2215868 6.4419865,5.153277 6.4769778,5.1154684 C 6.5119691,5.0776597 6.4898306,5.0865385 6.497571,5.0466873 C 6.5117411,4.9737348 6.4672348,4.52308 6.2710459,3.8086276 C 5.8382221,3.0048392 5.2079215,2.5342044 4.9118956,2.5017868 z"
+- id="path2232" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8722);stroke-width:1.18378782000000005;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.2320598,6.6863636 C 9.6715923,8.1091434 9.7272104,8.7568487 9.3003538,10.362442 C 8.8734993,11.96803 8.3688269,12.501065 5.6854848,12.503723 C 3.5418523,11.924813 2.1485268,10.151886 2.5753806,8.5462983 C 3.002236,6.9407045 5.0884273,6.1074547 7.2320598,6.6863636 z "
+- id="path2220"
+- transform="matrix(0.8565,0,0,0.833155,-1.639952,-0.917534)" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8746);stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 4.1673858,5.5985208 C 3.5054714,5.4505063 2.8569334,5.4716193 2.3921875,5.6460861 C 1.9012783,5.8303746 1.6129084,6.1118678 1.5170897,6.4546964 C 1.4218347,6.7955083 1.5091367,7.1942976 1.842126,7.5962639 C 2.1592142,7.9790353 2.7135907,8.3119339 3.3672964,8.5000048 C 4.2422495,8.4831842 4.7779308,8.3858367 4.9424724,8.2859609 C 5.1201805,8.1780935 5.2118965,8.0341525 5.3675199,7.4773506 C 5.5280018,6.9031664 5.529332,6.7148477 5.4425283,6.549827 C 5.3619401,6.3966226 4.9589342,6.0564559 4.1673858,5.5985208 z"
+- id="path2234" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8754);stroke-width:1.00000203;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 12.855285,4.500051 C 12.462919,4.4969506 11.922943,4.6374156 11.394658,4.8996821 C 10.844605,5.3646776 10.559734,5.7082145 10.522993,5.8041104 C 10.483512,5.9071611 10.474936,5.8852008 10.664344,6.1827083 C 10.766342,6.3429165 10.840542,6.4443185 10.876371,6.4771733 C 10.9122,6.5100281 10.886952,6.4911647 10.923488,6.4982065 C 10.991576,6.5113294 11.462538,6.4555529 12.219205,6.2458079 C 12.737907,5.9609072 13.130324,5.6126604 13.326454,5.2993132 C 13.531108,4.9723484 13.51988,4.7711454 13.467804,4.68935 C 13.41783,4.6108533 13.270794,4.5033345 12.855285,4.500051 z"
+- id="path2236" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8666);stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 11.375232,4.5493545 C 10.422975,6.6416097 9.9911458,6.6905364 8.9215873,6.3281422 C 7.8520275,5.9657484 7.4975249,5.534567 7.5000157,3.2363329 C 7.8893038,1.3991926 9.0732966,0.20229738 10.142856,0.56469125 C 11.212416,0.92708537 11.764519,2.7122143 11.375232,4.5493545 z"
+- id="path2192" />
+- <path
+- style="opacity:0.75;fill:none;fill-opacity:1;stroke:url(#linearGradient8730);stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 9.8631692,1.5360262 C 9.6347437,1.4415107 9.3708203,1.5274542 9.1023257,1.8595278 C 8.8466524,2.1757441 8.6265865,2.7251574 8.4999913,3.3774976 C 8.5099761,4.2473344 8.5751845,4.7795065 8.6426495,4.9452367 C 8.7155134,5.124228 8.8111337,5.2149983 9.1815803,5.3682774 C 9.5648319,5.5268552 9.6889381,5.5298463 9.7997656,5.4429315 C 9.9026575,5.3622401 10.127302,4.9625969 10.433802,4.1738094 C 10.533317,3.5150226 10.518933,2.8709279 10.4021,2.4069923 C 10.27869,1.9169393 10.091661,1.6305687 9.8631692,1.5360262 z"
+- id="path2230" />
+- <path
+- style="fill:#edd400;fill-opacity:1;stroke:url(#linearGradient8650);stroke-width:0.99999994000000003;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 10.411141,8.6353601 C 10.047567,9.96976 8.6723022,10.768109 7.3413532,10.417389 C 6.0104022,10.066669 5.2252873,8.6990358 5.5888616,7.3646359 C 5.9524355,6.0302378 7.3277,5.231889 8.6586509,5.5826094 C 9.9895999,5.9333292 10.774715,7.300962 10.411141,8.6353601 z"
+- id="path1317" />
+- <path
+- transform="matrix(1.208973,0.318578,-0.279444,1.025629,-3.144373,-8.523741)"
+- style="opacity:0.69907406999999999;fill:url(#linearGradient4381);fill-opacity:1;stroke:url(#linearGradient8658);stroke-width:0.86744213000000003;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 13.271623,12.360133 C 13.271623,13.140766 12.735537,13.774323 12.075002,13.774323 C 11.414466,13.774323 10.87838,13.140766 10.87838,12.360133 C 10.87838,11.579501 11.414466,10.945944 12.075002,10.945944 C 12.735537,10.945944 13.271623,11.579501 13.271623,12.360133 z "
+- id="path2319" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,218 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4239"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
+- sodipodi:docname="meanwhile.svg"
+- inkscape:export-filename="/home/hbons/Bureaublad/meanwhile.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4241">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8675">
+- <stop
+- style="stop-color:#fcaf3e;stop-opacity:1;"
+- offset="0"
+- id="stop8677" />
+- <stop
+- style="stop-color:#f57900;stop-opacity:1"
+- offset="1"
+- id="stop8679" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8667">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8669" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8671" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8650">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8652" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8654" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8642">
+- <stop
+- style="stop-color:#ce5c00;stop-opacity:1;"
+- offset="0"
+- id="stop8644" />
+- <stop
+- style="stop-color:#9f3400;stop-opacity:1"
+- offset="1"
+- id="stop8646" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8634">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8636" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8638" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8634"
+- id="linearGradient8640"
+- x1="9.2996664"
+- y1="-1.1926658"
+- x2="22.00433"
+- y2="12.53125"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8642"
+- id="linearGradient8648"
+- x1="8.701582"
+- y1="8.7882452"
+- x2="14.751598"
+- y2="21.009844"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8650"
+- id="linearGradient8656"
+- x1="5.3650107"
+- y1="-2.7280362"
+- x2="16.534615"
+- y2="7.1899891"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8642"
+- id="linearGradient8661"
+- gradientUnits="userSpaceOnUse"
+- x1="8.701582"
+- y1="8.7882452"
+- x2="14.751598"
+- y2="21.009844" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8667"
+- id="linearGradient8673"
+- x1="2.0414412"
+- y1="-0.75497365"
+- x2="26.409824"
+- y2="23.59227"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8675"
+- id="linearGradient8681"
+- x1="13.609824"
+- y1="12.881368"
+- x2="13.609824"
+- y2="19.507627"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="27.3287"
+- inkscape:cx="20.064702"
+- inkscape:cy="8.5317934"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- inkscape:snap-bbox="true"
+- inkscape:snap-nodes="false"
+- objecttolerance="10"
+- gridtolerance="10">
+- <inkscape:grid
+- type="xygrid"
+- id="grid7858"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4244">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- sodipodi:type="arc"
+- style="fill:#fcaf3e;fill-opacity:1;stroke:#ce5c00;stroke-width:2.02997327000000016;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
+- transform="matrix(0.4926164,0,0,0.4926165,2.7999985,1.0105418)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:none;fill-opacity:1;stroke:url(#linearGradient8656);stroke-width:3.38329315000000008;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4273"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827,4.0385542 A 5.074944,5.074944 0 1 1 5.4809394,4.0385542 A 5.074944,5.074944 0 1 1 15.630827,4.0385542 z"
+- transform="matrix(0.2955698,0,0,0.2955699,4.8799997,1.8063249)" />
+- <path
+- style="fill:url(#linearGradient8681);fill-opacity:1;stroke:url(#linearGradient8648);stroke-width:1.38365983999999997;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.764798,2.8497364 C 18.764798,6.4835545 17.015921,10.340055 12.458352,10.340055 C 7.9302336,10.340055 6.1696302,5.9347403 6.1696302,3.0077289 L 3.5191672,5.0743501 C 3.5191672,11.592509 7.7563904,12.376951 7.7563904,13.61498 C 7.7563904,14.942901 3.5055266,16.358274 3.5055266,21.425015 L 9.1348464,21.369834 C 9.1348464,19.244403 10.433516,15.786914 12.492742,15.786914 C 14.516622,15.786914 15.962656,19.213604 15.962656,21.335386 L 21.491428,21.351408 C 21.491428,15.947962 17.306969,15.024839 17.306969,13.58672 C 17.306969,12.395751 21.452377,11.632096 21.452377,5.0650054 L 18.764798,2.8497364 z"
+- id="rect2213"
+- sodipodi:nodetypes="czccccczccccc"
+- transform="matrix(0.725563,0,0,0.719891,-1.060965,0.139182)" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.3863388"
+- inkscape:original="M 18.75 2.84375 C 18.750001 6.477568 17.026319 10.34375 12.46875 10.34375 C 7.9406315 10.34375 6.15625 5.9270114 6.15625 3 L 3.53125 5.0625 C 3.53125 11.580659 7.75 12.386971 7.75 13.625 C 7.7499998 14.952921 3.5 16.370759 3.5 21.4375 L 9.125 21.375 C 9.1249997 19.249568 10.440774 15.78125 12.5 15.78125 C 14.52388 15.78125 15.96875 19.221968 15.96875 21.34375 L 21.5 21.34375 C 21.5 15.940304 17.3125 15.031869 17.3125 13.59375 C 17.3125 12.402781 21.4375 11.629591 21.4375 5.0625 L 18.75 2.84375 z "
+- style="fill:none;fill-opacity:1;stroke:url(#linearGradient8673);stroke-width:1.38365983999999997;stroke-miterlimit:4;stroke-opacity:1"
+- id="path8663"
+- d="M 19.8125,5.5 C 19.553993,6.6500796 19.130624,7.7658345 18.4375,8.75 C 17.214147,10.487035 15.139545,11.71875 12.46875,11.71875 C 9.7539446,11.71875 7.6786908,10.319904 6.46875,8.5625 C 5.8161471,7.614613 5.3955271,6.5877094 5.125,5.5625 L 5,5.65625 C 5.1326144,8.1177354 5.8516259,9.5128134 6.65625,10.40625 C 7.0969248,10.895565 7.5574921,11.26294 8,11.65625 C 8.2212539,11.852905 8.4668482,12.050594 8.6875,12.34375 C 8.9081518,12.636906 9.125,13.076568 9.125,13.625 C 9.1249998,14.696474 8.5196644,15.229886 8.0625,15.6875 C 7.6053356,16.145114 7.1243156,16.554217 6.65625,17.0625 C 5.973649,17.803752 5.4431444,18.79741 5.15625,20.03125 L 7.90625,20 C 8.0647552,19.034828 8.3367207,18.075404 8.8125,17.15625 C 9.5156693,15.797803 10.692058,14.40625 12.5,14.40625 C 14.29756,14.40625 15.483981,15.747434 16.21875,17.09375 C 16.715676,18.004266 16.982752,18.998 17.15625,19.96875 L 19.84375,19.96875 C 19.573522,18.630932 19.078136,17.632125 18.40625,16.9375 C 17.956341,16.472365 17.46334,16.095102 17,15.65625 C 16.53666,15.217398 15.9375,14.626068 15.9375,13.59375 C 15.9375,13.044739 16.156655,12.598898 16.375,12.3125 C 16.593345,12.026102 16.816217,11.846739 17.03125,11.65625 C 17.461317,11.275273 17.91606,10.919853 18.34375,10.4375 C 19.12911,9.5517623 19.845064,8.1414304 19.96875,5.625 L 19.8125,5.5 z"
+- transform="matrix(0.725563,0,0,0.719891,-1.060965,0.139182)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/msn.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,352 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4239"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
+- sodipodi:docname="msn.svg"
+- inkscape:export-filename="/home/hbons/Bureaublad/msn.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4241">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8709">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8711" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8713" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8701">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8703" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8705" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8693">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8695" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8697" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8685">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8687" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8689" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8677">
+- <stop
+- style="stop-color:#5c3566;stop-opacity:1;"
+- offset="0"
+- id="stop8679" />
+- <stop
+- style="stop-color:#874e96;stop-opacity:1"
+- offset="1"
+- id="stop8681" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8660">
+- <stop
+- style="stop-color:#275ba6;stop-opacity:1"
+- offset="0"
+- id="stop8662" />
+- <stop
+- style="stop-color:#183765;stop-opacity:1"
+- offset="1"
+- id="stop8664" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8652">
+- <stop
+- style="stop-color:#4e9a06;stop-opacity:1;"
+- offset="0"
+- id="stop8654" />
+- <stop
+- style="stop-color:#2f5f02;stop-opacity:1"
+- offset="1"
+- id="stop8656" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8644">
+- <stop
+- style="stop-color:#c4a000;stop-opacity:1;"
+- offset="0"
+- id="stop8646" />
+- <stop
+- style="stop-color:#786300;stop-opacity:1"
+- offset="1"
+- id="stop8648" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8636">
+- <stop
+- style="stop-color:#ce5d00;stop-opacity:1;"
+- offset="0"
+- id="stop8638" />
+- <stop
+- style="stop-color:#833b00;stop-opacity:1"
+- offset="1"
+- id="stop8640" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient2219"
+- inkscape:collect="always">
+- <stop
+- id="stop2221"
+- offset="0"
+- style="stop-color:#3465a4;stop-opacity:1;" />
+- <stop
+- id="stop2223"
+- offset="1"
+- style="stop-color:#3465a4;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient2228"
+- inkscape:collect="always">
+- <stop
+- id="stop2230"
+- offset="0"
+- style="stop-color:#f56600;stop-opacity:1;" />
+- <stop
+- id="stop2232"
+- offset="1"
+- style="stop-color:#f56600;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2228"
+- id="linearGradient4505"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
+- x1="20.007692"
+- y1="13.250565"
+- x2="18.727983"
+- y2="17.102213" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2219"
+- id="linearGradient4507"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.5438817,0,0,0.5799505,-0.3274572,-0.2722861)"
+- x1="10.200594"
+- y1="14.726058"
+- x2="13.252806"
+- y2="18.174761" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8636"
+- id="linearGradient8642"
+- x1="16.397886"
+- y1="7.1729202"
+- x2="19.359613"
+- y2="12.699073"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8644"
+- id="linearGradient8650"
+- x1="17.004478"
+- y1="15.059639"
+- x2="19.158651"
+- y2="19.232847"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.8565497,0,0,0.700607,-3.0651761,-0.162781)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8652"
+- id="linearGradient8658"
+- x1="11.425816"
+- y1="15.977947"
+- x2="13.070351"
+- y2="19.869415"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8660"
+- id="linearGradient8666"
+- x1="1.1384629"
+- y1="4.3090925"
+- x2="6.360837"
+- y2="9.665041"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8677"
+- id="linearGradient8683"
+- x1="9.734354"
+- y1="10.855804"
+- x2="8.227417"
+- y2="7.5956616"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8685"
+- id="linearGradient8691"
+- x1="2.27721"
+- y1="6.7656131"
+- x2="10.084975"
+- y2="12.919206"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8709"
+- id="linearGradient8733"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.789526,0,0,0.621298,-1.921384,0.986574)"
+- x1="18.850323"
+- y1="18.158928"
+- x2="17.372902"
+- y2="13.093926" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8701"
+- id="linearGradient8742"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.599236,0,0,0.624815,0.408284,1.315959)"
+- x1="12.687945"
+- y1="18.895752"
+- x2="11.633714"
+- y2="15.440485" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8693"
+- id="linearGradient8745"
+- gradientUnits="userSpaceOnUse"
+- x1="13.573946"
+- y1="3.1337965"
+- x2="11.223683"
+- y2="8.5642729" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="27.3287"
+- inkscape:cx="20.590777"
+- inkscape:cy="9.6812143"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1430"
+- inkscape:window-height="837"
+- inkscape:window-x="254"
+- inkscape:window-y="427"
+- inkscape:snap-nodes="false"
+- inkscape:snap-bbox="true"
+- objecttolerance="10"
+- gridtolerance="10">
+- <inkscape:grid
+- type="xygrid"
+- id="grid7864"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4244">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- style="fill:#edd400;fill-opacity:1;stroke:url(#linearGradient8650);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- d="M 12.726618,6.7821693 C 14.954366,7.315014 15.232686,13.499992 12.702089,13.499992 C 10.20215,13.499992 4.63567,4.846936 12.726618,6.7821693 z"
+- id="rect2194" />
+- <path
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8733);stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 10.464305,7.5102029 C 10.084666,7.5060849 9.6095224,7.6779929 9.5306688,8.0961333 C 9.4083085,8.8812767 9.7824927,9.6266355 10.172483,10.280772 C 10.718966,11.141573 11.429181,11.932478 12.346756,12.402887 C 12.624698,12.609701 12.991224,12.391706 13.128703,12.12186 C 13.685105,10.954392 13.588008,9.5514732 13.062635,8.3912413 C 12.867487,7.9910733 12.482071,7.658617 12.022113,7.639864 C 11.508321,7.5519031 10.987071,7.4717107 10.464305,7.5102029 z"
+- id="path2259" />
+- <path
+- transform="matrix(0.712542,0,0,0.698139,-0.834614,0.18154)"
+- style="fill:#73d216;fill-opacity:1;stroke:url(#linearGradient8658);stroke-width:1.41783130000000002;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
+- id="rect2201" />
+- <path
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:url(#linearGradient8742);stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 6.9969196,8.5005798 C 6.4095407,8.5652754 5.9363988,9.0353859 5.6504082,9.5247059 C 5.3128668,10.187546 5.6118436,10.924286 5.9818793,11.497377 C 6.4590192,12.279805 7.2102283,12.858859 7.9986562,13.300897 C 8.6344334,13.702713 8.4099456,12.64584 8.4957981,12.27224 C 8.4979791,11.096105 8.2902419,9.8546211 7.6065424,8.8720886 C 7.4570093,8.6818207 7.2484632,8.5134511 6.9969196,8.5005798 z"
+- id="path2254" />
+- <path
+- transform="matrix(0.720961,0,0,0.718898,-0.697672,-0.282723)"
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:white;stroke-width:1.389027;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z "
+- id="path2245" />
+- <path
+- style="fill:url(#linearGradient4507);fill-opacity:1;stroke:url(#linearGradient8666);stroke-width:1.00000106999999994;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 0.66009074,3.7661675 C 1.638065,2.0184654 11.689407,9.4126942 7.470982,10.391083 C 3.2580442,11.368199 -0.30791802,5.4960608 0.66009074,3.7661675 z"
+- id="rect2197" />
+- <path
+- transform="matrix(0.666514,0,0,0.713565,-0.165619,-0.134566)"
+- style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8691);stroke-width:1.45003652999999999;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 2.9037792,8.1978741 C 3.2143877,9.0316623 3.9610232,9.9051913 4.759397,10.781009 C 6.3561448,12.532642 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.247411,11.388991 9.1968152,10.475925 C 8.146221,9.5628599 6.8660046,8.7034079 5.6266656,8.0176219 C 4.3873265,7.3318362 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.5931708,7.3640855 2.9037792,8.1978741 z"
+- id="path2249"
+- sodipodi:nodetypes="csssssssc" />
+- <path
+- transform="matrix(0.700821,0,0,0.664862,-0.245183,-0.148725)"
+- style="fill:url(#linearGradient4505);fill-opacity:1;stroke:url(#linearGradient8642);stroke-width:1.46497786000000008;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
+- id="rect1317" />
+- <path
+- style="opacity:0.50000000000000000;fill:none;fill-opacity:1;stroke:url(#linearGradient8745);stroke-width:1.00000059999999991;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 13.641543,2.6087804 C 13.042222,2.7550593 12.566354,3.1867157 12.108436,3.5768078 C 11.18133,4.4213418 10.408475,5.418624 9.6753778,6.4315252 C 9.7266839,7.073663 10.22649,7.8212816 10.524225,8.4451141 C 11.523392,8.3745467 12.537477,8.14589 13.395949,7.6120796 C 13.929097,6.4895545 14.279568,5.2829939 14.46967,4.0564994 C 14.517847,3.5935306 14.505216,3.0568259 14.178422,2.69122 C 14.015215,2.4959594 13.853389,2.5338947 13.641543,2.6087804 z"
+- id="path1328"
+- sodipodi:nodetypes="ccccccsc" />
+- <path
+- style="fill:url(#linearGradient8683);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 7.84375,6.0625 C 7.2204009,5.7746851 6.7868533,6.5768349 7.0386107,7.0974232 C 7.2879783,8.4863432 7.8061372,9.8184408 8.4250523,11.082033 C 8.6624096,11.493677 8.9604116,12.091198 9.5358102,11.967269 C 10.350721,11.726246 9.8989976,10.67735 9.7858357,10.097672 C 9.4218582,8.8029479 8.9711599,7.5041911 8.2319551,6.3726804 C 8.1261729,6.2440217 7.9975858,6.1299296 7.84375,6.0625 z"
+- id="path2192" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/novell.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,163 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4248"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
+- sodipodi:docname="novell.svg"
+- inkscape:export-filename="/home/hbons/Bureaublad/Projecten/Pidgin/pidgin-mtn/pidgin/pixmaps/protocols/16/novell.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4250">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8681">
+- <stop
+- style="stop-color:#b90000;stop-opacity:1"
+- offset="0"
+- id="stop8683" />
+- <stop
+- style="stop-color:#660000;stop-opacity:1"
+- offset="1"
+- id="stop8685" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8673">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8675" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8677" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient8657">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop8659" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop8661" />
+- </linearGradient>
+- <inkscape:perspective
+- sodipodi:type="inkscape:persp3d"
+- inkscape:vp_x="0 : 8 : 1"
+- inkscape:vp_y="0 : 1000 : 0"
+- inkscape:vp_z="16 : 8 : 1"
+- inkscape:persp3d-origin="8 : 5.3333333 : 1"
+- id="perspective14" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8657"
+- id="linearGradient8663"
+- x1="13.540643"
+- y1="4.1059771"
+- x2="13.540643"
+- y2="27.537933"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8673"
+- id="linearGradient8679"
+- x1="17.568361"
+- y1="-2.2142286"
+- x2="17.568361"
+- y2="21.473934"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient8681"
+- id="linearGradient8687"
+- x1="7.2145119"
+- y1="6.08881"
+- x2="19.957991"
+- y2="21.372702"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="23.791015"
+- inkscape:cx="21.551698"
+- inkscape:cy="9.5685566"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- inkscape:grid-points="true"
+- inkscape:snap-nodes="false"
+- inkscape:snap-bbox="true"
+- objecttolerance="10"
+- gridtolerance="10">
+- <inkscape:grid
+- type="xygrid"
+- id="grid7853"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4253">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <rect
+- style="fill:#ef1e1e;fill-opacity:1;stroke:url(#linearGradient8687);stroke-width:1.27949666999999989;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect1326"
+- width="18.090118"
+- height="19.004496"
+- x="3.4549403"
+- y="2.4977543"
+- ry="1.9604023"
+- rx="1.9604023"
+- transform="matrix(0.773903,0,0,0.789287,-2.173788,-1.471445)" />
+- <path
+- style="fill:url(#linearGradient8679);fill-opacity:1;stroke:url(#linearGradient8663);stroke-width:1.32302749000000008;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 5.5,3.5 C 4.9023199,3.5 4.46875,3.9335697 4.46875,4.53125 L 4.46875,19.46875 C 4.46875,20.066429 4.9023192,20.499999 5.5,20.5 L 19.5,20.5 C 20.097679,20.5 20.53125,20.066429 20.53125,19.46875 L 20.53125,4.53125 C 20.53125,3.9335703 20.097679,3.5 19.5,3.5 L 5.5,3.5 z "
+- id="path2201"
+- transform="matrix(0.747082,0,0,0.764706,-1.838521,-1.176469)" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="0"
+- inkscape:original="M 4.03125 4 L 4 12 L 6 12 L 6 7.96875 L 11 13 L 11 5.03125 L 9 5.03125 L 9 8.96875 L 4.03125 4 z "
+- style="fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- id="path8697"
+- d="M 4.03125,4 L 4,12 L 6,12 L 6,7.96875 L 11,13 L 11,5.03125 L 9,5.03125 L 9,8.96875 L 4.03125,4 z" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/yahoo.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/16/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,138 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="16px"
+- height="16px"
+- id="svg4248"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/16/scalable"
+- sodipodi:docname="yahoo.svg"
+- inkscape:export-filename="/home/hbons/Bureaublad/yahoo.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4250">
+- <inkscape:perspective
+- sodipodi:type="inkscape:persp3d"
+- inkscape:vp_x="0 : 8 : 1"
+- inkscape:vp_y="0 : 1000 : 0"
+- inkscape:vp_z="16 : 8 : 1"
+- inkscape:persp3d-origin="8 : 5.3333333 : 1"
+- id="perspective17" />
+- <linearGradient
+- id="linearGradient4123"
+- inkscape:collect="always">
+- <stop
+- id="stop4125"
+- offset="0"
+- style="stop-color:#ff0000;stop-opacity:1;" />
+- <stop
+- id="stop4127"
+- offset="1"
+- style="stop-color:#ff0000;stop-opacity:0;" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient4123"
+- id="linearGradient6737"
+- gradientUnits="userSpaceOnUse"
+- x1="20.181133"
+- y1="12.686874"
+- x2="20.181133"
+- y2="5.3694997" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient4123"
+- id="linearGradient6739"
+- gradientUnits="userSpaceOnUse"
+- x1="10.378018"
+- y1="18.430471"
+- x2="5.8631868"
+- y2="-0.23792659"
+- gradientTransform="matrix(0.676847,0,0,0.662872,0.3362294,0.7829564)" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="36.060436"
+- inkscape:cx="15.360711"
+- inkscape:cy="8.3801083"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- inkscape:window-width="1440"
+- inkscape:window-height="847"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- inkscape:grid-points="false"
+- inkscape:guide-points="false"
+- gridtolerance="10"
+- inkscape:object-points="false"
+- inkscape:object-nodes="false"
+- objecttolerance="10"
+- inkscape:snap-bbox="true"
+- inkscape:snap-nodes="false">
+- <inkscape:grid
+- type="xygrid"
+- id="grid7857"
+- visible="true"
+- enabled="true" />
+- </sodipodi:namedview>
+- <metadata
+- id="metadata4253">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- style="fill:white;fill-opacity:1;stroke:none;stroke-width:1.49293232;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 0.24196135,4.148819 L 0.24910211,7.1529832 L 3.5563617,7.147764 L 7.6406917,12.763032 L 7.642012,14.664616 L 4.6774169,14.67713 L 4.6586789,17.695272 L 13.533193,17.684579 L 13.569765,14.669366 L 10.619662,14.679398 L 10.629019,12.755768 L 14.593143,8.6330885 L 16.51876,8.6465912 L 16.509766,5.6235735 L 12.050243,5.6188666 L 12.072495,7.7727612 L 10.847264,10.121315 L 8.9433829,10.071394 L 7.9521191,7.1118568 L 9.0229281,7.1259776 L 9.0246268,4.0988967 L 0.24196135,4.148819 z "
+- id="path6741"
+- sodipodi:nodetypes="cccccccccccccccccccccc"
+- transform="matrix(0.676847,0,0,0.662872,0.331396,0.782369)" />
+- <rect
+- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect3203"
+- width="0"
+- height="2.5118096"
+- x="6"
+- y="6.4881902"
+- transform="translate(-1.463597e-2,-4.995136)" />
+- <path
+- style="fill:url(#linearGradient6739);fill-opacity:1;stroke:#a40000;stroke-width:1.00000047999999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 6.5 3.5 L 0.5 3.53125 L 0.5 5.53125 L 2.75 5.53125 L 5.5 9.25 L 5.5 10.5 L 4.28125 10.5 C 3.3577546 10.5 3.5 11.5 3.5 11.5 L 3.5 12.5 L 6.5 12.5 L 9.5 12.5 L 9.5 11.21875 C 9.4999997 11.21875 9.4638896 10.5 8.71875 10.5 L 7.53125 10.5 L 7.53125 9.6875 L 10.21875 6.5 L 11.53125 6.5 L 11.5 4.5 L 8.5 4.5 L 8.5 5.8125 L 7.09375 7.5 L 6.65625 7.5 L 5.1875 5.5 L 6.5 5.5 L 6.5 3.5 z M 13.5 3.5 L 13.53125 9.9375 L 15.71875 3.5 L 13.5 3.5 z M 12.5 10.5 C 11.948 10.5 11.5 10.948002 11.5 11.5 C 11.5 12.051998 11.948 12.5 12.5 12.5 C 13.052 12.5 13.5 12.051998 13.5 11.5 C 13.5 10.948002 13.052001 10.5 12.5 10.5 z "
+- id="rect3219" />
+- <rect
+- style="fill:white;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect4115"
+- width="1"
+- height="1"
+- x="15"
+- y="12"
+- transform="matrix(0.672571,0,0,0.662714,0.148779,0.239809)" />
+- </g>
+-</svg>
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/16/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/16/yahoo.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/aim.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/facebook.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/gadu-gadu.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/google-talk.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/google-talk.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/icq.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/meanwhile.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/msn.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/mxit.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/myspace.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/novell.png differ
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/aim.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,187 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
+- sodipodi:docname="aim.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/aim.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2263">
+- <stop
+- style="stop-color:#edc100;stop-opacity:1;"
+- offset="0"
+- id="stop2265" />
+- <stop
+- style="stop-color:#edc100;stop-opacity:0;"
+- offset="1"
+- id="stop2267" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2255">
+- <stop
+- style="stop-color:#edc100;stop-opacity:1;"
+- offset="0"
+- id="stop2257" />
+- <stop
+- style="stop-color:#edc100;stop-opacity:0;"
+- offset="1"
+- id="stop2259" />
+- </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="radialGradient4330"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- cx="10.748654"
+- cy="10.457643"
+- fx="10.748654"
+- fy="10.457643"
+- r="6.6449099" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2255"
+- id="linearGradient2261"
+- x1="12.514956"
+- y1="18.246853"
+- x2="12.514956"
+- y2="-0.22752593"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2263"
+- id="linearGradient2269"
+- x1="11.725797"
+- y1="6.7099471"
+- x2="11.725797"
+- y2="-1.7656245"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="18.194454"
+- inkscape:cx="21.028138"
+- inkscape:cy="12.129637"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#edd400"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 11.958337,8.6532903 C 10.214088,7.6488702 9.8526923,12.097445 8.6371785,14.197294 C 7.4474897,16.252529 3.5065645,17.589535 3.5065645,17.589535 L 5.9517457,22.489783 L 11.922453,16.916072 C 11.922453,16.916072 15.933817,19.534872 17.160901,22.390612 L 20.390534,19.246933 C 20.390534,19.246933 18.693358,15.872721 14.921211,13.538266 L 20.491001,12.72627 L 19.715221,8.8524949 C 16.110632,9.7210318 13.926705,9.7867691 11.958337,8.6532903 z "
+- id="path1322"
+- sodipodi:nodetypes="czccccccccs" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path1324"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(0.688186,0,0,0.688819,6.743084,1.213885)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.25;fill:url(#radialGradient4330);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(1.805894,0,0,1.300982,-7.410933,6.474929)" />
+- <path
+- style="opacity:1;fill:url(#linearGradient2261);fill-opacity:1.0;stroke:#c4a000;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 11.958337,8.6532903 C 10.214088,7.6488702 9.8526923,12.097445 8.6371785,14.197294 C 7.4474897,16.252529 3.5065645,17.589535 3.5065645,17.589535 L 5.9517457,22.489783 L 11.922453,16.916072 C 11.922453,16.916072 15.933817,19.534872 17.160901,22.390612 L 20.390534,19.246933 C 20.390534,19.246933 18.693358,15.872721 14.921211,13.538266 L 20.491001,12.72627 L 19.715221,8.8524949 C 16.110632,9.7210318 13.926705,9.7867691 11.958337,8.6532903 z "
+- id="path4275"
+- sodipodi:nodetypes="czccccccccs" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.97533494"
+- inkscape:original="M 11.96875 8.65625 C 10.224501 7.6518295 9.8405138 12.087651 8.625 14.1875 C 7.4353113 16.242735 3.5 17.59375 3.5 17.59375 L 5.9375 22.5 L 11.9375 16.90625 C 11.9375 16.906249 15.929166 19.51926 17.15625 22.375 L 20.375 19.25 C 20.375001 19.25 18.678397 15.865705 14.90625 13.53125 L 20.5 12.71875 L 19.71875 8.84375 C 16.114161 9.7122866 13.937118 9.7897288 11.96875 8.65625 z "
+- xlink:href="#path4275"
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4304"
+- inkscape:href="#path4275"
+- d="M 11.5625,9.53125 C 11.452518,9.6624786 11.20418,10.047821 11,10.59375 C 10.56791,11.749055 10.203376,13.418405 9.46875,14.6875 C 8.6867322,16.038467 7.2662927,16.899179 6.0625,17.53125 C 5.412514,17.872536 5.2627915,17.893887 4.84375,18.0625 L 6.21875,20.90625 L 11.28125,16.1875 C 11.609827,15.89012 12.09758,15.851614 12.46875,16.09375 C 12.46875,16.09375 13.514111,16.786729 14.71875,17.84375 C 15.622229,18.636516 16.558838,19.686944 17.3125,20.84375 L 19.125,19.125 C 18.707223,18.391513 17.391924,16.222734 14.40625,14.375 C 14.042988,14.164323 13.855332,13.744801 13.940413,13.333577 C 14.025494,12.922352 14.364213,12.611735 14.78125,12.5625 L 19.34375,11.90625 L 18.9375,9.96875 C 15.910346,10.738935 13.497199,10.615244 11.5625,9.53125 z " />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:url(#linearGradient2269);fill-opacity:1.0;stroke:#c4a000;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(0.688186,0,0,0.688819,6.743084,1.213885)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;fill:#fce94f;fill-opacity:1;stroke:#ffffff;stroke-width:2.02834463;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4273"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(0.492994,0,0,0.493032,8.79793,2.010973)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,206 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
+- sodipodi:docname="gadu-gadu.svg"
+- inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/gadu-gadu.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <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" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="24.007726"
+- inkscape:cx="16.146337"
+- inkscape:cy="13.950539"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- fill="#fce94f"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="25" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <rect
+- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2235"
+- width="2.0000005"
+- height="3.000001"
+- x="-0.29289341"
+- y="7.3639612"
+- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
+- <rect
+- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2239"
+- width="2.0000033"
+- height="3.0000048"
+- x="-17.970564"
+- y="8.0710697"
+- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.4;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(1.429666,0,0,1.267135,-3.866981,6.748756)" />
+- <rect
+- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2192"
+- width="1.9907103"
+- height="3"
+- x="12"
+- y="1"
+- transform="translate(-1,1)" />
+- <rect
+- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2203"
+- width="2"
+- height="3"
+- x="12"
+- y="18"
+- transform="translate(-1,1)" />
+- <rect
+- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2211"
+- width="2"
+- height="3.4306233"
+- x="-12"
+- y="3"
+- transform="matrix(0,-1,1,0,-1,1)" />
+- <rect
+- style="opacity:1;fill:#db2424;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2213"
+- width="2"
+- height="3"
+- x="-12"
+- y="20"
+- transform="matrix(0,-1,1,0,-1,1)" />
+- <rect
+- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2237"
+- width="2.0000019"
+- height="3.0000029"
+- x="-0.29289412"
+- y="23.57716"
+- transform="matrix(0.707107,-0.707107,0.707107,0.707107,-1,1)" />
+- <rect
+- style="opacity:1;fill:#c00;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect2241"
+- width="2.0000048"
+- height="3.0000067"
+- x="-17.970566"
+- y="-8.24265"
+- transform="matrix(-0.707107,-0.707107,0.707107,-0.707107,-1,1)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#fce94f;fill-opacity:1;stroke:#c00;stroke-width:0.73921776;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2217"
+- sodipodi:cx="8.0702047"
+- sodipodi:cy="8.0363102"
+- sodipodi:rx="5.5372205"
+- sodipodi:ry="5.5372205"
+- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
+- transform="matrix(1.354195,0,0,1.35137,1.070845,1.157102)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.7;fill:none;fill-opacity:1;stroke:#c4a000;stroke-width:0.85407299;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:0.4848485"
+- id="path2222"
+- sodipodi:cx="8.0702047"
+- sodipodi:cy="8.0363102"
+- sodipodi:rx="5.5372205"
+- sodipodi:ry="5.5372205"
+- d="M 13.607425 8.0363102 A 5.5372205 5.5372205 0 1 1 2.5329843,8.0363102 A 5.5372205 5.5372205 0 1 1 13.607425 8.0363102 z"
+- transform="matrix(1.171277,0,0,1.170443,2.525066,2.61184)" />
+- <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="path2243"
+- sodipodi:cx="9.8489876"
+- sodipodi:cy="10.583912"
+- sodipodi:rx="1.2626907"
+- sodipodi:ry="1.0417198"
+- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
+- transform="matrix(0,1.18426,-0.959955,0,20.16009,-1.168408)" />
+- <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="path2245"
+- sodipodi:cx="9.8489876"
+- sodipodi:cy="10.583912"
+- sodipodi:rx="1.2626907"
+- sodipodi:ry="1.0417198"
+- d="M 11.111678 10.583912 A 1.2626907 1.0417198 0 1 1 8.5862969,10.583912 A 1.2626907 1.0417198 0 1 1 11.111678 10.583912 z"
+- transform="matrix(0,-1.187938,0.959951,0,3.839963,22.19998)" />
+- <path
+- style="opacity:1;fill:#555753;fill-opacity:1;stroke:none;stroke-width:1.10482609;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 17.0113,10.955978 C 17.0113,13.182328 15.218558,14.007827 13,14.007827 C 10.819611,14.007827 9.0496187,13.101106 8.9887006,10.913915 L 8,10.942262 C 8.0756746,13.659262 10.29145,15 13,15 C 15.758926,15 17.999999,13.724591 18,10.955978 L 17.0113,10.955978 z "
+- id="path2247"
+- sodipodi:nodetypes="csccscc"
+- transform="translate(-1,1)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/icq.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,291 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
+- sodipodi:docname="icq.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/icq.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2361">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2363" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2365" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2321">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2323" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2325" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2321"
+- id="linearGradient2327"
+- x1="11.787398"
+- y1="11.115861"
+- x2="12.405842"
+- y2="13.791453"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2361"
+- id="linearGradient2367"
+- x1="6.3009863"
+- y1="8.3052416"
+- x2="6.3009863"
+- y2="17.320574"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="10.44997"
+- inkscape:cx="19.566864"
+- inkscape:cy="19.726611"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#ef2929"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;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(1.805894,0,0,1.478325,-7.410928,3.04021)" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 12.963148,17.247339 C 12.171926,14.859179 12.454176,14.470485 13.497752,13.880864 C 14.541326,13.291244 15.108816,13.335817 16.744216,15.111033 C 17.767103,16.844843 17.750309,18.730526 16.706739,19.320144 C 15.663162,19.909767 13.986034,18.981148 12.963148,17.247339 z "
+- id="path2226"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.95876986"
+- inkscape:original="M 14.90625 13.59375 C 14.429506 13.434407 14.021787 13.58019 13.5 13.875 C 12.456424 14.464621 12.177528 14.86184 12.96875 17.25 C 13.991636 18.983809 15.675173 19.902122 16.71875 19.3125 C 17.76232 18.722882 17.772886 16.85881 16.75 15.125 C 15.9323 14.237392 15.382994 13.753093 14.90625 13.59375 z "
+- xlink:href="#path2226"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2242"
+- inkscape:href="#path2226"
+- d="M 14.6875,15.40625 C 14.513417,15.351665 14.472292,15.359975 14.03125,15.59375 C 13.796094,15.718394 13.674719,15.830029 13.625,15.875 C 13.575281,15.919971 13.600191,15.87903 13.59375,15.90625 C 13.581862,15.956485 13.642727,16.51095 13.9375,17.40625 C 14.348011,18.027075 14.877648,18.50949 15.34375,18.75 C 15.831028,19.001437 16.171295,18.981096 16.3125,18.90625 C 16.454211,18.831136 16.558976,18.656064 16.5625,18.1875 C 16.565896,17.735918 16.387216,17.080025 16,16.4375 C 15.331224,15.779693 14.857908,15.459683 14.6875,15.40625 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 16.771005,15.319703 C 14.33106,13.896777 14.27539,13.249081 14.702189,11.643547 C 15.128987,10.03802 15.633686,9.5050301 18.317374,9.5025628 C 20.461323,10.081613 21.854951,11.854605 21.428153,13.460133 C 21.001355,15.065667 18.914955,15.898753 16.771005,15.319703 z "
+- id="path2216"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.98264426"
+- inkscape:original="M 18.3125 9.5 C 15.628812 9.5024673 15.114298 10.050723 14.6875 11.65625 C 14.260701 13.261784 14.341304 13.889574 16.78125 15.3125 C 18.9252 15.89155 21.010703 15.074284 21.4375 13.46875 C 21.864298 11.863222 20.45645 10.07905 18.3125 9.5 z "
+- xlink:href="#path2216"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2238"
+- inkscape:href="#path2216"
+- d="M 18.21875,11.46875 C 17.125733,11.491249 16.482945,11.618664 16.28125,11.75 C 16.063159,11.892013 15.916049,12.106986 15.71875,12.84375 C 15.515581,13.602428 15.521796,13.851934 15.625,14.0625 C 15.720814,14.257989 16.227533,14.71374 17.21875,15.3125 C 18.053555,15.507642 18.8825,15.450801 19.46875,15.21875 C 20.087515,14.973829 20.440615,14.611396 20.5625,14.15625 C 20.683546,13.704238 20.542643,13.182022 20.125,12.65625 C 19.7273,12.155585 19.044575,11.716527 18.21875,11.46875 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.231066,10.043051 C 15.826638,10.834882 15.435297,10.552414 14.841659,9.5080341 C 14.248025,8.4636559 14.292902,7.895729 16.08021,6.2590696 C 17.825828,5.235395 19.724355,5.2521994 20.317989,6.2965763 C 20.911627,7.3409564 19.976685,9.0193762 18.231066,10.043051 z "
+- id="path2224"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.2295458,17.045044 C 4.8262841,17.837501 4.435133,17.554808 3.8417836,16.509603 C 3.2484366,15.464398 3.2932918,14.896022 5.0797326,13.258068 C 6.8245041,12.233585 8.7221095,12.250402 9.3154554,13.295606 C 9.9088085,14.34081 8.9743169,16.020559 7.2295458,17.045044 z "
+- id="path2228"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0000435"
+- inkscape:original="M 7.625 12.5 C 6.858334 12.493206 5.9661358 12.737758 5.09375 13.25 C 3.3073092 14.887954 3.2504031 15.454794 3.84375 16.5 C 4.4370994 17.545205 4.8154885 17.823707 7.21875 17.03125 C 8.9635211 16.006765 9.9058531 14.326454 9.3125 13.28125 C 9.0158271 12.758648 8.391666 12.506794 7.625 12.5 z "
+- xlink:href="#path2228"
+- style="opacity:0.35;fill:url(#linearGradient2367);fill-opacity:1.0;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- id="path2244"
+- inkscape:href="#path2228"
+- d="M 7.6875,14.46875 C 7.1850852,14.464327 6.4432058,14.680127 5.75,15.0625 C 5.0356604,15.736543 4.6689236,16.21317 4.625,16.34375 C 4.5776671,16.484465 4.5627519,16.46929 4.8125,16.90625 C 4.9456222,17.139159 5.046245,17.29527 5.09375,17.34375 C 5.141255,17.39223 5.1063252,17.364089 5.15625,17.375 C 5.2475037,17.394943 5.8597606,17.320365 6.8125,17.03125 C 7.5124448,16.612892 8.0523433,16.090381 8.3125,15.625 C 8.5782457,15.149621 8.5343603,14.864791 8.46875,14.75 C 8.3973728,14.625118 8.2193466,14.473432 7.6875,14.46875 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.6891342,15.77365 C 9.1118334,13.334726 9.7586709,13.278647 11.361671,13.703963 C 12.964665,14.129276 13.496553,14.633183 13.497097,17.314646 C 12.917316,19.457228 11.145785,20.850948 9.5427895,20.425634 C 7.93979,20.000318 7.109353,17.916231 7.6891342,15.77365 z "
+- id="path2218"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0089091"
+- inkscape:original="M 9.46875 13.65625 C 8.9288282 13.921971 8.3988496 14.561788 7.6875 15.78125 C 7.1077188 17.923831 7.9282505 20.012184 9.53125 20.4375 C 11.134246 20.862814 12.920219 19.455082 13.5 17.3125 C 13.499456 14.631037 12.977994 14.144063 11.375 13.71875 C 10.5735 13.506092 10.008672 13.390529 9.46875 13.65625 z "
+- xlink:href="#path2218"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2240"
+- inkscape:href="#path2218"
+- d="M 9.9375,15.46875 C 9.758584,15.557674 9.317928,16.067421 8.71875,17.0625 C 8.5249462,17.893222 8.580847,18.722852 8.8125,19.3125 C 9.0570015,19.934852 9.4058239,20.288908 9.84375,20.40625 C 10.284224,20.524275 10.791323,20.413461 11.3125,20 C 11.80879,19.606283 12.253545,18.915371 12.5,18.09375 C 12.478422,16.998381 12.350171,16.329407 12.21875,16.125 C 12.076813,15.904237 11.884049,15.788763 11.15625,15.59375 C 10.38798,15.387892 10.114118,15.380968 9.9375,15.46875 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 11.045283,4.7716972 C 11.837827,7.1821833 11.555107,7.5745105 10.509784,8.1696432 C 9.4644611,8.7647745 8.8960214,8.7197841 7.2578858,6.9279732 C 6.2332874,5.1779568 6.2501071,3.2746475 7.2954271,2.6795158 C 8.3407485,2.0843833 10.020684,3.0216808 11.045283,4.7716972 z "
+- id="path2222"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.96927398"
+- inkscape:original="M 8.1875 2.5 C 7.8669984 2.4684749 7.5425803 2.5387169 7.28125 2.6875 C 6.23593 3.2826317 6.2254015 5.1874835 7.25 6.9375 C 8.8881356 8.7293109 9.4546774 8.7513811 10.5 8.15625 C 11.545323 7.5611173 11.823794 7.1917363 11.03125 4.78125 C 10.262801 3.4687377 9.1490049 2.5945754 8.1875 2.5 z "
+- xlink:href="#path2222"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2232"
+- inkscape:href="#path2222"
+- d="M 8.15625,4.46875 C 7.9850798,4.4518474 7.8807377,4.4788593 7.84375,4.5 C 7.7166113,4.5726675 7.5662606,4.8028687 7.5625,5.34375 C 7.5588632,5.8668265 7.7601774,6.5753594 8.15625,7.28125 C 8.8326599,7.9986853 9.3286876,8.3591367 9.46875,8.40625 C 9.6195275,8.4569676 9.6232062,8.4698326 10.0625,8.21875 C 10.296133,8.0852146 10.416881,7.988326 10.46875,7.9375 C 10.520619,7.886674 10.519109,7.8993051 10.53125,7.84375 C 10.553442,7.7422051 10.477378,7.1419568 10.1875,6.1875 C 9.551335,5.1240857 8.6060031,4.5131619 8.15625,4.46875 z "
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.2320598,6.6863636 C 9.6715923,8.1091434 9.7272104,8.7568487 9.3003538,10.362442 C 8.8734993,11.96803 8.3688269,12.501065 5.6854848,12.503723 C 3.5418523,11.924813 2.1485268,10.151886 2.5753806,8.5462983 C 3.002236,6.9407045 5.0884273,6.1074547 7.2320598,6.6863636 z "
+- id="path2220"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0062078"
+- inkscape:original="M 7.21875 6.6875 C 5.0751175 6.1085911 2.9893554 6.9256565 2.5625 8.53125 C 2.1356462 10.136838 3.5438674 11.92109 5.6875 12.5 C 8.3708421 12.497342 8.8856453 11.980588 9.3125 10.375 C 9.7393566 8.7694067 9.6582823 8.1102797 7.21875 6.6875 z "
+- xlink:href="#path2220"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2234"
+- inkscape:href="#path2220"
+- d="M 6.90625,8.625 C 6.0757552,8.4313739 5.2679182,8.4577406 4.6875,8.6875 C 4.0744067,8.9301939 3.7136786,9.3024203 3.59375,9.75 C 3.4731424,10.200114 3.5937551,10.700108 4,11.21875 C 4.386622,11.71234 5.0555378,12.160107 5.875,12.40625 C 6.9710054,12.383966 7.6389832,12.256351 7.84375,12.125 C 8.0649019,11.983138 8.1794028,11.792477 8.375,11.0625 C 8.5781494,10.304338 8.5991322,10.046076 8.5,9.84375 C 8.40803,9.6560422 7.8949355,9.2223583 6.90625,8.625 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0066811"
+- inkscape:original="M 18.625 5.5 C 17.857962 5.4932111 16.966559 5.7381628 16.09375 6.25 C 14.306442 7.8866594 14.250116 8.4556221 14.84375 9.5 C 15.437388 10.54438 15.814322 10.823081 18.21875 10.03125 C 19.964369 9.0075752 20.906138 7.3256299 20.3125 6.28125 C 20.015683 5.7590616 19.392038 5.5067889 18.625 5.5 z "
+- xlink:href="#path2224"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2236"
+- inkscape:href="#path2224"
+- d="M 18.65625,6.625 C 18.144193,6.6204563 17.412705,6.8326612 16.71875,7.21875 C 15.998485,7.9033831 15.63724,8.4003618 15.59375,8.53125 C 15.546933,8.6721515 15.527986,8.6470459 15.78125,9.09375 C 15.914256,9.3283439 16.014881,9.4828276 16.0625,9.53125 C 16.110119,9.5796724 16.073321,9.5513897 16.125,9.5625 C 16.221307,9.5832048 16.847896,9.4973699 17.84375,9.1875 C 18.526233,8.7666523 19.058938,8.2387438 19.3125,7.78125 C 19.577081,7.3038742 19.539587,7.0311908 19.46875,6.90625 C 19.408404,6.7998131 19.198718,6.6298135 18.65625,6.625 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 16.312776,6.2243452 C 14.884428,8.6655097 14.236701,8.7225955 12.632405,8.2997676 C 11.028107,7.8769402 10.496367,7.373854 10.500103,4.6923611 C 11.08402,2.548855 12.859963,1.1523628 14.464261,1.5751903 C 16.068559,1.9980181 16.896691,4.0808393 16.312776,6.2243452 z "
+- id="path2192"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99950546"
+- inkscape:original="M 14.46875 1.5625 C 12.864452 1.1396725 11.083917 2.5439941 10.5 4.6875 C 10.496264 7.3689929 11.020702 7.8896727 12.625 8.3125 C 14.229296 8.7353279 14.884151 8.6599145 16.3125 6.21875 C 16.896415 4.0752441 16.073048 1.9853278 14.46875 1.5625 z "
+- xlink:href="#path2192"
+- style="opacity:0.4;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1;stroke-dasharray:none"
+- id="path2230"
+- inkscape:href="#path2192"
+- d="M 14.21875,2.53125 C 13.768437,2.4124791 13.248017,2.520656 12.71875,2.9375 C 12.214757,3.3344386 11.780816,4.0240635 11.53125,4.84375 C 11.550949,5.9366779 11.679626,6.6046957 11.8125,6.8125 C 11.956007,7.0369325 12.144428,7.1510597 12.875,7.34375 C 13.630622,7.5430474 13.875456,7.5464752 14.09375,7.4375 C 14.296413,7.3363279 14.739612,6.8347534 15.34375,5.84375 C 15.539967,5.0157934 15.511564,4.2073905 15.28125,3.625 C 15.03797,3.0098233 14.669402,2.6501106 14.21875,2.53125 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:0.43295163;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path1317"
+- sodipodi:cx="12.075002"
+- sodipodi:cy="12.360133"
+- sodipodi:rx="1.1966218"
+- sodipodi:ry="1.4141895"
+- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
+- transform="matrix(2.422923,0.638108,-0.560042,2.054325,-10.83461,-21.59688)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.4;fill:url(#linearGradient2327);fill-opacity:1.0;stroke:#ffffff;stroke-width:0.64902174;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2319"
+- sodipodi:cx="12.075002"
+- sodipodi:cy="12.360133"
+- sodipodi:rx="1.1966218"
+- sodipodi:ry="1.4141895"
+- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
+- transform="matrix(1.616292,0.425671,-0.373594,1.370406,-3.399047,-10.57838)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,172 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
+- sodipodi:docname="meanwhile.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/meanwhile.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2230">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2232" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2234" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2222">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2224" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2226" />
+- </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="radialGradient4330"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- cx="10.748654"
+- cy="10.457643"
+- fx="10.748654"
+- fy="10.457643"
+- r="6.6449099" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2222"
+- id="linearGradient2228"
+- x1="13.090998"
+- y1="0.78084093"
+- x2="13.090998"
+- y2="17.595036"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2230"
+- id="linearGradient2236"
+- x1="10.063863"
+- y1="-0.14116688"
+- x2="10.063863"
+- y2="7.1152339"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="13.788818"
+- inkscape:cx="4.860805"
+- inkscape:cy="9.6839037"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#f57900"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.3;fill:url(#radialGradient4330);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(1.805894,0,0,1.512171,-7.410928,4.606121)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.45242631;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(0.688186,0,0,0.688819,4.743084,1.209666)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.45;fill:url(#linearGradient2236);fill-opacity:1.0;stroke:#ffffff;stroke-width:2.02834463;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4273"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(0.492994,0,0,0.493032,6.809086,2.006754)" />
+- <path
+- style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 17.512653,3.583459 C 17.512653,5.7137825 16.562033,9.5267857 12.004464,9.5267857 C 7.4763459,9.5267857 6.5140012,5.7551862 6.5140012,3.5976845 L 2.5044094,4.4125109 C 2.5044094,11.110279 9.0401786,13.178571 9.0401786,13.178571 C 9.0401786,13.178571 4.4464285,16.409103 4.4464285,21.475844 L 9.5714286,21.522322 C 9.5714286,21.522322 10.279685,16.46875 12.089286,16.46875 C 13.943529,16.46875 15.401786,21.508929 15.401786,21.508929 L 20.502628,21.524951 C 20.502628,16.121505 15.254464,13.120535 15.254464,13.120535 C 15.254464,13.120535 21.508928,11.277721 21.508928,4.4267748 L 17.512653,3.583459 z "
+- id="rect2213"
+- sodipodi:nodetypes="czccccczccccc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.9525249"
+- inkscape:original="M 6.5 3.59375 L 2.5 4.40625 C 2.5000001 11.104018 9.03125 13.1875 9.03125 13.1875 C 9.0312503 13.1875 4.4375 16.402009 4.4375 21.46875 L 9.5625 21.53125 C 9.5625003 21.53125 10.284149 16.46875 12.09375 16.46875 C 13.947993 16.46875 15.40625 21.5 15.40625 21.5 L 20.5 21.53125 C 20.5 16.127803 15.25 13.125 15.25 13.125 C 15.25 13.125 21.5 11.288446 21.5 4.4375 L 17.5 3.59375 C 17.5 5.7240736 16.557569 9.53125 12 9.53125 C 7.4718818 9.5312498 6.5 5.7512517 6.5 3.59375 z "
+- xlink:href="#rect2213"
+- style="fill:url(#linearGradient2228);fill-opacity:1.0;stroke:#ffffff;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1;opacity:0.45"
+- id="path2220"
+- inkscape:href="#rect2213"
+- d="M 5.6875,4.75 L 3.53125,5.1875 C 3.766386,7.7468676 5.0307437,9.4444151 6.375,10.5625 C 7.8598463,11.797521 9.3125,12.28125 9.3125,12.28125 C 9.6563341,12.393071 9.9072283,12.689904 9.9602145,13.047561 C 10.013201,13.405218 9.8591447,13.762043 9.5625,13.96875 C 9.5625,13.96875 6.1077373,16.59996 5.5625,20.53125 L 8.8125,20.59375 C 8.8948827,20.11702 8.9443109,19.67024 9.25,18.71875 C 9.4690397,18.036965 9.7468494,17.32194 10.15625,16.71875 C 10.565651,16.11556 11.197223,15.53125 12.09375,15.53125 C 12.98807,15.53125 13.639348,16.079917 14.125,16.65625 C 14.610652,17.232583 14.993863,17.890429 15.3125,18.5625 C 15.787201,19.563742 15.924647,20.125238 16.0625,20.5625 L 19.34375,20.59375 C 18.746486,16.428966 14.78125,13.9375 14.78125,13.9375 C 14.463324,13.745958 14.285599,13.387197 14.325851,13.018218 C 14.366103,12.649239 14.617002,12.337237 14.96875,12.21875 C 14.96875,12.21875 16.343303,11.809333 17.75,10.625 C 19.032471,9.5452564 20.256269,7.8458143 20.46875,5.1875 L 18.3125,4.75 C 18.187549,5.7582509 17.936893,6.8360203 17.25,7.875 C 16.2955,9.3187557 14.544016,10.46875 12,10.46875 C 9.4708902,10.46875 7.7086662,9.3456824 6.75,7.90625 C 6.0601086,6.8703815 5.8152026,5.7643315 5.6875,4.75 z " />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/msn.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,223 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols"
+- sodipodi:docname="msn.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/msn2.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <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="linearGradient2228">
+- <stop
+- style="stop-color:#f56600;stop-opacity:1;"
+- offset="0"
+- id="stop2230" />
+- <stop
+- style="stop-color:#f56600;stop-opacity:0;"
+- offset="1"
+- id="stop2232" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2219">
+- <stop
+- style="stop-color:#3465a4;stop-opacity:1;"
+- offset="0"
+- id="stop2221" />
+- <stop
+- style="stop-color:#3465a4;stop-opacity:0;"
+- offset="1"
+- id="stop2223" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2219"
+- id="linearGradient2251"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.747158,0,0,0.74873,0.374035,0.608489)"
+- x1="9.9973583"
+- y1="14.918511"
+- x2="14.069712"
+- y2="18.218639" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2228"
+- id="linearGradient1330"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(0.782765,0,0,0.747651,1.035995,0.614065)"
+- x1="20.998175"
+- y1="11.741063"
+- x2="17.999571"
+- y2="18.866741" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="29.556977"
+- inkscape:cx="19.409996"
+- inkscape:cy="10.944939"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#edd400"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- 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:0.4;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.044119,0,0,0.346338,-18.44114,13.41659)" />
+- <path
+- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.436518,9.9127618 C 21.037357,10.673309 21.362289,19.501337 18.407881,19.501337 C 15.489266,19.501337 8.9905421,7.150538 18.436518,9.9127618 z "
+- id="rect2194"
+- sodipodi:nodetypes="czs" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.96520001"
+- inkscape:original="M 15.59375 9.53125 C 10.549483 10.044796 15.852462 19.5 18.40625 19.5 C 21.360658 19.5 21.038339 10.666797 18.4375 9.90625 C 17.256753 9.560972 16.31436 9.4578863 15.59375 9.53125 z "
+- xlink:href="#rect2194"
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
+- id="path2259"
+- inkscape:href="#rect2194"
+- d="M 16,10.75 C 15.512126,10.798024 15.253534,10.920051 15.09375,11.0625 C 14.933966,11.204949 14.83864,11.380838 14.78125,11.6875 C 14.66647,12.300825 14.844054,13.385232 15.3125,14.46875 C 15.780946,15.552268 16.512913,16.653582 17.21875,17.4375 C 17.924587,18.221418 18.67699,18.5625 18.75,18.5625 C 18.89196,18.5625 18.968845,18.54667 19.09375,18.4375 C 19.218655,18.32833 19.365593,18.098064 19.5,17.78125 C 19.768815,17.147621 19.923112,16.154119 19.90625,15.125 C 19.889388,14.095881 19.705611,13.023656 19.40625,12.25 C 19.106889,11.476344 18.724904,11.117253 18.53125,11.0625 C 17.425208,10.749781 16.582845,10.692627 16,10.75 z " />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 13.316085,20.509475 C 10.851196,20.509475 4.3258741,14.508937 9.3204332,11.066555 C 14.310647,7.6271659 15.818731,20.509475 13.316085,20.509475 z "
+- id="rect2201"
+- sodipodi:nodetypes="czz" />
+- <path
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 10.99506,11.498797 C 10.735658,11.486846 10.370038,11.588319 9.8835883,11.932121 C 8.8737,12.645867 8.5374239,13.351301 8.4999186,14.121547 C 8.4624133,14.891791 8.7901654,15.780902 9.3391937,16.607457 C 9.8882225,17.43401 10.661309,18.195719 11.403357,18.728462 C 12.145404,19.261206 12.809412,19.500227 13.070994,19.500227 C 13.222335,19.500227 13.331682,19.0625 13.39947,18.682848 C 13.535046,17.923542 13.548476,16.808781 13.376787,15.695196 C 13.205098,14.58161 12.846108,13.444035 12.401414,12.661929 C 11.95672,11.879824 11.481565,11.52121 10.99506,11.498797 z "
+- id="path2254"
+- sodipodi:nodetypes="cssssssssc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99454969"
+- inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
+- xlink:href="#rect1317"
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- id="path2245"
+- inkscape:href="#rect1317"
+- d="M 20,3.5 C 18.995087,3.678281 17.104383,5.3426949 15.71875,7.0625 C 14.498278,8.5773128 13.796939,9.7027104 13.59375,10.03125 L 15.0625,13.375 C 17.799931,13.187054 19.57299,12.186552 19.84375,12 C 19.951969,11.755173 20.691026,10.13991 21.15625,8.125 C 21.405718,7.0445423 21.52736,5.9263632 21.4375,5.09375 C 21.34764,4.2611368 21.117806,3.8050199 20.65625,3.5625 C 20.487599,3.4738843 20.316754,3.4438049 20,3.5 z " />
+- <path
+- style="opacity:1;fill:url(#linearGradient2251);fill-opacity:1;stroke:#204a87;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 1.7306799,5.8222291 C 3.0741729,3.5659039 16.882213,13.11203 11.087148,14.375153 C 5.2996209,15.636634 0.40087698,8.0555627 1.7306799,5.8222291 z "
+- id="rect2197"
+- sodipodi:nodetypes="czz" />
+- <path
+- style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999994;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 2.7390794,8.1722341 C 3.0496879,9.0060223 3.6590736,9.9821112 4.4574474,10.857929 C 6.0541952,12.609562 8.35926,13.89948 10.765977,13.389526 C 11.255672,13.285765 11.400406,13.151715 11.448617,13.081331 C 11.496824,13.010949 11.537361,12.912219 11.448617,12.641053 C 11.271127,12.098721 10.521911,11.132591 9.4713148,10.219525 C 8.4207206,9.3064602 7.0856043,8.3957283 5.8462653,7.7099423 C 4.6069262,7.0241566 3.3045923,6.5498939 2.7239802,6.4956482 C 2.4148401,6.4667656 2.428471,7.3384455 2.7390794,8.1722341 z "
+- id="path2249"
+- sodipodi:nodetypes="cssssssss" />
+- <path
+- style="opacity:1;fill:url(#linearGradient1330);fill-opacity:1;stroke:#ce5d00;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 12.478485,9.9508709 C 12.478485,9.9508709 17.866649,0.9861607 21.122294,2.6968071 C 24.404423,4.4213689 20.644961,12.673483 20.644961,12.673483 C 20.644961,12.673483 18.181394,14.512366 14.476578,14.512366 L 12.478485,9.9508709 z "
+- id="rect1317"
+- sodipodi:nodetypes="czccc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99298751"
+- inkscape:original="M 19.8125 2.53125 C 16.600144 3.1011521 12.46875 9.9375003 12.46875 9.9375 L 14.46875 14.5 C 18.173566 14.5 20.656251 12.6875 20.65625 12.6875 C 20.65625 12.6875 24.40713 4.4120618 21.125 2.6875 C 20.718044 2.4736692 20.271408 2.4498354 19.8125 2.53125 z "
+- xlink:href="#rect1317"
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- id="path1328"
+- inkscape:href="#rect1317"
+- d="M 20,3.5 C 18.994143,3.6784485 17.104459,5.3425998 15.71875,7.0625 C 14.49821,8.5773965 13.796948,9.7026949 13.59375,10.03125 L 15.0625,13.375 C 17.800353,13.18702 19.57294,12.186586 19.84375,12 C 19.951976,11.755161 20.690984,10.140091 21.15625,8.125 C 21.40574,7.0444453 21.527392,5.9266549 21.4375,5.09375 C 21.347608,4.2608451 21.11837,3.8053161 20.65625,3.5625 C 20.487225,3.4736876 20.316977,3.4437653 20,3.5 z " />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1.35211551;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2192"
+- sodipodi:cx="13.4375"
+- sodipodi:cy="15.825892"
+- sodipodi:rx="0.8035714"
+- sodipodi:ry="5.1116071"
+- d="M 14.241071 15.825892 A 0.8035714 5.1116071 0 1 1 12.633929,15.825892 A 0.8035714 5.1116071 0 1 1 14.241071 15.825892 z"
+- transform="matrix(0.603448,-0.487879,0.280285,0.679821,0.46572,8.794406)" />
+- <image
+- id="image1314"
+- height="31.456791"
+- width="30.814816"
+- sodipodi:absref="/home/hbons/Desktop/MSN_groups_butterfly.gif"
+- xlink:href="/home/hbons/Desktop/MSN_groups_butterfly.gif"
+- x="-32"
+- y="-23.456791"
+- style="opacity:0.72727272" />
+- <image
+- id="image2210"
+- height="8"
+- width="8"
+- sodipodi:absref="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
+- xlink:href="/home/hbons/Desktop/Gaim Refresh/Tango-Palette.png"
+- x="-16"
+- y="14" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/novell.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,140 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://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.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/22/scalable"
+- sodipodi:docname="novell.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/22/groupwise.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2190">
+- <stop
+- style="stop-color:#d3d7cf;stop-opacity:1;"
+- offset="0"
+- id="stop2192" />
+- <stop
+- style="stop-color:#d3d7cf;stop-opacity:0;"
+- offset="1"
+- id="stop2194" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2190"
+- id="radialGradient2196"
+- cx="4.3022962"
+- cy="7.5011024"
+- fx="4.3022962"
+- fy="7.5011024"
+- r="8.5"
+- gradientTransform="matrix(-2.567716,2.567716,-2.581797,-2.581795,54.64024,19.71367)"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="18.194454"
+- inkscape:cx="19.83031"
+- inkscape:cy="13.86181"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#00ffff"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;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(1.655402,0,0,1.055946,-5.793349,9.457294)" />
+- <rect
+- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect1326"
+- width="18.090118"
+- height="19.004496"
+- x="3.4549403"
+- y="2.4977543"
+- ry="2.0372119"
+- rx="2.0372119" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99578816"
+- inkscape:original="M 5.5 2.5 C 4.3713846 2.5 3.46875 3.4026344 3.46875 4.53125 L 3.46875 19.46875 C 3.46875 20.597365 4.3713846 21.499999 5.5 21.5 L 19.5 21.5 C 20.628615 21.5 21.53125 20.597365 21.53125 19.46875 L 21.53125 4.53125 C 21.53125 3.4026346 20.628615 2.5 19.5 2.5 L 5.5 2.5 z "
+- xlink:href="#rect1326"
+- style="opacity:1;fill:url(#radialGradient2196);fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2201"
+- inkscape:href="#rect1326"
+- d="M 4,2.5 C 3.7105801,2.5 3.5,2.7105801 3.5,3 L 3.5,20.65625 C 3.5,20.94567 3.6855275,21.125 4,21.125 L 20.46875,21.125 C 20.783223,21.125 20.96875,20.945671 20.96875,20.65625 L 20.96875,3 C 20.96875,2.7105794 20.758171,2.5 20.46875,2.5 L 4,2.5 z " />
+- <path
+- style="fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 7.9770722,7 L 7.9770722,17.002529 L 10.015316,17.002529 L 9.9655567,11.206846 L 14.876959,15.95387 L 17,18 L 17,8.0143877 L 14.995675,8.0143877 L 14.995675,13.760417 L 9.1049377,8.0476192 L 7.9770722,7 z "
+- id="rect1317"
+- sodipodi:nodetypes="ccccccccccc" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/yahoo.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/22/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,154 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="24"
+- height="24"
+- id="svg1307"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/scalable"
+- sodipodi:docname="yahoo.svg"
+- inkscape:export-filename="/home/hbons/GUI/Tango/Gaim Refresh/protocols/22/yahoo.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs1309">
+- <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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient4123">
+- <stop
+- style="stop-color:#ff0000;stop-opacity:1;"
+- offset="0"
+- id="stop4125" />
+- <stop
+- style="stop-color:#ff0000;stop-opacity:0;"
+- offset="1"
+- id="stop4127" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient4123"
+- id="linearGradient4129"
+- x1="20.102123"
+- y1="10.489645"
+- x2="20.102123"
+- y2="3.0395992"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient4123"
+- id="linearGradient4131"
+- x1="9.7634506"
+- y1="11.499014"
+- x2="9.7634506"
+- y2="0.12942761"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="29.290175"
+- inkscape:cx="18.292625"
+- inkscape:cy="12.739723"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- fill="#a40000"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="25" />
+- <metadata
+- id="metadata1312">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <rect
+- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect3203"
+- width="0"
+- height="2.5118096"
+- x="6"
+- y="6.4881902" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.6;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(1.730648,0,0,1.300982,-7.102139,4.474929)" />
+- <path
+- style="opacity:1;fill:url(#linearGradient4131);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999958;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 0.49908419,5.4951356 L 0.49908419,7.5376225 L 3.3376273,7.5964463 L 8.515629,12.953307 L 8.515629,15.459996 L 5.4587364,15.459996 L 5.4587364,17.502482 L 13.56886,17.502482 L 13.56886,15.459996 L 10.463631,15.459996 L 10.463631,12.891414 L 14.972535,8.5279191 L 16.532174,8.5279191 L 16.532174,6.5473259 L 11.478943,6.5473259 L 11.478943,8.5279191 L 12.040413,8.5279191 L 9.8296564,10.446619 L 9.1979396,10.446619 L 5.9890137,7.5376225 L 9.5449908,7.5376225 L 9.5449908,5.4951356 L 0.49908419,5.4951356 z "
+- id="rect3219"
+- sodipodi:nodetypes="ccccccccccccccccccccccc" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:0.97808969;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4110"
+- sodipodi:cx="16.860584"
+- sodipodi:cy="16.429377"
+- sodipodi:rx="1.3865612"
+- sodipodi:ry="1.5252173"
+- d="M 18.247145 16.429377 A 1.3865612 1.5252173 0 1 1 15.474023,16.429377 A 1.3865612 1.5252173 0 1 1 18.247145 16.429377 z"
+- transform="matrix(1.06013,0,0,0.986015,-0.904476,0.796501)" />
+- <path
+- style="fill:url(#linearGradient4129);fill-opacity:1.0;stroke:#a40000;stroke-width:0.99999994;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 18.485372,6.4981503 L 22.514636,6.4981503 L 18.576821,12.500953 L 18.485372,6.4981503 z "
+- id="rect4112"
+- sodipodi:nodetypes="cccc" />
+- </g>
+-</svg>
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/22/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/22/yahoo.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/aim.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/aim.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/facebook.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/facebook.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/gadu-gadu.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/gadu-gadu.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/icq.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/icq.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/meanwhile.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/meanwhile.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/msn.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/msn.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/mxit.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/mxit.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/myspace.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/myspace.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/novell.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/novell.png differ
+Binary files pidgin-2.10.7/pidgin/pixmaps/protocols/48/yahoo.png and pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/48/yahoo.png differ
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/aim.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/aim.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/aim.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/aim.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,188 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg2"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
+- sodipodi:docname="aim.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/aim.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2263">
+- <stop
+- style="stop-color:#edc100;stop-opacity:1;"
+- offset="0"
+- id="stop2265" />
+- <stop
+- style="stop-color:#edc100;stop-opacity:0;"
+- offset="1"
+- id="stop2267" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2255">
+- <stop
+- style="stop-color:#edc100;stop-opacity:1;"
+- offset="0"
+- id="stop2257" />
+- <stop
+- style="stop-color:#edc100;stop-opacity:0;"
+- offset="1"
+- id="stop2259" />
+- </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="radialGradient4330"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- cx="10.748654"
+- cy="10.457643"
+- fx="10.748654"
+- fy="10.457643"
+- r="6.6449099" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2255"
+- id="linearGradient2261"
+- x1="12.514956"
+- y1="18.690643"
+- x2="12.514956"
+- y2="3.9849093"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(1.943689,0,0,1.932352,0.678089,2.050925)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2263"
+- id="linearGradient2269"
+- x1="10.555883"
+- y1="8.0642843"
+- x2="10.555883"
+- y2="1.4995424"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="12.865422"
+- inkscape:cx="46.678288"
+- inkscape:cy="27.286544"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#edd400"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.99999982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 23.921379,18.772128 C 20.531101,16.831234 19.828661,25.427448 17.466079,29.485095 C 15.153694,33.456532 7.4937606,36.040098 7.4937606,36.040098 L 12.246433,45.509102 L 23.851631,34.738731 C 23.851631,34.738731 31.648476,39.799175 34.033545,45.317469 L 40.310948,39.242775 C 40.310948,39.242775 37.012166,32.72261 29.680284,28.21162 L 40.506226,26.642559 L 38.998349,19.157061 C 31.992149,20.83538 27.747274,20.962407 23.921379,18.772128 z "
+- id="path1324"
+- sodipodi:nodetypes="czccccccccs" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#ffffff;fill-opacity:1;stroke:none;stroke-width:0.72577804;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path1326"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(1.37826,0,0,1.377401,12.95457,3.935583)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.25;fill:url(#radialGradient4330);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(3.310805,0,0,2.323084,-11.5867,18.20601)" />
+- <path
+- style="opacity:1;fill:url(#linearGradient2261);fill-opacity:1;stroke:#b49500;stroke-width:0.99999982;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 23.921379,18.772128 C 20.531101,16.831234 21.460943,23.017888 19.098361,27.075535 C 16.785976,31.046972 7.4937606,36.040098 7.4937606,36.040098 L 12.246433,45.509102 L 23.851631,34.738731 C 23.851631,34.738731 31.648476,39.799175 34.033545,45.317469 L 40.310948,39.242775 C 40.310948,39.242775 37.012166,32.72261 29.680284,28.21162 L 40.661681,26.564831 L 38.687438,18.690695 C 31.681238,20.369014 27.747274,20.962407 23.921379,18.772128 z "
+- id="path4275"
+- sodipodi:nodetypes="czccccccccs" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.97533494"
+- inkscape:original="M 22.84375 18.40625 C 20.718205 18.345643 21.161009 23.512059 19.09375 27.0625 C 16.781366 31.033937 7.5 36.03125 7.5 36.03125 L 12.25 45.5 L 23.84375 34.75 C 23.84375 34.75 31.646181 39.794206 34.03125 45.3125 L 40.3125 39.25 C 40.312501 39.25 37.019382 32.72974 29.6875 28.21875 L 40.65625 26.5625 L 38.6875 18.6875 C 31.681299 20.365819 27.732145 20.971529 23.90625 18.78125 C 23.482465 18.538638 23.147399 18.414908 22.84375 18.40625 z "
+- xlink:href="#path4275"
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999988;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4304"
+- inkscape:href="#path4275"
+- d="M 22.53125,19.15625 C 22.35655,19.185124 22.015713,19.423413 21.625,20.09375 C 21.234287,20.764087 20.848022,21.75407 20.46875,22.875 C 19.710206,25.11686 19.002281,27.842341 17.84375,29.84375 C 16.485288,32.190546 13.833524,33.858876 11.53125,35.0625 C 9.7758989,35.980194 8.9024732,36.291093 8.25,36.53125 L 12,44.09375 L 22.8125,34 C 23.141077,33.70262 23.62883,33.664114 24,33.90625 C 24,33.90625 26.045443,35.241847 28.375,37.28125 C 30.391732,39.046791 32.509362,41.396107 33.9375,43.96875 L 38.875,39.1875 C 38.425182,38.341062 35.513684,33.014709 28.875,28.90625 C 28.511738,28.695573 28.324082,28.276051 28.409163,27.864827 C 28.494244,27.453602 28.832963,27.142985 29.25,27.09375 L 39.1875,25.65625 L 38.03125,19.96875 C 31.456326,21.456721 26.979371,21.554763 23.03125,19.28125 C 22.754401,19.121827 22.666044,19.133971 22.53125,19.15625 z " />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:url(#linearGradient2269);fill-opacity:1;stroke:#b49500;stroke-width:0.72577804;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(1.37826,0,0,1.377401,13.96243,3.935583)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;fill:#fce94f;fill-opacity:1;stroke:#ffffff;stroke-width:0.84666103;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4273"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(1.181111,0,0,1.181111,16.03826,4.728084)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/gadu-gadu.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,215 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48px"
+- height="48px"
+- id="svg1307"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48/scalable"
+- sodipodi:docname="gadu-gadu.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/gadu-gadu.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs1309">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2447">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2449" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2451" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2233">
+- <stop
+- style="stop-color:#eeeeec;stop-opacity:1;"
+- offset="0"
+- id="stop2235" />
+- <stop
+- style="stop-color:#eeeeec;stop-opacity:0;"
+- offset="1"
+- id="stop2237" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2233"
+- id="linearGradient2279"
+- gradientUnits="userSpaceOnUse"
+- x1="24.450865"
+- y1="5.1375499"
+- x2="24.450865"
+- y2="31.487988" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2447"
+- id="linearGradient2453"
+- x1="24.5"
+- y1="0.33943355"
+- x2="24.5"
+- y2="19.724688"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="15.004828"
+- inkscape:cx="40.53287"
+- inkscape:cy="23.900599"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- fill="#ef2929"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="972"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata1312">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;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(3.160314,0,0,2.745459,-9.969125,9.788968)" />
+- <path
+- style="opacity:1;fill:#ef2929;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 22.5,4.5130623 L 22.5,8.6366327 C 19.782905,9.0005399 17.277282,10.079925 15.21875,11.698071 L 12.0625,8.5116761 L 9.5,11.073287 L 12.6875,14.259683 C 11.068793,16.317502 9.9577835,18.791017 9.59375,21.50717 L 5.5,21.50717 L 5.5,25.505784 L 9.59375,25.505784 C 9.9535644,28.234089 11.062591,30.718808 12.6875,32.78451 L 9.5,35.970906 L 12.0625,38.501278 L 15.21875,35.346123 C 17.277282,36.964269 19.782905,38.043654 22.5,38.407561 L 22.5,42.499891 L 26.5,42.499891 L 26.5,38.407561 C 29.229107,38.042044 31.717452,36.944842 33.78125,35.314883 L 36.96875,38.501278 L 39.5,35.970906 L 36.3125,32.78451 C 37.936789,30.719597 39.014761,28.232873 39.375,25.505784 L 43.5,25.505784 L 43.5,21.50717 L 39.375,21.50717 C 39.010966,18.791018 37.931208,16.317502 36.3125,14.259683 L 39.5,11.073287 L 36.96875,8.5116761 L 33.78125,11.698071 L 33.75,11.698071 C 31.691468,10.079924 29.217095,9.0005401 26.5,8.6366327 L 26.5,4.5130623 L 22.5,4.5130623 z M 23.8125,11.354441 C 24.033452,11.344807 24.274977,11.354441 24.5,11.354441 C 31.700731,11.354441 36.65625,16.339482 36.65625,23.537717 C 36.656248,30.735953 31.700731,35.689753 24.5,35.689753 C 17.29927,35.689754 12.502002,30.735951 12.502002,23.537717 C 12.502002,16.564428 16.962974,11.653081 23.8125,11.354441 z "
+- id="path2394"
+- sodipodi:nodetypes="cccccccccccccccccccccccccccccccccccssssc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1"
+- inkscape:original="M 22.5 4.5 L 22.5 8.625 C 19.782905 8.988907 17.277282 10.069354 15.21875 11.6875 L 12.0625 8.5 L 9.5 11.0625 L 12.6875 14.25 C 11.068793 16.307819 9.9577835 18.783847 9.59375 21.5 L 5.5 21.5 L 5.5 25.5 L 9.59375 25.5 C 9.9535644 28.228306 11.062591 30.715548 12.6875 32.78125 L 9.5 35.96875 L 12.0625 38.5 L 15.21875 35.34375 C 17.277282 36.961896 19.782905 38.042343 22.5 38.40625 L 22.5 42.5 L 26.5 42.5 L 26.5 38.40625 C 29.229107 38.040732 31.717452 36.942459 33.78125 35.3125 L 36.96875 38.5 L 39.5 35.96875 L 36.3125 32.78125 C 37.936789 30.716335 39.014761 28.227089 39.375 25.5 L 43.5 25.5 L 43.5 21.5 L 39.375 21.5 C 39.010966 18.783848 37.931208 16.307819 36.3125 14.25 L 39.5 11.0625 L 36.96875 8.5 L 33.78125 11.6875 L 33.75 11.6875 C 31.691468 10.069353 29.217095 8.9889074 26.5 8.625 L 26.5 4.5 L 22.5 4.5 z M 23.8125 11.34375 C 24.033452 11.334116 24.274977 11.34375 24.5 11.34375 C 31.700731 11.34375 36.65625 16.333015 36.65625 23.53125 C 36.656248 30.729485 31.700731 35.6875 24.5 35.6875 C 17.29927 35.6875 12.5 30.729484 12.5 23.53125 C 12.5 16.55796 16.962974 11.64239 23.8125 11.34375 z "
+- xlink:href="#path2394"
+- style="opacity:0.2;fill:url(#linearGradient2453);fill-opacity:1.0;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2445"
+- inkscape:href="#path2394"
+- d="M 23.5,5.5 L 23.5,8.625 C 23.503929,9.1319208 23.127956,9.5616039 22.625,9.625 C 20.085855,9.9650737 17.762357,10.960594 15.84375,12.46875 C 15.44664,12.797268 14.864902,12.77021 14.5,12.40625 L 12.0625,9.9375 L 10.9375,11.0625 L 13.40625,13.53125 C 13.77021,13.896152 13.797268,14.47789 13.46875,14.875 C 11.953567,16.801212 10.932828,19.095048 10.59375,21.625 C 10.530354,22.127956 10.100671,22.503929 9.59375,22.5 L 6.5,22.5 L 6.5,24.5 L 9.59375,24.5 C 10.100671,24.496071 10.530354,24.872044 10.59375,25.375 C 10.929039,27.917339 11.948302,30.223346 13.46875,32.15625 C 13.797268,32.55336 13.77021,33.135098 13.40625,33.5 L 10.9375,35.96875 L 12.03125,37.09375 L 14.5,34.625 C 14.864902,34.26104 15.44664,34.233982 15.84375,34.5625 C 17.762357,36.070656 20.085855,37.066176 22.625,37.40625 C 23.127956,37.469646 23.503929,37.899329 23.5,38.40625 L 23.5,41.5 L 25.5,41.5 L 25.5,38.40625 C 25.496071,37.899329 25.872044,37.469646 26.375,37.40625 C 28.92215,37.065102 31.227806,36.054308 33.15625,34.53125 C 33.55336,34.202732 34.135098,34.22979 34.5,34.59375 L 36.96875,37.0625 L 38.0625,35.96875 L 35.59375,33.5 C 35.22979,33.135098 35.202732,32.55336 35.53125,32.15625 C 37.047015,30.229299 38.038333,27.923642 38.375,25.375 C 38.438396,24.872044 38.868079,24.496071 39.375,24.5 L 42.5,24.5 L 42.5,22.5 L 39.375,22.5 C 38.868079,22.503929 38.438396,22.127956 38.375,21.625 C 38.034921,19.087581 37.042567,16.796296 35.53125,14.875 C 35.202732,14.47789 35.22979,13.896152 35.59375,13.53125 L 38.09375,11.03125 L 36.96875,9.9375 L 34.5,12.40625 C 34.307701,12.592396 34.048815,12.693699 33.78125,12.6875 L 33.75,12.6875 C 33.522871,12.68767 33.302449,12.610522 33.125,12.46875 C 31.202527,10.957555 28.913145,9.9649402 26.375,9.625 C 25.872044,9.5616039 25.496071,9.1319208 25.5,8.625 L 25.5,5.5 L 23.5,5.5 z M 23.78125,10.34375 C 24.062872,10.331471 24.303519,10.34375 24.5,10.34375 C 32.162653,10.34375 37.65625,15.874058 37.65625,23.53125 C 37.656248,31.188442 32.15976,36.6875 24.5,36.6875 C 20.67012,36.6875 17.391923,35.341265 15.09375,33 C 12.795577,30.658735 11.5,27.35261 11.5,23.53125 C 11.5,16.131287 16.473536,10.662367 23.78125,10.34375 z " />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#edd400;fill-opacity:1;fill-rule:evenodd;stroke:#a40000;stroke-width:1.08146787;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2198"
+- sodipodi:cx="24.450865"
+- sodipodi:cy="23.959385"
+- sodipodi:rx="14.03053"
+- sodipodi:ry="14.03053"
+- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
+- transform="matrix(0.924879,0,0,0.924459,1.889957,1.34006)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:url(#linearGradient2279);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1.12198293;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2277"
+- sodipodi:cx="24.450865"
+- sodipodi:cy="23.959385"
+- sodipodi:rx="14.03053"
+- sodipodi:ry="14.03053"
+- d="M 38.481395 23.959385 A 14.03053 14.03053 0 1 1 10.420335,23.959385 A 14.03053 14.03053 0 1 1 38.481395 23.959385 z"
+- transform="matrix(0.890914,0,0,0.891279,2.716374,2.14037)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2200"
+- sodipodi:cx="10.54341"
+- sodipodi:cy="-2.7068274"
+- sodipodi:rx="2.4204714"
+- sodipodi:ry="1.7230475"
+- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
+- transform="matrix(0.827565,0,0,0.87352,11.27774,22.85935)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#2e3436;fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:2;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2202"
+- sodipodi:cx="10.54341"
+- sodipodi:cy="-2.7068274"
+- sodipodi:rx="2.4204714"
+- sodipodi:ry="1.7230475"
+- d="M 12.963882 -2.7068274 A 2.4204714 1.7230475 0 1 1 8.1229389,-2.7068274 A 2.4204714 1.7230475 0 1 1 12.963882 -2.7068274 z"
+- transform="matrix(0.827567,0,0,0.87352,20.27772,22.86958)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#2e3436;stroke-width:4.5851903;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2204"
+- sodipodi:cx="24.450865"
+- sodipodi:cy="23.959385"
+- sodipodi:rx="14.03053"
+- sodipodi:ry="14.03053"
+- d="M 36.657066,30.877796 A 14.03053,14.03053 0 0 1 11.928959,30.288496"
+- transform="matrix(0.453563,0,0,0.419476,13.51464,14.26249)"
+- sodipodi:start="0.51564596"
+- sodipodi:end="2.6736"
+- sodipodi:open="true" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;fill:none;fill-opacity:1;fill-rule:evenodd;stroke:#ffffff;stroke-width:0.75245398;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2465"
+- sodipodi:cx="26.658085"
+- sodipodi:cy="20.675463"
+- sodipodi:rx="9.863492"
+- sodipodi:ry="8.2640066"
+- d="M 36.521577 20.675463 A 9.863492 8.2640066 0 1 1 16.794593,20.675463 A 9.863492 8.2640066 0 1 1 36.521577 20.675463 z"
+- transform="matrix(1.216989,0,0,1.451287,-7.948546,-6.503855)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/google-talk.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/google-talk.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/google-talk.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/google-talk.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,261 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- id="svg2417"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- width="48"
+- height="48"
+- version="1.0"
+- sodipodi:docbase="/home/vinicius/tango-icon-theme-code/protocols/scalable"
+- sodipodi:docname="google-talk.svg"
+- inkscape:export-filename="/home/vinicius/tango-icon-theme-code/protocols/48x48/google-talk.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <metadata
+- id="metadata2422">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- <dc:title>Google Talk Icon</dc:title>
+- <dc:date>2006-12-03</dc:date>
+- <dc:creator>
+- <cc:Agent>
+- <dc:title>Vinicius Scopel Depizzol</dc:title>
+- </cc:Agent>
+- </dc:creator>
+- <dc:source>vdepizzol@gmail.com</dc:source>
+- <dc:subject>
+- <rdf:Bag>
+- <rdf:li>Google Talk</rdf:li>
+- <rdf:li>GTalk</rdf:li>
+- <rdf:li>VOIP</rdf:li>
+- <rdf:li>Protocol</rdf:li>
+- </rdf:Bag>
+- </dc:subject>
+- <cc:license
+- rdf:resource="http://creativecommons.org/licenses/by-sa/2.0/" />
+- </cc:Work>
+- <cc:License
+- rdf:about="http://creativecommons.org/licenses/by-sa/2.0/">
+- <cc:permits
+- rdf:resource="http://web.resource.org/cc/Reproduction" />
+- <cc:permits
+- rdf:resource="http://web.resource.org/cc/Distribution" />
+- <cc:requires
+- rdf:resource="http://web.resource.org/cc/Notice" />
+- <cc:requires
+- rdf:resource="http://web.resource.org/cc/Attribution" />
+- <cc:permits
+- rdf:resource="http://web.resource.org/cc/DerivativeWorks" />
+- <cc:requires
+- rdf:resource="http://web.resource.org/cc/ShareAlike" />
+- </cc:License>
+- </rdf:RDF>
+- </metadata>
+- <defs
+- id="defs2420">
+- <linearGradient
+- id="linearGradient3299">
+- <stop
+- style="stop-color:#000000;stop-opacity:0.11764706;"
+- offset="0"
+- id="stop3301" />
+- <stop
+- style="stop-color:#000000;stop-opacity:0;"
+- offset="1"
+- id="stop3303" />
+- </linearGradient>
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3299"
+- id="radialGradient3305"
+- cx="15.993708"
+- cy="26.722889"
+- fx="15.993708"
+- fy="26.722889"
+- r="15.912521"
+- gradientTransform="matrix(1,0,0,0.295918,-3.769888e-16,18.8151)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- id="linearGradient3527">
+- <stop
+- style="stop-color:#90ba1f;stop-opacity:1;"
+- offset="0"
+- id="stop3529" />
+- <stop
+- style="stop-color:#638205;stop-opacity:1;"
+- offset="1"
+- id="stop3531" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient3518">
+- <stop
+- style="stop-color:#e7d000;stop-opacity:1;"
+- offset="0"
+- id="stop3520" />
+- <stop
+- style="stop-color:#c4a000;stop-opacity:1;"
+- offset="1"
+- id="stop3522" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient3486">
+- <stop
+- style="stop-color:#ef2929;stop-opacity:1;"
+- offset="0"
+- id="stop3488" />
+- <stop
+- style="stop-color:#cc0000;stop-opacity:1;"
+- offset="1"
+- id="stop3490" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient3510">
+- <stop
+- style="stop-color:#3465a4;stop-opacity:1;"
+- offset="0"
+- id="stop3512" />
+- <stop
+- style="stop-color:#204a87;stop-opacity:1;"
+- offset="1"
+- id="stop3514" />
+- </linearGradient>
+- <linearGradient
+- id="linearGradient3286">
+- <stop
+- style="stop-color:#d1d1d1;stop-opacity:1;"
+- offset="0"
+- id="stop3288" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="1"
+- id="stop3290" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3527"
+- id="linearGradient4249"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(2.465389,0,0,2.513895,-105.5963,47.11115)"
+- x1="55.483334"
+- y1="-14.40625"
+- x2="55.483334"
+- y2="-7.9999866" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3518"
+- id="linearGradient4252"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(2.901968,0,0,2.518653,-127.7063,47.25387)"
+- x1="53.162479"
+- y1="-14.322747"
+- x2="53.162479"
+- y2="-9.9868765" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3486"
+- id="linearGradient4255"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(2.48585,0,0,2.48585,-103.0483,47.16833)"
+- x1="49.45462"
+- y1="-12.934268"
+- x2="49.45462"
+- y2="-8.0529032" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3510"
+- id="linearGradient4258"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(2.48585,0,0,2.48585,-100.3774,47.19573)"
+- x1="45.5"
+- y1="-14"
+- x2="45.5"
+- y2="-8.1156492" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3286"
+- id="linearGradient4262"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(2.99378,0,0,2.99378,9.552849e-2,-0.965622)"
+- x1="8"
+- y1="15"
+- x2="8"
+- y2="0.9916327" />
+- </defs>
+- <sodipodi:namedview
+- inkscape:window-height="714"
+- inkscape:window-width="1014"
+- inkscape:pageshadow="2"
+- inkscape:pageopacity="0"
+- borderopacity="1"
+- bordercolor="#666666"
+- pagecolor="#ffffff"
+- id="base"
+- showgrid="false"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:zoom="1"
+- inkscape:cx="27.558407"
+- inkscape:cy="20.353863"
+- inkscape:window-x="0"
+- inkscape:window-y="0"
+- inkscape:current-layer="svg2417"
+- showborder="false"
+- inkscape:showpageshadow="false" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:url(#radialGradient3305);fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+- id="path2424"
+- sodipodi:cx="15.993708"
+- sodipodi:cy="26.722889"
+- sodipodi:rx="15.912521"
+- sodipodi:ry="4.7088075"
+- d="M 31.906229,26.722889 A 15.912521,4.7088075 0 1 1 31.906148,26.707864"
+- sodipodi:start="0"
+- sodipodi:end="6.2799944"
+- sodipodi:open="true"
+- transform="matrix(1.45896,0,0,1.538545,0.742037,-1.869655)" />
+- <path
+- id="path3264"
+- d="M 21.80045,3.5250496 C 10.471905,4.3704822 1.592428,11.452408 1.592428,19.990844 C 1.592428,26.29506 6.3896918,31.807945 13.473996,34.585527 C 13.301077,37.113716 12.611393,40.274075 10.57377,42.444203 C 16.402876,42.263357 20.689781,39.28536 23.484452,36.456639 C 23.677129,36.460226 23.851935,36.456639 24.045787,36.456639 C 36.451938,36.456639 46.499142,29.098509 46.499142,19.990844 L 46.499142,19.897289 C 46.459634,10.808172 36.426737,3.5250496 24.045787,3.5250496 C 23.270404,3.5250496 22.555687,3.4686875 21.80045,3.5250496 z "
+- style="fill:url(#linearGradient4262);fill-opacity:1;fill-rule:nonzero;stroke:#797979;stroke-width:0.99999946;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-dashoffset:0;stroke-opacity:1"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- sodipodi:nodetypes="ccccccccccccccccc"
+- id="path3552"
+- d="M 14.063569,10.992619 L 10.975162,10.992619 L 10.975162,15.008301 L 9,15.008301 L 9,18.010155 L 10.975162,18.010155 L 10.975162,24.823081 C 10.975162,28.316382 16.413217,26.749332 16.906897,25.946127 L 16.765885,23.742745 C 16.14428,24.364355 14.063569,24.882059 14.063569,24.09267 L 14.063569,18.010155 L 16.089796,18.010155 L 16.089796,15.008301 L 14.063569,15.008301 L 14.063569,11.090553 L 14.063569,11.090553 L 14.063569,10.992619 z "
+- style="fill:url(#linearGradient4258);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+- <path
+- style="fill:url(#linearGradient4255);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1"
+- d="M 20.513467,15.031036 C 20.138171,15.089956 19.656414,15.165467 19.228078,15.318859 C 17.702481,15.865192 16.671718,16.778263 16.671718,16.778263 L 17.928902,19.157272 C 19.392632,18.022338 22.111019,16.595753 21.828421,20.24551 C 16.134551,19.714196 14.746648,23.348506 16.160515,25.369297 C 17.612211,27.444158 20.173876,27.641863 21.329645,26.185476 C 21.514145,25.952987 21.740964,25.678231 21.873764,25.369297 C 22.016347,25.75349 22.226874,26.072865 22.417883,26.321505 C 22.574471,26.517581 23.312178,27.152657 24.004897,27.137684 C 24.806193,27.120365 25.583813,26.58185 26,25.958759 C 25.645136,26.22137 24.252362,25.650216 24.231613,24.779835 L 24.231613,18.29575 C 24.142462,16.667478 22.425687,14.730825 20.513467,15.031036 z M 21.193616,23.328851 C 21.034551,24.122851 19.396586,24.681233 18.790423,24.326402 C 17.894487,23.801947 19.229645,22.393776 20.377437,22.376643 C 21.417389,22.361119 21.33274,22.634384 21.193616,23.328851 z "
+- id="path3554"
+- sodipodi:nodetypes="cscccsscsscccccsss" />
+- <path
+- id="path3558"
+- d="M 29,11 L 26.098032,11 L 26.098032,27.104637 L 29,27.104637 L 29,11 z "
+- style="fill:url(#linearGradient4252);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+- <path
+- sodipodi:nodetypes="ccccccccccccc"
+- id="path3560"
+- d="M 30,10.895363 L 30,19.851112 L 30,27 L 32.963722,27 L 32.963722,22.924045 L 36.561805,27.064163 L 38.705904,25.193137 L 34.676855,20.715264 L 38.705904,16.23739 L 36.754295,14.238037 L 32.968278,18.187047 C 32.968278,18.187047 32.963722,10.895363 32.963722,10.895363 L 30,10.895363 z "
+- style="fill:url(#linearGradient4249);fill-opacity:1;fill-rule:evenodd;stroke:none;stroke-width:1px;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1" />
+- <path
+- style="fill:#ffffff;fill-opacity:1;fill-rule:nonzero;stroke:none;stroke-width:3;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dashoffset:0;stroke-opacity:1"
+- d="M 21.84375,4.03125 C 16.273135,4.4469767 11.295199,6.3799921 7.75,9.25 C 4.204801,12.120008 2.09375,15.904106 2.09375,20 C 2.093752,26.050562 6.709849,31.401486 13.65625,34.125 C 13.889662,34.247612 13.966606,34.430582 13.96875,34.625 C 13.8154,36.867085 13.233839,39.586592 11.6875,41.78125 C 16.756159,41.27394 20.580438,38.669315 23.125,36.09375 C 23.324492,35.928053 23.831229,35.96875 24.03125,35.96875 C 30.135475,35.96875 35.660367,34.1562 39.625,31.25 C 43.589633,28.3438 46,24.369973 46,20 L 46,19.90625 C 45.981043,15.545078 43.55655,11.604324 39.59375,8.71875 C 35.63095,5.8331761 30.123683,4.03125 24.03125,4.03125 C 23.381564,4.0312499 22.681539,3.982177 21.84375,4.03125 z M 24.03125,5.03125 C 29.927599,5.03125 35.264412,6.757119 39.03125,9.5 C 42.798088,12.242881 44.982638,15.911852 45,19.90625 L 45,20 C 45,24.002253 42.800008,27.674883 39.03125,30.4375 C 35.262492,33.200117 29.937773,34.96875 24.03125,34.96875 C 23.079654,34.946683 22.695929,35.117383 22.40625,35.40625 C 20.316957,37.520999 17.387178,39.593629 13.59375,40.46875 C 14.470139,38.520138 14.848653,36.443413 14.96875,34.6875 C 15.010593,33.903846 14.715478,33.607465 14.03125,33.1875 C 7.360656,30.572123 3.093751,25.543254 3.09375,20 C 3.09375,16.250753 5.042528,12.754344 8.40625,10.03125 C 11.769972,7.3081563 16.52295,5.4329977 21.90625,5.03125 C 22.667268,4.9737265 23.342191,5.0312499 24.03125,5.03125 z "
+- id="path6054"
+- sodipodi:nodetypes="csscccccsccssccsccscscccsscs" />
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/icq.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/icq.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/icq.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/icq.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,440 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg2"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
+- sodipodi:docname="icq.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/icq.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2256">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2258" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2260" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2248">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2250" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2252" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2240">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2242" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2244" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2232">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2234" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2236" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2224">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2226" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2228" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2216">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2218" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2220" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2208">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2210" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2212" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2361">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2363" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2365" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2321">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2323" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2325" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2321"
+- id="linearGradient2327"
+- x1="11.787398"
+- y1="11.115861"
+- x2="12.185872"
+- y2="12.839791"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2361"
+- id="linearGradient2367"
+- x1="14.592834"
+- y1="24.232048"
+- x2="14.592834"
+- y2="31.007147"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2208"
+- id="linearGradient2214"
+- x1="28.089931"
+- y1="3.8865747"
+- x2="28.089931"
+- y2="15.058928"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2216"
+- id="linearGradient2222"
+- x1="36.696918"
+- y1="10.99979"
+- x2="36.696918"
+- y2="20.717306"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2224"
+- id="linearGradient2230"
+- x1="36.701996"
+- y1="20.379145"
+- x2="36.701996"
+- y2="29.063459"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2232"
+- id="linearGradient2238"
+- x1="17.892992"
+- y1="6.7056818"
+- x2="17.892992"
+- y2="16.46983"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2240"
+- id="linearGradient2246"
+- x1="12.732279"
+- y1="14.645196"
+- x2="12.732279"
+- y2="23.238768"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2248"
+- id="linearGradient2254"
+- x1="21.683891"
+- y1="24.981401"
+- x2="21.683891"
+- y2="36.415653"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2256"
+- id="linearGradient2262"
+- x1="30.265167"
+- y1="27.26486"
+- x2="30.265167"
+- y2="35.256603"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="14.778489"
+- inkscape:cx="38.03465"
+- inkscape:cy="24.512139"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#ef2929"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;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(3.009823,0,0,2.74546,-8.351546,7.855242)" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 26.367384,35.737238 C 24.85713,31.115741 25.395878,30.363552 27.387814,29.222534 C 29.379747,28.081519 30.462949,28.167777 33.584537,31.603121 C 35.536982,34.958339 35.504926,38.607457 33.513001,39.748468 C 31.521063,40.889489 28.319827,39.092453 26.367384,35.737238 z "
+- id="path2226"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.95876986"
+- inkscape:original="M 28.75 28.625 C 28.319559 28.723691 27.872983 28.933496 27.375 29.21875 C 25.383064 30.359768 24.864746 31.128501 26.375 35.75 C 28.327443 39.105215 31.508063 40.891023 33.5 39.75 C 35.491925 38.608989 35.546194 34.948968 33.59375 31.59375 C 31.252559 29.017242 30.041322 28.328926 28.75 28.625 z "
+- xlink:href="#path2226"
+- style="opacity:0.4;fill:url(#linearGradient2262);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2242"
+- inkscape:href="#path2226"
+- d="M 28.96875,26.5 C 28.686015,26.564825 28.303156,26.736844 27.84375,27 C 27.368858,27.272027 27.042376,27.491026 26.84375,27.6875 C 26.645124,27.883974 26.558141,28.035355 26.5,28.3125 C 26.386493,28.853563 26.554045,30.085975 27.25,32.25 C 28.145595,33.765674 29.317595,34.913452 30.40625,35.53125 C 31.510083,36.157661 32.416733,36.195758 33.03125,35.84375 C 33.64681,35.491146 34.046689,34.69972 34.0625,33.4375 C 34.077874,32.210233 33.659976,30.628765 32.8125,29.125 C 31.711537,27.921881 30.874722,27.139693 30.28125,26.78125 C 29.672583,26.41363 29.393014,26.402725 28.96875,26.5 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:0.99999982;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 33.709491,31.278338 C 29.169302,28.745112 29.065713,27.592023 29.859889,24.733701 C 30.654065,21.875391 31.593198,20.926512 36.586936,20.922121 C 40.576342,21.952999 43.16957,25.109445 42.375396,27.967758 C 41.581221,30.826078 37.6989,32.309217 33.709491,31.278338 z "
+- id="path2216"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.98264426"
+- inkscape:original="M 36.59375 20.9375 C 31.600012 20.941891 30.669177 21.860439 29.875 24.71875 C 29.080824 27.577072 29.17856 28.748025 33.71875 31.28125 C 37.708159 32.312129 41.580824 30.82707 42.375 27.96875 C 43.169174 25.110437 40.583155 21.968378 36.59375 20.9375 z "
+- xlink:href="#path2216"
+- style="opacity:0.4;fill:url(#linearGradient2230);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2238"
+- inkscape:href="#path2216"
+- d="M 36.4375,18.8125 C 34.127551,18.828525 32.839067,19.094363 32.1875,19.5 C 31.517812,19.916918 31.190595,20.545455 30.8125,21.90625 C 30.427461,23.292046 30.362754,23.987827 30.6875,24.625 C 31.003678,25.245362 31.967431,26.095761 34.0625,27.28125 C 35.838582,27.720407 37.581667,27.600958 38.90625,27.09375 C 40.254639,26.577426 41.138951,25.730758 41.4375,24.65625 C 41.735829,23.582532 41.424738,22.405518 40.53125,21.3125 C 39.654391,20.239825 38.199379,19.288753 36.4375,18.8125 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 36.67848,22.648043 C 32.052133,24.231706 31.299156,23.66677 30.15694,21.57801 C 29.014732,19.489253 29.101081,18.3534 32.540028,15.08008 C 35.898764,13.032731 39.551708,13.066339 40.693916,15.155093 C 41.836132,17.243854 40.037215,20.600694 36.67848,22.648043 z "
+- id="path2224"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- style="fill:#ef2929;fill-opacity:1;stroke:#a40000;stroke-width:1.00000167;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 15.680976,33.623016 C 11.05302,35.149988 10.299782,34.605272 9.1571703,32.591284 C 8.0145636,30.577295 8.100941,29.482102 11.541085,26.325956 C 14.900987,24.351896 18.555202,24.3843 19.697807,26.398287 C 20.840426,28.412273 19.040877,31.648952 15.680976,33.623016 z "
+- id="path2228"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0000435"
+- inkscape:original="M 16.4375 24.875 C 14.961133 24.861908 13.211201 25.32547 11.53125 26.3125 C 8.091106 29.468646 8.0136433 30.579759 9.15625 32.59375 C 10.298862 34.607738 11.059544 35.151972 15.6875 33.625 C 19.047401 31.650936 20.830119 28.420236 19.6875 26.40625 C 19.116197 25.399256 17.913867 24.888092 16.4375 24.875 z "
+- xlink:href="#path2228"
+- style="opacity:0.35;fill:url(#linearGradient2367);fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- id="path2244"
+- inkscape:href="#path2228"
+- d="M 16.4375,25.5625 C 15.225911,25.551756 13.660678,25.986763 12.15625,26.84375 C 10.550146,28.330129 9.7557904,29.328548 9.5625,29.90625 C 9.3649665,30.496634 9.5025865,30.849414 10.03125,31.78125 C 10.302942,32.260138 10.523169,32.613015 10.71875,32.8125 C 10.914331,33.011985 11.040068,33.097389 11.3125,33.15625 C 11.836378,33.269438 13.116625,33.081343 15.21875,32.40625 C 16.739932,31.503646 17.889523,30.32189 18.5,29.21875 C 19.115832,28.105933 19.160409,27.206976 18.8125,26.59375 C 18.466678,25.984194 17.687878,25.573588 16.4375,25.5625 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- transform="translate(-3.261295e-4,1.945628e-4)" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000036;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 15.781196,31.980797 C 18.406839,27.241987 19.600601,27.133027 22.558995,27.959412 C 25.517377,28.785792 26.498997,29.764879 26.5,34.97494 C 25.429993,39.137961 22.160569,41.845948 19.202184,41.019566 C 16.24379,40.193181 14.711189,36.143816 15.781196,31.980797 z "
+- id="path2218"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0089091"
+- inkscape:original="M 20.625 27.5625 C 18.918105 27.466646 17.750483 28.414643 15.78125 31.96875 C 14.711243 36.131769 16.229105 40.204865 19.1875 41.03125 C 22.145885 41.857632 25.429993 39.13177 26.5 34.96875 C 26.498997 29.758689 25.520883 28.79513 22.5625 27.96875 C 21.822902 27.762154 21.193965 27.594451 20.625 27.5625 z "
+- xlink:href="#path2218"
+- style="opacity:0.4;fill:url(#linearGradient2254);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2240"
+- inkscape:href="#path2218"
+- d="M 20.5625,25.5 C 19.907811,25.463235 19.561004,25.566238 18.96875,26.09375 C 18.39939,26.600871 17.659523,27.663233 16.75,29.28125 C 16.300255,31.130934 16.385773,32.955321 16.90625,34.34375 C 17.438569,35.763767 18.360161,36.690332 19.46875,37 C 20.577929,37.309833 21.771436,36.972415 22.90625,36.03125 C 24.020697,35.106976 25.004678,33.595596 25.5,31.75 C 25.485662,29.33285 25.202556,27.963789 24.78125,27.28125 C 24.348724,26.580535 23.69033,26.268606 22.28125,25.875 C 21.548137,25.670215 20.975703,25.523204 20.5625,25.5 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 22.589636,12.085809 C 24.174724,16.906782 23.609284,17.691436 21.518638,18.881701 C 19.427991,20.071964 18.291112,19.981984 15.014841,16.398361 C 12.965643,12.898328 12.999283,9.0917088 15.089923,7.9014452 C 17.180566,6.7111801 20.540438,8.5857754 22.589636,12.085809 z "
+- id="path2222"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.96927398"
+- inkscape:original="M 16.84375 7.5625 C 16.202747 7.4994497 15.616411 7.6086837 15.09375 7.90625 C 13.00311 9.0965136 12.950802 12.906217 15 16.40625 C 18.276271 19.989873 19.440602 20.065263 21.53125 18.875 C 23.621896 17.684735 24.178838 16.914723 22.59375 12.09375 C 21.056852 9.4687248 18.76676 7.7516509 16.84375 7.5625 z "
+- xlink:href="#path2222"
+- style="opacity:0.4;fill:url(#linearGradient2238);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2232"
+- inkscape:href="#path2222"
+- d="M 16.75,5.46875 C 16.27484,5.4220124 15.902933,5.4936816 15.5625,5.6875 C 14.90056,6.0643619 14.484412,6.9299953 14.46875,8.25 C 14.453381,9.5453187 14.903286,11.163341 15.8125,12.75 C 17.344427,14.407623 18.369904,15.229192 19,15.4375 C 19.647022,15.651404 20.092056,15.52125 21.0625,14.96875 C 21.562192,14.684261 21.911138,14.459507 22.125,14.25 C 22.338862,14.040493 22.436992,13.887548 22.5,13.59375 C 22.621375,13.027792 22.42463,11.70151 21.71875,9.5 C 20.300551,7.1027674 18.170695,5.6084922 16.75,5.46875 z "
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- transform="translate(0,6.766591e-2)" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000072;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 15.110245,15.90519 C 19.82436,18.526878 19.931835,19.720374 19.106984,22.678924 C 18.282136,25.637465 17.306916,26.619664 12.121668,26.624562 C 7.9793465,25.557832 5.2869063,22.290944 6.1117518,19.332403 C 6.9366004,16.373851 10.967924,14.838461 15.110245,15.90519 z "
+- id="path2220"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0062078"
+- inkscape:original="M 12.0625 15.5625 C 9.1424837 15.682984 6.7436363 17.124836 6.125 19.34375 C 5.3001545 22.302291 7.9826786 25.558271 12.125 26.625 C 17.310248 26.620102 18.268903 25.64604 19.09375 22.6875 C 19.918601 19.72895 19.839115 18.527938 15.125 15.90625 C 14.08942 15.639568 13.035839 15.522339 12.0625 15.5625 z "
+- xlink:href="#path2220"
+- style="opacity:0.4;fill:url(#linearGradient2246);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2234"
+- inkscape:href="#path2220"
+- d="M 12.09375,13.5 C 9.4814409,13.607788 7.5619569,14.883144 7.09375,16.5625 C 6.7827532,17.677978 7.1032888,18.873814 8.03125,20 C 8.9425567,21.105974 10.44513,22.068869 12.28125,22.5625 C 14.685442,22.546282 16.040043,22.264255 16.71875,21.84375 C 17.415725,21.411927 17.731987,20.753401 18.125,19.34375 C 18.525721,17.906458 18.614647,17.219888 18.28125,16.5625 C 17.956369,15.921903 16.929755,15.04136 14.75,13.8125 C 13.845755,13.591694 12.918322,13.465977 12.09375,13.5 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0066811"
+- inkscape:original="M 37.4375 13.5625 C 35.961646 13.548922 34.210618 14.070075 32.53125 15.09375 C 29.092303 18.36707 29.014042 19.473742 30.15625 21.5625 C 31.298466 23.65126 32.061155 24.239913 36.6875 22.65625 C 40.046235 20.608901 41.829716 17.245011 40.6875 15.15625 C 40.116396 14.111873 38.913354 13.576078 37.4375 13.5625 z "
+- xlink:href="#path2224"
+- style="opacity:0.4;fill:url(#linearGradient2222);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2236"
+- inkscape:href="#path2224"
+- d="M 37.4375,11.5 C 36.209007,11.488698 34.640843,11.934525 33.125,12.84375 C 31.572994,14.343465 30.790495,15.387459 30.59375,16 C 30.38941,16.636186 30.501711,17.062882 31.03125,18.03125 C 31.303727,18.529526 31.551384,18.882242 31.75,19.09375 C 31.948616,19.305258 32.078397,19.376294 32.34375,19.4375 C 32.849897,19.554247 34.121629,19.37131 36.1875,18.6875 C 37.705568,17.753005 38.884734,16.530737 39.5,15.375 C 40.120629,14.209188 40.168638,13.213767 39.8125,12.5625 C 39.457388,11.913107 38.674773,11.511383 37.4375,11.5 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 33.125387,15.014401 C 30.26869,19.896731 28.973236,20.010902 25.764644,19.165247 C 22.556047,18.319592 21.492567,17.31342 21.500039,11.950433 C 22.667874,7.6634206 26.219761,4.8704358 29.428357,5.7160909 C 32.636953,6.5617466 34.293217,10.72739 33.125387,15.014401 z "
+- id="path2192"
+- sodipodi:nodetypes="cscsc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99950546"
+- inkscape:original="M 27 5.71875 C 24.592663 6.34847 22.375877 8.7222409 21.5 11.9375 C 21.492528 17.300487 22.541402 18.310595 25.75 19.15625 C 28.958592 20.001905 30.268305 19.88233 33.125 15 C 34.29283 10.712989 32.646097 6.5644059 29.4375 5.71875 C 28.635351 5.5073362 27.802446 5.5088433 27 5.71875 z "
+- xlink:href="#path2192"
+- style="opacity:0.4;fill:url(#linearGradient2214);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2230"
+- inkscape:href="#path2192"
+- d="M 27.25,3.625 C 25.314633,4.1312603 23.314958,6.1607857 22.5,9.03125 C 22.510826,11.522864 22.789343,12.909624 23.25,13.625 C 23.722547,14.358839 24.464582,14.720327 26,15.125 C 27.560661,15.536327 28.366368,15.654754 29.125,15.28125 C 29.867191,14.91584 30.838854,13.842149 32.1875,11.5625 C 32.678344,9.6587072 32.56307,7.7926235 32,6.375 C 31.424078,4.9250185 30.443053,3.9559128 29.1875,3.625 C 28.551361,3.4573398 27.889759,3.4576495 27.25,3.625 z "
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/path2232.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:0.21428883;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path1317"
+- sodipodi:cx="12.075002"
+- sodipodi:cy="12.360133"
+- sodipodi:rx="1.1966218"
+- sodipodi:ry="1.4141895"
+- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
+- transform="matrix(4.891864,1.290148,-1.13072,4.153499,-20.5947,-43.34178)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.4;fill:url(#linearGradient2327);fill-opacity:1;stroke:#ffffff;stroke-width:0.25782824;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2319"
+- sodipodi:cx="12.075002"
+- sodipodi:cy="12.360133"
+- sodipodi:rx="1.1966218"
+- sodipodi:ry="1.4141895"
+- d="M 13.271623 12.360133 A 1.1966218 1.4141895 0 1 1 10.87838,12.360133 A 1.1966218 1.4141895 0 1 1 13.271623 12.360133 z"
+- transform="matrix(4.068634,1.071527,-0.940435,3.449674,-13.02699,-32.06442)" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/meanwhile.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/meanwhile.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/meanwhile.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/meanwhile.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,174 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg2"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
+- sodipodi:docname="meanwhile.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/meanwhile.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2195">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2197" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2199" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2230">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2232" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2234" />
+- </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="radialGradient4330"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(-0.842757,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- cx="10.748654"
+- cy="10.457643"
+- fx="10.748654"
+- fy="10.457643"
+- r="6.6449099" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2230"
+- id="linearGradient2236"
+- x1="10.177145"
+- y1="-1.3535745"
+- x2="10.177145"
+- y2="8.1371298"
+- gradientUnits="userSpaceOnUse" />
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2195"
+- id="radialGradient2211"
+- cx="30.5625"
+- cy="23.172834"
+- fx="30.5625"
+- fy="23.172834"
+- r="23.5"
+- gradientTransform="matrix(1.330958,-1.200379e-32,1.144509e-32,1.269011,-10.11491,-9.053927)"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="16.976026"
+- inkscape:cx="38.972041"
+- inkscape:cy="25.781032"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#f57900"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.3;fill:url(#radialGradient4330);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(3.583369,0,0,3.000545,-14.70523,9.779617)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:1;fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:0.67679459;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4302"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(1.477556,0,0,1.477551,8.403577,4.033323)" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.6;fill:url(#linearGradient2236);fill-opacity:1;stroke:#ffffff;stroke-width:0.78084576;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path4273"
+- sodipodi:cx="10.555883"
+- sodipodi:cy="4.0385542"
+- sodipodi:rx="5.074944"
+- sodipodi:ry="5.074944"
+- d="M 15.630827 4.0385542 A 5.074944 5.074944 0 1 1 5.4809394,4.0385542 A 5.074944 5.074944 0 1 1 15.630827 4.0385542 z"
+- transform="matrix(1.280662,0,0,1.280662,10.48149,4.827989)" />
+- <path
+- style="fill:#f57900;fill-opacity:1;stroke:#ce5c00;stroke-width:1.00000119;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 34.49131,8.6205284 C 34.49131,13.938683 32.849731,20.518688 23.898198,20.518688 C 15.00451,20.518688 13.526711,13.679495 13.526711,8.6600767 L 5.4949228,9.8762415 C 5.4949228,23.237275 17.664236,26.553794 17.664236,26.553794 C 17.664236,26.553794 9.1712538,34.298165 9.1712538,44.405547 L 19.237281,44.498262 C 19.237281,44.498262 21.456328,35.564348 25.010569,35.564348 C 28.652494,35.564348 30.6887,44.471546 30.6887,44.471546 L 40.362294,44.503507 C 40.362294,33.010164 30.381957,26.578174 30.381957,26.578174 C 30.381957,26.578174 42.614757,23.170121 42.614757,9.5035195 L 34.49131,8.6205284 z "
+- id="rect2213"
+- sodipodi:nodetypes="czccccczccccc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.9525249"
+- inkscape:original="M 34.5 8.625 C 34.5 13.943155 32.857783 20.53125 23.90625 20.53125 C 15.012563 20.53125 13.53125 13.675668 13.53125 8.65625 L 5.5 9.875 C 5.5000002 23.236033 17.65625 26.5625 17.65625 26.5625 C 17.65625 26.562499 9.15625 34.298868 9.15625 44.40625 L 19.25 44.5 C 19.249999 44.500002 21.445759 35.5625 25 35.5625 C 28.641925 35.562502 30.6875 44.46875 30.6875 44.46875 L 40.375 44.5 C 40.375001 33.006658 30.375 26.59375 30.375 26.59375 C 30.375001 26.593749 42.625 23.166602 42.625 9.5 L 34.5 8.625 z "
+- xlink:href="#rect2213"
+- style="opacity:0.6;fill:url(#radialGradient2211);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2220"
+- inkscape:href="#rect2213"
+- d="M 45.40625,11.75 C 45.26383,14.467634 44.656918,17.754917 42.6875,20.65625 C 40.459732,23.938183 36.552927,26.5 30.5,26.5 C 24.488156,26.5 20.637234,23.994802 18.4375,20.75 C 16.4845,17.869153 15.883719,14.581533 15.75,11.84375 L 7.5625,13.15625 C 7.8022289,20.855399 11.189172,25.378007 14.65625,28.03125 C 18.250337,30.781689 21.8125,31.5 21.8125,31.5 C 22.153479,31.568346 22.430121,31.817069 22.53422,32.148884 C 22.638319,32.4807 22.553332,32.842875 22.3125,33.09375 C 22.3125,33.09375 12.834342,43.464627 12.34375,55.4375 L 23.625,55.5625 C 23.775583,54.968024 24.284703,52.850143 25.46875,50.125 C 26.139238,48.581838 26.957479,47.047605 27.96875,45.8125 C 28.980021,44.577395 30.249533,43.59375 31.8125,43.59375 C 33.392834,43.59375 34.682884,44.544922 35.6875,45.78125 C 36.692116,47.017578 37.481015,48.583576 38.125,50.125 C 39.262583,52.847886 39.73782,54.93884 39.875,55.53125 L 50.59375,55.5625 C 49.991815,42.90975 37.8125,33.21875 37.8125,33.21875 C 37.516383,32.984647 37.386427,32.597781 37.481159,32.232384 C 37.575892,31.866987 37.877442,31.591993 38.25,31.53125 C 38.25,31.53125 42.11079,30.902899 45.96875,28.21875 C 49.692789,25.627775 53.310428,21.149688 53.5625,13.28125 L 45.40625,11.75 z " />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/msn.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/msn.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/msn.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/msn.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,174 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg2"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
+- sodipodi:docname="msn.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/msn.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <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>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2228">
+- <stop
+- style="stop-color:#f56600;stop-opacity:1;"
+- offset="0"
+- id="stop2230" />
+- <stop
+- style="stop-color:#f56600;stop-opacity:0;"
+- offset="1"
+- id="stop2232" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2219">
+- <stop
+- style="stop-color:#3465a4;stop-opacity:1;"
+- offset="0"
+- id="stop2221" />
+- <stop
+- style="stop-color:#3465a4;stop-opacity:0;"
+- offset="1"
+- id="stop2223" />
+- </linearGradient>
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient3816"
+- id="radialGradient1358"
+- gradientUnits="userSpaceOnUse"
+- cx="31.112698"
+- cy="19.008621"
+- fx="31.112698"
+- fy="19.008621"
+- r="8.6620579"
+- gradientTransform="matrix(1.904859,0,0,0.57723,-32.76529,27.09015)" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2219"
+- id="linearGradient1360"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(1.427299,0,0,1.408267,0.332861,3.39912)"
+- x1="10.329217"
+- y1="14.96656"
+- x2="16.580788"
+- y2="20.092552" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2228"
+- id="linearGradient1362"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(1.489007,0,0,1.428565,1.731241,3.002037)"
+- x1="20.998175"
+- y1="11.741063"
+- x2="18.544895"
+- y2="23.366545" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="14.778489"
+- inkscape:cx="32.469518"
+- inkscape:cy="22.977647"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#edd400"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- style="opacity:0.4;color:#000000;fill:url(#radialGradient1358);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-dashoffset:0;stroke-opacity:1;visibility:visible;display:inline;overflow:visible"
+- d="M 43.00001,38.062496 C 43.00001,40.822496 35.608012,43.062496 26.500013,43.062496 C 17.392013,43.062496 10.000014,40.822496 10.000014,38.062496 C 10.000014,35.302496 17.392013,33.062496 26.500013,33.062496 C 35.608012,33.062496 43.00001,35.302496 43.00001,38.062496 z "
+- id="path4318" />
+- <path
+- style="fill:#edd400;fill-opacity:1;stroke:#c4a000;stroke-width:1.00000083;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 34.662639,20.335823 C 39.495137,21.781376 40.098879,38.560591 34.609432,38.560591 C 29.18649,38.560591 17.111515,15.085731 34.662639,20.335823 z "
+- id="rect2194" />
+- <path
+- style="opacity:0.5;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.00000024;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 29.5,20.59375 C 28.488762,20.699063 27.850577,20.9863 27.40625,21.40625 C 26.961923,21.8262 26.695785,22.399576 26.5625,23.15625 C 26.295929,24.669599 26.724448,26.888006 27.625,29.09375 C 28.525552,31.299494 29.853318,33.518217 31.21875,35.125 C 32.584182,36.731783 34.047656,37.59375 34.625,37.59375 C 35.065414,37.59375 35.396266,37.452251 35.75,37.125 C 36.103734,36.797749 36.436723,36.267837 36.71875,35.5625 C 37.282805,34.151825 37.566795,32.092358 37.53125,30 C 37.495705,27.907642 37.16426,25.762788 36.5625,24.125 C 35.96074,22.487212 35.097603,21.497403 34.375,21.28125 C 32.261511,20.64904 30.658881,20.473061 29.5,20.59375 z "
+- id="path2259" />
+- <path
+- style="fill:#73d216;fill-opacity:1;stroke:#4e9a06;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 24.98559,40.707419 C 20.31754,40.707419 7.959768,29.343494 17.418553,22.824249 C 26.869109,16.310672 29.725145,40.707419 24.98559,40.707419 z "
+- id="rect2201" />
+- <path
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999911;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 20.429472,22.564494 C 19.813992,22.53919 18.946491,22.754031 17.792299,23.48193 C 15.396153,24.993077 14.598274,26.486625 14.509287,28.117394 C 14.420299,29.74816 15.197952,31.630592 16.500622,33.380577 C 17.803294,35.130559 19.637587,36.743254 21.398232,37.871181 C 23.158877,38.999109 24.734359,39.505165 25.355011,39.505165 C 25.714095,39.505165 25.973542,38.578409 26.134382,37.774606 C 26.456061,36.166999 26.487926,33.806821 26.080561,31.449134 C 25.673198,29.091442 24.821426,26.682961 23.766308,25.027083 C 22.711189,23.371206 21.583796,22.611947 20.429472,22.564494 z "
+- id="path2254" />
+- <path
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 38.290982,9.1309894 C 35.842841,9.5672523 32.283411,12.929344 29.603482,16.28724 C 27.08796,19.439138 25.478582,22.11333 25.259732,22.47474 L 28.572232,30.03724 C 34.665525,29.832673 38.559865,27.128092 38.853482,26.91224 C 39.014293,26.551466 40.549044,23.055678 41.478482,19.03724 C 41.967713,16.922043 42.260097,14.730906 42.072232,12.97474 C 41.884367,11.218574 41.30548,10.015388 40.103482,9.3809894 C 39.532517,9.0796416 38.992058,9.0060564 38.290982,9.1309894 z "
+- id="path2245" />
+- <path
+- style="fill:url(#linearGradient1360);fill-opacity:1;stroke:#204a87;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 2.9244668,13.205506 C 5.4909473,8.9616426 31.868508,26.916697 20.798169,29.292473 C 9.7422309,31.665159 0.38413836,17.406122 2.9244668,13.205506 z "
+- id="rect2197" />
+- <path
+- style="opacity:0.2;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999905;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 4.0077208,17.150417 C 4.6613048,18.933996 5.9435775,21.021975 7.6235197,22.895457 C 10.983405,26.64242 15.833733,29.401717 20.89796,28.310863 C 21.928379,28.088904 22.232928,27.802155 22.334374,27.651594 C 22.435813,27.501039 22.52111,27.289844 22.334374,26.709786 C 21.960899,25.54967 20.384396,23.482994 18.173725,21.529832 C 15.963059,19.576669 13.153701,17.6285 10.545878,16.161517 C 7.9380537,14.694536 5.1976761,13.680027 3.975949,13.563989 C 3.3254548,13.502207 3.3541371,15.366838 4.0077208,17.150417 z "
+- id="path2249" />
+- <path
+- style="fill:url(#linearGradient1362);fill-opacity:1;stroke:#ce5d00;stroke-width:1.00000048;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 23.497613,20.84222 C 23.497613,20.84222 33.747199,3.7130144 39.940221,6.9816102 C 46.183621,10.276795 39.032218,26.044415 39.032218,26.044415 C 39.032218,26.044415 34.34592,29.558038 27.298467,29.558038 L 23.497613,20.84222 z "
+- id="rect1317" />
+- <path
+- style="opacity:0.25;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:1.0000006;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 37.65625,7.5937494 C 35.207156,8.0301823 31.648755,11.392008 28.96875,14.75 C 26.453156,17.901987 24.843855,20.576081 24.625,20.9375 L 27.9375,28.5 C 34.029365,28.295478 37.922857,25.592475 38.21875,25.375 C 38.379566,25.014217 39.91427,21.518622 40.84375,17.5 C 41.333003,15.384706 41.625396,13.193957 41.4375,11.4375 C 41.249604,9.6810425 40.671312,8.4784456 39.46875,7.8437494 C 38.897466,7.5422332 38.357596,7.4687683 37.65625,7.5937494 z "
+- id="path1328" />
+- <path
+- style="fill:#75507b;fill-opacity:1;stroke:#5c3566;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 25.75715,25.780775 C 27.420525,29.605605 28.313593,33.06003 27.750608,33.491546 C 27.187623,33.923061 25.380722,31.169067 23.717348,27.344236 C 22.053974,23.519407 21.160905,20.064982 21.72389,19.633467 C 22.286875,19.201951 24.093776,21.955945 25.75715,25.780775 z "
+- id="path2192" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/mxit.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/mxit.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/mxit.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/mxit.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,24 +0,0 @@
+-<?xml version="1.0" encoding="utf-8"?>
+-<!-- Generator: Adobe Illustrator 13.0.2, SVG Export Plug-In . SVG Version: 6.00 Build 14948) -->
+-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.0//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
+-<svg version="1.0" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
+- width="48px" height="48px" viewBox="0 0 48 48" enable-background="new 0 0 48 48" xml:space="preserve">
+-<image overflow="visible" width="34" height="39" xlink:href="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgEASABIAAD/7AARRHVja3kAAQAEAAAAHgAA/+4AIUFkb2JlAGTAAAAAAQMA
+-EAMCAwYAAAH0AAACSgAAA6n/2wCEABALCwsMCxAMDBAXDw0PFxsUEBAUGx8XFxcXFx8eFxoaGhoX
+-Hh4jJSclIx4vLzMzLy9AQEBAQEBAQEBAQEBAQEABEQ8PERMRFRISFRQRFBEUGhQWFhQaJhoaHBoa
+-JjAjHh4eHiMwKy4nJycuKzU1MDA1NUBAP0BAQEBAQEBAQEBAQP/CABEIACgAIwMBIgACEQEDEQH/
+-xACyAAEAAwEBAAAAAAAAAAAAAAAAAQMFBAIBAAMBAQAAAAAAAAAAAAAAAAABAgMEEAABBAECBgMB
+-AAAAAAAAAAABAAIDBAUREyESIhQVRRAjNQYRAAEDAgMDBwgLAAAAAAAAAAERAgMAEiETBDFRIkFh
+-cUIUhcWhMlKDs9M01GKSIzNzwyRkhJQVEgABAwAGCQUAAAAAAAAAAAAAARECIUFRYYESEDFxodEy
+-QoKicjNDNIT/2gAMAwEAAhEDEQAAANWbtDvwx51+eStam/NlFqUEyBo7eck8dAFoyr//2gAIAQIA
+-AQUAe+RpEry7QJ4POA4FDeR3V9q//9oACAEDAAEFAAAUWjRDTTh8dC6V0r//2gAIAQEAAQUAiihn
+-hNOsu1rBMr0HLks9hi7UdSE5ytyx5evM/J6dx6rCcInfp3ON2+CZfVY1z46RMm9IHyveZpW+q8Vc
+-rtkr51qbF/QEx0s04eCg2//aAAgBAgIGPwBoxWSbRIyisXvNSfZsJrbFYkFblRlP1FOTHK+J8fid
+-XuefE//aAAgBAwIGPwCmTDpJzsE9Tkrzs0VlXLuP/9oACAEBAQY/AIZ54GanU6mJk8sksTZnEyNa
+-9Be11rW3IAMK+ChH8SP3dY6KH+pH7uvhNORy2wxscOhzGtc01n9rmvzP85bup2zs2b+JZ1q0csgJ
+-adHC3hRVMcR5SN1XWSIqLw7fr0GNa8KQ242oC7Aea4moCAFc14cd4FqV3n4lWjP7KL2cNXfT/Kph
+-3ZPtDUL0Nrbmk7i61K7z8SrQyNAd+khaQSm2OPmO6s5G3XXWrgllm1KLyjCjbUN2LSXLsFBha0BW
+-kkOJ80g7Leau8vEqy9HPEdO0/ZRTxOe6NvoNeyWPhHIow31wt0rvVS/MVjHph6qX5iuKXTQr1mwv
+-Lhzi+dwXpFZWdNZk5SX9fMzs/Z95fivkr//Z" transform="matrix(0.9999 0 0 0.9999 7.0146 6.0142)">
+-</image>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/novell.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/novell.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/novell.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/novell.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,167 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg2"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/scalable"
+- sodipodi:docname="novell.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/groupwise.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs4">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2190">
+- <stop
+- style="stop-color:#d3d7cf;stop-opacity:1;"
+- offset="0"
+- id="stop2192" />
+- <stop
+- style="stop-color:#d3d7cf;stop-opacity:0;"
+- offset="1"
+- id="stop2194" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2238">
+- <stop
+- style="stop-color:#eeeeec;stop-opacity:1;"
+- offset="0"
+- id="stop2240" />
+- <stop
+- style="stop-color:#eeeeec;stop-opacity:0;"
+- offset="1"
+- id="stop2242" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2238"
+- id="linearGradient2244"
+- x1="11.76915"
+- y1="3.4633243"
+- x2="11.76915"
+- y2="11.990735"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(1.888889,0,0,1.818182,2.77778,1.26862)" />
+- <radialGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2190"
+- id="radialGradient2196"
+- cx="4.3022962"
+- cy="7.5011024"
+- fx="4.3022962"
+- fy="7.5011024"
+- r="8.5"
+- gradientTransform="matrix(-2.567716,2.567716,-2.581797,-2.581795,54.64024,19.71367)"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="12.865422"
+- inkscape:cx="44.509337"
+- inkscape:cy="25.527163"
+- inkscape:document-units="px"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- fill="#00ffff"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata7">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer"
+- id="layer1">
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.5;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.934577,0,0,2.111893,-7.042754,16.91046)" />
+- <rect
+- style="opacity:1;fill:#eeeeec;fill-opacity:1;stroke:#888a85;stroke-width:0.9999997;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect1326"
+- width="33.012436"
+- height="35.008015"
+- x="7.4937739"
+- y="5.4919853"
+- ry="4.0986137"
+- rx="4.0986137" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.99578816"
+- inkscape:original="M 11.59375 5.5 C 9.323118 5.5 7.5 7.323118 7.5 9.59375 L 7.5 36.40625 C 7.5 38.676882 9.3231175 40.5 11.59375 40.5 L 36.40625 40.5 C 38.676882 40.5 40.5 38.676882 40.5 36.40625 L 40.5 9.59375 C 40.5 7.323118 38.676882 5.5 36.40625 5.5 L 11.59375 5.5 z "
+- xlink:href="#rect1326"
+- style="opacity:1;fill:url(#radialGradient2196);fill-opacity:1;stroke:#ffffff;stroke-width:1.00000048;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2201"
+- inkscape:href="#rect1326"
+- d="M 9.5,5.5 C 8.9264847,5.5 8.5,5.9264831 8.5,6.5 L 8.5,37.5 C 8.5,38.073517 8.9264835,38.499999 9.5,38.5 L 38.5,38.5 C 39.073514,38.5 39.5,38.073514 39.5,37.5 L 39.5,6.5 C 39.5,5.9264836 39.073514,5.5 38.5,5.5 L 9.5,5.5 z " />
+- <path
+- style="fill:#cc0000;fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 16,13.995893 L 16,32.182309 L 19.840233,32.182309 L 19.746482,21.644702 L 29.000001,30.275655 L 33,33.995893 L 33,15.840234 L 29.223673,15.840234 L 29.223673,26.287561 L 18.124999,15.900655 L 16,13.995893 z "
+- id="rect1317"
+- sodipodi:nodetypes="ccccccccccc" />
+- <path
+- style="fill:url(#linearGradient2244);fill-opacity:1;stroke:none;stroke-width:1;stroke-miterlimit:4;stroke-opacity:1"
+- d="M 16,13.995893 L 16,32.182309 L 19.840234,32.182309 L 19.746482,21.644702 L 29.000001,30.275655 L 33,33.995893 L 33,15.840234 L 29.223673,15.840234 L 29.223673,26.287561 L 18.124999,15.900655 L 16,13.995893 z "
+- id="path2228"
+- sodipodi:nodetypes="ccccccccccc" />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/yahoo.svg pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/yahoo.svg
+--- pidgin-2.10.7/pidgin/pixmaps/protocols/scalable/yahoo.svg 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/pixmaps/protocols/scalable/yahoo.svg 1969-12-31 21:00:00.000000000 -0300
+@@ -1,174 +0,0 @@
+-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+-<!-- Created with Inkscape (http://www.inkscape.org/) -->
+-<svg
+- xmlns:dc="http://purl.org/dc/elements/1.1/"
+- xmlns:cc="http://creativecommons.org/ns#"
+- xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
+- 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://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+- xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+- width="48"
+- height="48"
+- id="svg1307"
+- sodipodi:version="0.32"
+- inkscape:version="0.46"
+- version="1.0"
+- sodipodi:docbase="/home/hbons/Desktop/Gaim Refresh/protocols/48"
+- sodipodi:docname="yahoo.svg"
+- inkscape:export-filename="/home/hbons/Desktop/Gaim Refresh/protocols/48/yahoo.png"
+- inkscape:export-xdpi="90"
+- inkscape:export-ydpi="90"
+- inkscape:output_extension="org.inkscape.output.svg.inkscape">
+- <defs
+- id="defs1309">
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient2211">
+- <stop
+- style="stop-color:#ffffff;stop-opacity:1;"
+- offset="0"
+- id="stop2213" />
+- <stop
+- style="stop-color:#ffffff;stop-opacity:0;"
+- offset="1"
+- id="stop2215" />
+- </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,5.698892e-16,-4.565819e-9,-0.35721,19.80716,14.19321)"
+- gradientUnits="userSpaceOnUse" />
+- <linearGradient
+- inkscape:collect="always"
+- id="linearGradient4123">
+- <stop
+- style="stop-color:#ff0000;stop-opacity:1;"
+- offset="0"
+- id="stop4125" />
+- <stop
+- style="stop-color:#ff0000;stop-opacity:0;"
+- offset="1"
+- id="stop4127" />
+- </linearGradient>
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient4123"
+- id="linearGradient2206"
+- gradientUnits="userSpaceOnUse"
+- gradientTransform="matrix(1.871443,0,0,1.871443,1.990827,1.339082)"
+- x1="9.7634506"
+- y1="11.499014"
+- x2="9.7634506"
+- y2="0.12942761" />
+- <linearGradient
+- inkscape:collect="always"
+- xlink:href="#linearGradient2211"
+- id="linearGradient2217"
+- x1="36.249207"
+- y1="7.6495404"
+- x2="36.249207"
+- y2="23.063982"
+- gradientUnits="userSpaceOnUse" />
+- </defs>
+- <sodipodi:namedview
+- id="base"
+- pagecolor="#ffffff"
+- bordercolor="#666666"
+- borderopacity="1.0"
+- inkscape:pageopacity="0.0"
+- inkscape:pageshadow="2"
+- inkscape:zoom="11.098901"
+- inkscape:cx="49.54817"
+- inkscape:cy="29.700698"
+- inkscape:current-layer="layer1"
+- showgrid="true"
+- inkscape:grid-bbox="true"
+- inkscape:document-units="px"
+- fill="#a40000"
+- showguides="true"
+- inkscape:guide-bbox="true"
+- inkscape:window-width="1268"
+- inkscape:window-height="971"
+- inkscape:window-x="6"
+- inkscape:window-y="21" />
+- <metadata
+- id="metadata1312">
+- <rdf:RDF>
+- <cc:Work
+- rdf:about="">
+- <dc:format>image/svg+xml</dc:format>
+- <dc:type
+- rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
+- </cc:Work>
+- </rdf:RDF>
+- </metadata>
+- <g
+- id="layer1"
+- inkscape:label="Layer 1"
+- inkscape:groupmode="layer">
+- <rect
+- style="opacity:0;fill:none;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="rect3203"
+- width="0"
+- height="2.5118096"
+- x="6"
+- y="6.4881902" />
+- <path
+- sodipodi:type="arc"
+- style="opacity:0.6;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(3.163562,0,0,2.111892,-10.02562,12.91459)" />
+- <path
+- style="opacity:1;fill:#ff0000;fill-opacity:1;stroke:#a40000;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 36.593752,13.5 L 36.750002,24.71875 L 44.125002,13.5 L 36.593752,13.5 z M 33.406252,30.34375 C 32.052922,30.519922 31.000003,31.724054 31.000002,33.15625 C 31.000002,34.70982 32.231505,35.96875 33.750002,35.96875 C 35.268499,35.96875 36.500002,34.70982 36.500002,33.15625 C 36.500002,31.60268 35.268499,30.343751 33.750002,30.34375 C 33.631369,30.34375 33.520941,30.32882 33.406252,30.34375 z "
+- id="path4110" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-1.0402364"
+- inkscape:original="M 36.59375 13.5 L 36.75 24.71875 L 44.125 13.5 L 36.59375 13.5 z M 33.40625 30.34375 C 32.052918 30.519922 31.000001 31.724054 31 33.15625 C 31 34.70982 32.231503 35.96875 33.75 35.96875 C 35.268495 35.96875 36.5 34.70982 36.5 33.15625 C 36.499998 31.60268 35.268497 30.343751 33.75 30.34375 C 33.631365 30.34375 33.520939 30.32882 33.40625 30.34375 z "
+- xlink:href="#path4110"
+- style="opacity:0.35;fill:url(#linearGradient2217);fill-opacity:1;stroke:#ffffff;stroke-width:1;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2209"
+- inkscape:href="#path4110"
+- d="M 37.625,15.0625 L 37.71875,21.875 L 42.1875,15.0625 L 37.625,15.0625 z M 33.53125,31.90625 C 32.711111,32.013013 32.031251,32.765143 32.03125,33.6875 C 32.031249,34.691344 32.806451,35.46875 33.75,35.46875 C 34.693551,35.46875 35.46875,34.691346 35.46875,33.6875 C 35.468751,32.683656 34.69355,31.906251 33.75,31.90625 C 33.544091,31.90625 33.473148,31.913814 33.53125,31.90625 z " />
+- <path
+- style="opacity:1;fill:url(#linearGradient2206);fill-opacity:1;stroke:#a40000;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- d="M 2.6545432,11.532816 L 4.353345,15.445312 L 7.741467,15.555398 L 17.47685,25.310159 L 17.4318,31.506326 L 12.428056,31.384739 L 11.665952,34.499424 L 27.339128,34.54589 L 26.551973,31.519888 L 21.572919,31.603085 L 21.572919,25.191498 L 28.209096,17.523843 L 31.468823,17.433744 L 32.573193,13.532585 L 23.168883,13.473142 L 21.694773,17.410562 L 23.776066,17.4644 L 19.977012,20.889333 L 13.198929,15.445312 L 17.758833,15.445312 L 20.124034,11.577865 L 2.6545432,11.532816 z "
+- id="rect3219"
+- sodipodi:nodetypes="cccccccccccccccccccccc" />
+- <path
+- sodipodi:type="inkscape:offset"
+- inkscape:radius="-0.98856229"
+- inkscape:original="M 2.65625 11.53125 L 4.34375 15.4375 L 7.75 15.5625 L 17.46875 25.3125 L 17.4375 31.5 L 12.4375 31.375 L 11.65625 34.5 L 27.34375 34.53125 L 26.5625 31.53125 L 21.5625 31.59375 L 21.5625 25.1875 L 28.21875 17.53125 L 31.46875 17.4375 L 32.5625 13.53125 L 23.15625 13.46875 L 21.6875 17.40625 L 23.78125 17.46875 L 19.96875 20.875 L 13.1875 15.4375 L 17.75 15.4375 L 20.125 11.5625 L 2.65625 11.53125 z "
+- xlink:href="#rect3219"
+- style="opacity:0.35;fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:0.99999976;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
+- id="path2204"
+- inkscape:href="#rect3219"
+- d="M 4.15625,13.0625 L 5,15 L 7.78125,15.09375 C 8.0317447,15.110809 8.266366,15.222533 8.4375,15.40625 L 18.15625,25.15625 C 18.347286,25.335037 18.45966,25.58226 18.46875,25.84375 L 18.4375,32.03125 C 18.44087,32.30297 18.33225,32.564099 18.137167,32.75327 C 17.942084,32.942442 17.677738,33.042977 17.40625,33.03125 L 13.21875,32.9375 L 12.9375,34.03125 L 26.0625,34.0625 L 25.78125,33.0625 L 21.5625,33.125 C 21.296354,33.12807 21.040212,33.0237 20.852006,32.835494 C 20.6638,32.647288 20.55943,32.391146 20.5625,32.125 L 20.5625,25.71875 C 20.562717,25.476777 20.651667,25.243286 20.8125,25.0625 L 27.46875,17.40625 C 27.649517,17.19593 27.910308,17.071204 28.1875,17.0625 L 30.71875,17 L 31.28125,15.0625 L 23.84375,15 L 23.125,16.96875 L 23.8125,17 C 24.228223,17.002399 24.598033,17.264612 24.737859,17.656122 C 24.877684,18.047632 24.757648,18.48479 24.4375,18.75 L 20.625,22.15625 C 20.263408,22.479557 19.720674,22.492795 19.34375,22.1875 L 12.5625,16.75 C 12.215365,16.491727 12.076498,16.037735 12.219751,15.629463 C 12.363005,15.221191 12.755094,14.953499 13.1875,14.96875 L 17.1875,14.96875 L 18.34375,13.09375 L 4.15625,13.0625 z " />
+- </g>
+-</svg>
+diff -Nur pidgin-2.10.7/pidgin/plugins/cap/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/cap/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.in 2013-08-16 23:57:24.360620508 -0300
+@@ -185,8 +185,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -248,8 +246,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/cap/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/cap/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/cap/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,82 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for cap plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = cap
+-
+-# This is where sqlite3.[ch] from the sqlite "amalgamation" archive were extracted to
+-# This is available from http://www.sqlite.org/download.html
+-SQLITE_TOP ?= $(WIN32_DEV_TOP)/sqlite-3.4.1
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(SQLITE_TOP) \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = cap.c \
+- $(SQLITE_TOP)/sqlite3.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgobject-2.0 \
+- -lintl \
+- -lpurple \
+- -lpidgin
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-$(OBJECTS): $(PIDGIN_CONFIG_H)
+-
+-$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/disco/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/disco/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.in 2013-08-16 23:57:28.064067349 -0300
+@@ -186,8 +186,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -249,8 +247,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/disco/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/disco/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,79 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for xmppdisco plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = xmppdisco
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = xmppdisco.c \
+- gtkdisco.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgobject-2.0 \
+- -lpango-1.0 \
+- -lgdk_pixbuf-2.0 \
+- -lintl \
+- -lpurple \
+- -lpidgin
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-$(OBJECTS): $(PIDGIN_CONFIG_H)
+-
+-$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/disco/xmppdisco.c pidgin-2.10.7-nonprism/pidgin/plugins/disco/xmppdisco.c
+--- pidgin-2.10.7/pidgin/plugins/disco/xmppdisco.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/disco/xmppdisco.c 2013-08-16 23:39:46.921427463 -0300
+@@ -250,9 +250,6 @@
+ const char *from;
+ const char *to;
+ } disco_type_mappings[] = {
+- { "gadu-gadu", "gadu-gadu" }, /* the prpl is prpl-gg, but list_icon returns "gadu-gadu" */
+- { "sametime", "meanwhile" },
+- { "myspaceim", "myspace" },
+ { "xmpp", "jabber" }, /* prpl-jabber (mentioned in case the prpl is renamed so this line will match) */
+ { NULL, NULL }
+ };
+@@ -388,8 +385,7 @@
+
+ if (item_data->parent->type == XMPP_DISCO_SERVICE_TYPE_CHAT) {
+ /* This is a hacky first-order approximation. Any MUC
+- * component that has a >1 level hierarchy (a Yahoo MUC
+- * transport component probably does) will violate this.
++ * component that has a >1 level hierarchy will violate this.
+ *
+ * On the other hand, this is better than querying all the
+ * chats at conference.jabber.org to enumerate them.
+diff -Nur pidgin-2.10.7/pidgin/plugins/gestures/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/gestures/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/gestures/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gestures/Makefile.in 2013-08-16 23:57:32.194193933 -0300
+@@ -187,8 +187,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -250,8 +248,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/add_buddy_dialog.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/add_buddy_dialog.c
+--- pidgin-2.10.7/pidgin/plugins/gevolution/add_buddy_dialog.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/add_buddy_dialog.c 2013-08-16 21:26:56.293625899 -0300
+@@ -288,21 +288,13 @@
+ {
+ EContact *contact = E_CONTACT(c->data);
+ const char *name;
+- GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells, *ggs;
++ GList *jabbers;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+- aims = e_contact_get(contact, E_CONTACT_IM_AIM);
+ jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
+- yahoos = e_contact_get(contact, E_CONTACT_IM_YAHOO);
+- msns = e_contact_get(contact, E_CONTACT_IM_MSN);
+- icqs = e_contact_get(contact, E_CONTACT_IM_ICQ);
+- novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
+- ggs = e_contact_get(contact, E_CONTACT_IM_GADUGADU);
+-
+- if (aims == NULL && jabbers == NULL && yahoos == NULL &&
+- msns == NULL && icqs == NULL && novells == NULL &&
+- ggs == NULL)
++
++ if (jabbers == NULL)
+ {
+ GtkTreeIter iter;
+
+@@ -315,13 +307,7 @@
+ }
+ else
+ {
+- add_ims(dialog, contact, name, aims, "prpl-aim");
+ add_ims(dialog, contact, name, jabbers, "prpl-jabber");
+- add_ims(dialog, contact, name, yahoos, "prpl-yahoo");
+- add_ims(dialog, contact, name, msns, "prpl-msn");
+- add_ims(dialog, contact, name, icqs, "prpl-icq");
+- add_ims(dialog, contact, name, novells, "prpl-novell");
+- add_ims(dialog, contact, name, ggs, "prpl-gg");
+ }
+ }
+
+@@ -367,7 +353,7 @@
+ {
+ EContact *contact = E_CONTACT(l->data);
+ const char *name;
+- GList *aims, *jabbers, *yahoos, *msns, *icqs, *novells, *ggs;
++ GList *jabbers;
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+@@ -377,17 +363,9 @@
+ continue;
+ }
+
+- aims = e_contact_get(contact, E_CONTACT_IM_AIM);
+ jabbers = e_contact_get(contact, E_CONTACT_IM_JABBER);
+- yahoos = e_contact_get(contact, E_CONTACT_IM_YAHOO);
+- msns = e_contact_get(contact, E_CONTACT_IM_MSN);
+- icqs = e_contact_get(contact, E_CONTACT_IM_ICQ);
+- novells = e_contact_get(contact, E_CONTACT_IM_GROUPWISE);
+- ggs = e_contact_get(contact, E_CONTACT_IM_GADUGADU);
+-
+- if (aims == NULL && jabbers == NULL && yahoos == NULL &&
+- msns == NULL && icqs == NULL && novells == NULL &&
+- ggs == NULL)
++
++ if (jabbers == NULL)
+ {
+ GtkTreeIter iter;
+
+@@ -400,13 +378,7 @@
+ }
+ else
+ {
+- add_ims(dialog, contact, name, aims, "prpl-aim");
+ add_ims(dialog, contact, name, jabbers, "prpl-jabber");
+- add_ims(dialog, contact, name, yahoos, "prpl-yahoo");
+- add_ims(dialog, contact, name, msns, "prpl-msn");
+- add_ims(dialog, contact, name, icqs, "prpl-icq");
+- add_ims(dialog, contact, name, novells, "prpl-novell");
+- add_ims(dialog, contact, name, ggs, "prpl-gg");
+ }
+ }
+ }
+diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/gevolution.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/gevolution.c
+--- pidgin-2.10.7/pidgin/plugins/gevolution/gevolution.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/gevolution.c 2013-08-16 21:14:05.483056049 -0300
+@@ -119,13 +119,7 @@
+
+ name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
+
+- update_ims_from_contact(contact, name, "prpl-aim", E_CONTACT_IM_AIM);
+ update_ims_from_contact(contact, name, "prpl-jabber", E_CONTACT_IM_JABBER);
+- update_ims_from_contact(contact, name, "prpl-yahoo", E_CONTACT_IM_YAHOO);
+- update_ims_from_contact(contact, name, "prpl-msn", E_CONTACT_IM_MSN);
+- update_ims_from_contact(contact, name, "prpl-icq", E_CONTACT_IM_ICQ);
+- update_ims_from_contact(contact, name, "prpl-novell", E_CONTACT_IM_GROUPWISE);
+- update_ims_from_contact(contact, name, "prpl-gg", E_CONTACT_IM_GADUGADU);
+ }
+
+ static void
+diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/gevo-util.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/gevo-util.c
+--- pidgin-2.10.7/pidgin/plugins/gevolution/gevo-util.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/gevo-util.c 2013-08-16 23:20:45.692374640 -0300
+@@ -99,20 +99,8 @@
+
+ protocol_id = purple_account_get_protocol_id(account);
+
+- if (!strcmp(protocol_id, "prpl-aim"))
+- protocol_field = E_CONTACT_IM_AIM;
+- else if (!strcmp(protocol_id, "prpl-icq"))
+- protocol_field = E_CONTACT_IM_ICQ;
+- else if (!strcmp(protocol_id, "prpl-msn"))
+- protocol_field = E_CONTACT_IM_MSN;
+- else if (!strcmp(protocol_id, "prpl-yahoo"))
+- protocol_field = E_CONTACT_IM_YAHOO;
+- else if (!strcmp(protocol_id, "prpl-jabber"))
++ if (!strcmp(protocol_id, "prpl-jabber"))
+ protocol_field = E_CONTACT_IM_JABBER;
+- else if (!strcmp(protocol_id, "prpl-novell"))
+- protocol_field = E_CONTACT_IM_GROUPWISE;
+- else if (!strcmp(protocol_id, "prpl-gg"))
+- protocol_field = E_CONTACT_IM_GADUGADU;
+
+ return protocol_field;
+ }
+@@ -169,18 +157,6 @@
+ {
+ PurpleAccount *account = purple_buddy_get_account(buddy);
+ const char *prpl_id = purple_account_get_protocol_id(account);
+-
+- if (!strcmp(prpl_id, "prpl-msn"))
+- {
+- mail = g_strdup(purple_normalize(account,
+- purple_buddy_get_name(buddy)));
+- }
+- else if (!strcmp(prpl_id, "prpl-yahoo"))
+- {
+- mail = g_strdup_printf("%s@yahoo.com",
+- purple_normalize(account,
+- purple_buddy_get_name(buddy)));
+- }
+ }
+
+ return mail;
+diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/gevolution/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/Makefile.in 2013-08-16 23:57:35.817638327 -0300
+@@ -190,8 +190,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -253,8 +251,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/gevolution/new_person_dialog.c pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/new_person_dialog.c
+--- pidgin-2.10.7/pidgin/plugins/gevolution/new_person_dialog.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/gevolution/new_person_dialog.c 2013-08-16 21:23:26.207116339 -0300
+@@ -141,20 +141,8 @@
+ if (*email)
+ e_contact_set(contact, E_CONTACT_EMAIL_1, (gpointer)email);
+
+- if (!strcmp(im_service, "prpl-aim"))
+- field = E_CONTACT_IM_AIM;
+- else if (!strcmp(im_service, "prpl-icq"))
+- field = E_CONTACT_IM_ICQ;
+- else if (!strcmp(im_service, "prpl-yahoo"))
+- field = E_CONTACT_IM_YAHOO;
+- else if (!strcmp(im_service, "prpl-jabber"))
++ if (!strcmp(im_service, "prpl-jabber"))
+ field = E_CONTACT_IM_JABBER;
+- else if (!strcmp(im_service, "prpl-msn"))
+- field = E_CONTACT_IM_MSN;
+- else if (!strcmp(im_service, "prpl-novell"))
+- field = E_CONTACT_IM_GROUPWISE;
+- else if (!strcmp(im_service, "prpl-gg"))
+- field = E_CONTACT_IM_GADUGADU;
+
+ if (field > 0)
+ {
+diff -Nur pidgin-2.10.7/pidgin/plugins/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.in 2013-08-16 23:57:14.680323828 -0300
+@@ -393,8 +393,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -456,8 +454,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,118 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of Pidgin Plugins
+-#
+-
+-PIDGIN_TREE_TOP := ../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-DISCO_PLUGIN := ./disco
+-GTKPERL_PLUGIN := ./perl
+-TICKER_PLUGIN := ./ticker
+-TRANSPARENCY_PLUGIN := ./win32/transparency
+-WINPREFS_PLUGIN := ./win32/winprefs
+-
+-.SUFFIXES:
+-.SUFFIXES: .c .dll
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgobject-2.0 \
+- -lgmodule-2.0 \
+- -lgdk_pixbuf-2.0 \
+- -lpango-1.0 \
+- -lcairo \
+- -lintl \
+- -lws2_32 \
+- -lpurple \
+- -lpidgin
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all clean plugins install
+-
+-all: plugins
+- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE)
+- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE)
+-
+-install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
+- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) install
+- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install
+- cp *.dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-THEMEEDIT_SRC = themeedit.c themeedit-icon.c
+-THEMEEDIT_OBJECTS = $(THEMEEDIT_SRC:%.c=%.o)
+-
+-themeedit.dll: $(THEMEEDIT_OBJECTS)
+- $(CC) -shared $(THEMEEDIT_OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
+-
+-%.dll: %.c $(PURPLE_CONFIG_H) $(PURPLE_VERSION_H)
+- $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@.o -c $<
+- $(CC) -shared $@.o $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $@
+-
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-plugins: \
+- convcolors.dll \
+- extplacement.dll \
+- gtkbuddynote.dll \
+- history.dll \
+- iconaway.dll \
+- markerline.dll \
+- notify.dll \
+- pidginrc.dll \
+- relnot.dll \
+- sendbutton.dll \
+- spellchk.dll \
+- themeedit.dll \
+- timestamp_format.dll \
+- timestamp.dll \
+- xmppconsole.dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -f *.o *.dll
+- $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) clean
+- $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) clean
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/musicmessaging/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/musicmessaging/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/musicmessaging/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/musicmessaging/Makefile.in 2013-08-16 23:57:39.504417995 -0300
+@@ -193,8 +193,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -256,8 +254,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/perl/common/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/perl/common/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/perl/common/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/common/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,113 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for Pidgin perl module.
+-#
+-
+-PIDGIN_TREE_TOP := ../../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-GCCWARNINGS += -Wno-comment -Wno-unused -Wno-nested-externs
+-
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-
+-TARGET = Pidgin
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS = -I. \
+- -I$(PIDGIN_TREE_TOP) \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PERL_LIB_TOP)/CORE
+-
+-LIB_PATHS += -L$(PERL_LIB_TOP) \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP) \
+- -L$(PURPLE_PERL_TOP) \
+- -L$(GTK_TOP)/lib
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-XS_FILES = \
+- Pidgin.xs \
+- GtkAccount.xs \
+- GtkBlist.xs \
+- GtkConn.xs \
+- GtkConv.xs \
+- GtkConvWin.xs \
+- GtkDebug.xs \
+- GtkDialogs.xs \
+- GtkFt.xs \
+- GtkIMHtml.xs \
+- GtkIMHtmlToolbar.xs \
+- GtkLog.xs \
+- GtkMenuTray.xs \
+- GtkPlugin.xs \
+- GtkPluginPref.xs \
+- GtkPounce.xs \
+- GtkPrefs.xs \
+- GtkPrivacy.xs \
+- GtkRoomlist.xs \
+- GtkSavedStatuses.xs \
+- GtkSound.xs \
+- GtkStatusBox.xs \
+- GtkThemes.xs \
+- GtkUtils.xs
+-
+-
+-C_FILES = $(XS_FILES:%.xs=%.c)
+-OBJECTS = $(C_FILES:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lperl510 \
+- -lperl \
+- -lpurple \
+- -lpidgin \
+- -lglib-2.0
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGETS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-$(PURPLE_INSTALL_PERL_DIR)/Purple.pm:
+- $(MAKE) -C $(PURPLE_PERL_TOP)/common -f $(MINGW_MAKEFILE) install
+-
+-install: all $(PURPLE_INSTALL_PERL_DIR)/Purple.pm
+- rm -f $(PIDGIN_INSTALL_PERL_DIR)/$(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin/$(TARGET).pm
+- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
+- cp $(TARGET).pm $(PIDGIN_INSTALL_PERL_DIR)
+- mkdir -p $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
+-
+-$(C_FILES): $(PIDGIN_CONFIG_H)
+-
+-$(TARGET).dll: $(PIDGIN_DLL).a $(PURPLE_PERL_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(DLL_LD_FLAGS) $(LIBS) -o $(TARGET).dll
+-
+-##
+-## CLEAN
+-##
+-clean:
+- rm -f *.o $(C_FILES) $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/perl/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/perl/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.in 2013-08-16 23:57:43.767882012 -0300
+@@ -121,8 +121,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -184,8 +182,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/perl/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/perl/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/perl/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,25 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for perl plugin loader plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all:
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
+-
+-install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
+diff -Nur pidgin-2.10.7/pidgin/plugins/ticker/Makefile.in pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.in
+--- pidgin-2.10.7/pidgin/plugins/ticker/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.in 2013-08-16 23:56:58.146483798 -0300
+@@ -185,8 +185,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -248,8 +246,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/pidgin/plugins/ticker/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/ticker/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/ticker/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,77 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for ticker plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = ticker
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = ticker.c \
+- gtkticker.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgobject-2.0 \
+- -lintl \
+- -lpurple \
+- -lpidgin
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: $(PIDGIN_INSTALL_PLUGINS_DIR) all
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-$(OBJECTS): $(PIDGIN_CONFIG_H)
+-
+-$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/transparency/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/win32/transparency/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,76 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32trans plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = win2ktrans
+-DEFINES += -D_WIN32_WINNT=0x0500
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = win2ktrans.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgmodule-2.0 \
+- -lgobject-2.0 \
+- -lintl \
+- -lpidgin \
+- -lpurple
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/transparency/win2ktrans.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/win2ktrans.c
+--- pidgin-2.10.7/pidgin/plugins/win32/transparency/win2ktrans.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/transparency/win2ktrans.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,723 +0,0 @@
+-/*
+- * Pidgin - Transparency plugin
+- *
+- * Copyright (C) 1998-2002, Rob Flynn <rob@marko.net>
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- * Copyright (C) 2005, Daniel Atallah <daniel_atallah@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License as
+- * published by the Free Software Foundation; either version 2 of the
+- * License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+- * 02111-1301, USA.
+- *
+- */
+-#ifndef _WIN32_WINNT
+-#define _WIN32_WINNT 0x0500
+-#endif
+-#include <gdk/gdkwin32.h>
+-#include "internal.h"
+-
+-#include "core.h"
+-#include "prefs.h"
+-#include "debug.h"
+-
+-#include "gtkconv.h"
+-#include "gtkplugin.h"
+-#include "gtkprefs.h"
+-#include "gtkblist.h"
+-#include "gtkutils.h"
+-#include "signals.h"
+-#include "version.h"
+-
+-/*
+- * MACROS & DEFINES
+- */
+-#define WINTRANS_PLUGIN_ID "gtk-win-trans"
+-
+-#define blist (purple_get_blist() \
+- ? (PIDGIN_BLIST(purple_get_blist()) \
+- ? ((PIDGIN_BLIST(purple_get_blist()))->window) \
+- : NULL) \
+- : NULL)
+-
+-/*
+- * DATA STRUCTS
+- */
+-typedef struct {
+- GtkWidget *win;
+- GtkWidget *slider;
+-} slider_win;
+-
+-/*
+- * LOCALS
+- */
+-static const char *OPT_WINTRANS_IM_ENABLED= "/plugins/gtk/win32/wintrans/im_enabled";
+-static const char *OPT_WINTRANS_IM_ALPHA = "/plugins/gtk/win32/wintrans/im_alpha";
+-static const char *OPT_WINTRANS_IM_SLIDER = "/plugins/gtk/win32/wintrans/im_slider";
+-static const char *OPT_WINTRANS_IM_ONFOCUS= "/plugins/gtk/win32/wintrans/im_solid_onfocus";
+-static const char *OPT_WINTRANS_IM_ONTOP = "/plugins/gtk/win32/wintrans/im_always_on_top";
+-static const char *OPT_WINTRANS_BL_ENABLED= "/plugins/gtk/win32/wintrans/bl_enabled";
+-static const char *OPT_WINTRANS_BL_ALPHA = "/plugins/gtk/win32/wintrans/bl_alpha";
+-static const char *OPT_WINTRANS_BL_ONFOCUS= "/plugins/gtk/win32/wintrans/bl_solid_onfocus";
+-static const char *OPT_WINTRANS_BL_ONTOP = "/plugins/gtk/win32/wintrans/bl_always_on_top";
+-static GSList *window_list = NULL;
+-
+-/*
+- * CODE
+- */
+-
+-/* Set window transparency level */
+-static void set_wintrans(GtkWidget *window, int alpha, gboolean enabled,
+- gboolean always_on_top) {
+-
+- HWND hWnd = GDK_WINDOW_HWND(window->window);
+- LONG style = GetWindowLong(hWnd, GWL_EXSTYLE);
+- if (enabled) {
+- style |= WS_EX_LAYERED;
+- } else {
+- style &= ~WS_EX_LAYERED;
+- }
+- SetWindowLong(hWnd, GWL_EXSTYLE, style);
+-
+-
+- if (enabled) {
+- SetWindowPos(hWnd,
+- always_on_top ? HWND_TOPMOST : HWND_NOTOPMOST,
+- 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+- SetLayeredWindowAttributes(hWnd, 0, alpha, LWA_ALPHA);
+- } else {
+- /* Ask the window and its children to repaint */
+- SetWindowPos(hWnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+-
+- RedrawWindow(hWnd, NULL, NULL,
+- RDW_ERASE | RDW_INVALIDATE | RDW_FRAME | RDW_ALLCHILDREN);
+- }
+-
+-}
+-
+-/* When a conv window is focused, if we're only transparent when unfocused,
+- * deal with transparency */
+-static gboolean focus_conv_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
+- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)
+- && purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS)) {
+- GtkWidget *window = (GtkWidget *) d;
+- if (e->in) { /* Focused */
+- set_wintrans(window, 0, FALSE,
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+- } else {
+- set_wintrans(window,
+- purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
+- TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+- }
+- }
+- return FALSE;
+-}
+-
+-/* When buddy list window is focused,
+- * if we're only transparent when unfocused, deal with transparency */
+-static gboolean focus_blist_win_cb(GtkWidget *w, GdkEventFocus *e, gpointer d) {
+- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)
+- && purple_prefs_get_bool(OPT_WINTRANS_BL_ONFOCUS)) {
+- GtkWidget *window = (GtkWidget *) d;
+- if (e->in) { /* Focused */
+- set_wintrans(window, 0, FALSE,
+- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
+- } else {
+- set_wintrans(window,
+- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
+- TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
+- }
+- }
+- return FALSE;
+-}
+-
+-static void change_alpha(GtkWidget *w, gpointer data) {
+- int alpha = gtk_range_get_value(GTK_RANGE(w));
+- purple_prefs_set_int(OPT_WINTRANS_IM_ALPHA, alpha);
+-
+- /* If we're in no-transparency on focus mode,
+- * don't take effect immediately */
+- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS))
+- set_wintrans(GTK_WIDGET(data), alpha, TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+-}
+-
+-
+-static GtkWidget *wintrans_slider(GtkWidget *win) {
+- GtkWidget *hbox;
+- GtkWidget *label, *slider;
+- GtkWidget *frame;
+-
+- int imalpha = purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA);
+-
+- frame = gtk_frame_new(NULL);
+- gtk_frame_set_shadow_type(GTK_FRAME(frame), GTK_SHADOW_NONE);
+- gtk_widget_show(frame);
+-
+- hbox = gtk_hbox_new(FALSE, 5);
+- gtk_container_add(GTK_CONTAINER(frame), hbox);
+-
+- label = gtk_label_new(_("Opacity:"));
+- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+- gtk_widget_show(hbox);
+-
+- slider = gtk_hscale_new_with_range(50, 255, 1);
+- gtk_range_set_value(GTK_RANGE(slider), imalpha);
+- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
+-
+- /* On slider val change, update window's transparency level */
+- g_signal_connect(GTK_OBJECT(slider), "value-changed",
+- G_CALLBACK(change_alpha), win);
+-
+- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
+-
+- /* Set the initial transparency level */
+- set_wintrans(win, imalpha, TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+-
+- gtk_widget_show_all(hbox);
+-
+- return frame;
+-}
+-
+-static slider_win* find_slidwin(GtkWidget *win) {
+- GSList *tmp = window_list;
+-
+- while (tmp) {
+- if (((slider_win*) (tmp->data))->win == win)
+- return (slider_win*) tmp->data;
+- tmp = tmp->next;
+- }
+- return NULL;
+-}
+-
+-/* Clean up transparency stuff for the conv window */
+-static void cleanup_conv_window(PidginWindow *win) {
+- GtkWidget *window = win->window;
+- slider_win *slidwin = NULL;
+-
+- /* Remove window from the window list */
+- purple_debug_info(WINTRANS_PLUGIN_ID,
+- "Conv window destroyed... removing from list\n");
+-
+- if ((slidwin = find_slidwin(window))) {
+- window_list = g_slist_remove(window_list, slidwin);
+- g_free(slidwin);
+- }
+-
+- /* Remove the focus cbs */
+- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
+- G_CALLBACK(focus_conv_win_cb), window);
+-}
+-
+-static void
+-conversation_delete_cb(PurpleConversation *conv) {
+- PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
+- /* If it is the last conversation in the window, cleanup */
+- if (win != NULL && pidgin_conv_window_get_gtkconv_count(win) == 1)
+- cleanup_conv_window(win);
+-}
+-
+-static void set_blist_trans(GtkWidget *w, const char *pref) {
+- gboolean enabled = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w));
+- purple_prefs_set_bool(pref, enabled);
+- if (blist) {
+- set_wintrans(blist, purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
+- purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED),
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+- }
+-}
+-
+-static void add_slider(GtkWidget *win) {
+- GList *wl, *wl1;
+- GtkWidget *vbox = NULL;
+-
+- /* Look up this window to see if it already has a slider */
+- if (!find_slidwin(win)) {
+- GtkWidget *slider_box = NULL;
+- slider_win *slidwin = NULL;
+- GtkRequisition slidereq;
+- gint width, height;
+-
+- /* Get top vbox */
+- for (wl1 = wl = gtk_container_get_children(
+- GTK_CONTAINER(win));
+- wl != NULL;
+- wl = wl->next) {
+- if (GTK_IS_VBOX(GTK_OBJECT(wl->data)))
+- vbox = GTK_WIDGET(wl->data);
+- else {
+- purple_debug_error(WINTRANS_PLUGIN_ID,
+- "no vbox found\n");
+- return;
+- }
+- }
+- g_list_free(wl1);
+-
+- slider_box = wintrans_slider(win);
+- /* Figure out how tall the slider wants to be */
+- gtk_widget_size_request(slider_box, &slidereq);
+- gtk_window_get_size(GTK_WINDOW(win), &width, &height);
+- gtk_box_pack_start(GTK_BOX(vbox),
+- slider_box, FALSE, FALSE, 0);
+-#if 0 /*Now that we save window sizes, don't resize it or else it causes windows to grow*/
+- /* Make window taller so we don't slowly collapse its message area */
+- gtk_window_resize(GTK_WINDOW(win), width,
+- (height + slidereq.height));
+-#endif
+- /* Add window to list, to track that it has a slider */
+- slidwin = g_new0(slider_win, 1);
+- slidwin->win = win;
+- slidwin->slider = slider_box;
+- window_list = g_slist_append(window_list, slidwin);
+- }
+-}
+-
+-static void remove_sliders() {
+- if (window_list) {
+- GSList *tmp = window_list;
+- while (tmp) {
+- slider_win *slidwin = (slider_win*) tmp->data;
+- if (slidwin != NULL &&
+- GTK_IS_WINDOW(slidwin->win)) {
+-#if 0
+- GtkRequisition slidereq;
+- gint width, height;
+- /* Figure out how tall the slider was */
+- gtk_widget_size_request(
+- slidwin->slider, &slidereq);
+- gtk_window_get_size(
+- GTK_WINDOW(slidwin->win),
+- &width, &height);
+-#endif
+- gtk_widget_destroy(slidwin->slider);
+-#if 0
+- gtk_window_resize(
+- GTK_WINDOW(slidwin->win),
+- width, (height - slidereq.height));
+-#endif
+- }
+- g_free(slidwin);
+- tmp = tmp->next;
+- }
+- g_slist_free(window_list);
+- window_list = NULL;
+- }
+-}
+-
+-/* Remove all transparency related aspects from conversation windows */
+-static void remove_convs_wintrans(gboolean remove_signal) {
+- GList *wins;
+-
+- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
+- PidginWindow *win = wins->data;
+- GtkWidget *window = win->window;
+-
+- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED))
+- set_wintrans(window, 0, FALSE, FALSE);
+-
+- /* Remove the focus cbs */
+- if (remove_signal)
+- g_signal_handlers_disconnect_by_func(G_OBJECT(window),
+- G_CALLBACK(focus_conv_win_cb), window);
+- }
+-
+- remove_sliders();
+-}
+-
+-static void set_conv_window_trans(PidginWindow *oldwin, PidginWindow *newwin) {
+- GtkWidget *win = newwin->window;
+-
+- /* check prefs to see if we want trans */
+- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
+- set_wintrans(win, purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA),
+- TRUE, purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+-
+- if (purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER)) {
+- add_slider(win);
+- }
+- }
+-
+- /* If we're moving from one window to another,
+- * add the focus listeners to the new window if not already there */
+- if (oldwin != NULL && oldwin != newwin) {
+- if (pidgin_conv_window_get_gtkconv_count(newwin) == 0) {
+- g_signal_connect(G_OBJECT(win), "focus_in_event",
+- G_CALLBACK(focus_conv_win_cb), win);
+- g_signal_connect(G_OBJECT(win), "focus_out_event",
+- G_CALLBACK(focus_conv_win_cb), win);
+- }
+-
+- /* If we've moved the last conversation, cleanup the window */
+- if (pidgin_conv_window_get_gtkconv_count(oldwin) == 1)
+- cleanup_conv_window(oldwin);
+- }
+-}
+-
+-static void update_convs_wintrans(GtkWidget *toggle_btn, const char *pref) {
+- purple_prefs_set_bool(pref, gtk_toggle_button_get_active(
+- GTK_TOGGLE_BUTTON(toggle_btn)));
+-
+- if (purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED)) {
+- GList *wins;
+-
+- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
+- PidginWindow *win = wins->data;
+- set_conv_window_trans(NULL, win);
+- }
+-
+- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_SLIDER))
+- remove_sliders();
+- }
+- else
+- remove_convs_wintrans(FALSE);
+-}
+-
+-static void
+-conv_updated_cb(PurpleConversation *conv, PurpleConvUpdateType type) {
+- PidginConversation *pconv = PIDGIN_CONVERSATION(conv);
+- PidginWindow *win = pidgin_conv_get_window(pconv);
+-
+- if (type == PURPLE_CONV_UPDATE_UNSEEN && !pidgin_conv_is_hidden(pconv)
+- && pconv->unseen_state == PIDGIN_UNSEEN_NONE
+- && pidgin_conv_window_get_gtkconv_count(win) == 1) {
+- GtkWidget *window = win->window;
+- gboolean has_focus;
+-
+- g_object_get(G_OBJECT(window), "has-toplevel-focus", &has_focus, NULL);
+-
+- if (!has_focus || !purple_prefs_get_bool(OPT_WINTRANS_IM_ONFOCUS))
+- set_conv_window_trans(NULL, win);
+-
+- if (g_signal_handler_find(G_OBJECT(window), G_SIGNAL_MATCH_FUNC,
+- 0, 0, NULL, G_CALLBACK(focus_conv_win_cb), NULL) == 0) {
+- g_signal_connect(G_OBJECT(window), "focus_in_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- g_signal_connect(G_OBJECT(window), "focus_out_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- }
+- }
+-}
+-
+-static void
+-new_conversation_cb(PurpleConversation *conv) {
+- PidginWindow *win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
+-
+- /* If it is the first conversation in the window,
+- * add the sliders, and set transparency */
+- if (!pidgin_conv_is_hidden(PIDGIN_CONVERSATION(conv)) && pidgin_conv_window_get_gtkconv_count(win) == 1) {
+- GtkWidget *window = win->window;
+-
+- set_conv_window_trans(NULL, win);
+-
+- g_signal_connect(G_OBJECT(window), "focus_in_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- g_signal_connect(G_OBJECT(window), "focus_out_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- }
+-}
+-
+-static void
+-blist_created_cb(PurpleBuddyList *purple_blist, gpointer data) {
+- if (blist) {
+- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED)) {
+- set_wintrans(blist,
+- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA),
+- TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_BL_ONTOP));
+- }
+-
+- g_signal_connect(G_OBJECT(blist), "focus_in_event",
+- G_CALLBACK(focus_blist_win_cb), blist);
+- g_signal_connect(G_OBJECT(blist), "focus_out_event",
+- G_CALLBACK(focus_blist_win_cb), blist);
+- }
+-}
+-
+-static void alpha_change(GtkWidget *w, gpointer data) {
+- GList *wins;
+- int imalpha = gtk_range_get_value(GTK_RANGE(w));
+-
+- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
+- PidginWindow *win = wins->data;
+- set_wintrans(win->window, imalpha, TRUE,
+- purple_prefs_get_bool(OPT_WINTRANS_IM_ONTOP));
+- }
+-}
+-
+-static void alpha_pref_set_int (GtkWidget *w, GdkEventFocus *e, const char *pref)
+-{
+- int alpha = gtk_range_get_value(GTK_RANGE(w));
+- purple_prefs_set_int(pref, alpha);
+-}
+-
+-static void bl_alpha_change(GtkWidget *w, gpointer data) {
+- if (blist)
+- change_alpha(w, blist);
+-}
+-
+-static void update_existing_convs() {
+- GList *wins;
+-
+- for (wins = pidgin_conv_windows_get_list(); wins; wins = wins->next) {
+- PidginWindow *win = wins->data;
+- GtkWidget *window = win->window;
+-
+- set_conv_window_trans(NULL, win);
+-
+- g_signal_connect(G_OBJECT(window), "focus_in_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- g_signal_connect(G_OBJECT(window), "focus_out_event",
+- G_CALLBACK(focus_conv_win_cb), window);
+- }
+-}
+-
+-/*
+- * EXPORTED FUNCTIONS
+- */
+-static gboolean plugin_load(PurplePlugin *plugin) {
+-
+- purple_signal_connect(purple_conversations_get_handle(),
+- "conversation-created", plugin,
+- PURPLE_CALLBACK(new_conversation_cb), NULL);
+-
+- /* Set callback to remove window from the list, if the window is destroyed */
+- purple_signal_connect(purple_conversations_get_handle(),
+- "deleting-conversation", plugin,
+- PURPLE_CALLBACK(conversation_delete_cb), NULL);
+-
+- purple_signal_connect(pidgin_conversations_get_handle(),
+- "conversation-dragging", plugin,
+- PURPLE_CALLBACK(set_conv_window_trans), NULL);
+-
+- purple_signal_connect(purple_conversations_get_handle(),
+- "conversation-updated", plugin,
+- PURPLE_CALLBACK(conv_updated_cb), NULL);
+-
+- update_existing_convs();
+-
+- if (blist)
+- blist_created_cb(NULL, NULL);
+- else
+- purple_signal_connect(pidgin_blist_get_handle(),
+- "gtkblist-created", plugin,
+- PURPLE_CALLBACK(blist_created_cb), NULL);
+-
+-
+- return TRUE;
+-}
+-
+-static gboolean plugin_unload(PurplePlugin *plugin) {
+- purple_debug_info(WINTRANS_PLUGIN_ID, "Unloading win2ktrans plugin\n");
+-
+- remove_convs_wintrans(TRUE);
+-
+- if (blist) {
+- if (purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED))
+- set_wintrans(blist, 0, FALSE, FALSE);
+-
+- /* Remove the focus cbs */
+- g_signal_handlers_disconnect_by_func(G_OBJECT(blist),
+- G_CALLBACK(focus_blist_win_cb), blist);
+- }
+-
+- return TRUE;
+-}
+-
+-static GtkWidget *get_config_frame(PurplePlugin *plugin) {
+- GtkWidget *ret;
+- GtkWidget *imtransbox, *bltransbox;
+- GtkWidget *hbox;
+- GtkWidget *label, *slider;
+- GtkWidget *button;
+- GtkWidget *trans_box;
+-
+- ret = gtk_vbox_new(FALSE, 18);
+- gtk_container_set_border_width(GTK_CONTAINER (ret), 12);
+-
+- /* IM Convo trans options */
+- imtransbox = pidgin_make_frame(ret, _("IM Conversation Windows"));
+- button = pidgin_prefs_checkbox(_("_IM window transparency"),
+- OPT_WINTRANS_IM_ENABLED, imtransbox);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(update_convs_wintrans),
+- (gpointer) OPT_WINTRANS_IM_ENABLED);
+-
+- trans_box = gtk_vbox_new(FALSE, 18);
+- if (!purple_prefs_get_bool(OPT_WINTRANS_IM_ENABLED))
+- gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE);
+- gtk_widget_show(trans_box);
+-
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(pidgin_toggle_sensitive), trans_box);
+-
+- button = pidgin_prefs_checkbox(_("_Show slider bar in IM window"),
+- OPT_WINTRANS_IM_SLIDER, trans_box);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(update_convs_wintrans),
+- (gpointer) OPT_WINTRANS_IM_SLIDER);
+-
+- button = pidgin_prefs_checkbox(
+- _("Remove IM window transparency on focus"),
+- OPT_WINTRANS_IM_ONFOCUS, trans_box);
+-
+- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_IM_ONTOP,
+- trans_box);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(update_convs_wintrans),
+- (gpointer) OPT_WINTRANS_IM_ONTOP);
+-
+- gtk_box_pack_start(GTK_BOX(imtransbox), trans_box, FALSE, FALSE, 5);
+-
+- /* IM transparency slider */
+- hbox = gtk_hbox_new(FALSE, 5);
+-
+- label = gtk_label_new(_("Opacity:"));
+- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+-
+- slider = gtk_hscale_new_with_range(50, 255, 1);
+- gtk_range_set_value(GTK_RANGE(slider),
+- purple_prefs_get_int(OPT_WINTRANS_IM_ALPHA));
+- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
+-
+- g_signal_connect(GTK_OBJECT(slider), "value-changed",
+- G_CALLBACK(alpha_change), NULL);
+- g_signal_connect(GTK_OBJECT(slider), "focus-out-event",
+- G_CALLBACK(alpha_pref_set_int),
+- (gpointer) OPT_WINTRANS_IM_ALPHA);
+-
+- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
+-
+- gtk_widget_show_all(hbox);
+-
+- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
+-
+- /* Buddy List trans options */
+- bltransbox = pidgin_make_frame (ret, _("Buddy List Window"));
+- button = pidgin_prefs_checkbox(_("_Buddy List window transparency"),
+- OPT_WINTRANS_BL_ENABLED, bltransbox);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(set_blist_trans),
+- (gpointer) OPT_WINTRANS_BL_ENABLED);
+-
+- trans_box = gtk_vbox_new(FALSE, 18);
+- if (!purple_prefs_get_bool(OPT_WINTRANS_BL_ENABLED))
+- gtk_widget_set_sensitive(GTK_WIDGET(trans_box), FALSE);
+- gtk_widget_show(trans_box);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(pidgin_toggle_sensitive), trans_box);
+- button = pidgin_prefs_checkbox(
+- _("Remove Buddy List window transparency on focus"),
+- OPT_WINTRANS_BL_ONFOCUS, trans_box);
+- button = pidgin_prefs_checkbox(_("Always on top"), OPT_WINTRANS_BL_ONTOP,
+- trans_box);
+- g_signal_connect(GTK_OBJECT(button), "clicked",
+- G_CALLBACK(set_blist_trans),
+- (gpointer) OPT_WINTRANS_BL_ONTOP);
+- gtk_box_pack_start(GTK_BOX(bltransbox), trans_box, FALSE, FALSE, 5);
+-
+- /* IM transparency slider */
+- hbox = gtk_hbox_new(FALSE, 5);
+-
+- label = gtk_label_new(_("Opacity:"));
+- gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 5);
+-
+- slider = gtk_hscale_new_with_range(50, 255, 1);
+- gtk_range_set_value(GTK_RANGE(slider),
+- purple_prefs_get_int(OPT_WINTRANS_BL_ALPHA));
+-
+- gtk_widget_set_usize(GTK_WIDGET(slider), 200, -1);
+-
+- g_signal_connect(GTK_OBJECT(slider), "value-changed",
+- G_CALLBACK(bl_alpha_change), NULL);
+- g_signal_connect(GTK_OBJECT(slider), "focus-out-event",
+- G_CALLBACK(alpha_pref_set_int),
+- (gpointer) OPT_WINTRANS_BL_ALPHA);
+-
+- gtk_box_pack_start(GTK_BOX(hbox), slider, FALSE, TRUE, 5);
+-
+- gtk_widget_show_all(hbox);
+-
+- gtk_box_pack_start(GTK_BOX(trans_box), hbox, FALSE, FALSE, 5);
+-
+- gtk_widget_show_all(ret);
+- return ret;
+-}
+-
+-static PidginPluginUiInfo ui_info =
+-{
+- get_config_frame,
+- 0, /* page_num (Reserved) */
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static PurplePluginInfo info =
+-{
+- PURPLE_PLUGIN_MAGIC,
+- PURPLE_MAJOR_VERSION,
+- PURPLE_MINOR_VERSION,
+- PURPLE_PLUGIN_STANDARD, /**< type */
+- PIDGIN_PLUGIN_TYPE, /**< ui_requirement */
+- 0, /**< flags */
+- NULL, /**< dependencies */
+- PURPLE_PRIORITY_DEFAULT, /**< priority */
+- WINTRANS_PLUGIN_ID, /**< id */
+- N_("Transparency"), /**< name */
+- DISPLAY_VERSION, /**< version */
+- /** summary */
+- N_("Variable Transparency for the buddy list and conversations."),
+- /** description */
+- N_("This plugin enables variable alpha transparency on conversation windows and the buddy list.\n\n"
+- "* Note: This plugin requires Win2000 or greater."),
+- "Herman Bloggs <hermanator12002@yahoo.com>", /**< author */
+- PURPLE_WEBSITE, /**< homepage */
+- plugin_load, /**< load */
+- plugin_unload, /**< unload */
+- NULL, /**< destroy */
+- &ui_info, /**< ui_info */
+- NULL, /**< extra_info */
+- NULL, /**< prefs_info */
+- NULL, /**< actions */
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- purple_prefs_add_none("/plugins/gtk/win32");
+- purple_prefs_add_none("/plugins/gtk/win32/wintrans");
+- purple_prefs_add_bool(OPT_WINTRANS_IM_ENABLED, FALSE);
+- purple_prefs_add_int(OPT_WINTRANS_IM_ALPHA, 255);
+- purple_prefs_add_bool(OPT_WINTRANS_IM_SLIDER, FALSE);
+- purple_prefs_add_bool(OPT_WINTRANS_IM_ONFOCUS, FALSE);
+- purple_prefs_add_bool(OPT_WINTRANS_IM_ONTOP, FALSE);
+- purple_prefs_add_bool(OPT_WINTRANS_BL_ENABLED, FALSE);
+- purple_prefs_add_int(OPT_WINTRANS_BL_ALPHA, 255);
+- purple_prefs_add_bool(OPT_WINTRANS_BL_ONFOCUS, FALSE);
+- purple_prefs_add_bool(OPT_WINTRANS_BL_ONTOP, FALSE);
+-}
+-
+-PURPLE_INIT_PLUGIN(wintrans, init_plugin, info)
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.c
+--- pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,693 +0,0 @@
+-/*
+- * purple - WinPurple Options Plugin
+- *
+- * File: gtkappbar.c
+- * Date: August 2, 2003
+- * Description: Appbar functionality for Windows GTK+ applications
+- *
+- * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-/*
+- * TODO:
+- * - Move 'App on top' feature from Trans plugin to here
+- * - Bug: Multiple Show/Hide Desktop calls causes client area to disappear
+- */
+-#include <windows.h>
+-#include <winver.h>
+-#include <stdio.h>
+-#include <gtk/gtk.h>
+-#include <gdk/gdkwin32.h>
+-#include "gtkappbar.h"
+-#include "debug.h"
+-
+-#define APPBAR_CALLBACK WM_USER + 1010
+-
+-typedef HMONITOR WINAPI purple_MonitorFromPoint(POINT, DWORD);
+-typedef HMONITOR WINAPI purple_MonitorFromWindow(HWND, DWORD);
+-typedef BOOL WINAPI purple_GetMonitorInfo(HMONITOR, LPMONITORINFO);
+-
+-static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side);
+-
+-/* Retrieve the rectangular display area from the specified monitor
+- * Return TRUE if successful, otherwise FALSE
+- */
+-static gboolean
+-get_rect_from_monitor(HMODULE hmod, HMONITOR monitor, RECT *rect) {
+- purple_GetMonitorInfo *the_GetMonitorInfo;
+- MONITORINFO info;
+-
+- if (!(the_GetMonitorInfo = (purple_GetMonitorInfo*)
+- GetProcAddress(hmod, "GetMonitorInfoA"))) {
+- return FALSE;
+- }
+-
+- info.cbSize = sizeof(info);
+- if (!the_GetMonitorInfo(monitor, &info)) {
+- return FALSE;
+- }
+-
+- CopyRect(rect, &(info.rcMonitor));
+-
+- return TRUE;
+-}
+-
+-/**
+- * This will only work on Win98+ and Win2K+
+- * Return TRUE if successful, otherwise FALSE
+- */
+-static gboolean
+-get_rect_at_point_multimonitor(POINT pt, RECT *rect) {
+- HMODULE hmod;
+- purple_MonitorFromPoint *the_MonitorFromPoint;
+- HMONITOR monitor;
+-
+- if (!(hmod = GetModuleHandle("user32"))) {
+- return FALSE;
+- }
+-
+- if (!(the_MonitorFromPoint = (purple_MonitorFromPoint*)
+- GetProcAddress(hmod, "MonitorFromPoint"))) {
+- return FALSE;
+- }
+-
+- monitor =
+- the_MonitorFromPoint(pt, MONITOR_DEFAULTTOPRIMARY);
+-
+- return get_rect_from_monitor(hmod, monitor, rect);
+-}
+-
+-/**
+- * This will only work on Win98+ and Win2K+
+- * Return TRUE if successful, otherwise FALSE
+- */
+-static gboolean
+-get_rect_of_window_multimonitor(HWND window, RECT *rect) {
+- HMODULE hmod;
+- purple_MonitorFromWindow *the_MonitorFromWindow;
+- HMONITOR monitor;
+-
+- if (!(hmod = GetModuleHandle("user32"))) {
+- return FALSE;
+- }
+-
+- if (!(the_MonitorFromWindow = (purple_MonitorFromWindow*)
+- GetProcAddress(hmod, "MonitorFromWindow"))) {
+- return FALSE;
+- }
+-
+- monitor =
+- the_MonitorFromWindow(window, MONITOR_DEFAULTTOPRIMARY);
+-
+- return get_rect_from_monitor(hmod, monitor, rect);
+-}
+-
+-/*
+- * Fallback if cannot get the RECT from the monitor directly
+- */
+-static void get_default_workarea(RECT *rect) {
+- if (!SystemParametersInfo(SPI_GETWORKAREA, 0, &rect, FALSE)) {
+- /* I don't think this will ever happen */
+- rect->left = 0;
+- rect->top = 0;
+- rect->bottom = GetSystemMetrics(SM_CYSCREEN);
+- rect->right = GetSystemMetrics(SM_CXSCREEN);
+- }
+-}
+-
+-/* Retrieve the rectangle of the active work area at a point */
+-static void get_rect_at_point(POINT pt, RECT *rc) {
+- if (!get_rect_at_point_multimonitor(pt, rc)) {
+- get_default_workarea(rc);
+- }
+-}
+-
+-/* Retrieve the rectangle of the active work area of a window*/
+-static void get_rect_of_window(HWND window, RECT *rc) {
+- if (!get_rect_of_window_multimonitor(window, rc)) {
+- get_default_workarea(rc);
+- }
+-}
+-
+-static void get_window_normal_rc(HWND hwnd, RECT *rc) {
+- WINDOWPLACEMENT wplc;
+- GetWindowPlacement(hwnd, &wplc);
+- CopyRect(rc, &wplc.rcNormalPosition);
+-}
+-#if 0
+-static void print_rect(RECT *rc) {
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "RECT: L:%ld R:%ld T:%ld B:%ld\n",
+- rc->left, rc->right, rc->top, rc->bottom);
+-}
+-#endif
+-/** Set the window style to be the "Tool Window" style - small header, no min/max buttons */
+-static void set_toolbar(HWND hwnd, gboolean val) {
+- LONG style = GetWindowLong(hwnd, GWL_EXSTYLE);
+-
+- if(val && !(style & WS_EX_TOOLWINDOW))
+- style |= WS_EX_TOOLWINDOW;
+- else if(!val && style & WS_EX_TOOLWINDOW)
+- style &= ~WS_EX_TOOLWINDOW;
+- else
+- return;
+- SetWindowLong(hwnd, GWL_EXSTYLE, style);
+- SetWindowPos(hwnd, 0, 0, 0, 0, 0,
+- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+-
+-/* This really should be the following, but SWP_FRAMECHANGED strangely causes initermittent problems "Show Desktop" done more than once.
+- * Not having SWP_FRAMECHANGED *should* cause the Style not to be applied, but i haven't noticed any problems
+- * SWP_NOMOVE | SWP_NOSIZE | SWP_NOZORDER | SWP_FRAMECHANGED);
+- */
+-}
+-/** Register the window as an appbar */
+-static gboolean gtk_appbar_register(GtkAppBar *ab, HWND hwnd) {
+- APPBARDATA abd;
+-
+- abd.cbSize = sizeof(APPBARDATA);
+- abd.hWnd = hwnd;
+- abd.uCallbackMessage = APPBAR_CALLBACK;
+-
+- ab->registered = SHAppBarMessage(ABM_NEW, &abd);
+-
+- return ab->registered;
+-}
+-/** Unregister the window as an appbar */
+-static gboolean gtk_appbar_unregister(GtkAppBar *ab, HWND hwnd) {
+- APPBARDATA abd;
+-
+- if(!ab->registered)
+- return TRUE;
+-
+- abd.cbSize = sizeof(APPBARDATA);
+- abd.hWnd = hwnd;
+-
+- SHAppBarMessage(ABM_REMOVE, &abd); /** This always returns TRUE */
+-
+- ab->registered = FALSE;
+-
+- ab->docked = FALSE;
+- ab->undocking = FALSE;
+- ab->docking = FALSE;
+-
+- return TRUE;
+-}
+-
+-static void gtk_appbar_querypos(GtkAppBar *ab, HWND hwnd, RECT rcWorkspace) {
+- APPBARDATA abd;
+- guint iWidth = 0;
+-
+- if(!ab->registered)
+- gtk_appbar_register(ab, hwnd);
+-
+- abd.hWnd = hwnd;
+- abd.cbSize = sizeof(APPBARDATA);
+- abd.uEdge = ab->side;
+-
+- iWidth = ab->docked_rect.right - ab->docked_rect.left;
+-
+- abd.rc.top = rcWorkspace.top;
+- abd.rc.bottom = rcWorkspace.bottom;
+- switch (abd.uEdge)
+- {
+- case ABE_LEFT:
+- abd.rc.left = rcWorkspace.left;
+- abd.rc.right = rcWorkspace.left + iWidth;
+- break;
+-
+- case ABE_RIGHT:
+- abd.rc.right = rcWorkspace.right;
+- abd.rc.left = rcWorkspace.right - iWidth;
+- break;
+- }
+-
+- /* Ask the system for the screen space */
+- SHAppBarMessage(ABM_QUERYPOS, &abd);
+-
+- switch (abd.uEdge)
+- {
+- case ABE_LEFT:
+- abd.rc.right = abd.rc.left + iWidth;
+- break;
+-
+- case ABE_RIGHT:
+- abd.rc.left = abd.rc.right - iWidth;
+- break;
+- }
+-
+- CopyRect(&(ab->docked_rect), &abd.rc);
+-}
+-/* Actually set the size and screen location of the appbar */
+-static void gtk_appbar_setpos(GtkAppBar *ab, HWND hwnd) {
+- APPBARDATA abd;
+-
+- if(!ab->registered)
+- gtk_appbar_register(ab, hwnd);
+-
+- abd.hWnd = hwnd;
+- abd.cbSize = sizeof(APPBARDATA);
+- CopyRect(&abd.rc, &(ab->docked_rect));
+- abd.uEdge = ab->side;
+-
+- SHAppBarMessage(ABM_SETPOS, &abd);
+-}
+-/** Let any callbacks know that we have docked or undocked */
+-static void gtk_appbar_dispatch_dock_cbs(GtkAppBar *ab, gboolean val) {
+- GSList *lst = ab->dock_cbs;
+-
+- while(lst) {
+- GtkAppBarDockCB dock_cb = lst->data;
+- dock_cb(val);
+- lst = lst->next;
+- }
+-}
+-
+-static GdkFilterReturn wnd_moving(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+- POINT cp;
+- RECT *rc = (RECT*)msg->lParam;
+- RECT monRect;
+- int side = -1;
+- long dockAreaWidth = 0;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_moving\n");
+-
+- GetCursorPos(&cp);
+- get_rect_at_point(cp, &monRect);
+-
+- dockAreaWidth = (monRect.right - monRect.left) / 10;
+- /* Which part of the screen are we in ? */
+- if (cp.x > (monRect.right - dockAreaWidth)) {
+- side = ABE_RIGHT;
+- } else if (cp.x < (monRect.left + dockAreaWidth)) {
+- side = ABE_LEFT;
+- }
+-
+- if(!ab->docked) {
+- if( (side == ABE_RIGHT || side == ABE_LEFT) ) {
+- if( !ab->docking ) {
+- ab->side = side;
+- GetWindowRect(msg->hwnd, &(ab->docked_rect));
+- gtk_appbar_querypos(ab, msg->hwnd, monRect);
+-
+- /* save pre-docking height */
+- ab->undocked_height = rc->bottom - rc->top;
+- ab->docking = TRUE;
+- }
+- }
+- else
+- ab->docking = FALSE;
+- }
+- else if(side < 0) {
+- gtk_appbar_unregister(ab, msg->hwnd);
+- ab->undocking = TRUE;
+- rc->bottom = rc->top + ab->undocked_height;
+- }
+-
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static GdkFilterReturn wnd_sizing(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_sizing\n");
+- if(ab->docked) {
+- RECT *rc = (RECT*)msg->lParam;
+- if(ab->side == ABE_LEFT && msg->wParam == WMSZ_RIGHT) {
+- ab->docked_rect.right = rc->right;
+- gtk_appbar_setpos(ab, msg->hwnd);
+- }
+- else if(ab->side == ABE_RIGHT && msg->wParam == WMSZ_LEFT) {
+- ab->docked_rect.left = rc->left;
+- gtk_appbar_setpos(ab, msg->hwnd);
+- }
+- return GDK_FILTER_REMOVE;
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-/** Notify the system that the appbar has been activated */
+-static GdkFilterReturn wnd_activate(GtkAppBar *ab, GdkXEvent *xevent) {
+- if (ab->registered) {
+- APPBARDATA abd;
+- MSG *msg = (MSG*)xevent;
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_activate\n");
+-
+- abd.hWnd = msg->hwnd;
+- abd.cbSize = sizeof(APPBARDATA);
+-
+- SHAppBarMessage(ABM_ACTIVATE, &abd);
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static void show_hide(GtkAppBar *ab, gboolean hide) {
+- purple_debug_info("gtkappbar", "show_hide(%d)\n", hide);
+-
+- if (hide) {
+- purple_debug_info("gtkappbar", "hidden\n");
+- gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
+- ab->docked = TRUE;
+- ab->iconized = TRUE;
+- } else {
+- ab->iconized = FALSE;
+- purple_debug_info("gtkappbar", "shown\n");
+- ab->docked = FALSE;
+- gtk_appbar_do_dock(ab, ab->side);
+- }
+-
+-}
+-
+-/** Notify the system that the appbar's position has changed */
+-static GdkFilterReturn wnd_poschanged(GtkAppBar *ab, GdkXEvent *xevent) {
+- if (ab->registered) {
+- APPBARDATA abd;
+- MSG *msg = (MSG*)xevent;
+-
+- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "wnd_poschanged\n");
+-
+- abd.hWnd = msg->hwnd;
+- abd.cbSize = sizeof(APPBARDATA);
+-
+- SHAppBarMessage(ABM_WINDOWPOSCHANGED, &abd);
+-
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-/** The window is about to change */
+-static GdkFilterReturn wnd_poschanging(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+- WINDOWPOS *wpos = (WINDOWPOS*)msg->lParam;
+-
+- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "wnd_poschanging\n");
+-
+- if(ab->docked || ab->docking) {
+- wpos->x = ab->docked_rect.left;
+- wpos->y = ab->docked_rect.top;
+- wpos->cx = ab->docked_rect.right - ab->docked_rect.left;
+- wpos->cy = ab->docked_rect.bottom - ab->docked_rect.top;
+- if(IsIconic(msg->hwnd))
+- set_toolbar(msg->hwnd, FALSE);
+- /*return GDK_FILTER_REMOVE;*/
+- }
+-
+- if (ab->docked) {
+- if (ab->iconized && wpos->flags & SWP_SHOWWINDOW)
+- show_hide(ab, FALSE);
+- else if (!ab->iconized && wpos->flags & SWP_HIDEWINDOW)
+- show_hide(ab, TRUE);
+- }
+-
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static GdkFilterReturn wnd_exitsizemove(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_exitsizemove\n");
+- if(ab->docking) {
+- gtk_appbar_setpos(ab, msg->hwnd);
+- ab->docking = FALSE;
+- ab->docked = TRUE;
+- ShowWindow(msg->hwnd, SW_HIDE);
+- set_toolbar(msg->hwnd, TRUE);
+- ShowWindow(msg->hwnd, SW_SHOW);
+- gtk_appbar_dispatch_dock_cbs(ab, TRUE);
+- } else if(ab->undocking) {
+- ShowWindow(msg->hwnd, SW_HIDE);
+- set_toolbar(msg->hwnd, FALSE);
+- ShowWindow(msg->hwnd, SW_SHOW);
+- gtk_appbar_dispatch_dock_cbs(ab, FALSE);
+- ab->undocking = FALSE;
+- }
+-
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static GdkFilterReturn wnd_showwindow(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- purple_debug_info("gtkappbar", "wnd_showwindow\n");
+- if(msg->wParam && ab->docked) {
+- show_hide(ab, FALSE);
+- } else if(!msg->wParam && ab->docked) {
+- show_hide(ab, TRUE);
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-/** The window's size has changed */
+-static GdkFilterReturn wnd_size(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_size\n");
+-
+- if(msg->wParam == SIZE_MINIMIZED) {
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Minimize\n");
+- if(ab->docked) {
+- gtk_appbar_unregister(ab, GDK_WINDOW_HWND(ab->win->window));
+- ab->docked = TRUE;
+- }
+- }
+- else if(msg->wParam == SIZE_RESTORED) {
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "Restore\n");
+- if (!ab->iconized && ab->docked) {
+- gtk_appbar_do_dock(ab, ab->side);
+- }
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static GdkFilterReturn wnd_nchittest(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- if(ab->docked) {
+- UINT ret = DefWindowProc(msg->hwnd, msg->message, msg->wParam, msg->lParam);
+-
+- switch(ret) {
+- case HTBOTTOM:
+- case HTBOTTOMLEFT:
+- case HTBOTTOMRIGHT:
+- case HTTOP:
+- case HTTOPLEFT:
+- case HTTOPRIGHT:
+- return GDK_FILTER_REMOVE;
+- case HTLEFT:
+- if(ab->side == ABE_LEFT)
+- return GDK_FILTER_REMOVE;
+- break;
+- case HTRIGHT:
+- if(ab->side == ABE_RIGHT)
+- return GDK_FILTER_REMOVE;
+- break;
+- }
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-#if 0
+-static GdkFilterReturn wnd_initmenupopup(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+-
+- if(ab->docked && HIWORD(msg->lParam)) {
+- HMENU sysmenu = GetSystemMenu(msg->hwnd, FALSE);
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "wnd_initpopupmenu: docked: %d ismenu: %d\n", ab->docked, IsMenu(sysmenu));
+- if(EnableMenuItem(sysmenu, SC_MAXIMIZE, MF_BYCOMMAND|MF_GRAYED)<0)
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MAXIMIZE Menu item does not exist\n");
+- if(EnableMenuItem(sysmenu, SC_MOVE, MF_BYCOMMAND|MF_GRAYED)<0)
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "SC_MOVE Menu item does not exist\n");
+- return GDK_FILTER_CONTINUE;
+- }
+- else
+- GetSystemMenu(msg->hwnd, TRUE);
+- return GDK_FILTER_CONTINUE;
+-}
+-#endif
+-
+-static GdkFilterReturn gtk_appbar_callback(GtkAppBar *ab, GdkXEvent *xevent) {
+- MSG *msg = (MSG*)xevent;
+- RECT orig, windowRect;
+-
+- switch (msg->wParam) {
+- case ABN_STATECHANGE:
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_STATECHANGE\n");
+- break;
+-
+- case ABN_FULLSCREENAPP:
+- purple_debug(PURPLE_DEBUG_MISC, "gtkappbar", "gtk_appbar_callback: ABN_FULLSCREENAPP: %d\n", (BOOL)msg->lParam);
+- if (!ab->iconized && ab->docked) {
+- if ((BOOL)msg->lParam) {
+- SetWindowPos(msg->hwnd, HWND_BOTTOM, 0, 0, 0, 0,
+- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
+- } else {
+- SetWindowPos(msg->hwnd, HWND_NOTOPMOST, 0, 0, 0, 0,
+- SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE | SWP_FRAMECHANGED);
+- }
+- }
+-
+- break;
+- case ABN_POSCHANGED:
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: ABN_POSCHANGED\n");
+- CopyRect(&orig, &(ab->docked_rect));
+- get_rect_of_window(msg->hwnd, &windowRect);
+- gtk_appbar_querypos(ab, msg->hwnd, windowRect);
+- if (EqualRect(&orig, &(ab->docked_rect)) == 0) {
+- MoveWindow(msg->hwnd, ab->docked_rect.left, ab->docked_rect.top,
+- ab->docked_rect.right - ab->docked_rect.left,
+- ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
+- }
+- gtk_appbar_setpos(ab, msg->hwnd);
+- break;
+-#if 0
+- default:
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_callback: %d\n", msg->wParam);
+-#endif
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static GdkFilterReturn gtk_appbar_event_filter(GdkXEvent *xevent, GdkEvent *event, gpointer data) {
+- MSG *msg = (MSG*)xevent;
+-
+- /*printf("MSG: %s\n", message_to_string (msg->message));*/
+- switch(msg->message) {
+- case WM_EXITSIZEMOVE:
+- return wnd_exitsizemove(data, xevent);
+- case WM_WINDOWPOSCHANGING:
+- return wnd_poschanging(data, xevent);
+- case WM_WINDOWPOSCHANGED:
+- return wnd_poschanged(data, xevent);
+- case WM_ACTIVATE:
+- return wnd_activate(data, xevent);
+- case WM_SIZING:
+- return wnd_sizing(data, xevent);
+- case WM_MOVING:
+- return wnd_moving(data, xevent);
+- case WM_SHOWWINDOW:
+- return wnd_showwindow(data, xevent);
+- case WM_NCHITTEST:
+- return wnd_nchittest(data, xevent);
+-#if 0
+- case WM_INITMENUPOPUP:
+- return wnd_initmenupopup(data, xevent);
+-#endif
+- case WM_SIZE:
+- return wnd_size(data, xevent);
+- case APPBAR_CALLBACK:
+- return gtk_appbar_callback(data, xevent);
+-#if 0
+- default:
+- purple_debug_info("gtkappbar", "gtk_appbar_event_filter %d\n", msg->message);
+-#endif
+- }
+- return GDK_FILTER_CONTINUE;
+-}
+-
+-static void gtk_appbar_do_dock(GtkAppBar *ab, UINT side) {
+- RECT orig, windowRect;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_do_dock\n");
+-
+- if(!ab || !IsWindow(GDK_WINDOW_HWND(ab->win->window)))
+- return;
+-
+- ab->side = side;
+- get_window_normal_rc(GDK_WINDOW_HWND(ab->win->window), &(ab->docked_rect));
+- CopyRect(&orig, &(ab->docked_rect));
+- get_rect_of_window(GDK_WINDOW_HWND(ab->win->window), &windowRect);
+- gtk_appbar_querypos(ab, GDK_WINDOW_HWND(ab->win->window), windowRect);
+- if(EqualRect(&orig, &(ab->docked_rect)) == 0)
+- MoveWindow(GDK_WINDOW_HWND(ab->win->window),
+- ab->docked_rect.left,
+- ab->docked_rect.top,
+- ab->docked_rect.right - ab->docked_rect.left,
+- ab->docked_rect.bottom - ab->docked_rect.top, TRUE);
+- gtk_appbar_setpos(ab, GDK_WINDOW_HWND(ab->win->window));
+- ab->docked = TRUE;
+-}
+-
+-void gtk_appbar_dock(GtkAppBar *ab, UINT side) {
+- HWND hwnd;
+-
+- g_return_if_fail(ab != NULL);
+-
+- hwnd = GDK_WINDOW_HWND(ab->win->window);
+-
+- g_return_if_fail(IsWindow(hwnd));
+-
+- ab->iconized = IsIconic(hwnd);
+-
+- if (!ab->docked && !ab->iconized)
+- ShowWindow(hwnd, SW_HIDE);
+- gtk_appbar_do_dock(ab, side);
+- set_toolbar(hwnd, TRUE);
+- if (!ab->iconized)
+- ShowWindow(hwnd, SW_SHOW);
+-}
+-
+-void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb) {
+- if(!ab)
+- return;
+- ab->dock_cbs = g_slist_prepend(ab->dock_cbs, dock_cb);
+-}
+-
+-GtkAppBar *gtk_appbar_add(GtkWidget *win) {
+- GtkAppBar *ab;
+-
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_add\n");
+-
+- if(!win)
+- return NULL;
+- ab = g_new0(GtkAppBar, 1);
+- ab->win = win;
+-
+- /* init docking coords */
+- get_window_normal_rc(GDK_WINDOW_HWND(win->window), &(ab->docked_rect));
+-
+- /* Add main window filter */
+- gdk_window_add_filter(win->window,
+- gtk_appbar_event_filter,
+- ab);
+- return ab;
+-}
+-
+-void gtk_appbar_remove(GtkAppBar *ab) {
+- HWND hwnd;
+- purple_debug(PURPLE_DEBUG_INFO, "gtkappbar", "gtk_appbar_remove\n");
+-
+- if(!ab)
+- return;
+-
+- hwnd = GDK_WINDOW_HWND(ab->win->window);
+- gdk_window_remove_filter(ab->win->window,
+- gtk_appbar_event_filter,
+- ab);
+- if(ab->docked) {
+- gtk_window_resize(GTK_WINDOW(ab->win),
+- ab->docked_rect.right - ab->docked_rect.left,
+- ab->undocked_height);
+- if (!ab->iconized)
+- ShowWindow(hwnd, SW_HIDE);
+- set_toolbar(hwnd, FALSE);
+- if (!ab->iconized)
+- ShowWindow(hwnd, SW_SHOW);
+- }
+- gtk_appbar_unregister(ab, hwnd);
+-
+- while (ab->dock_cbs)
+- ab->dock_cbs = g_slist_remove(ab->dock_cbs, ab->dock_cbs->data);
+-
+- g_free(ab);
+-}
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.h pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.h
+--- pidgin-2.10.7/pidgin/plugins/win32/winprefs/gtkappbar.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/gtkappbar.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,59 +0,0 @@
+-/*
+- * purple - WinPurple Options Plugin
+- *
+- * File: gtkappbar.h
+- * Date: August 2, 2003
+- * Description: Appbar functionality for Windows GTK+ applications
+- *
+- * Copyright (C) 2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _GTKAPPBAR_H_
+-#define _GTKAPPBAR_H_
+-
+-#include <glib.h>
+-#include <gtk/gtk.h>
+-
+-typedef struct {
+- GtkWidget *win;
+- /** The rectangle of the screen area used for docking */
+- RECT docked_rect;
+- /** The height of the window prior to docking */
+- UINT undocked_height;
+- /** The side of the screen to which the window is docked*/
+- UINT side;
+- /** Is the window currently docked? */
+- gboolean docked;
+- /** Is the window currently in the process of docking? */
+- gboolean docking;
+- gboolean undocking;
+- /** Is the window currently registered as an appbar */
+- gboolean registered;
+- /** Callback functions to notify of dock state change */
+- GSList *dock_cbs;
+- /** Is the window currently iconized? */
+- gboolean iconized;
+-} GtkAppBar;
+-
+-typedef void (*GtkAppBarDockCB)(gboolean);
+-
+-GtkAppBar *gtk_appbar_add(GtkWidget *win);
+-void gtk_appbar_remove(GtkAppBar *ab);
+-void gtk_appbar_dock(GtkAppBar *ab, UINT side);
+-void gtk_appbar_add_dock_cb(GtkAppBar *ab, GtkAppBarDockCB dock_cb);
+-
+-#endif /* _GTKAPPBAR_H_ */
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/Makefile.mingw pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/Makefile.mingw
+--- pidgin-2.10.7/pidgin/plugins/win32/winprefs/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,82 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for winprefs plugin.
+-#
+-
+-PIDGIN_TREE_TOP := ../../../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-TARGET = winprefs
+-DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES))
+-DEFINES += -DWINVER=0x500
+-
+-##
+-## INCLUDE PATHS
+-##
+-INCLUDE_PATHS += -I. \
+- -I$(GTK_TOP)/include \
+- -I$(GTK_TOP)/include/gtk-2.0 \
+- -I$(GTK_TOP)/include/glib-2.0 \
+- -I$(GTK_TOP)/include/pango-1.0 \
+- -I$(GTK_TOP)/include/atk-1.0 \
+- -I$(GTK_TOP)/include/cairo \
+- -I$(GTK_TOP)/lib/glib-2.0/include \
+- -I$(GTK_TOP)/lib/gtk-2.0/include \
+- -I$(PURPLE_TOP) \
+- -I$(PURPLE_TOP)/win32 \
+- -I$(PIDGIN_TOP) \
+- -I$(PIDGIN_TOP)/win32 \
+- -I$(PIDGIN_TREE_TOP)
+-
+-LIB_PATHS += -L$(GTK_TOP)/lib \
+- -L$(PURPLE_TOP) \
+- -L$(PIDGIN_TOP)
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-C_SRC = winprefs.c \
+- gtkappbar.c
+-
+-OBJECTS = $(C_SRC:%.c=%.o)
+-
+-##
+-## LIBRARIES
+-##
+-LIBS = -lgtk-win32-2.0 \
+- -lglib-2.0 \
+- -lgdk-win32-2.0 \
+- -lgmodule-2.0 \
+- -lgobject-2.0 \
+- -lws2_32 \
+- -lintl \
+- -lpurple \
+- -lpidgin
+-
+-include $(PIDGIN_COMMON_RULES)
+-
+-##
+-## TARGET DEFINITIONS
+-##
+-.PHONY: all install clean
+-
+-all: $(TARGET).dll
+-
+-install: $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+- cp $(TARGET).dll $(PIDGIN_INSTALL_PLUGINS_DIR)
+-
+-##
+-## BUILD DLL
+-##
+-$(TARGET).dll: $(PURPLE_DLL).a $(PIDGIN_DLL).a $(OBJECTS)
+- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll
+-
+-##
+-## CLEAN RULES
+-##
+-clean:
+- rm -rf $(OBJECTS)
+- rm -rf $(TARGET).dll
+-
+-include $(PIDGIN_COMMON_TARGETS)
+diff -Nur pidgin-2.10.7/pidgin/plugins/win32/winprefs/winprefs.c pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/winprefs.c
+--- pidgin-2.10.7/pidgin/plugins/win32/winprefs/winprefs.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/plugins/win32/winprefs/winprefs.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,391 +0,0 @@
+-/*
+- * pidgin - Windows Pidgin Options Plugin
+- *
+- * Pidgin 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#include <gtk/gtk.h>
+-#include <gdk/gdkwin32.h>
+-
+-#include "internal.h"
+-
+-#include "gtkwin32dep.h"
+-
+-#include "core.h"
+-#include "debug.h"
+-#include "prefs.h"
+-#include "signals.h"
+-#include "version.h"
+-
+-#include "gtkappbar.h"
+-#include "gtkblist.h"
+-#include "gtkconv.h"
+-#include "gtkplugin.h"
+-#include "gtkprefs.h"
+-#include "gtkutils.h"
+-
+-/*
+- * MACROS & DEFINES
+- */
+-#define WINPREFS_PLUGIN_ID "gtk-win-prefs"
+-
+-#define RUNKEY "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run"
+-
+-/*
+- * LOCALS
+- */
+-static const char *PREF_DBLIST_DOCKABLE = "/plugins/gtk/win32/winprefs/dblist_dockable";
+-static const char *PREF_DBLIST_DOCKED = "/plugins/gtk/win32/winprefs/dblist_docked";
+-static const char *PREF_DBLIST_HEIGHT = "/plugins/gtk/win32/winprefs/dblist_height";
+-static const char *PREF_DBLIST_SIDE = "/plugins/gtk/win32/winprefs/dblist_side";
+-static const char *PREF_BLIST_ON_TOP = "/plugins/gtk/win32/winprefs/blist_on_top";
+-/* Deprecated */
+-static const char *PREF_CHAT_BLINK = "/plugins/gtk/win32/winprefs/chat_blink";
+-static const char *PREF_DBLIST_ON_TOP = "/plugins/gtk/win32/winprefs/dblist_on_top";
+-
+-static PurplePlugin *handle = NULL;
+-static GtkAppBar *blist_ab = NULL;
+-static GtkWidget *blist = NULL;
+-static guint blist_visible_cb_id = 0;
+-
+-enum {
+- BLIST_TOP_NEVER = 0,
+- BLIST_TOP_ALWAYS,
+- BLIST_TOP_DOCKED,
+-};
+-
+-/*
+- * CODE
+- */
+-
+-/* BLIST DOCKING */
+-
+-static void blist_save_state() {
+- if(blist_ab) {
+- if(purple_prefs_get_bool(PREF_DBLIST_DOCKABLE) && blist_ab->docked) {
+- purple_prefs_set_int(PREF_DBLIST_HEIGHT, blist_ab->undocked_height);
+- purple_prefs_set_int(PREF_DBLIST_SIDE, blist_ab->side);
+- purple_prefs_set_bool(PREF_DBLIST_DOCKED, blist_ab->docked);
+- } else
+- purple_prefs_set_bool(PREF_DBLIST_DOCKED, FALSE);
+- }
+-}
+-
+-static void blist_set_ontop(gboolean val) {
+- if(!blist)
+- return;
+-
+- gtk_window_set_keep_above(GTK_WINDOW(PIDGIN_BLIST(purple_get_blist())->window), val);
+-}
+-
+-static void blist_dock_cb(gboolean val) {
+- if(val) {
+- purple_debug_info(WINPREFS_PLUGIN_ID, "Blist Docking...\n");
+- if(purple_prefs_get_int(PREF_BLIST_ON_TOP) != BLIST_TOP_NEVER)
+- blist_set_ontop(TRUE);
+- } else {
+- purple_debug_info(WINPREFS_PLUGIN_ID, "Blist Undocking...\n");
+- blist_set_ontop(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS);
+- }
+-}
+-
+-static void blist_set_dockable(gboolean val) {
+- if(val) {
+- if(blist_ab == NULL && blist != NULL) {
+- blist_ab = gtk_appbar_add(blist);
+- gtk_appbar_add_dock_cb(blist_ab, blist_dock_cb);
+- }
+- } else {
+- if(blist_ab != NULL) {
+- gtk_appbar_remove(blist_ab);
+- blist_ab = NULL;
+- }
+-
+- blist_set_ontop(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS);
+- }
+-}
+-
+-/* PLUGIN CALLBACKS */
+-
+-/* We need this because the blist destroy cb won't be called before the
+- plugin is unloaded, when quitting */
+-static void purple_quit_cb() {
+- purple_debug_info(WINPREFS_PLUGIN_ID, "purple_quit_cb: removing appbar\n");
+- blist_save_state();
+- blist_set_dockable(FALSE);
+-}
+-
+-/* Listen for the first time the window stops being withdrawn */
+-static void blist_visible_cb(const char *pref, PurplePrefType type,
+- gconstpointer value, gpointer user_data) {
+- if(purple_prefs_get_bool(pref)) {
+- gtk_appbar_dock(blist_ab,
+- purple_prefs_get_int(PREF_DBLIST_SIDE));
+-
+- if(purple_prefs_get_int(PREF_BLIST_ON_TOP)
+- == BLIST_TOP_DOCKED)
+- blist_set_ontop(TRUE);
+-
+- /* We only need to be notified about this once */
+- purple_prefs_disconnect_callback(blist_visible_cb_id);
+- }
+-}
+-
+-/* This needs to be delayed otherwise, when the blist is originally created and
+- * hidden, it'll trigger the blist_visible_cb */
+-static gboolean listen_for_blist_visible_cb(gpointer data) {
+- if (handle != NULL)
+- blist_visible_cb_id =
+- purple_prefs_connect_callback(handle,
+- PIDGIN_PREFS_ROOT "/blist/list_visible",
+- blist_visible_cb, NULL);
+-
+- return FALSE;
+-}
+-
+-static void blist_create_cb(PurpleBuddyList *purple_blist, void *data) {
+- purple_debug_info(WINPREFS_PLUGIN_ID, "buddy list created\n");
+-
+- blist = PIDGIN_BLIST(purple_blist)->window;
+-
+- if(purple_prefs_get_bool(PREF_DBLIST_DOCKABLE)) {
+- blist_set_dockable(TRUE);
+- if(purple_prefs_get_bool(PREF_DBLIST_DOCKED)) {
+- blist_ab->undocked_height = purple_prefs_get_int(PREF_DBLIST_HEIGHT);
+- if(!(gdk_window_get_state(blist->window)
+- & GDK_WINDOW_STATE_WITHDRAWN)) {
+- gtk_appbar_dock(blist_ab,
+- purple_prefs_get_int(PREF_DBLIST_SIDE));
+- if(purple_prefs_get_int(PREF_BLIST_ON_TOP)
+- == BLIST_TOP_DOCKED)
+- blist_set_ontop(TRUE);
+- } else {
+- g_idle_add(listen_for_blist_visible_cb, NULL);
+- }
+- }
+- }
+-
+- if(purple_prefs_get_int(PREF_BLIST_ON_TOP) == BLIST_TOP_ALWAYS)
+- blist_set_ontop(TRUE);
+-
+-}
+-
+-/* WIN PREFS GENERAL */
+-
+-static void
+-winprefs_set_autostart(GtkWidget *w) {
+- char *runval = NULL;
+-
+- if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)))
+- runval = g_strdup_printf("\"%s" G_DIR_SEPARATOR_S "pidgin.exe\"", wpurple_install_dir());
+-
+- if(!wpurple_write_reg_string(HKEY_CURRENT_USER, RUNKEY, "Pidgin", runval)
+- /* For Win98 */
+- && !wpurple_write_reg_string(HKEY_LOCAL_MACHINE, RUNKEY, "Pidgin", runval))
+- purple_debug_error(WINPREFS_PLUGIN_ID, "Could not set registry key value\n");
+-
+- g_free(runval);
+-}
+-
+-static void
+-winprefs_set_multiple_instances(GtkWidget *w) {
+- wpurple_write_reg_string(HKEY_CURRENT_USER, "Environment", "PIDGIN_MULTI_INST",
+- gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(w)) ? "1" : NULL);
+-}
+-
+-static void
+-winprefs_set_blist_dockable(const char *pref, PurplePrefType type,
+- gconstpointer value, gpointer user_data)
+-{
+- blist_set_dockable(GPOINTER_TO_INT(value));
+-}
+-
+-static void
+-winprefs_set_blist_ontop(const char *pref, PurplePrefType type,
+- gconstpointer value, gpointer user_data)
+-{
+- gint setting = purple_prefs_get_int(PREF_BLIST_ON_TOP);
+- if((setting == BLIST_TOP_DOCKED && blist_ab && blist_ab->docked)
+- || setting == BLIST_TOP_ALWAYS)
+- blist_set_ontop(TRUE);
+- else
+- blist_set_ontop(FALSE);
+-}
+-
+-/*
+- * EXPORTED FUNCTIONS
+- */
+-
+-static gboolean plugin_load(PurplePlugin *plugin) {
+- handle = plugin;
+-
+- /* blist docking init */
+- if(purple_get_blist() && PIDGIN_BLIST(purple_get_blist())
+- && PIDGIN_BLIST(purple_get_blist())->window) {
+- blist_create_cb(purple_get_blist(), NULL);
+- }
+-
+- /* This really shouldn't happen anymore generally, but if for some strange
+- reason, the blist is recreated, we need to set it up again. */
+- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-created",
+- plugin, PURPLE_CALLBACK(blist_create_cb), NULL);
+-
+- purple_signal_connect((void*)purple_get_core(), "quitting", plugin,
+- PURPLE_CALLBACK(purple_quit_cb), NULL);
+-
+- purple_prefs_connect_callback(handle, PREF_BLIST_ON_TOP,
+- winprefs_set_blist_ontop, NULL);
+- purple_prefs_connect_callback(handle, PREF_DBLIST_DOCKABLE,
+- winprefs_set_blist_dockable, NULL);
+-
+- return TRUE;
+-}
+-
+-static gboolean plugin_unload(PurplePlugin *plugin) {
+- blist_set_dockable(FALSE);
+- blist_set_ontop(FALSE);
+-
+- handle = NULL;
+-
+- return TRUE;
+-}
+-
+-static GtkWidget* get_config_frame(PurplePlugin *plugin) {
+- GtkWidget *ret;
+- GtkWidget *vbox;
+- GtkWidget *button;
+- char *run_key_val;
+- char *tmp;
+-
+- ret = gtk_vbox_new(FALSE, 18);
+- gtk_container_set_border_width(GTK_CONTAINER(ret), 12);
+-
+- /* Autostart */
+- vbox = pidgin_make_frame(ret, _("Startup"));
+- tmp = g_strdup_printf(_("_Start %s on Windows startup"), PIDGIN_NAME);
+- button = gtk_check_button_new_with_mnemonic(tmp);
+- g_free(tmp);
+- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+- if ((run_key_val = wpurple_read_reg_string(HKEY_CURRENT_USER, RUNKEY, "Pidgin"))
+- || (run_key_val = wpurple_read_reg_string(HKEY_LOCAL_MACHINE, RUNKEY, "Pidgin"))) {
+- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+- g_free(run_key_val);
+- }
+- g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(winprefs_set_autostart), NULL);
+- gtk_widget_show(button);
+-
+- button = gtk_check_button_new_with_mnemonic(_("Allow multiple instances"));
+- gtk_box_pack_start(GTK_BOX(vbox), button, FALSE, FALSE, 0);
+- if ((run_key_val = wpurple_read_reg_string(HKEY_CURRENT_USER, "Environment", "PIDGIN_MULTI_INST"))) {
+- gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(button), TRUE);
+- g_free(run_key_val);
+- }
+- g_signal_connect(G_OBJECT(button), "clicked", G_CALLBACK(winprefs_set_multiple_instances), NULL);
+- gtk_widget_show(button);
+-
+- /* Buddy List */
+- vbox = pidgin_make_frame(ret, _("Buddy List"));
+- pidgin_prefs_checkbox(_("_Dockable Buddy List"),
+- PREF_DBLIST_DOCKABLE, vbox);
+-
+- /* Blist On Top */
+- pidgin_prefs_dropdown(vbox, _("_Keep Buddy List window on top:"),
+- PURPLE_PREF_INT, PREF_BLIST_ON_TOP,
+- _("Never"), BLIST_TOP_NEVER,
+- _("Always"), BLIST_TOP_ALWAYS,
+- /* XXX: Did this ever work? */
+- _("Only when docked"), BLIST_TOP_DOCKED,
+- NULL);
+-
+- gtk_widget_show_all(ret);
+- return ret;
+-}
+-
+-static PidginPluginUiInfo ui_info =
+-{
+- get_config_frame,
+- 0,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static PurplePluginInfo info =
+-{
+- PURPLE_PLUGIN_MAGIC,
+- PURPLE_MAJOR_VERSION,
+- PURPLE_MINOR_VERSION,
+- PURPLE_PLUGIN_STANDARD,
+- PIDGIN_PLUGIN_TYPE,
+- 0,
+- NULL,
+- PURPLE_PRIORITY_DEFAULT,
+- WINPREFS_PLUGIN_ID,
+- N_("Windows Pidgin Options"),
+- DISPLAY_VERSION,
+- N_("Options specific to Pidgin for Windows."),
+- N_("Provides options specific to Pidgin for Windows, such as buddy list docking."),
+- "Herman Bloggs <hermanator12002@yahoo.com>",
+- PURPLE_WEBSITE,
+- plugin_load,
+- plugin_unload,
+- NULL,
+- &ui_info,
+- NULL,
+- NULL,
+- NULL,
+-
+- /* padding */
+- NULL,
+- NULL,
+- NULL,
+- NULL
+-};
+-
+-static void
+-init_plugin(PurplePlugin *plugin)
+-{
+- purple_prefs_add_none("/plugins/gtk");
+- purple_prefs_add_none("/plugins/gtk/win32");
+- purple_prefs_add_none("/plugins/gtk/win32/winprefs");
+- purple_prefs_add_bool(PREF_DBLIST_DOCKABLE, FALSE);
+- purple_prefs_add_bool(PREF_DBLIST_DOCKED, FALSE);
+- purple_prefs_add_int(PREF_DBLIST_HEIGHT, 0);
+- purple_prefs_add_int(PREF_DBLIST_SIDE, 0);
+-
+- /* Convert old preferences */
+- if(purple_prefs_exists(PREF_DBLIST_ON_TOP)) {
+- gint blist_top = BLIST_TOP_NEVER;
+- if(purple_prefs_get_bool(PREF_BLIST_ON_TOP))
+- blist_top = BLIST_TOP_ALWAYS;
+- else if(purple_prefs_get_bool(PREF_DBLIST_ON_TOP))
+- blist_top = BLIST_TOP_DOCKED;
+- purple_prefs_remove(PREF_BLIST_ON_TOP);
+- purple_prefs_remove(PREF_DBLIST_ON_TOP);
+- purple_prefs_add_int(PREF_BLIST_ON_TOP, blist_top);
+- } else
+- purple_prefs_add_int(PREF_BLIST_ON_TOP, BLIST_TOP_NEVER);
+- purple_prefs_remove(PREF_CHAT_BLINK);
+-}
+-
+-PURPLE_INIT_PLUGIN(winprefs, init_plugin, info)
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/gtkdocklet-win32.c pidgin-2.10.7-nonprism/pidgin/win32/gtkdocklet-win32.c
+--- pidgin-2.10.7/pidgin/win32/gtkdocklet-win32.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/gtkdocklet-win32.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,671 +0,0 @@
+-/*
+- * System tray icon (aka docklet) plugin for Winpidgin
+- *
+- * Copyright (C) 2002-3 Robert McQueen <robot101@debian.org>
+- * Copyright (C) 2003 Herman Bloggs <hermanator12002@yahoo.com>
+- * Inspired by a similar plugin by:
+- * John (J5) Palmieri <johnp@martianrock.com>
+- *
+- * This program is free software; you can redistribute it and/or
+- * modify it under the terms of the GNU General Public License as
+- * published by the Free Software Foundation; either version 2 of the
+- * License, or (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful, but
+- * WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+- * General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
+- * 02111-1301, USA.
+- */
+-#define _WIN32_IE 0x0500
+-#include <windows.h>
+-#include <gdk/gdkwin32.h>
+-#include <gdk/gdk.h>
+-
+-#include "internal.h"
+-#include "gtkblist.h"
+-#include "debug.h"
+-
+-#include "resource.h"
+-#include "MinimizeToTray.h"
+-#include "gtkwin32dep.h"
+-#include "gtkdocklet.h"
+-#include "pidginstock.h"
+-
+-/*
+- * DEFINES, MACROS & DATA TYPES
+- */
+-#define WM_TRAYMESSAGE WM_USER /* User defined WM Message */
+-
+-/*
+- * LOCALS
+- */
+-static HWND systray_hwnd = NULL;
+-/* additional two cached_icons entries for pending and connecting icons */
+-static HICON cached_icons[PURPLE_STATUS_NUM_PRIMITIVES + 2];
+-static GtkWidget *image = NULL;
+-/* This is used to trigger click events on so they appear to GTK+ as if they are triggered by input */
+-static GtkWidget *dummy_button = NULL;
+-static GtkWidget *dummy_window = NULL;
+-static NOTIFYICONDATAW _nicon_data;
+-
+-static gboolean dummy_button_cb(GtkWidget *widget, GdkEventButton *event, gpointer user_data) {
+- pidgin_docklet_clicked(event->button);
+- return TRUE;
+-}
+-
+-static LRESULT CALLBACK systray_mainmsg_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
+- static UINT taskbarRestartMsg; /* static here means value is kept across multiple calls to this func */
+-
+- switch(msg) {
+- case WM_CREATE:
+- purple_debug_info("docklet", "WM_CREATE\n");
+- taskbarRestartMsg = RegisterWindowMessageW(L"TaskbarCreated");
+- break;
+-
+- case WM_TIMER:
+- purple_debug_info("docklet", "WM_TIMER\n");
+- break;
+-
+- case WM_DESTROY:
+- purple_debug_info("docklet", "WM_DESTROY\n");
+- break;
+-
+- case WM_TRAYMESSAGE:
+- {
+- int type = 0;
+- GdkEvent *event;
+- GdkEventButton *event_btn;
+-
+- /* We'll use Double Click - Single click over on linux */
+- if(lparam == WM_LBUTTONDBLCLK)
+- type = 1;
+- else if(lparam == WM_MBUTTONUP)
+- type = 2;
+- else if(lparam == WM_RBUTTONUP)
+- type = 3;
+- else
+- break;
+-
+- gtk_widget_show_all(dummy_window);
+- event = gdk_event_new(GDK_BUTTON_PRESS);
+- event_btn = (GdkEventButton *) event;
+- event_btn->window = g_object_ref (gdk_get_default_root_window());
+- event_btn->send_event = TRUE;
+- event_btn->time = GetTickCount();
+- event_btn->axes = NULL;
+- event_btn->state = 0;
+- event_btn->button = type;
+- event_btn->device = gdk_display_get_default ()->core_pointer;
+- event->any.window = g_object_ref(dummy_window->window);
+- gdk_window_set_user_data(event->any.window, dummy_button);
+-
+- gtk_main_do_event((GdkEvent *)event);
+- gtk_widget_hide(dummy_window);
+- gdk_event_free((GdkEvent *)event);
+-
+- break;
+- }
+- default:
+- if (msg == taskbarRestartMsg) {
+- /* explorer crashed and left us hanging...
+- This will put the systray icon back in it's place, when it restarts */
+- Shell_NotifyIconW(NIM_ADD, &_nicon_data);
+- }
+- break;
+- }/* end switch */
+-
+- return DefWindowProc(hwnd, msg, wparam, lparam);
+-}
+-
+-/* Create hidden window to process systray messages */
+-static HWND systray_create_hiddenwin() {
+- WNDCLASSEXW wcex;
+- wchar_t *wname;
+-
+- wname = L"WinpidginSystrayWinCls";
+-
+- wcex.cbSize = sizeof(wcex);
+- wcex.style = 0;
+- wcex.lpfnWndProc = systray_mainmsg_handler;
+- wcex.cbClsExtra = 0;
+- wcex.cbWndExtra = 0;
+- wcex.hInstance = winpidgin_exe_hinstance();
+- wcex.hIcon = NULL;
+- wcex.hCursor = NULL,
+- wcex.hbrBackground = NULL;
+- wcex.lpszMenuName = NULL;
+- wcex.lpszClassName = wname;
+- wcex.hIconSm = NULL;
+-
+- RegisterClassExW(&wcex);
+-
+- /* Create the window */
+- return (CreateWindowW(wname, L"", 0, 0, 0, 0, 0, GetDesktopWindow(), NULL, winpidgin_exe_hinstance(), 0));
+-}
+-
+-static void systray_init_icon(HWND hWnd) {
+- wchar_t *w;
+- ZeroMemory(&_nicon_data, sizeof(_nicon_data));
+- _nicon_data.cbSize = sizeof(NOTIFYICONDATAW);
+- _nicon_data.hWnd = hWnd;
+- _nicon_data.uID = 0;
+- _nicon_data.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
+- _nicon_data.uCallbackMessage = WM_TRAYMESSAGE;
+- _nicon_data.hIcon = NULL;
+- w = g_utf8_to_utf16(PIDGIN_NAME, -1, NULL, NULL, NULL);
+- wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t));
+- g_free(w);
+- Shell_NotifyIconW(NIM_ADD, &_nicon_data);
+- pidgin_docklet_embedded();
+-}
+-
+-/* This is ganked from GTK+.
+- * When we can use GTK+ 2.10 and the GtkStatusIcon stuff, this will no longer be necesary */
+-#define WIN32_GDI_FAILED(api) printf("GDI FAILED %s\n", api)
+-
+-static gboolean
+-_gdk_win32_pixbuf_to_hicon_supports_alpha (void)
+-{
+- static gboolean is_win_xp=FALSE, is_win_xp_checked=FALSE;
+-
+- if (!is_win_xp_checked)
+- {
+- is_win_xp_checked = TRUE;
+-
+- if (!G_WIN32_IS_NT_BASED ())
+- is_win_xp = FALSE;
+- else
+- {
+- OSVERSIONINFO version;
+-
+- memset (&version, 0, sizeof (version));
+- version.dwOSVersionInfoSize = sizeof (version);
+- is_win_xp = GetVersionEx (&version)
+- && version.dwPlatformId == VER_PLATFORM_WIN32_NT
+- && (version.dwMajorVersion > 5
+- || (version.dwMajorVersion == 5 && version.dwMinorVersion >= 1));
+- }
+- }
+- return is_win_xp;
+-}
+-
+-static HBITMAP
+-create_alpha_bitmap (gint size,
+- guchar **outdata)
+-{
+- BITMAPV5HEADER bi;
+- HDC hdc;
+- HBITMAP hBitmap;
+-
+- ZeroMemory (&bi, sizeof (BITMAPV5HEADER));
+- bi.bV5Size = sizeof (BITMAPV5HEADER);
+- bi.bV5Height = bi.bV5Width = size;
+- bi.bV5Planes = 1;
+- bi.bV5BitCount = 32;
+- bi.bV5Compression = BI_BITFIELDS;
+- /* The following mask specification specifies a supported 32 BPP
+- * alpha format for Windows XP (BGRA format).
+- */
+- bi.bV5RedMask = 0x00FF0000;
+- bi.bV5GreenMask = 0x0000FF00;
+- bi.bV5BlueMask = 0x000000FF;
+- bi.bV5AlphaMask = 0xFF000000;
+-
+- /* Create the DIB section with an alpha channel. */
+- hdc = GetDC (NULL);
+- if (!hdc)
+- {
+- WIN32_GDI_FAILED ("GetDC");
+- return NULL;
+- }
+- hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bi, DIB_RGB_COLORS,
+- (PVOID *) outdata, NULL, (DWORD)0);
+- if (hBitmap == NULL)
+- WIN32_GDI_FAILED ("CreateDIBSection");
+- ReleaseDC (NULL, hdc);
+-
+- return hBitmap;
+-}
+-
+-static HBITMAP
+-create_color_bitmap (gint size,
+- guchar **outdata,
+- gint bits)
+-{
+- struct {
+- BITMAPV4HEADER bmiHeader;
+- RGBQUAD bmiColors[2];
+- } bmi;
+- HDC hdc;
+- HBITMAP hBitmap;
+-
+- ZeroMemory (&bmi, sizeof (bmi));
+- bmi.bmiHeader.bV4Size = sizeof (BITMAPV4HEADER);
+- bmi.bmiHeader.bV4Height = bmi.bmiHeader.bV4Width = size;
+- bmi.bmiHeader.bV4Planes = 1;
+- bmi.bmiHeader.bV4BitCount = bits;
+- bmi.bmiHeader.bV4V4Compression = BI_RGB;
+-
+- /* when bits is 1, these will be used.
+- * bmiColors[0] already zeroed from ZeroMemory()
+- */
+- bmi.bmiColors[1].rgbBlue = 0xFF;
+- bmi.bmiColors[1].rgbGreen = 0xFF;
+- bmi.bmiColors[1].rgbRed = 0xFF;
+-
+- hdc = GetDC (NULL);
+- if (!hdc)
+- {
+- WIN32_GDI_FAILED ("GetDC");
+- return NULL;
+- }
+- hBitmap = CreateDIBSection (hdc, (BITMAPINFO *)&bmi, DIB_RGB_COLORS,
+- (PVOID *) outdata, NULL, (DWORD)0);
+- if (hBitmap == NULL)
+- WIN32_GDI_FAILED ("CreateDIBSection");
+- ReleaseDC (NULL, hdc);
+-
+- return hBitmap;
+-}
+-
+-static gboolean
+-pixbuf_to_hbitmaps_alpha_winxp (GdkPixbuf *pixbuf,
+- HBITMAP *color,
+- HBITMAP *mask)
+-{
+- /* Based on code from
+- * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
+- */
+- HBITMAP hColorBitmap, hMaskBitmap;
+- guchar *indata, *inrow;
+- guchar *colordata, *colorrow, *maskdata, *maskbyte;
+- gint width, height, size, i, i_offset, j, j_offset, rowstride;
+- guint maskstride, mask_bit;
+-
+- width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
+- height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
+-
+- /* The bitmaps are created square */
+- size = MAX (width, height);
+-
+- hColorBitmap = create_alpha_bitmap (size, &colordata);
+- if (!hColorBitmap)
+- return FALSE;
+- hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
+- if (!hMaskBitmap)
+- {
+- DeleteObject (hColorBitmap);
+- return FALSE;
+- }
+-
+- /* MSDN says mask rows are aligned to "LONG" boundaries */
+- maskstride = (((size + 31) & ~31) >> 3);
+-
+- indata = gdk_pixbuf_get_pixels (pixbuf);
+- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+-
+- if (width > height)
+- {
+- i_offset = 0;
+- j_offset = (width - height) / 2;
+- }
+- else
+- {
+- i_offset = (height - width) / 2;
+- j_offset = 0;
+- }
+-
+- for (j = 0; j < height; j++)
+- {
+- colorrow = colordata + 4*(j+j_offset)*size + 4*i_offset;
+- maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
+- mask_bit = (0x80 >> (i_offset % 8));
+- inrow = indata + (height-j-1)*rowstride;
+- for (i = 0; i < width; i++)
+- {
+- colorrow[4*i+0] = inrow[4*i+2];
+- colorrow[4*i+1] = inrow[4*i+1];
+- colorrow[4*i+2] = inrow[4*i+0];
+- colorrow[4*i+3] = inrow[4*i+3];
+- if (inrow[4*i+3] == 0)
+- maskbyte[0] |= mask_bit; /* turn ON bit */
+- else
+- maskbyte[0] &= ~mask_bit; /* turn OFF bit */
+- mask_bit >>= 1;
+- if (mask_bit == 0)
+- {
+- mask_bit = 0x80;
+- maskbyte++;
+- }
+- }
+- }
+-
+- *color = hColorBitmap;
+- *mask = hMaskBitmap;
+-
+- return TRUE;
+-}
+-
+-static gboolean
+-pixbuf_to_hbitmaps_normal (GdkPixbuf *pixbuf,
+- HBITMAP *color,
+- HBITMAP *mask)
+-{
+- /* Based on code from
+- * http://www.dotnet247.com/247reference/msgs/13/66301.aspx
+- */
+- HBITMAP hColorBitmap, hMaskBitmap;
+- guchar *indata, *inrow;
+- guchar *colordata, *colorrow, *maskdata, *maskbyte;
+- gint width, height, size, i, i_offset, j, j_offset, rowstride, nc, bmstride;
+- gboolean has_alpha;
+- guint maskstride, mask_bit;
+-
+- width = gdk_pixbuf_get_width (pixbuf); /* width of icon */
+- height = gdk_pixbuf_get_height (pixbuf); /* height of icon */
+-
+- /* The bitmaps are created square */
+- size = MAX (width, height);
+-
+- hColorBitmap = create_color_bitmap (size, &colordata, 24);
+- if (!hColorBitmap)
+- return FALSE;
+- hMaskBitmap = create_color_bitmap (size, &maskdata, 1);
+- if (!hMaskBitmap)
+- {
+- DeleteObject (hColorBitmap);
+- return FALSE;
+- }
+-
+- /* rows are always aligned on 4-byte boundarys */
+- bmstride = size * 3;
+- if (bmstride % 4 != 0)
+- bmstride += 4 - (bmstride % 4);
+-
+- /* MSDN says mask rows are aligned to "LONG" boundaries */
+- maskstride = (((size + 31) & ~31) >> 3);
+-
+- indata = gdk_pixbuf_get_pixels (pixbuf);
+- rowstride = gdk_pixbuf_get_rowstride (pixbuf);
+- nc = gdk_pixbuf_get_n_channels (pixbuf);
+- has_alpha = gdk_pixbuf_get_has_alpha (pixbuf);
+-
+- if (width > height)
+- {
+- i_offset = 0;
+- j_offset = (width - height) / 2;
+- }
+- else
+- {
+- i_offset = (height - width) / 2;
+- j_offset = 0;
+- }
+-
+- for (j = 0; j < height; j++)
+- {
+- colorrow = colordata + (j+j_offset)*bmstride + 3*i_offset;
+- maskbyte = maskdata + (j+j_offset)*maskstride + i_offset/8;
+- mask_bit = (0x80 >> (i_offset % 8));
+- inrow = indata + (height-j-1)*rowstride;
+- for (i = 0; i < width; i++)
+- {
+- if (has_alpha && inrow[nc*i+3] < 128)
+- {
+- colorrow[3*i+0] = colorrow[3*i+1] = colorrow[3*i+2] = 0;
+- maskbyte[0] |= mask_bit; /* turn ON bit */
+- }
+- else
+- {
+- colorrow[3*i+0] = inrow[nc*i+2];
+- colorrow[3*i+1] = inrow[nc*i+1];
+- colorrow[3*i+2] = inrow[nc*i+0];
+- maskbyte[0] &= ~mask_bit; /* turn OFF bit */
+- }
+- mask_bit >>= 1;
+- if (mask_bit == 0)
+- {
+- mask_bit = 0x80;
+- maskbyte++;
+- }
+- }
+- }
+-
+- *color = hColorBitmap;
+- *mask = hMaskBitmap;
+-
+- return TRUE;
+-}
+-
+-static HICON
+-pixbuf_to_hicon (GdkPixbuf *pixbuf)
+-{
+- gint x = 0, y = 0;
+- gboolean is_icon = TRUE;
+- ICONINFO ii;
+- HICON icon;
+- gboolean success;
+-
+- if (pixbuf == NULL)
+- return NULL;
+-
+- if (_gdk_win32_pixbuf_to_hicon_supports_alpha() && gdk_pixbuf_get_has_alpha (pixbuf))
+- success = pixbuf_to_hbitmaps_alpha_winxp (pixbuf, &ii.hbmColor, &ii.hbmMask);
+- else
+- success = pixbuf_to_hbitmaps_normal (pixbuf, &ii.hbmColor, &ii.hbmMask);
+-
+- if (!success)
+- return NULL;
+-
+- ii.fIcon = is_icon;
+- ii.xHotspot = x;
+- ii.yHotspot = y;
+- icon = CreateIconIndirect (&ii);
+- DeleteObject (ii.hbmColor);
+- DeleteObject (ii.hbmMask);
+- return icon;
+-}
+-
+-static HICON load_hicon_from_stock(const char *stock) {
+- HICON hicon = NULL;
+- GdkPixbuf *pixbuf = gtk_widget_render_icon(image, stock,
+- gtk_icon_size_from_name(PIDGIN_ICON_SIZE_TANGO_EXTRA_SMALL), NULL);
+-
+- if (pixbuf) {
+- hicon = pixbuf_to_hicon(pixbuf);
+- g_object_unref(pixbuf);
+- } else
+- purple_debug_error("docklet", "Unable to load pixbuf for %s.\n", stock);
+-
+- return hicon;
+-}
+-
+-
+-static void systray_change_icon(HICON hicon) {
+- g_return_if_fail(hicon != NULL);
+-
+- _nicon_data.hIcon = hicon;
+- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
+-}
+-
+-static void systray_remove_nid(void) {
+- Shell_NotifyIconW(NIM_DELETE, &_nicon_data);
+-}
+-
+-static void winpidgin_tray_update_icon(PurpleStatusPrimitive status,
+- gboolean connecting, gboolean pending) {
+-
+- int icon_index;
+- g_return_if_fail(image != NULL);
+-
+- if(connecting)
+- icon_index = PURPLE_STATUS_NUM_PRIMITIVES;
+- else if(pending)
+- icon_index = PURPLE_STATUS_NUM_PRIMITIVES+1;
+- else
+- icon_index = status;
+-
+- g_return_if_fail(icon_index < (sizeof(cached_icons) / sizeof(HICON)));
+-
+- /* Look up and cache the HICON if we don't already have it */
+- if (cached_icons[icon_index] == NULL) {
+- const gchar *icon_name = NULL;
+- switch (status) {
+- case PURPLE_STATUS_OFFLINE:
+- icon_name = PIDGIN_STOCK_TRAY_OFFLINE;
+- break;
+- case PURPLE_STATUS_AWAY:
+- icon_name = PIDGIN_STOCK_TRAY_AWAY;
+- break;
+- case PURPLE_STATUS_UNAVAILABLE:
+- icon_name = PIDGIN_STOCK_TRAY_BUSY;
+- break;
+- case PURPLE_STATUS_EXTENDED_AWAY:
+- icon_name = PIDGIN_STOCK_TRAY_XA;
+- break;
+- case PURPLE_STATUS_INVISIBLE:
+- icon_name = PIDGIN_STOCK_TRAY_INVISIBLE;
+- break;
+- default:
+- icon_name = PIDGIN_STOCK_TRAY_AVAILABLE;
+- break;
+- }
+-
+- if (pending)
+- icon_name = PIDGIN_STOCK_TRAY_PENDING;
+- if (connecting)
+- icon_name = PIDGIN_STOCK_TRAY_CONNECT;
+-
+- g_return_if_fail(icon_name != NULL);
+-
+- cached_icons[icon_index] = load_hicon_from_stock(icon_name);
+- }
+-
+- systray_change_icon(cached_icons[icon_index]);
+-}
+-
+-static void winpidgin_tray_blank_icon() {
+- _nicon_data.hIcon = NULL;
+- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
+-}
+-
+-static void winpidgin_tray_set_tooltip(gchar *tooltip) {
+- const char *value = tooltip;
+- wchar_t *w;
+- if (value == NULL) {
+- value = PIDGIN_NAME;
+- }
+- w = g_utf8_to_utf16(value, -1, NULL, NULL, NULL);
+- wcsncpy(_nicon_data.szTip, w, sizeof(_nicon_data.szTip) / sizeof(wchar_t));
+- g_free(w);
+- Shell_NotifyIconW(NIM_MODIFY, &_nicon_data);
+-}
+-
+-static void winpidgin_tray_minimize(PidginBuddyList *gtkblist) {
+- MinimizeWndToTray(GDK_WINDOW_HWND(gtkblist->window->window));
+-}
+-
+-static void winpidgin_tray_maximize(PidginBuddyList *gtkblist) {
+- RestoreWndFromTray(GDK_WINDOW_HWND(gtkblist->window->window));
+-}
+-
+-
+-static void winpidgin_tray_create() {
+- OSVERSIONINFO osinfo;
+- /* dummy window to process systray messages */
+- systray_hwnd = systray_create_hiddenwin();
+-
+- dummy_window = gtk_window_new(GTK_WINDOW_POPUP);
+- dummy_button = gtk_button_new();
+- gtk_container_add(GTK_CONTAINER(dummy_window), dummy_button);
+-
+- /* We trigger the click event indirectly so that gtk_get_current_event_state() is TRUE when the event is handled */
+- g_signal_connect(G_OBJECT(dummy_button), "button-press-event",
+- G_CALLBACK(dummy_button_cb), NULL);
+-
+- image = gtk_image_new();
+- g_object_ref_sink(image);
+-
+- osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
+- GetVersionEx(&osinfo);
+-
+- /* Load icons, and init systray notify icon
+- * NOTE: Windows < XP only supports displaying 4-bit images in the Systray,
+- * 2K and ME will use the highest color depth that the desktop will support,
+- * but will scale it back to 4-bits for display.
+- * That is why we use custom 4-bit icons for pre XP Windowses */
+- if (osinfo.dwMajorVersion < 5 || (osinfo.dwMajorVersion == 5 && osinfo.dwMinorVersion == 0))
+- {
+- cached_icons[PURPLE_STATUS_OFFLINE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_OFFLINE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_AVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_AVAILABLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_AWAY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_EXTENDED_AWAY] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_XA_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_UNAVAILABLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_BUSY_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_NUM_PRIMITIVES] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_CONNECTING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_NUM_PRIMITIVES+1] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_PENDING_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- cached_icons[PURPLE_STATUS_INVISIBLE] = (HICON) LoadImage(winpidgin_dll_hinstance(),
+- MAKEINTRESOURCE(PIDGIN_TRAY_INVISIBLE_4BIT), IMAGE_ICON, 16, 16, LR_CREATEDIBSECTION);
+- }
+-
+- /* Create icon in systray */
+- systray_init_icon(systray_hwnd);
+-
+- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-hiding",
+- pidgin_docklet_get_handle(), PURPLE_CALLBACK(winpidgin_tray_minimize), NULL);
+- purple_signal_connect(pidgin_blist_get_handle(), "gtkblist-unhiding",
+- pidgin_docklet_get_handle(), PURPLE_CALLBACK(winpidgin_tray_maximize), NULL);
+-
+- purple_debug_info("docklet", "created\n");
+-}
+-
+-static void winpidgin_tray_destroy() {
+- int cached_cnt = sizeof(cached_icons) / sizeof(HICON);
+- systray_remove_nid();
+-
+- purple_signals_disconnect_by_handle(pidgin_docklet_get_handle());
+-
+- DestroyWindow(systray_hwnd);
+- pidgin_docklet_remove();
+-
+- while (--cached_cnt >= 0) {
+- if (cached_icons[cached_cnt] != NULL)
+- DestroyIcon(cached_icons[cached_cnt]);
+- cached_icons[cached_cnt] = NULL;
+- }
+-
+- g_object_unref(image);
+- image = NULL;
+-
+- gtk_widget_destroy(dummy_window);
+- dummy_button = NULL;
+- dummy_window = NULL;
+-}
+-
+-static struct docklet_ui_ops winpidgin_tray_ops =
+-{
+- winpidgin_tray_create,
+- winpidgin_tray_destroy,
+- winpidgin_tray_update_icon,
+- winpidgin_tray_blank_icon,
+- winpidgin_tray_set_tooltip,
+- NULL
+-};
+-
+-/* Used by docklet's plugin load func */
+-void docklet_ui_init() {
+- /* Initialize the cached icons to NULL */
+- ZeroMemory(cached_icons, sizeof(cached_icons));
+-
+- pidgin_docklet_set_ui_ops(&winpidgin_tray_ops);
+-}
+diff -Nur pidgin-2.10.7/pidgin/win32/gtkwin32dep.c pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.c
+--- pidgin-2.10.7/pidgin/win32/gtkwin32dep.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,562 +0,0 @@
+-/**
+- * @file gtkwin32dep.c UI Win32 Specific Functionality
+- * @ingroup win32
+- *
+- * Pidgin 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#define _WIN32_IE 0x500
+-#ifndef WINVER
+-#define WINVER 0x0500 /* W2K */
+-#endif
+-#include <windows.h>
+-#include <io.h>
+-#include <stdlib.h>
+-#include <stdio.h>
+-#include <winuser.h>
+-
+-#include <glib.h>
+-#include <glib/gstdio.h>
+-#include <gtk/gtk.h>
+-#include <gdk/gdkwin32.h>
+-
+-#include "internal.h"
+-
+-#include "debug.h"
+-#include "notify.h"
+-#include "network.h"
+-
+-#include "resource.h"
+-#include "zlib.h"
+-#include "untar.h"
+-
+-#include "gtkwin32dep.h"
+-#include "win32dep.h"
+-#include "gtkconv.h"
+-#include "gtkconn.h"
+-#include "util.h"
+-#ifdef USE_GTKSPELL
+-#include "wspell.h"
+-#endif
+-
+-/*
+- * GLOBALS
+- */
+-HINSTANCE exe_hInstance = 0;
+-HINSTANCE dll_hInstance = 0;
+-HWND messagewin_hwnd;
+-static int gtkwin32_handle;
+-
+-static gboolean pwm_handles_connections = TRUE;
+-
+-
+-/*
+- * PUBLIC CODE
+- */
+-
+-HINSTANCE winpidgin_exe_hinstance(void) {
+- return exe_hInstance;
+-}
+-
+-HINSTANCE winpidgin_dll_hinstance(void) {
+- return dll_hInstance;
+-}
+-
+-int winpidgin_gz_decompress(const char* in, const char* out) {
+- gzFile fin;
+- FILE *fout;
+- char buf[1024];
+- int ret;
+-
+- if((fin = gzopen(in, "rb"))) {
+- if(!(fout = g_fopen(out, "wb"))) {
+- purple_debug_error("winpidgin_gz_decompress", "Error opening file: %s\n", out);
+- gzclose(fin);
+- return 0;
+- }
+- }
+- else {
+- purple_debug_error("winpidgin_gz_decompress", "gzopen failed to open: %s\n", in);
+- return 0;
+- }
+-
+- while((ret = gzread(fin, buf, 1024))) {
+- if(fwrite(buf, 1, ret, fout) < ret) {
+- purple_debug_error("wpurple_gz_decompress", "Error writing %d bytes to file\n", ret);
+- gzclose(fin);
+- fclose(fout);
+- return 0;
+- }
+- }
+- fclose(fout);
+- gzclose(fin);
+-
+- if(ret < 0) {
+- purple_debug_error("winpidgin_gz_decompress", "gzread failed while reading: %s\n", in);
+- return 0;
+- }
+-
+- return 1;
+-}
+-
+-int winpidgin_gz_untar(const char* filename, const char* destdir) {
+- char tmpfile[_MAX_PATH];
+- char template[]="wpidginXXXXXX";
+-
+- sprintf(tmpfile, "%s%s%s", g_get_tmp_dir(), G_DIR_SEPARATOR_S, _mktemp(template));
+- if(winpidgin_gz_decompress(filename, tmpfile)) {
+- int ret;
+- if(untar(tmpfile, destdir, UNTAR_FORCE | UNTAR_QUIET))
+- ret = 1;
+- else {
+- purple_debug_error("winpidgin_gz_untar", "Failure untarring %s\n", tmpfile);
+- ret = 0;
+- }
+- g_unlink(tmpfile);
+- return ret;
+- }
+- else {
+- purple_debug_error("winpidgin_gz_untar", "Failed to gz decompress %s\n", filename);
+- return 0;
+- }
+-}
+-
+-void winpidgin_shell_execute(const char *target, const char *verb, const char *clazz) {
+-
+- SHELLEXECUTEINFOW wsinfo;
+- wchar_t *w_uri, *w_verb, *w_clazz = NULL;
+-
+- g_return_if_fail(target != NULL);
+- g_return_if_fail(verb != NULL);
+-
+- w_uri = g_utf8_to_utf16(target, -1, NULL, NULL, NULL);
+- w_verb = g_utf8_to_utf16(verb, -1, NULL, NULL, NULL);
+-
+- memset(&wsinfo, 0, sizeof(wsinfo));
+- wsinfo.cbSize = sizeof(wsinfo);
+- wsinfo.lpVerb = w_verb;
+- wsinfo.lpFile = w_uri;
+- wsinfo.nShow = SW_SHOWNORMAL;
+- wsinfo.fMask |= SEE_MASK_FLAG_NO_UI;
+- if (clazz != NULL) {
+- w_clazz = g_utf8_to_utf16(clazz, -1, NULL, NULL, NULL);
+- wsinfo.fMask |= SEE_MASK_CLASSNAME;
+- wsinfo.lpClass = w_clazz;
+- }
+-
+- if(!ShellExecuteExW(&wsinfo))
+- purple_debug_error("winpidgin", "Error opening URI: %s error: %d\n",
+- target, (int) wsinfo.hInstApp);
+-
+- g_free(w_uri);
+- g_free(w_verb);
+- g_free(w_clazz);
+-
+-}
+-
+-void winpidgin_notify_uri(const char *uri) {
+- /* Allow a few commonly used and "safe" schemes to go to the specific
+- * class handlers and send everything else to the default http browser.
+- * This isn't optimal, but should cover the most common cases. I didn't
+- * see any better secure solutions when I did some research.
+- */
+- gchar *scheme = g_uri_parse_scheme(uri);
+- if (scheme && (g_ascii_strcasecmp(scheme, "https") == 0
+- || g_ascii_strcasecmp(scheme, "ftp") == 0
+- || g_ascii_strcasecmp(scheme, "mailto") == 0))
+- winpidgin_shell_execute(uri, "open", scheme);
+- else
+- winpidgin_shell_execute(uri, "open", "http");
+- g_free(scheme);
+-}
+-
+-#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
+-#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
+-
+-static void*
+-winpidgin_netconfig_changed_cb(void *data)
+-{
+- pwm_handles_connections = FALSE;
+-
+- return NULL;
+-}
+-
+-static void*
+-winpidgin_get_handle(void)
+-{
+- static int handle;
+-
+- return &handle;
+-}
+-
+-static gboolean
+-winpidgin_pwm_reconnect()
+-{
+- purple_signal_disconnect(purple_network_get_handle(), "network-configuration-changed",
+- winpidgin_get_handle(), PURPLE_CALLBACK(winpidgin_netconfig_changed_cb));
+-
+- if (pwm_handles_connections == TRUE) {
+- PurpleConnectionUiOps *ui_ops = pidgin_connections_get_ui_ops();
+-
+- purple_debug_info("winpidgin", "Resumed from standby, reconnecting accounts.\n");
+-
+- if (ui_ops != NULL && ui_ops->network_connected != NULL)
+- ui_ops->network_connected();
+- } else {
+- purple_debug_info("winpidgin", "Resumed from standby, gtkconn will handle reconnecting.\n");
+- pwm_handles_connections = TRUE;
+- }
+-
+- return FALSE;
+-}
+-
+-static LRESULT CALLBACK message_window_handler(HWND hwnd, UINT msg, WPARAM wparam, LPARAM lparam) {
+-
+- if (msg == PIDGIN_WM_FOCUS_REQUEST) {
+- purple_debug_info("winpidgin", "Got external Buddy List focus request.");
+- purple_blist_set_visible(TRUE);
+- return TRUE;
+- } else if (msg == PIDGIN_WM_PROTOCOL_HANDLE) {
+- char *proto_msg = (char *) lparam;
+- purple_debug_info("winpidgin", "Got protocol handler request: %s\n", proto_msg ? proto_msg : "");
+- purple_got_protocol_handler_uri(proto_msg);
+- return TRUE;
+- } else if (msg == WM_POWERBROADCAST) {
+- if (wparam == PBT_APMQUERYSUSPEND) {
+- purple_debug_info("winpidgin", "Windows requesting permission to suspend.\n");
+- return TRUE;
+- } else if (wparam == PBT_APMSUSPEND) {
+- PurpleConnectionUiOps *ui_ops = pidgin_connections_get_ui_ops();
+-
+- purple_debug_info("winpidgin", "Entering system standby, disconnecting accounts.\n");
+-
+- if (ui_ops != NULL && ui_ops->network_disconnected != NULL)
+- ui_ops->network_disconnected();
+-
+- purple_signal_connect(purple_network_get_handle(), "network-configuration-changed", winpidgin_get_handle(),
+- PURPLE_CALLBACK(winpidgin_netconfig_changed_cb), NULL);
+-
+- return TRUE;
+- } else if (wparam == PBT_APMRESUMESUSPEND) {
+- purple_debug_info("winpidgin", "Resuming from system standby.\n");
+- /* TODO: It seems like it'd be wise to use the NLA message, if possible, instead of this. */
+- purple_timeout_add_seconds(1, winpidgin_pwm_reconnect, NULL);
+- return TRUE;
+- }
+- }
+-
+- return DefWindowProc(hwnd, msg, wparam, lparam);
+-}
+-
+-static HWND winpidgin_message_window_init(void) {
+- HWND win_hwnd;
+- WNDCLASSEX wcx;
+- LPCTSTR wname;
+-
+- wname = TEXT("WinpidginMsgWinCls");
+-
+- wcx.cbSize = sizeof(wcx);
+- wcx.style = 0;
+- wcx.lpfnWndProc = message_window_handler;
+- wcx.cbClsExtra = 0;
+- wcx.cbWndExtra = 0;
+- wcx.hInstance = winpidgin_exe_hinstance();
+- wcx.hIcon = NULL;
+- wcx.hCursor = NULL;
+- wcx.hbrBackground = NULL;
+- wcx.lpszMenuName = NULL;
+- wcx.lpszClassName = wname;
+- wcx.hIconSm = NULL;
+-
+- RegisterClassEx(&wcx);
+-
+- /* Create the window */
+- if(!(win_hwnd = CreateWindow(wname, TEXT("WinpidginMsgWin"), 0, 0, 0, 0, 0,
+- NULL, NULL, winpidgin_exe_hinstance(), 0))) {
+- purple_debug_error("winpidgin",
+- "Unable to create message window.\n");
+- return NULL;
+- }
+-
+- return win_hwnd;
+-}
+-
+-static gboolean stop_flashing(GtkWidget *widget, GdkEventFocus *event, gpointer data) {
+- GtkWindow *window = data;
+- gpointer handler_id;
+-
+- winpidgin_window_flash(window, FALSE);
+-
+- if ((handler_id = g_object_get_data(G_OBJECT(window), "flash_stop_handler_id"))) {
+- g_signal_handler_disconnect(G_OBJECT(window), (gulong) GPOINTER_TO_UINT(handler_id));
+- g_object_steal_data(G_OBJECT(window), "flash_stop_handler_id");
+- }
+-
+- return FALSE;
+-}
+-
+-void
+-winpidgin_window_flash(GtkWindow *window, gboolean flash) {
+- GdkWindow * gdkwin;
+- FLASHWINFO info;
+-
+- g_return_if_fail(window != NULL);
+-
+- gdkwin = GTK_WIDGET(window)->window;
+-
+- g_return_if_fail(GDK_IS_WINDOW(gdkwin));
+- g_return_if_fail(GDK_WINDOW_TYPE(gdkwin) != GDK_WINDOW_CHILD);
+-
+- if(GDK_WINDOW_DESTROYED(gdkwin))
+- return;
+-
+- memset(&info, 0, sizeof(FLASHWINFO));
+- info.cbSize = sizeof(FLASHWINFO);
+- info.hwnd = GDK_WINDOW_HWND(gdkwin);
+- if (flash) {
+- DWORD flashCount;
+- info.uCount = 3;
+- if (SystemParametersInfo(SPI_GETFOREGROUNDFLASHCOUNT, 0, &flashCount, 0))
+- info.uCount = flashCount;
+- info.dwFlags = FLASHW_ALL | FLASHW_TIMER;
+- } else
+- info.dwFlags = FLASHW_STOP;
+- FlashWindowEx(&info);
+- info.dwTimeout = 0;
+-
+-}
+-
+-void
+-winpidgin_conv_blink(PurpleConversation *conv, PurpleMessageFlags flags) {
+- PidginWindow *win;
+- GtkWindow *window;
+-
+- /* Don't flash for our own messages or system messages */
+- if(flags & PURPLE_MESSAGE_SEND || flags & PURPLE_MESSAGE_SYSTEM)
+- return;
+-
+- if(conv == NULL) {
+- purple_debug_info("winpidgin", "No conversation found to blink.\n");
+- return;
+- }
+-
+- win = pidgin_conv_get_window(PIDGIN_CONVERSATION(conv));
+- if(win == NULL) {
+- purple_debug_info("winpidgin", "No conversation windows found to blink.\n");
+- return;
+- }
+- window = GTK_WINDOW(win->window);
+-
+- /* Don't flash if the window is in the foreground */
+- if (GetForegroundWindow() == GDK_WINDOW_HWND(GTK_WIDGET(window)->window))
+- return;
+-
+- winpidgin_window_flash(window, TRUE);
+- /* Stop flashing when window receives focus */
+- if (g_object_get_data(G_OBJECT(window), "flash_stop_handler_id") == NULL) {
+- gulong handler_id = g_signal_connect(G_OBJECT(window), "focus-in-event",
+- G_CALLBACK(stop_flashing), window);
+- g_object_set_data(G_OBJECT(window), "flash_stop_handler_id", GUINT_TO_POINTER(handler_id));
+- }
+-}
+-
+-static gboolean
+-winpidgin_conv_im_blink(PurpleAccount *account, const char *who, char **message,
+- PurpleConversation *conv, PurpleMessageFlags flags, void *data)
+-{
+- if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/win32/blink_im"))
+- winpidgin_conv_blink(conv, flags);
+- return FALSE;
+-}
+-
+-void winpidgin_init(HINSTANCE hint) {
+- typedef void (__cdecl* LPFNSETLOGFILE)(const LPCSTR);
+- LPFNSETLOGFILE MySetLogFile;
+- gchar *exchndl_dll_path;
+-
+- purple_debug_info("winpidgin", "winpidgin_init start\n");
+-
+- exe_hInstance = hint;
+-
+- exchndl_dll_path = g_build_filename(wpurple_install_dir(), "exchndl.dll", NULL);
+- MySetLogFile = (LPFNSETLOGFILE) wpurple_find_and_loadproc(exchndl_dll_path, "SetLogFile");
+- g_free(exchndl_dll_path);
+- exchndl_dll_path = NULL;
+- if (MySetLogFile) {
+- gchar *debug_dir, *locale_debug_dir;
+-
+- debug_dir = g_build_filename(purple_user_dir(), "pidgin.RPT", NULL);
+- locale_debug_dir = g_locale_from_utf8(debug_dir, -1, NULL, NULL, NULL);
+-
+- purple_debug_info("winpidgin", "Setting exchndl.dll LogFile to %s\n", debug_dir);
+-
+- MySetLogFile(locale_debug_dir);
+-
+- g_free(debug_dir);
+- g_free(locale_debug_dir);
+- }
+-
+-#ifdef USE_GTKSPELL
+- winpidgin_spell_init();
+-#endif
+- purple_debug_info("winpidgin", "GTK+ :%u.%u.%u\n",
+- gtk_major_version, gtk_minor_version, gtk_micro_version);
+-
+- messagewin_hwnd = winpidgin_message_window_init();
+-
+- purple_debug_info("winpidgin", "winpidgin_init end\n");
+-}
+-
+-void winpidgin_post_init(void) {
+-
+- purple_prefs_add_none(PIDGIN_PREFS_ROOT "/win32");
+- purple_prefs_add_bool(PIDGIN_PREFS_ROOT "/win32/blink_im", TRUE);
+-
+- purple_signal_connect(pidgin_conversations_get_handle(),
+- "displaying-im-msg", &gtkwin32_handle, PURPLE_CALLBACK(winpidgin_conv_im_blink),
+- NULL);
+-
+-}
+-
+-/* Windows Cleanup */
+-
+-void winpidgin_cleanup(void) {
+- purple_debug_info("winpidgin", "winpidgin_cleanup\n");
+-
+- if(messagewin_hwnd)
+- DestroyWindow(messagewin_hwnd);
+-
+-}
+-
+-/* DLL initializer */
+-/* suppress gcc "no previous prototype" warning */
+-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved);
+-BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) {
+- dll_hInstance = hinstDLL;
+- return TRUE;
+-}
+-
+-static gboolean
+-get_WorkingAreaRectForWindow(HWND hwnd, RECT *workingAreaRc) {
+-
+- HMONITOR monitor;
+- MONITORINFO info;
+-
+- monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTOPRIMARY);
+-
+- info.cbSize = sizeof(info);
+- if(!GetMonitorInfo(monitor, &info))
+- return FALSE;
+-
+- CopyRect(workingAreaRc, &(info.rcWork));
+- return TRUE;
+-}
+-
+-void winpidgin_ensure_onscreen(GtkWidget *win) {
+- RECT winR, wAR, intR;
+- HWND hwnd = GDK_WINDOW_HWND(win->window);
+-
+- g_return_if_fail(hwnd != NULL);
+- GetWindowRect(hwnd, &winR);
+-
+- purple_debug_info("win32placement",
+- "Window RECT: L:%ld R:%ld T:%ld B:%ld\n",
+- winR.left, winR.right,
+- winR.top, winR.bottom);
+-
+- if(!get_WorkingAreaRectForWindow(hwnd, &wAR)) {
+- purple_debug_info("win32placement",
+- "Couldn't get multimonitor working area\n");
+- if(!SystemParametersInfo(SPI_GETWORKAREA, 0, &wAR, FALSE)) {
+- /* I don't think this will ever happen */
+- wAR.left = 0;
+- wAR.top = 0;
+- wAR.bottom = GetSystemMetrics(SM_CYSCREEN);
+- wAR.right = GetSystemMetrics(SM_CXSCREEN);
+- }
+- }
+-
+- purple_debug_info("win32placement",
+- "Working Area RECT: L:%ld R:%ld T:%ld B:%ld\n",
+- wAR.left, wAR.right,
+- wAR.top, wAR.bottom);
+-
+- /** If the conversation window doesn't intersect perfectly, move it to do so */
+- if(!(IntersectRect(&intR, &winR, &wAR)
+- && EqualRect(&intR, &winR))) {
+- purple_debug_info("win32placement",
+- "conversation window out of working area, relocating\n");
+-
+- /* Make sure the working area is big enough. */
+- if ((winR.right - winR.left) <= (wAR.right - wAR.left)
+- && (winR.bottom - winR.top) <= (wAR.bottom - wAR.top)) {
+- /* Is it off the bottom? */
+- if (winR.bottom > wAR.bottom) {
+- winR.top = wAR.bottom - (winR.bottom - winR.top);
+- winR.bottom = wAR.bottom;
+- }
+- /* Is it off the top? */
+- else if (winR.top < wAR.top) {
+- winR.bottom = wAR.top + (winR.bottom - winR.top);
+- winR.top = wAR.top;
+- }
+-
+- /* Is it off the left? */
+- if (winR.left < wAR.left) {
+- winR.right = wAR.left + (winR.right - winR.left);
+- winR.left = wAR.left;
+- }
+- /* Is it off the right? */
+- else if (winR.right > wAR.right) {
+- winR.left = wAR.right - (winR.right - winR.left);
+- winR.right = wAR.right;
+- }
+-
+- } else {
+- /* We couldn't salvage it; move it to the top left corner of the working area */
+- winR.right = wAR.left + (winR.right - winR.left);
+- winR.bottom = wAR.top + (winR.bottom - winR.top);
+- winR.left = wAR.left;
+- winR.top = wAR.top;
+- }
+-
+- purple_debug_info("win32placement",
+- "Relocation RECT: L:%ld R:%ld T:%ld B:%ld\n",
+- winR.left, winR.right,
+- winR.top, winR.bottom);
+-
+- MoveWindow(hwnd, winR.left, winR.top,
+- (winR.right - winR.left),
+- (winR.bottom - winR.top), TRUE);
+- }
+-
+-}
+-
+-DWORD winpidgin_get_lastactive() {
+- DWORD result = 0;
+-
+- LASTINPUTINFO lii;
+- memset(&lii, 0, sizeof(lii));
+- lii.cbSize = sizeof(lii);
+- if (GetLastInputInfo(&lii))
+- result = lii.dwTime;
+-
+- return result;
+-}
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/gtkwin32dep.h pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.h
+--- pidgin-2.10.7/pidgin/win32/gtkwin32dep.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/gtkwin32dep.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,50 +0,0 @@
+-/**
+- * @file gtkwin32dep.h UI Win32 Specific Functionality
+- * @ingroup win32
+- *
+- * Pidgin 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
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- */
+-#ifndef _GTKWIN32DEP_H_
+-#define _GTKWIN32DEP_H_
+-#include <windows.h>
+-#include <gtk/gtk.h>
+-#include "conversation.h"
+-
+-HINSTANCE winpidgin_dll_hinstance(void);
+-HINSTANCE winpidgin_exe_hinstance(void);
+-
+-/* Utility */
+-int winpidgin_gz_decompress(const char* in, const char* out);
+-int winpidgin_gz_untar(const char* filename, const char* destdir);
+-
+-/* Misc */
+-void winpidgin_notify_uri(const char *uri);
+-void winpidgin_shell_execute(const char *target, const char *verb, const char *clazz);
+-void winpidgin_ensure_onscreen(GtkWidget *win);
+-void winpidgin_conv_blink(PurpleConversation *conv, PurpleMessageFlags flags);
+-void winpidgin_window_flash(GtkWindow *window, gboolean flash);
+-DWORD winpidgin_get_lastactive(void);
+-
+-/* init / cleanup */
+-void winpidgin_init(HINSTANCE);
+-void winpidgin_post_init(void);
+-void winpidgin_cleanup(void);
+-
+-#endif /* _GTKWIN32DEP_H_ */
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/MinimizeToTray.c pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.c
+--- pidgin-2.10.7/pidgin/win32/MinimizeToTray.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,119 +0,0 @@
+-/* MinimizeToTray
+- *
+- * A couple of routines to show how to make it produce a custom caption
+- * animation to make it look like we are minimizing to and maximizing
+- * from the system tray
+- *
+- * These routines are public domain, but it would be nice if you dropped
+- * me a line if you use them!
+- *
+- * 1.0 29.06.2000 Initial version
+- * 1.1 01.07.2000 The window retains it's place in the Z-order of windows
+- * when minimized/hidden. This means that when restored/shown, it doesn't
+- * always appear as the foreground window unless we call SetForegroundWindow
+- *
+- * Copyright 2000 Matthew Ellis <m.t.ellis@bigfoot.com>
+- */
+-#define _WIN32_WINNT 0x0500
+-#include <windows.h>
+-#include "MinimizeToTray.h"
+-
+-#define DEFAULT_RECT_WIDTH 150
+-#define DEFAULT_RECT_HEIGHT 30
+-
+-static void GetTrayWndRect(LPRECT lpTrayRect) {
+- APPBARDATA appBarData;
+- HWND hShellTrayWnd = FindWindowEx(NULL, NULL, TEXT("Shell_TrayWnd"),
+- NULL);
+-
+- if(hShellTrayWnd) {
+- HWND hTrayNotifyWnd = FindWindowEx(hShellTrayWnd, NULL,
+- TEXT("TrayNotifyWnd"), NULL);
+-
+- if(hTrayNotifyWnd) {
+- GetWindowRect(hTrayNotifyWnd,lpTrayRect);
+- return;
+- }
+- }
+-
+- appBarData.cbSize = sizeof(appBarData);
+- if(SHAppBarMessage(ABM_GETTASKBARPOS, &appBarData)) {
+- switch(appBarData.uEdge) {
+- case ABE_LEFT:
+- case ABE_RIGHT:
+- lpTrayRect->top = appBarData.rc.bottom - 100;
+- lpTrayRect->bottom = appBarData.rc.bottom - 16;
+- lpTrayRect->left = appBarData.rc.left;
+- lpTrayRect->right = appBarData.rc.right;
+- break;
+- case ABE_TOP:
+- case ABE_BOTTOM:
+- lpTrayRect->top = appBarData.rc.top;
+- lpTrayRect->bottom = appBarData.rc.bottom;
+- lpTrayRect->left = appBarData.rc.right - 100;
+- lpTrayRect->right = appBarData.rc.right - 16;
+- break;
+- }
+- return;
+- }
+-
+- hShellTrayWnd = FindWindowEx(NULL, NULL, TEXT("Shell_TrayWnd"), NULL);
+- if(hShellTrayWnd) {
+- GetWindowRect(hShellTrayWnd, lpTrayRect);
+- if(lpTrayRect->right-lpTrayRect->left > DEFAULT_RECT_WIDTH)
+- lpTrayRect->left = lpTrayRect->right - DEFAULT_RECT_WIDTH;
+- if(lpTrayRect->bottom-lpTrayRect->top > DEFAULT_RECT_HEIGHT)
+- lpTrayRect->top=lpTrayRect->bottom - DEFAULT_RECT_HEIGHT;
+-
+- return;
+- }
+-
+- SystemParametersInfo(SPI_GETWORKAREA, 0, lpTrayRect, 0);
+- lpTrayRect->left = lpTrayRect->right - DEFAULT_RECT_WIDTH;
+- lpTrayRect->top = lpTrayRect->bottom - DEFAULT_RECT_HEIGHT;
+-}
+-
+-static BOOL GetDoAnimateMinimize(void) {
+- ANIMATIONINFO ai;
+-
+- ai.cbSize = sizeof(ai);
+- SystemParametersInfo(SPI_GETANIMATION, sizeof(ai), &ai, 0);
+-
+- return ai.iMinAnimate ? TRUE : FALSE;
+-}
+-
+-void MinimizeWndToTray(HWND hWnd) {
+-
+- if(!IsWindowVisible(hWnd))
+- return;
+-
+- if(GetDoAnimateMinimize()) {
+- RECT rcFrom, rcTo;
+-
+- GetWindowRect(hWnd, &rcFrom);
+- GetTrayWndRect(&rcTo);
+-
+- DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
+- }
+-
+- ShowWindow(hWnd, SW_HIDE);
+-}
+-
+-void RestoreWndFromTray(HWND hWnd) {
+-
+- if(IsWindowVisible(hWnd))
+- return;
+-
+- if(GetDoAnimateMinimize()) {
+- RECT rcFrom, rcTo;
+- GetTrayWndRect(&rcFrom);
+- GetWindowRect(hWnd, &rcTo);
+-
+- DrawAnimatedRects(hWnd, IDANI_CAPTION, &rcFrom, &rcTo);
+- }
+-
+- ShowWindow(hWnd, SW_SHOW);
+- SetActiveWindow(hWnd);
+- SetForegroundWindow(hWnd);
+-}
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/MinimizeToTray.h pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.h
+--- pidgin-2.10.7/pidgin/win32/MinimizeToTray.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/MinimizeToTray.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,7 +0,0 @@
+-#ifndef _MINIMIZE_TO_TRAY_H_
+-#define _MINIMIZE_TO_TRAY_H_
+-
+-void MinimizeWndToTray(HWND hWnd);
+-void RestoreWndFromTray(HWND hWnd);
+-
+-#endif /* _MINIMIZE_TO_TRAY_H_ */
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/available.lst pidgin-2.10.7-nonprism/pidgin/win32/nsis/available.lst
+--- pidgin-2.10.7/pidgin/win32/nsis/available.lst 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/available.lst 1969-12-31 21:00:00.000000000 -0300
+@@ -1,100 +0,0 @@
+-#This file is from ftp://ftp.services.openoffice.org/pub/OpenOffice.org/contrib/dictionaries/available.lst
+-af,ZA,af_ZA,Afrikaans (South Africa),af_ZA.zip
+-ak,GH,ak_GH,Akan (Ghana),ak_GH.zip
+-sq,AL,sq_AL,Albanian (Albania),sq_AL.zip
+-bg,BG,bg_BG,Bulgarian (Bulgaria),bg_BG.zip
+-ca,ES,ca_ES,Catalan (Spain),ca_ES.zip
+-cop,EG,cop_EG,Coptic (Egypt),cop_EG.zip
+-hr,HR,hr_HR,Croatian (Croatia),hr_HR.zip
+-cs,CZ,cs_CZ,Czech (Czech Republic),cs_CZ.zip
+-da,DK,da_DK,Danish (Denmark),da_DK.zip
+-nl,NL,nl_NL,Dutch (Netherlands),nl_NL.zip
+-nl,NL,nl_med,Dutch Medical (Netherlands),nl_med.zip
+-en,AU,en_AU,English (Australia),en_AU.zip
+-en,CA,en_CA,English (Canada),en_CA.zip
+-en,NZ,en_NZ,English (New Zealand),en_NZ.zip
+-en,ZA,en_ZA,English (South Africa),en_ZA.zip
+-en,GB,en_GB,English (United Kingdom),en_GB.zip
+-en,US,en_US,English (United States),en_US.zip
+-eo,ANY,eo_l3,Esperanto,eo.zip
+-et,EE,et_EE,Estonian (Estonia),et_EE.zip
+-fo,FO,fo_FO,Faroese (Faroe Islands),fo_FO.zip
+-fr,FR,fr_FR-classique,Franais Classique,fr_FR-classique_1-3-2.zip
+-fr,FR,fr_FR-1990,Franais Rforme 1990,fr_FR-1990_1-3-2.zip
+-fr,FR,fr_FR,Franais Rforme 1990 & Classique,fr_FR_1-3-2.zip
+-fy,NL,fy_NL,Frisian (Netherlands),fy_NL.zip
+-gl,ES,gl_ES,Galician (Spain),gl_ES.zip
+-gsc,FR,gsc_FR,Gascon (France),gsc_FR.zip
+-de,AT,de_AT,German (Austria Extension),de_AT.zip
+-de,AT,de_AT_frami,German (Austria) neu 08/2006 (frami),de_AT_frami.zip
+-de,DE,de_DE,German (Germany),de_DE.zip
+-de,DE,de_DE_frami,German (Germany) neu 08/2006 (frami),de_DE_frami.zip
+-de,CH,de_CH,German (Switzerland),de_CH.zip
+-de,CT,de_CH_frami,German (Switzerland) neu 08/2006 (frami),de_CH_frami.zip
+-el,GR,el_GR,Greek (Greece),el_GR.zip
+-gu,IN,gu_IN,Gujarati (India),gu_IN.zip
+-he,IL,he_IL,Hebrew (Israel),he_IL.zip
+-hil,PH,hil_PH,Hiligaynon (Philippines),hil_PH.zip
+-hu,HU,hu_HU,Hungarian (Hungary),hu_HU.zip
+-hu,HU,hu_HU_comb,Hungarian (Hungary) collected compounds,hu_HU_comb.zip
+-id,ID,id_ID,Indonesian (Indonesia),id_ID.zip
+-ga,IE,ga_IE,Irish (Ireland),ga_IE.zip
+-it,IT,it_IT,Italian (Italy),it_IT.zip
+-sw,KE,sw_KE,Kiswahili (Africa),sw_KE.zip
+-ku,TR,ku_TR,Kurdish (Turkey),ku_TR.zip
+-it,IT,la,Latin,la.zip
+-lv,LV,lv_LV,Latvian (Latvia),lv_LV.zip
+-lt,LT,lt_LT,Lithuanian (Lithuania),lt_LT.zip
+-mk,MK,mk_MK,Macedonian (Macedonia),mk_MK.zip
+-ms,MY,ms_MY,Malay (Malaysia),ms_MY.zip
+-mi,NZ,mi_NZ,Maori (New Zealand),mi_NZ.zip
+-mr,IN,mr_IN,Marathi (India),mr_IN.zip
+-mos,BF,mos_BF,Moore,ms_BF.zip
+-nr,ZA,nr_ZA,Ndebele (South Africa),nr_ZA.zip
+-ne,NP,ne_NP,Nepali (Nepal),ne_NP.zip
+-ns,ZA,ns_ZA,Northern Sotho (South Africa),ns_ZA.zip
+-nb,NO,nb_NO,Norwegian Bokmaal (Norway),nb_NO.zip
+-nn,NO,nn_NO,Norwegian Nynorsk (Norway),nn_NO.zip
+-oc,FR,oc_FR,Occitan (Languedoc),oc_FR.zip
+-pl,PL,pl_PL,Polish (Poland),pl_PL.zip
+-pt,BR,pt_BR,Portuguese (Brazil),pt_BR.zip
+-pt,PT,pt_PT,Portuguese (Portugal),pt_PT.zip
+-ro,RO,ro_RO,Romanian (Romania),ro_RO.zip
+-ru,RU,ru_RU,Russian (Russia),ru_RU.zip
+-ru,RU,ru_RU_ye,Russian_ye (Russia),ru_RU_ye.zip
+-ru,RU,ru_RU_yo,Russian_yo (Russia),ru_RU_yo.zip
+-gd,GB,gd_GB,Scots Gaelic (Scotland),gd_GB.zip
+-tn,ZA,tn_ZA,Setswana (Africa),tn_ZA.zip
+-sk,SK,sk_SK,Slovak (Slovakia),sk_SK.zip
+-sl,SI,sl_SI,Slovenian (Slovenia),sl_SI.zip
+-st,ZA,st_ZA,Southern Sotho (South Africa),st_ZA.zip
+-es,AR,es_AR,Spanish (Argentina),es_AR.zip
+-es,BZ,es_HN,Spanish (Belize),es_HN.zip
+-es,BO,es_BO,Spanish (Bolivia),es_BO.zip
+-es,CL,es_CL,Spanish (Chile),es_CL.zip
+-es,CO,es_CO,Spanish (Colombia),es_CO.zip
+-es,CR,es_CR,Spanish (Costa Rica),es_CR.zip
+-es,CU,es_CU,Spanish (Cuba),es_CU.zip
+-es,DO,es_DO,Spanish (Dominican Republic),es_DO.zip
+-es,EC,es_EC,Spanish (Ecuador),es_EC.zip
+-es,SV,es_SV,Spanish (El Salvador),es_SV.zip
+-es,GT,es_GT,Spanish (Guatemala),es_GT.zip
+-es,MX,es_MX,Spanish (Mexico),es_MX.zip
+-es,NI,es_NI,Spanish (Nicaragua),es_NI.zip
+-es,PA,es_PA,Spanish (Panama),es_PA.zip
+-es,PY,es_PY,Spanish (Paraguay),es_PY.zip
+-es,PE,es_PE,Spanish (Peru),es_PE.zip
+-es,PR,es_PR,Spanish (Puerto Rico),es_PR.zip
+-es,ES,es_ES,Spanish (Spain),es_ES.zip
+-es,UY,es_UY,Spanish (Uruguay),es_UY.zip
+-es,VE,es_VE,Spanish (Venezuela),es_VE.zip
+-ss,ZA,ss_ZA,Swati (South Africa),ss_ZA.zip
+-sv,SE,sv_SE,Swedish (Sweden),sv_SE.zip
+-ts,ZA,ts_ZA,Tsonga (South Africa),ts_ZA.zip
+-uk,UA,uk_UA,Ukrainian (Ukraine),uk_UA.zip
+-ur,PK,ur_PK,Urdu,ur_PK.zip
+-ve,ZA,ve_ZA,Venda (South Africa),ve_ZA.zip
+-vi,VN,vi_VN,Vietnamese (Viet-Nam),vi_VN.zip
+-cy,GB,cy_GB,Welsh (Wales),cy_GB.zip
+-xh,ZA,xh_ZA,Xhosa (South Africa),xh_ZA.zip
+-zu,ZA,zu_ZA,Zulu (South Africa),zu_ZA.zip
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/create_nsis_translations.pl pidgin-2.10.7-nonprism/pidgin/win32/nsis/create_nsis_translations.pl
+--- pidgin-2.10.7/pidgin/win32/nsis/create_nsis_translations.pl 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/create_nsis_translations.pl 1969-12-31 21:00:00.000000000 -0300
+@@ -1,390 +0,0 @@
+-#!/usr/bin/perl
+-#
+-# create_nsis_translations.pl
+-#
+-# Copyright (C) 2000-2009 Bruno Coudoin
+-#
+-# 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 3 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, see <http://www.gnu.org/licenses/>.
+-#
+-
+-use strict;
+-
+-sub usage {
+- print 'create_nsis_translations.pl translations installer tmp_dir
+- translations
+- This is an input file that contains all the
+- translated strings. If must be formated as a GNU/Linux
+- desktop file and contains multiple strings entry.
+- For example you must have:
+- toBe=To be or not to be
+- toBe[fr]=Etre ou ne pas etre
+-
+- installer
+- This is your nsis installer source file. You must include
+- in it the marker @INSERT_TRANSLATIONS@ before you use any
+- translation string.
+- After that you can use the variable $(toBe) in your file.
+-
+- tmp_dir
+- This is a directory in which temporary files needed for
+- the translation system.
+- It will be created if non existant.
+- You can remove it once you have created your installer.
+-';
+-}
+-
+-my $translations;
+-if (! $ARGV[0] || ! -f $ARGV[0])
+-{
+- usage();
+-}
+-else
+-{
+- $translations = $ARGV[0];
+-}
+-
+-shift;
+-my $installer;
+-if (! $ARGV[0] || ! -f $ARGV[0])
+-{
+- usage();
+-}
+-else
+-{
+- $installer = $ARGV[0];
+-}
+-
+-shift;
+-my $tmp_dir;
+-if (! $ARGV[0] )
+-{
+- usage();
+-}
+-else
+-{
+- $tmp_dir = $ARGV[0];
+-
+- if ( ! -d $tmp_dir )
+- {
+- mkdir $tmp_dir or die "ERROR: '$tmp_dir' $!\n";
+- }
+-}
+-
+-print "Processing translation file '$translations'\n";
+-print " NSIS source file '$installer'\n";
+-print " Working dir '$tmp_dir'\n";
+-
+-# Commented out locales that are not available in nsis
+-# Map value is ["NSISFilename", "Encoding", "LCID"]
+-my %localeNames = (
+- "af" => ["Afrikaans", "WINDOWS-1252", "1078"],
+-# "am" => ["Amharic", "UTF-8"],
+- "ar" => ["Arabic", "WINDOWS-1256", "1025"],
+- "be" => ["Belarusian", "WINDOWS-1251", "1059"],
+- "bg" => ["Bulgarian", "WINDOWS-1251", "1026"],
+- "bs" => ["Bosnian", "WINDOWS-1250", "5146"],
+- "br" => ["Breton", "WINDOWS-1252", "1150"],
+- "ca" => ["Catalan", "WINDOWS-1252", "1027"],
+- "cs" => ["Czech", "WINDOWS-1250", "1029"],
+- "cy" => ["Welsh", "WINDOWS-1252", "1160"],
+- "da" => ["Danish", "WINDOWS-1252", "1030"],
+- "de" => ["German", "WINDOWS-1252", "1031"],
+-# "dz" => ["Dzongkha", "UTF-8"],
+- "el" => ["Greek", "WINDOWS-1253", "1032"],
+- "en" => ["English", "WINDOWS-1252", "1033"],
+- "eo" => ["Esperanto", "WINDOWS-1252", "9998"],
+- "es" => ["Spanish", "WINDOWS-1252", "1034"],
+- "et" => ["Estonian", "WINDOWS-1257", "1061"],
+- "eu" => ["Basque", "WINDOWS-1252", "1069"],
+- "fa" => ["Farsi", "WINDOWS-1256", "1065"],
+- "fi" => ["Finnish", "WINDOWS-1252", "1035"],
+- "fr" => ["French", "WINDOWS-1252", "1036"],
+- "ga" => ["Irish", "WINDOWS-1252", "2108"],
+- "gl" => ["Galician", "WINDOWS-1252", "1110"],
+-# "gu" => ["Gujarati", "UTF-8"],
+- "he" => ["Hebrew", "WINDOWS-1255", "1037"],
+-# "hi" => ["Hindi", "UTF-8"],
+- "hr" => ["Croatian", "WINDOWS-1250", "1050"],
+- "hu" => ["Hungarian", "WINDOWS-1250", "1038"],
+- "id" => ["Indonesian", "WINDOWS-1252", "1057"],
+- "is" => ["Icelandic", "WINDOWS-1252", "15"], #This should be 1039!
+- "it" => ["Italian", "WINDOWS-1252", "1040"],
+- "ja" => ["Japanese", "CP932", "1041"],
+-# "ka" => ["Georgian", "UTF-8"],
+- "ko" => ["Korean", "CP949", "1042"],
+- "ku" => ["Kurdish", "WINDOWS-1254", "9999"],
+- "lb" => ["Luxembourgish", "WINDOWS-1252", "4103"],
+- "lt" => ["Lithuanian", "WINDOWS-1257", "1063"],
+- "lv" => ["Latvian", "WINDOWS-1257", "1062"],
+- "mk" => ["Macedonian", "WINDOWS-1251", "1071"],
+-# "ml" => ["Malayalam", "UTF-8"],
+-# "mr" => ["Marathi", "UTF-8"],
+- "mn" => ["Mongolian", "WINDOWS-1251", "1104"],
+- "ms" => ["Malay", "WINDOWS-1252", "1086"],
+- "nb" => ["Norwegian", "WINDOWS-1252", "1044"],
+-# "ne" => ["Nepal", "UTF-8"],
+- "nl" => ["Dutch", "WINDOWS-1252", "1043"],
+- "nn" => ["NorwegianNynorsk", "WINDOWS-1252", "2068"],
+-# "oc" => ["Occitan", "WINDOWS-1252"],
+-# "pa" => ["Punjabi", "UTF-8"],
+- "pl" => ["Polish", "WINDOWS-1250", "1045"],
+- "pt" => ["Portuguese", "WINDOWS-1252", "2070"],
+- "pt_BR" => ["PortugueseBR", "WINDOWS-1252", "1046"],
+- "ro" => ["Romanian", "WINDOWS-1250", "1048"],
+- "ru" => ["Russian", "WINDOWS-1251", "1049"],
+-# "rw" => ["Kinyarwanda", "UTF-8"],
+- "sk" => ["Slovak", "WINDOWS-1250", "1051"],
+- "sl" => ["Slovenian", "WINDOWS-1250", "1060"],
+-# "so" => ["Somali", "UTF-8"],
+- "sq" => ["Albanian", "WINDOWS-1252", "1052"],
+- "sr" => ["Serbian", "WINDOWS-1251", "3098"],
+- "sr\@latin" => ["SerbianLatin", "WINDOWS-1250", "2074"],
+- "sv" => ["Swedish", "WINDOWS-1252", "1053"],
+-# "ta" => ["Tamil", "UTF-8"],
+- "th" => ["Thai", "WINDOWS-874", "1054"],
+- "tr" => ["Turkish", "WINDOWS-1254", "1055"],
+- "uk" => ["Ukrainian", "WINDOWS-1251", "1058"],
+- "uz" => ["Uzbek", "WINDOWS-1252", "1091"],
+-# "ur" => ["Urdu", "UTF-8"],
+-# "vi" => ["Vietnamese", "WINDOWS-1258"],
+-# "wa" => ["Walloon", "WINDOWS-1252"],
+- "zh_CN" => ["SimpChinese", "WINDOWS-936", "2052"],
+- "zh_TW" => ["TradChinese", "CP950", "1028"],
+-);
+-
+-my @localeKeys = keys(%localeNames);
+-
+-# Create the holder for the results
+-# %result{"locale"}{"stringname"} = result line
+-print "Parsing nsis_translations.desktop\n";
+-my %result;
+-
+-# Create a hash of the keys to translate
+-open (MYFILE, $translations);
+-while (<MYFILE>) {
+- chomp $_;
+- if ($_ =~ /Encoding=UTF-8/)
+- {
+- next;
+- }
+- elsif ($_ =~ /^(\w+)=(.*)/)
+- {
+- my $line = "!define $1 \"$2\"\n";
+- $result{"en"}{"$1"} = $line;
+- }
+- elsif ($_ =~ /^(\w+)\[(\w+)\]=(.*)/)
+- {
+- my $line = "!define $1 \"$3\"\n";
+- $result{"$2"}{"$1"} = $line;
+- }
+-}
+-close (MYFILE);
+-
+-# Lets insert the default languages
+-# in the installer file which means replacing:
+-# @INSERTMACRO_MUI_LANGUAGE@
+-# By the list of locales:
+-# !insertmacro MUI_LANGUAGE "French"
+-
+-my $muiLanguages;
+-$muiLanguages = '
+- ;; English goes first because its the default. The rest are
+- ;; in alphabetical order (at least the strings actually displayed
+- ;; will be).
+- !insertmacro MUI_LANGUAGE "English"
+-';
+-
+-# The specific GCompris translation for the installer
+-# replacing:
+-# @GCOMPRIS_MACRO_INCLUDE_LANGFILE@
+-# By the list of locales:
+-# !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE "ALBANIAN" "${GCOMPRIS_NSIS_INCLUDE_PATH}\translations\albanian.nsh"
+-
+-my $gcomprisLanguages;
+-
+-$gcomprisLanguages .= '
+-;--------------------------------
+-;Translations
+- !define GCOMPRIS_DEFAULT_LANGFILE "${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\en.nsh"
+-;;
+-;; Windows GCompris NSIS installer language macros
+-;;
+-
+-!macro GCOMPRIS_MACRO_DEFAULT_STRING LABEL VALUE
+- !ifndef "${LABEL}"
+- !define "${LABEL}" "${VALUE}"
+- !ifdef INSERT_DEFAULT
+- !warning "${LANG} lang file missing ${LABEL}, using default..."
+- !endif
+- !endif
+-!macroend
+-
+-!macro GCOMPRIS_MACRO_LANGSTRING_INSERT LABEL LANG
+- LangString "${LABEL}" "${LANG_${LANG}}" "${${LABEL}}"
+- !undef "${LABEL}"
+-!macroend
+-
+-!macro GCOMPRIS_MACRO_LANGUAGEFILE_BEGIN LANG
+- !define CUR_LANG "${LANG}"
+-!macroend
+-';
+-
+-
+-# GCOMPRIS_MACRO_LANGUAGEFILE_END
+-$gcomprisLanguages .= '
+-!macro GCOMPRIS_MACRO_LANGUAGEFILE_END
+- !define INSERT_DEFAULT
+- !include "${GCOMPRIS_DEFAULT_LANGFILE}"
+- !undef INSERT_DEFAULT
+-
+- ; String labels should match those from the default language file.
+-';
+-
+-my $text_en = $result{"en"};
+-foreach my $keyEn (keys(%$text_en)) {
+- $gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_LANGSTRING_INSERT $keyEn \${CUR_LANG}";
+- $gcomprisLanguages .= "\n";
+-}
+-
+-$gcomprisLanguages .= '
+- !undef CUR_LANG
+-!macroend
+-';
+-
+-$gcomprisLanguages .= '
+-!macro GCOMPRIS_MACRO_INCLUDE_LANGFILE LANG FILE
+- !insertmacro GCOMPRIS_MACRO_LANGUAGEFILE_BEGIN "${LANG}"
+- !include "${FILE}"
+- !insertmacro GCOMPRIS_MACRO_LANGUAGEFILE_END
+-!macroend
+-';
+-
+-#
+-# Create each nsh translation file
+-#
+-
+-print "Creating the nsh default file\n";
+-open (DESC, ">$tmp_dir/en.nsh");
+-print DESC ";; Auto generated file by create_nsis_translations.pl\n";
+-foreach my $keyEn (keys(%$text_en)) {
+- my $line = $result{'en'}{$keyEn};
+- $line =~ s/!define /!insertmacro GCOMPRIS_MACRO_DEFAULT_STRING /;
+- print DESC $line;
+-}
+-close DESC;
+-
+-$gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE".
+- " \"ENGLISH\"".
+- " \"\${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\en.nsh\"\n";
+-
+-my $selectTranslationFunction = '
+-!macro SELECT_TRANSLATION_SECTION LANG_NAME LANG_CODE
+- StrCmp "$LANGUAGE" "${LANG_${LANG_NAME}}" 0 end_${LANG_CODE}
+- !insertmacro SelectSection ${SecLang_${LANG_CODE}}
+- Goto done
+- end_${LANG_CODE}:
+-!macroend
+-; Convert the current $LANGUAGE to a language code that we can use for translation mo selection
+-; If there\'s a better way to do this, I\'d love to know it
+-!macro SELECT_TRANSLATION_FUNCTION
+-';
+-
+-#
+-# Two pass are needed:
+-# - create the utf8 file
+-# - transform it to the proper windows locale
+-#
+-print "Creating the nsh locale files\n";
+-foreach my $lang (@localeKeys) {
+- if ( $lang eq "en" ) { next; }
+- open (DESC, ">$tmp_dir/$lang.nsh.utf8");
+- print DESC ";; Auto generated file by create_nsis_translations.pl\n";
+- print DESC ";; Code Page: $localeNames{$lang}[1]\n";
+-
+- my $text_locale = $result{"$lang"};
+- my $total_key_count = 0;
+- my $found_key_count = 0;
+- foreach my $keyEn (keys(%$text_en)) {
+- my $found = 0;
+- $total_key_count++;
+- foreach my $keyLocale (keys(%$text_locale)) {
+- # Fine, we found a translation
+- if ( $keyLocale eq $keyEn )
+- {
+- print DESC "$result{$lang}{$keyLocale}";
+- $found = 1;
+- $found_key_count++;
+- last;
+- }
+- }
+- # English keys are the reference.
+- # If not found they are inserted
+- #if ( ! $found )
+- #{
+- # print DESC "$result{'en'}{$keyEn}";
+- #}
+- }
+- close DESC;
+-
+- # If we have at least 50% of the keys found, include the language
+- if (($found_key_count * 1.0 / $total_key_count) >= 0.5) {
+- $muiLanguages .= " !insertmacro MUI_LANGUAGE \"$localeNames{$lang}[0]\"\n";
+- $gcomprisLanguages .= " !insertmacro GCOMPRIS_MACRO_INCLUDE_LANGFILE".
+- " \"". uc($localeNames{$lang}[0]) . "\"".
+- " \"\${GCOMPRIS_NSIS_INCLUDE_PATH}\\translations\\$lang.nsh\"\n";
+- $selectTranslationFunction .= " !insertmacro SELECT_TRANSLATION_SECTION".
+- " \"" . uc($localeNames{$lang}[0]) . "\" \"$lang\"\n";
+- } else {
+- print "Ignoring language $lang because it is less than 50% translated ($found_key_count of $total_key_count).\n";
+- next;
+- }
+-
+-
+- # iconv conversion
+- system("iconv -f UTF-8 -t $localeNames{$lang}[1] $tmp_dir/$lang.nsh.utf8 > $tmp_dir/$lang.nsh");
+- if ($? ne 0)
+- {
+- die("ERROR: Failed to run: iconv -f UTF-8 -t $localeNames{$lang}[1] $lang.nsh.utf8 > $lang.nsh\n");
+- }
+- #`rm $tmp_dir/$lang.nsh.utf8`;
+-
+-}
+-
+-$selectTranslationFunction .= '
+-done:
+-!macroend
+-';
+-
+-# We have all the data, let's replace it
+-my $gcomprisInstaller;
+-open (MYFILE, $installer);
+-while (<MYFILE>) {
+- if ($_ =~ /\@INSERT_TRANSLATIONS\@/)
+- {
+- print "Processing \@INSERT_TRANSLATIONS\@\n";
+- $gcomprisInstaller .= $muiLanguages;
+- $gcomprisInstaller .= $gcomprisLanguages;
+- $gcomprisInstaller .= $selectTranslationFunction;
+- }
+- else
+- {
+- $gcomprisInstaller .= "$_";
+- }
+-}
+-close (MYFILE);
+-
+-# Rewrite the file with the replaced data
+-open (MYFILE, ">$installer");
+-print MYFILE "$gcomprisInstaller";
+-close (MYFILE);
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/generate_gtk_zip.sh pidgin-2.10.7-nonprism/pidgin/win32/nsis/generate_gtk_zip.sh
+--- pidgin-2.10.7/pidgin/win32/nsis/generate_gtk_zip.sh 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/generate_gtk_zip.sh 1969-12-31 21:00:00.000000000 -0300
+@@ -1,140 +0,0 @@
+-#!/bin/bash
+-# Script to generate zip file for GTK+ runtime to be included in Pidgin installer
+-
+-PIDGIN_BASE=$1
+-GPG_SIGN=$2
+-
+-if [ ! -e $PIDGIN_BASE/ChangeLog ]; then
+- echo $(basename $0) must must have the pidgin base dir specified as a parameter.
+- exit 1
+-fi
+-
+-STAGE_DIR=`readlink -f $PIDGIN_BASE/pidgin/win32/nsis/gtk_runtime_stage`
+-#Subdirectory of $STAGE_DIR
+-INSTALL_DIR=Gtk
+-CONTENTS_FILE=$INSTALL_DIR/CONTENTS
+-PIDGIN_VERSION=$( < $PIDGIN_BASE/VERSION )
+-
+-#This needs to be changed every time there is any sort of change.
+-BUNDLE_VERSION=2.16.6.1
+-BUNDLE_SHA1SUM=5e16b7efb11943e8c80bc390f6c38df904fd36ed
+-ZIP_FILE="$PIDGIN_BASE/pidgin/win32/nsis/gtk-runtime-$BUNDLE_VERSION.zip"
+-
+-#Download the existing file (so that we distribute the exact same file for all releases with the same bundle version)
+-FILE="$ZIP_FILE"
+-if [ ! -e "$FILE" ]; then
+- wget "https://pidgin.im/win32/download_redir.php?version=$PIDGIN_VERSION&gtk_version=$BUNDLE_VERSION&dl_pkg=gtk" -O "$FILE"
+-fi
+-CHECK_SHA1SUM=`sha1sum $FILE`
+-CHECK_SHA1SUM=${CHECK_SHA1SUM%%\ *}
+-if [ "$CHECK_SHA1SUM" != "$BUNDLE_SHA1SUM" ]; then
+- echo "sha1sum ($CHECK_SHA1SUM) for $FILE doesn't match expected value of $BUNDLE_SHA1SUM"
+- # Allow "devel" versions to build their own bundles if the download doesn't succeed
+- if [[ "$PIDGIN_VERSION" == *"devel" ]]; then
+- echo "Continuing GTK+ Bundle creation for development version of Pidgin"
+- else
+- exit 1
+- fi
+-else
+- exit 0
+-fi
+-
+-
+-ATK="http://ftp.gnome.org/pub/gnome/binaries/win32/atk/1.32/atk_1.32.0-2_win32.zip ATK 1.32.0-2 sha1sum:3c31c9d6b19af840e2bd8ccbfef4072a6548dc4e"
+-#Cairo 1.10.2 has a bug that can be seen when selecting text
+-#CAIRO="http://ftp.gnome.org/pub/GNOME/binaries/win32/dependencies/cairo_1.10.2-2_win32.zip Cairo 1.10.2-2 sha1sum:d44cd66a9f4d7d29a8f2c28d1c1c5f9b0525ba44"
+-CAIRO="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/cairo_1.8.10-1_win32.zip Cairo 1.8.10-1 sha1sum:a08476cccd807943958610977a138c4d6097c7b8"
+-EXPAT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/expat_2.1.0-1_win32.zip Expat 2.1.0-1 gpg:0x71D4DDE53F188CBE"
+-FONTCONFIG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/fontconfig_2.8.0-2_win32.zip Fontconfig 2.8.0-2 sha1sum:37a3117ea6cc50c8a88fba9b6018f35a04fa71ce"
+-FREETYPE="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/freetype_2.4.10-1_win32.zip Freetype 2.4.10-1 gpg:0x71D4DDE53F188CBE"
+-GETTEXT="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/gettext-runtime_0.18.1.1-2_win32.zip Gettext 0.18.1.1-2 sha1sum:a7cc1ce2b99b408d1bbea9a3b4520fcaf26783b3"
+-GLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/glib/2.28/glib_2.28.8-1_win32.zip Glib 2.28.8-1 sha1sum:5d158f4c77ca0b5508e1042955be573dd940b574"
+-GTK="http://ftp.acc.umu.se/pub/gnome/binaries/win32/gtk+/2.16/gtk+_2.16.6-2_win32.zip GTK+ 2.16.6-2 sha1sum:012853e6de814ebda0cc4459f9eed8ae680e6d17"
+-LIBPNG="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/libpng_1.4.12-1_win32.zip libpng 1.4.12-1 gpg:0x71D4DDE53F188CBE"
+-PANGO="http://ftp.gnome.org/pub/gnome/binaries/win32/pango/1.29/pango_1.29.4-1_win32.zip Pango 1.29.4-1 sha1sum:3959319bd04fbce513458857f334ada279b8cdd4"
+-ZLIB="http://ftp.gnome.org/pub/gnome/binaries/win32/dependencies/zlib_1.2.5-2_win32.zip zlib 1.2.5-2 sha1sum:568907188761df2d9309196e447d91bbc5555d2b"
+-
+-ALL="ATK CAIRO EXPAT FONTCONFIG FREETYPE GETTEXT GLIB GTK LIBPNG PANGO ZLIB"
+-
+-mkdir -p $STAGE_DIR
+-cd $STAGE_DIR
+-
+-rm -rf $INSTALL_DIR
+-mkdir $INSTALL_DIR
+-
+-#new CONTENTS file
+-echo Bundle Version $BUNDLE_VERSION > $CONTENTS_FILE
+-
+-function download_and_extract {
+- URL=${1%%\ *}
+- VALIDATION=${1##*\ }
+- NAME=${1%\ *}
+- NAME=${NAME#*\ }
+- FILE=$(basename $URL)
+- if [ ! -e $FILE ]; then
+- echo Downloading $NAME
+- wget $URL || exit 1
+- fi
+- VALIDATION_TYPE=${VALIDATION%%:*}
+- VALIDATION_VALUE=${VALIDATION##*:}
+- if [ $VALIDATION_TYPE == 'sha1sum' ]; then
+- CHECK_SHA1SUM=`sha1sum $FILE`
+- CHECK_SHA1SUM=${CHECK_SHA1SUM%%\ *}
+- if [ "$CHECK_SHA1SUM" != "$VALIDATION_VALUE" ]; then
+- echo "sha1sum ($CHECK_SHA1SUM) for $FILE doesn't match expected value of $VALIDATION_VALUE"
+- exit 1
+- fi
+- elif [ $VALIDATION_TYPE == 'gpg' ]; then
+- if [ ! -e "$FILE.asc" ]; then
+- echo Downloading GPG key for $NAME
+- wget "$URL.asc" || exit 1
+- fi
+- #Use our own keyring to avoid adding stuff to the main keyring
+- #This doesn't use $GPG_SIGN because we don't this validation to be bypassed when people are skipping signing output
+- GPG_BASE="gpg -q --keyring $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg"
+- if [[ ! -e $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg \
+- || `$GPG_BASE --list-keys "$VALIDATION_VALUE" > /dev/null && echo -n "0"` -ne 0 ]]; then
+- touch $STAGE_DIR/$VALIDATION_VALUE-keyring.gpg
+- $GPG_BASE --no-default-keyring --keyserver pgp.mit.edu --recv-key "$VALIDATION_VALUE" || exit 1
+- fi
+- $GPG_BASE --verify "$FILE.asc" || (echo "$FILE failed signature verification"; exit 1) || exit 1
+- else
+- echo "Unrecognized validation type of $VALIDATION_TYPE"
+- exit 1
+- fi
+- EXTENSION=${FILE##*.}
+- #This is an OpenSuSE build service RPM
+- if [ $EXTENSION == 'rpm' ]; then
+- echo "Generating zip from $FILE"
+- FILE=$(../rpm2zip.sh $FILE)
+- fi
+- unzip -q $FILE -d $INSTALL_DIR || exit 1
+- echo "$NAME" >> $CONTENTS_FILE
+-}
+-
+-for VAL in $ALL
+-do
+- VAR=${!VAL}
+- download_and_extract "$VAR"
+-done
+-
+-#Default GTK+ Theme to MS-Windows
+-echo gtk-theme-name = \"MS-Windows\" > $INSTALL_DIR/etc/gtk-2.0/gtkrc
+-
+-#Blow away translations that we don't have in Pidgin
+-for LOCALE_DIR in $INSTALL_DIR/share/locale/*
+-do
+- LOCALE=$(basename $LOCALE_DIR)
+- if [ ! -e $PIDGIN_BASE/po/$LOCALE.po ]; then
+- echo Removing $LOCALE translation as it is missing from Pidgin
+- rm -r $LOCALE_DIR
+- fi
+-done
+-
+-#Generate zip file to be included in installer
+-rm -f $ZIP_FILE
+-zip -9 -r $ZIP_FILE Gtk
+-($GPG_SIGN -ab $ZIP_FILE && $GPG_SIGN --verify $ZIP_FILE.asc) || exit 1
+-
+-exit 0
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/nsis_translations.desktop.in pidgin-2.10.7-nonprism/pidgin/win32/nsis/nsis_translations.desktop.in
+--- pidgin-2.10.7/pidgin/win32/nsis/nsis_translations.desktop.in 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/nsis_translations.desktop.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,62 +0,0 @@
+-[Desktop Entry]
+-Encoding=UTF-8
+-
+-_INSTALLERISRUNNING=The installer is already running.
+-_PIDGINISRUNNING=An instance of Pidgin is currently running. Please exit Pidgin and try again.
+-
+-# "Next >" appears on a button on the License Page of the Installer
+-_PIDGINLICENSEBUTTON=Next >
+-# $(^Name) is the current Version name (e.g. Pidgin 2.7.0). $_CLICK will become a translated version of "Click Next to continue." DO NOT translate the CLICK in $_CLICK. It will break the installer.
+-_PIDGINLICENSEBOTTOMTEXT=$(^Name) is released under the GNU General Public License (GPL). The license is provided here for information purposes only. $_CLICK
+-
+-#Installer Subsection Text
+-_PIDGINSECTIONTITLE=Pidgin Instant Messaging Client (required)
+-#Installer Subsection Text
+-_GTKSECTIONTITLE=GTK+ Runtime (required if not present)
+-#Installer Subsection Text
+-_PIDGINSHORTCUTSSECTIONTITLE=Shortcuts
+-#Installer Subsection Text
+-_PIDGINDESKTOPSHORTCUTSECTIONTITLE=Desktop
+-#Installer Subsection Text
+-_PIDGINSTARTMENUSHORTCUTSECTIONTITLE=Start Menu
+-#Installer Subsection Text
+-_TRANSLATIONSSECTIONTITLE=Localizations
+-#Installer Subsection Detailed Description
+-_PIDGINSECTIONDESCRIPTION=Core Pidgin files and dlls
+-#Installer Subsection Detailed Description
+-_PIDGINSHORTCUTSSECTIONDESCRIPTION=Shortcuts for starting Pidgin
+-#Installer Subsection Detailed Description
+-_PIDGINDESKTOPSHORTCUTDESC=Create a shortcut to Pidgin on the Desktop
+-#Installer Subsection Detailed Description
+-_PIDGINSTARTMENUSHORTCUTDESC=Create a Start Menu entry for Pidgin
+-#Installer Subsection Detailed Description
+-_GTKSECTIONDESCRIPTION=A multi-platform GUI toolkit, used by Pidgin
+-#Installer Subsection Text
+-_DEBUGSYMBOLSSECTIONTITLE=Debug Symbols (for reporting crashes)
+-
+-# Text displayed on Installer Finish Page
+-_PIDGINFINISHVISITWEBSITE=Visit the Pidgin Web Page
+-
+-_PIDGINPROMPTCONTINUEWITHOUTUNINSTALL=Unable to uninstall the currently installed version of Pidgin. The new version will be installed without removing the currently installed version.
+-
+-_PIDGINPROMPTFORCENOGTK=Pidgin requires a compatible GTK+ Runtime (which doesn't appear to be already present).$\rAre you sure you want to skip installing the GTK+ Runtime?
+-
+-#Installer Subsection Text
+-_URIHANDLERSSECTIONTITLE=URI Handlers
+-
+-#Installer Subsection Text
+-_PIDGINSPELLCHECKSECTIONTITLE=Spellchecking Support
+-# $R3 will display the URL that the Dictionary failed to download from
+-_PIDGINSPELLCHECKERROR=Error Installing Spellchecking ($R3).$\rIf retrying fails, manual installation instructions are at: http://developer.pidgin.im/wiki/Installing%20Pidgin#manual_win32_spellcheck_installation
+-#Installer Subsection Detailed Description
+-_PIDGINSPELLCHECKSECTIONDESCRIPTION=Support for Spellchecking. (Internet connection required for installation)
+-
+-# $R2 will display the URL that the Debug Symbols failed to download from
+-_PIDGINDEBUGSYMBOLSERROR=Error Installing Debug Symbols ($R2).$\rIf retrying fails, you may need to use the 'Offline Installer' from http://pidgin.im/download/windows/ .
+-
+-# $R2 will display the URL that the GTK+ Runtime failed to download from
+-_PIDGINGTKDOWNLOADERROR=Error Downloading the GTK+ Runtime ($R2).$\rThis is required for Pidgin to function; if retrying fails, you may need to use the 'Offline Installer' from http://pidgin.im/download/windows/ .
+-
+-_PIDGINUNINSTALLERROR1=The uninstaller could not find registry entries for Pidgin.$\rIt is likely that another user installed this application.
+-_PIDGINUNINSTALLERROR2=You do not have permission to uninstall this application.
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/pidgin-installer.nsi pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-installer.nsi
+--- pidgin-2.10.7/pidgin/win32/nsis/pidgin-installer.nsi 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-installer.nsi 1969-12-31 21:00:00.000000000 -0300
+@@ -1,1339 +0,0 @@
+-; Installer script for win32 Pidgin
+-; Original Author: Herman Bloggs <hermanator12002@yahoo.com>
+-; Updated By: Daniel Atallah <daniel_atallah@yahoo.com>
+-
+-; NOTE: this .NSI script is intended for NSIS 2.27+
+-;
+-
+-;--------------------------------
+-;Global Variables
+-Var name
+-Var STARTUP_RUN_KEY
+-Var CURRENT_GTK_STATE
+-Var WARNED_GTK_STATE
+-
+-;--------------------------------
+-;Configuration
+-
+-;The name var is set in .onInit
+-Name $name
+-
+-!ifdef OFFLINE_INSTALLER
+-OutFile "pidgin-${PIDGIN_VERSION}-offline.exe"
+-!else
+-OutFile "pidgin-${PIDGIN_VERSION}.exe"
+-!endif
+-
+-SetCompressor /SOLID lzma
+-ShowInstDetails show
+-ShowUninstDetails show
+-SetDateSave on
+-RequestExecutionLevel highest
+-
+-; $name and $INSTDIR are set in .onInit function..
+-
+-!include "MUI.nsh"
+-!include "Sections.nsh"
+-!include "LogicLib.nsh"
+-!include "Memento.nsh"
+-
+-!include "FileFunc.nsh"
+-!insertmacro GetParameters
+-!insertmacro GetOptions
+-!insertmacro GetParent
+-
+-!include "WordFunc.nsh"
+-!insertmacro VersionCompare
+-!insertmacro WordFind
+-!insertmacro un.WordFind
+-
+-!include "TextFunc.nsh"
+-
+-;--------------------------------
+-;Defines
+-
+-!define PIDGIN_NSIS_INCLUDE_PATH "."
+-
+-; Remove these and the stuff that uses them at some point
+-!define OLD_GAIM_REG_KEY "SOFTWARE\gaim"
+-!define OLD_GAIM_UNINSTALL_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Gaim"
+-!define OLD_GAIM_UNINST_EXE "gaim-uninst.exe"
+-
+-!define PIDGIN_REG_KEY "SOFTWARE\pidgin"
+-!define PIDGIN_UNINSTALL_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\Pidgin"
+-
+-!define HKLM_APP_PATHS_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\App Paths\pidgin.exe"
+-!define STARTUP_RUN_KEY "SOFTWARE\Microsoft\Windows\CurrentVersion\Run"
+-!define PIDGIN_UNINST_EXE "pidgin-uninst.exe"
+-
+-!define GTK_MIN_VERSION "2.14.0"
+-!define PERL_REG_KEY "SOFTWARE\Perl"
+-!define PERL_DLL "perl510.dll"
+-
+-!define DOWNLOADER_URL "https://pidgin.im/win32/download_redir.php?version=${PIDGIN_VERSION}"
+-
+-!define MEMENTO_REGISTRY_ROOT HKLM
+-!define MEMENTO_REGISTRY_KEY "${PIDGIN_UNINSTALL_KEY}"
+-
+-;--------------------------------
+-;Version resource
+-VIProductVersion "${PIDGIN_PRODUCT_VERSION}"
+-VIAddVersionKey "ProductName" "Pidgin"
+-VIAddVersionKey "FileVersion" "${PIDGIN_VERSION}"
+-VIAddVersionKey "ProductVersion" "${PIDGIN_VERSION}"
+-VIAddVersionKey "LegalCopyright" ""
+-!ifdef OFFLINE_INSTALLER
+-VIAddVersionKey "FileDescription" "Pidgin Installer (Offline)"
+-!else
+-VIAddVersionKey "FileDescription" "Pidgin Installer"
+-!endif
+-
+-;--------------------------------
+-;Reserve files used in .onInit
+-;for faster start-up
+-ReserveFile "${NSISDIR}\Plugins\System.dll"
+-ReserveFile "${NSISDIR}\Plugins\UserInfo.dll"
+-!insertmacro MUI_RESERVEFILE_INSTALLOPTIONS
+-!insertmacro MUI_RESERVEFILE_LANGDLL
+-
+-;--------------------------------
+-;Modern UI Configuration
+-
+- !define MUI_ICON ".\pixmaps\pidgin-install.ico"
+- !define MUI_UNICON ".\pixmaps\pidgin-install.ico"
+- !define MUI_WELCOMEFINISHPAGE_BITMAP ".\pixmaps\pidgin-intro.bmp"
+- !define MUI_HEADERIMAGE
+- !define MUI_HEADERIMAGE_BITMAP ".\pixmaps\pidgin-header.bmp"
+-
+- ; Alter License section
+- !define MUI_LICENSEPAGE_BUTTON $(PIDGINLICENSEBUTTON)
+- !define MUI_LICENSEPAGE_TEXT_BOTTOM $(PIDGINLICENSEBOTTOMTEXT)
+-
+- !define MUI_LANGDLL_REGISTRY_ROOT "HKCU"
+- !define MUI_LANGDLL_REGISTRY_KEY ${PIDGIN_REG_KEY}
+- !define MUI_LANGDLL_REGISTRY_VALUENAME "Installer Language"
+-
+- !define MUI_COMPONENTSPAGE_SMALLDESC
+- !define MUI_ABORTWARNING
+-
+- ;Finish Page config
+- !define MUI_FINISHPAGE_NOAUTOCLOSE
+- ;!define MUI_FINISHPAGE_RUN "$INSTDIR\pidgin.exe"
+- ;!define MUI_FINISHPAGE_RUN_NOTCHECKED
+- !define MUI_FINISHPAGE_LINK $(PIDGINFINISHVISITWEBSITE)
+- !define MUI_FINISHPAGE_LINK_LOCATION "http://pidgin.im"
+-
+-;--------------------------------
+-;Pages
+-
+- !define MUI_PAGE_CUSTOMFUNCTION_PRE preWelcomePage
+- !insertmacro MUI_PAGE_WELCOME
+- !insertmacro MUI_PAGE_LICENSE "../../../COPYING"
+- !insertmacro MUI_PAGE_COMPONENTS
+-
+- ; Pidgin install dir page
+- !insertmacro MUI_PAGE_DIRECTORY
+-
+- !insertmacro MUI_PAGE_INSTFILES
+- !insertmacro MUI_PAGE_FINISH
+-
+- !insertmacro MUI_UNPAGE_WELCOME
+- !insertmacro MUI_UNPAGE_CONFIRM
+- !insertmacro MUI_UNPAGE_INSTFILES
+- !insertmacro MUI_UNPAGE_FINISH
+-
+-;--------------------------------
+-;Languages
+-
+- !include "${PIDGIN_NSIS_INCLUDE_PATH}\langmacros.nsh"
+-
+-;--------------------------------
+-
+-;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+-;; Start Install Sections ;;
+-;;;;;;;;;;;;;;;;;;;;;;;;;;;;
+-
+-;--------------------------------
+-;Uninstall any old version of Pidgin (or Gaim)
+-
+-Section -SecUninstallOldPidgin
+- ; Check install rights..
+- Call CheckUserInstallRights
+- Pop $R0
+-
+- ;First try to uninstall Pidgin
+- StrCpy $R4 ${PIDGIN_REG_KEY}
+- StrCpy $R5 ${PIDGIN_UNINSTALL_KEY}
+- StrCpy $R6 ${PIDGIN_UNINST_EXE}
+- StrCpy $R7 "Pidgin"
+-
+- start_comparison:
+- ;If pidgin is currently set to run on startup,
+- ; save the section of the Registry where the setting is before uninstalling,
+- ; so we can put it back after installing the new version
+- ClearErrors
+- ReadRegStr $STARTUP_RUN_KEY HKCU "${STARTUP_RUN_KEY}" $R7
+- IfErrors +3
+- StrCpy $STARTUP_RUN_KEY "HKCU"
+- Goto +5
+- ClearErrors
+- ReadRegStr $STARTUP_RUN_KEY HKLM "${STARTUP_RUN_KEY}" $R7
+- IfErrors +2
+- StrCpy $STARTUP_RUN_KEY "HKLM"
+-
+- StrCmp $R0 "HKLM" compare_hklm
+- StrCmp $R0 "HKCU" compare_hkcu done
+-
+- compare_hkcu:
+- ReadRegStr $R1 HKCU $R4 ""
+- ReadRegStr $R2 HKCU $R4 "Version"
+- ReadRegStr $R3 HKCU "$R5" "UninstallString"
+- Goto try_uninstall
+-
+- compare_hklm:
+- ReadRegStr $R1 HKLM $R4 ""
+- ReadRegStr $R2 HKLM $R4 "Version"
+- ReadRegStr $R3 HKLM "$R5" "UninstallString"
+-
+- ; If a previous version exists, remove it
+- try_uninstall:
+- StrCmp $R1 "" no_version_found
+- ; Version key started with 0.60a3. Prior versions can't be
+- ; automatically uninstalled.
+- StrCmp $R2 "" uninstall_problem
+- ; Check if we have uninstall string..
+- IfFileExists $R3 0 uninstall_problem
+- ; Have uninstall string, go ahead and uninstall.
+- SetOverwrite on
+- ; Need to copy uninstaller outside of the install dir
+- ClearErrors
+- CopyFiles /SILENT $R3 "$TEMP\$R6"
+- SetOverwrite off
+- IfErrors uninstall_problem
+- ; Ready to uninstall..
+- ClearErrors
+- ExecWait '"$TEMP\$R6" /S /UPGRADE=1 _?=$R1'
+- IfErrors exec_error
+- Delete "$TEMP\$R6"
+- Goto done
+-
+- exec_error:
+- Delete "$TEMP\$R6"
+- Goto uninstall_problem
+-
+- no_version_found:
+- ;We've already tried to fallback to an old gaim instance
+- StrCmp $R7 "Gaim" done
+- ; If we couldn't uninstall Pidgin, try to uninstall Gaim
+- StrCpy $STARTUP_RUN_KEY "NONE"
+- StrCpy $R4 ${OLD_GAIM_REG_KEY}
+- StrCpy $R5 ${OLD_GAIM_UNINSTALL_KEY}
+- StrCpy $R6 ${OLD_GAIM_UNINST_EXE}
+- StrCpy $R7 "Gaim"
+- Goto start_comparison
+-
+- uninstall_problem:
+- ; We can't uninstall. Either the user must manually uninstall or we ignore and reinstall over it.
+- MessageBox MB_OKCANCEL $(PIDGINPROMPTCONTINUEWITHOUTUNINSTALL) /SD IDOK IDOK done
+- Quit
+- done:
+-SectionEnd
+-
+-
+-;--------------------------------
+-;GTK+ Runtime Install Section
+-
+-Section $(GTKSECTIONTITLE) SecGtk
+-
+- InitPluginsDir
+- StrCpy $R1 "$PLUGINSDIR\gtk.zip"
+-!ifdef OFFLINE_INSTALLER
+-
+- SetOutPath $PLUGINSDIR
+- File /oname=gtk.zip ".\gtk-runtime-${GTK_INSTALL_VERSION}.zip"
+-
+-!else
+-
+- ; We need to download the GTK+ runtime
+- retry:
+- StrCpy $R2 "${DOWNLOADER_URL}&gtk_version=${GTK_INSTALL_VERSION}&dl_pkg=gtk"
+- DetailPrint "Downloading GTK+ Runtime ... ($R2)"
+- NSISdl::download /TIMEOUT=10000 $R2 $R1
+- Pop $R0
+- ;StrCmp $R0 "cancel" done
+- StrCmp $R0 "success" 0 prompt_retry
+-
+- Push "${GTK_SHA1SUM}"
+- Push "$R1" ; Filename
+- Call CheckSHA1Sum
+- Pop $R0
+-
+- StrCmp "$R0" "0" extract
+- prompt_retry:
+- MessageBox MB_RETRYCANCEL "$(PIDGINGTKDOWNLOADERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
+-
+- extract:
+-!endif
+-
+- ;Delete the old Gtk directory
+- RMDir /r "$INSTDIR\Gtk"
+-
+- SetOutPath "$INSTDIR"
+- nsisunz::UnzipToLog $R1 "$INSTDIR"
+- Pop $R0
+- StrCmp $R0 "success" +2
+- DetailPrint "$R0" ;print error message to log
+-
+-!ifndef OFFLINE_INSTALLER
+- done:
+-!endif
+-SectionEnd ; end of GTK+ section
+-
+-;--------------------------------
+-;Pidgin Install Section
+-
+-Section $(PIDGINSECTIONTITLE) SecPidgin
+- SectionIn 1 RO
+-
+- ; Check install rights..
+- Call CheckUserInstallRights
+- Pop $R0
+-
+- StrCmp $R0 "NONE" pidgin_install_files
+- StrCmp $R0 "HKLM" pidgin_hklm pidgin_hkcu
+-
+- pidgin_hklm:
+- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "" "$INSTDIR\pidgin.exe"
+- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "Path" "$INSTDIR\Gtk\bin"
+- WriteRegStr HKLM ${PIDGIN_REG_KEY} "" "$INSTDIR"
+- WriteRegStr HKLM ${PIDGIN_REG_KEY} "Version" "${PIDGIN_VERSION}"
+- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\pidgin.exe"
+- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayName" "Pidgin"
+- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "DisplayVersion" "${PIDGIN_VERSION}"
+- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "HelpLink" "http://developer.pidgin.im/wiki/Using Pidgin"
+- WriteRegDWORD HKLM "${PIDGIN_UNINSTALL_KEY}" "NoModify" 1
+- WriteRegDWORD HKLM "${PIDGIN_UNINSTALL_KEY}" "NoRepair" 1
+- WriteRegStr HKLM "${PIDGIN_UNINSTALL_KEY}" "UninstallString" "$INSTDIR\${PIDGIN_UNINST_EXE}"
+- ; Sets scope of the desktop and Start Menu entries for all users.
+- SetShellVarContext "all"
+- Goto pidgin_install_files
+-
+- pidgin_hkcu:
+- WriteRegStr HKCU ${PIDGIN_REG_KEY} "" "$INSTDIR"
+- WriteRegStr HKCU ${PIDGIN_REG_KEY} "Version" "${PIDGIN_VERSION}"
+- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayIcon" "$INSTDIR\pidgin.exe"
+- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayName" "Pidgin"
+- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "DisplayVersion" "${PIDGIN_VERSION}"
+- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "HelpLink" "http://developer.pidgin.im/wiki/Using Pidgin"
+- WriteRegDWORD HKCU "${PIDGIN_UNINSTALL_KEY}" "NoModify" 1
+- WriteRegDWORD HKCU "${PIDGIN_UNINSTALL_KEY}" "NoRepair" 1
+- WriteRegStr HKCU "${PIDGIN_UNINSTALL_KEY}" "UninstallString" "$INSTDIR\${PIDGIN_UNINST_EXE}"
+- Goto pidgin_install_files
+-
+- pidgin_install_files:
+- SetOutPath "$INSTDIR"
+- ; Pidgin files
+- SetOverwrite on
+-
+- ;Delete old liboscar and libjabber since they tend to be problematic
+- Delete "$INSTDIR\plugins\liboscar.dll"
+- Delete "$INSTDIR\plugins\libjabber.dll"
+-
+- File /r /x locale /x Gtk ..\..\..\${PIDGIN_INSTALL_DIR}\*.*
+-
+- ; Check if Perl is installed, if so add it to the AppPaths
+- ReadRegStr $R2 HKLM ${PERL_REG_KEY} ""
+- StrCmp $R2 "" 0 perl_exists
+- ReadRegStr $R2 HKCU ${PERL_REG_KEY} ""
+- StrCmp $R2 "" perl_done perl_exists
+-
+- perl_exists:
+- IfFileExists "$R2\bin\${PERL_DLL}" 0 perl_done
+- StrCmp $R0 "HKLM" 0 perl_done
+- ReadRegStr $R3 HKLM "${HKLM_APP_PATHS_KEY}" "Path"
+- WriteRegStr HKLM "${HKLM_APP_PATHS_KEY}" "Path" "$R3;$R2\bin"
+-
+- perl_done:
+-
+- SetOutPath "$INSTDIR"
+-
+- ; If we don't have install rights we're done
+- StrCmp $R0 "NONE" done
+- SetOverwrite off
+-
+- ; write out uninstaller
+- SetOverwrite on
+- WriteUninstaller "$INSTDIR\${PIDGIN_UNINST_EXE}"
+- SetOverwrite off
+-
+- ; If we previously had pidgin set up to run on startup, make it do so again
+- StrCmp $STARTUP_RUN_KEY "HKCU" +1 +2
+- WriteRegStr HKCU "${STARTUP_RUN_KEY}" "Pidgin" "$INSTDIR\pidgin.exe"
+- StrCmp $STARTUP_RUN_KEY "HKLM" +1 +2
+- WriteRegStr HKLM "${STARTUP_RUN_KEY}" "Pidgin" "$INSTDIR\pidgin.exe"
+-
+- done:
+-SectionEnd ; end of default Pidgin section
+-
+-;--------------------------------
+-;Shortcuts
+-
+-SectionGroup /e $(PIDGINSHORTCUTSSECTIONTITLE) SecShortcuts
+- Section /o $(PIDGINDESKTOPSHORTCUTSECTIONTITLE) SecDesktopShortcut
+- SetOverwrite on
+- CreateShortCut "$DESKTOP\Pidgin.lnk" "$INSTDIR\pidgin.exe"
+- SetOverwrite off
+- SectionEnd
+- Section $(PIDGINSTARTMENUSHORTCUTSECTIONTITLE) SecStartMenuShortcut
+- SetOverwrite on
+- CreateShortCut "$SMPROGRAMS\Pidgin.lnk" "$INSTDIR\pidgin.exe"
+- SetOverwrite off
+- SectionEnd
+-SectionGroupEnd
+-
+-;--------------------------------
+-;URI Handling
+-
+-!macro URI_SECTION proto
+- Section /o "${proto}:" SecURI_${proto}
+- Push "${proto}"
+- Call RegisterURIHandler
+- SectionEnd
+-!macroend
+-SectionGroup /e $(URIHANDLERSSECTIONTITLE) SecURIHandlers
+- !insertmacro URI_SECTION "aim"
+- !insertmacro URI_SECTION "msnim"
+- !insertmacro URI_SECTION "myim"
+- !insertmacro URI_SECTION "ymsgr"
+- !insertmacro URI_SECTION "xmpp"
+-SectionGroupEnd
+-
+-;--------------------------------
+-;Translations
+-
+-!macro LANG_SECTION lang
+- ${MementoUnselectedSection} "${lang}" SecLang_${lang}
+- SetOutPath "$INSTDIR\locale\${lang}\LC_MESSAGES"
+- File "..\..\..\${PIDGIN_INSTALL_DIR}\locale\${lang}\LC_MESSAGES\*.mo"
+- SetOutPath "$INSTDIR"
+- ${MementoSectionEnd}
+-!macroend
+-SectionGroup $(TRANSLATIONSSECTIONTITLE) SecTranslations
+- # pidgin-translations is generated based on the contents of the locale directory
+- !include "pidgin-translations.nsh"
+-SectionGroupEnd
+-${MementoSectionDone}
+-
+-;--------------------------------
+-;Spell Checking
+-
+-!macro SPELLCHECK_SECTION lang lang_name lang_file
+- Section /o "${lang_name}" SecSpell_${lang}
+- Push ${lang_file}
+- Push ${lang}
+- Call InstallDict
+- SectionEnd
+-!macroend
+-SectionGroup $(PIDGINSPELLCHECKSECTIONTITLE) SecSpellCheck
+- !include "pidgin-spellcheck.nsh"
+-SectionGroupEnd
+-
+-Section /o $(DEBUGSYMBOLSSECTIONTITLE) SecDebugSymbols
+-
+- InitPluginsDir
+- StrCpy $R1 "$PLUGINSDIR\dbgsym.zip"
+-!ifdef OFFLINE_INSTALLER
+-
+- SetOutPath $PLUGINSDIR
+- File /oname=dbgsym.zip "..\..\..\pidgin-${PIDGIN_VERSION}-dbgsym.zip"
+-
+-!else
+-
+- ; We need to download the debug symbols
+- retry:
+- StrCpy $R2 "${DOWNLOADER_URL}&dl_pkg=dbgsym"
+- DetailPrint "Downloading Debug Symbols... ($R2)"
+- NSISdl::download /TIMEOUT=10000 $R2 $R1
+- Pop $R0
+- StrCmp $R0 "cancel" done
+- StrCmp $R0 "success" 0 prompt_retry
+-
+- Push "${DEBUG_SYMBOLS_SHA1SUM}"
+- Push "$R1" ; Filename
+- Call CheckSHA1Sum
+- Pop $R0
+-
+- StrCmp "$R0" "0" extract
+- prompt_retry:
+- MessageBox MB_RETRYCANCEL "$(PIDGINDEBUGSYMBOLSERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
+-
+- extract:
+-!endif
+-
+- SetOutPath "$INSTDIR"
+- nsisunz::UnzipToLog $R1 "$INSTDIR"
+- Pop $R0
+- StrCmp $R0 "success" +2
+- DetailPrint "$R0" ;print error message to log
+-
+-!ifndef OFFLINE_INSTALLER
+- done:
+-!endif
+-SectionEnd
+-
+-;--------------------------------
+-;Uninstaller Section
+-
+-
+-Section Uninstall
+- Call un.CheckUserInstallRights
+- Pop $R0
+- StrCmp $R0 "NONE" no_rights
+- StrCmp $R0 "HKCU" try_hkcu try_hklm
+-
+- try_hkcu:
+- ReadRegStr $R0 HKCU ${PIDGIN_REG_KEY} ""
+- StrCmp $R0 $INSTDIR 0 cant_uninstall
+- ; HKCU install path matches our INSTDIR so uninstall
+- DeleteRegKey HKCU ${PIDGIN_REG_KEY}
+- DeleteRegKey HKCU "${PIDGIN_UNINSTALL_KEY}"
+- Goto cont_uninstall
+-
+- try_hklm:
+- ReadRegStr $R0 HKLM ${PIDGIN_REG_KEY} ""
+- StrCmp $R0 $INSTDIR 0 try_hkcu
+- ; HKLM install path matches our INSTDIR so uninstall
+- DeleteRegKey HKLM ${PIDGIN_REG_KEY}
+- DeleteRegKey HKLM "${PIDGIN_UNINSTALL_KEY}"
+- DeleteRegKey HKLM "${HKLM_APP_PATHS_KEY}"
+- ; Sets start menu and desktop scope to all users..
+- SetShellVarContext "all"
+-
+- cont_uninstall:
+- ; The WinPrefs plugin may have left this behind..
+- DeleteRegValue HKCU "${STARTUP_RUN_KEY}" "Pidgin"
+- DeleteRegValue HKLM "${STARTUP_RUN_KEY}" "Pidgin"
+- ; Remove Language preference info
+- DeleteRegValue HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+-
+- ; Remove any URI handlers
+- ; I can't think of an easy way to maintain a list in a single place
+- Push "aim"
+- Call un.UnregisterURIHandler
+- Push "msnim"
+- Call un.UnregisterURIHandler
+- Push "myim"
+- Call un.UnregisterURIHandler
+- Push "ymsgr"
+- Call un.UnregisterURIHandler
+- Push "xmpp"
+- Call un.UnregisterURIHandler
+-
+- Delete "$INSTDIR\ca-certs\AddTrust_External_Root.pem"
+- Delete "$INSTDIR\ca-certs\America_Online_Root_Certification_Authority_1.pem"
+- Delete "$INSTDIR\ca-certs\AOL_Member_CA.pem"
+- Delete "$INSTDIR\ca-certs\CAcert_Class3.pem"
+- Delete "$INSTDIR\ca-certs\CAcert_Root.pem"
+- Delete "$INSTDIR\ca-certs\Deutsche_Telekom_Root_CA_2.pem"
+- Delete "$INSTDIR\ca-certs\DigiCertHighAssuranceCA-3.pem"
+- Delete "$INSTDIR\ca-certs\Entrust.net_Secure_Server_CA.pem"
+- Delete "$INSTDIR\ca-certs\Equifax_Secure_CA.pem"
+- Delete "$INSTDIR\ca-certs\Equifax_Secure_Global_eBusiness_CA-1.pem"
+- Delete "$INSTDIR\ca-certs\Go_Daddy_Class_2_CA.pem"
+- Delete "$INSTDIR\ca-certs\GTE_CyberTrust_Global_Root.pem"
+- Delete "$INSTDIR\ca-certs\Microsoft_Internet_Authority.pem"
+- Delete "$INSTDIR\ca-certs\Microsoft_Internet_Authority_2010.pem"
+- Delete "$INSTDIR\ca-certs\Microsoft_Secure_Server_Authority.pem"
+- Delete "$INSTDIR\ca-certs\Microsoft_Secure_Server_Authority_2010.pem"
+- Delete "$INSTDIR\ca-certs\StartCom_Certification_Authority.pem"
+- Delete "$INSTDIR\ca-certs\StartCom_Free_SSL_CA.pem"
+- Delete "$INSTDIR\ca-certs\Thawte_Premium_Server_CA.pem"
+- Delete "$INSTDIR\ca-certs\Thawte_Primary_Root_CA.pem"
+- Delete "$INSTDIR\ca-certs\ValiCert_Class_2_VA.crt"
+- Delete "$INSTDIR\ca-certs\VeriSign_Class3_Extended_Validation_CA.pem"
+- Delete "$INSTDIR\ca-certs\Verisign_Class3_Primary_CA.pem"
+- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G2.pem"
+- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5.pem"
+- Delete "$INSTDIR\ca-certs\VeriSign_Class_3_Public_Primary_Certification_Authority_-_G5_2.pem"
+- Delete "$INSTDIR\ca-certs\VeriSign_International_Server_Class_3_CA.pem"
+- Delete "$INSTDIR\ca-certs\Verisign_RSA_Secure_Server_CA.pem"
+- RMDir "$INSTDIR\ca-certs"
+- RMDir /r "$INSTDIR\locale"
+- RMDir /r "$INSTDIR\pixmaps"
+- Delete "$INSTDIR\plugins\autoaccept.dll"
+- Delete "$INSTDIR\plugins\buddynote.dll"
+- Delete "$INSTDIR\plugins\convcolors.dll"
+- Delete "$INSTDIR\plugins\extplacement.dll"
+- Delete "$INSTDIR\plugins\gtkbuddynote.dll"
+- Delete "$INSTDIR\plugins\history.dll"
+- Delete "$INSTDIR\plugins\iconaway.dll"
+- Delete "$INSTDIR\plugins\idle.dll"
+- Delete "$INSTDIR\plugins\joinpart.dll"
+- Delete "$INSTDIR\plugins\libaim.dll"
+- Delete "$INSTDIR\plugins\libbonjour.dll"
+- Delete "$INSTDIR\plugins\libgg.dll"
+- Delete "$INSTDIR\plugins\libicq.dll"
+- Delete "$INSTDIR\plugins\libirc.dll"
+- Delete "$INSTDIR\plugins\libmsn.dll"
+- Delete "$INSTDIR\plugins\libmxit.dll"
+- Delete "$INSTDIR\plugins\libmyspace.dll"
+- Delete "$INSTDIR\plugins\libnapster.dll"
+- Delete "$INSTDIR\plugins\libnovell.dll"
+- Delete "$INSTDIR\plugins\libsametime.dll"
+- Delete "$INSTDIR\plugins\libsilc.dll"
+- Delete "$INSTDIR\plugins\libsimple.dll"
+- Delete "$INSTDIR\plugins\libtoc.dll"
+- Delete "$INSTDIR\plugins\libyahoo.dll"
+- Delete "$INSTDIR\plugins\libyahoojp.dll"
+- Delete "$INSTDIR\plugins\libxmpp.dll"
+- Delete "$INSTDIR\plugins\log_reader.dll"
+- Delete "$INSTDIR\plugins\markerline.dll"
+- Delete "$INSTDIR\plugins\newline.dll"
+- Delete "$INSTDIR\plugins\notify.dll"
+- Delete "$INSTDIR\plugins\offlinemsg.dll"
+- Delete "$INSTDIR\plugins\perl.dll"
+- Delete "$INSTDIR\plugins\pidginrc.dll"
+- Delete "$INSTDIR\plugins\psychic.dll"
+- Delete "$INSTDIR\plugins\relnot.dll"
+- Delete "$INSTDIR\plugins\sendbutton.dll"
+- Delete "$INSTDIR\plugins\spellchk.dll"
+- Delete "$INSTDIR\plugins\ssl-nss.dll"
+- Delete "$INSTDIR\plugins\ssl.dll"
+- Delete "$INSTDIR\plugins\statenotify.dll"
+- Delete "$INSTDIR\plugins\tcl.dll"
+- Delete "$INSTDIR\plugins\themeedit.dll"
+- Delete "$INSTDIR\plugins\ticker.dll"
+- Delete "$INSTDIR\plugins\timestamp.dll"
+- Delete "$INSTDIR\plugins\timestamp_format.dll"
+- Delete "$INSTDIR\plugins\win2ktrans.dll"
+- Delete "$INSTDIR\plugins\winprefs.dll"
+- Delete "$INSTDIR\plugins\xmppconsole.dll"
+- Delete "$INSTDIR\plugins\xmppdisco.dll"
+- RMDir /r "$INSTDIR\plugins\perl"
+- RMDir "$INSTDIR\plugins"
+- RMDir /r "$INSTDIR\sasl2"
+- Delete "$INSTDIR\sounds\purple\alert.wav"
+- Delete "$INSTDIR\sounds\purple\login.wav"
+- Delete "$INSTDIR\sounds\purple\logout.wav"
+- Delete "$INSTDIR\sounds\purple\receive.wav"
+- Delete "$INSTDIR\sounds\purple\send.wav"
+- RMDir "$INSTDIR\sounds\purple"
+- RMDir "$INSTDIR\sounds"
+- Delete "$INSTDIR\spellcheck\libenchant.dll"
+- Delete "$INSTDIR\spellcheck\libgtkspell-0.dll"
+- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_aspell.dll"
+- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_ispell.dll"
+- Delete "$INSTDIR\spellcheck\lib\enchant\libenchant_myspell.dll"
+- RMDir "$INSTDIR\spellcheck\lib\enchant"
+- RMDir "$INSTDIR\spellcheck\lib"
+- RMDir "$INSTDIR\spellcheck"
+- Delete "$INSTDIR\freebl3.dll"
+- Delete "$INSTDIR\libjabber.dll"
+- Delete "$INSTDIR\libnspr4.dll"
+- Delete "$INSTDIR\libmeanwhile-1.dll"
+- Delete "$INSTDIR\liboscar.dll"
+- Delete "$INSTDIR\libplc4.dll"
+- Delete "$INSTDIR\libplds4.dll"
+- Delete "$INSTDIR\libpurple.dll"
+- Delete "$INSTDIR\libsasl.dll"
+- Delete "$INSTDIR\libsilc-1-1-2.dll"
+- Delete "$INSTDIR\libsilcclient-1-1-3.dll"
+- Delete "$INSTDIR\libssp-0.dll"
+- Delete "$INSTDIR\libxml2-2.dll"
+- Delete "$INSTDIR\libymsg.dll"
+- Delete "$INSTDIR\nss3.dll"
+- Delete "$INSTDIR\nssutil3.dll"
+- Delete "$INSTDIR\pidgin.dll"
+- Delete "$INSTDIR\pidgin.exe"
+- Delete "$INSTDIR\smime3.dll"
+- Delete "$INSTDIR\softokn3.dll"
+- Delete "$INSTDIR\sqlite3.dll"
+- Delete "$INSTDIR\ssl3.dll"
+- Delete "$INSTDIR\${PIDGIN_UNINST_EXE}"
+- Delete "$INSTDIR\exchndl.dll"
+- Delete "$INSTDIR\install.log"
+-
+- ; Remove the debug symbols
+- RMDir /r "$INSTDIR\pidgin-${PIDGIN_VERSION}-dbgsym"
+-
+- ; Remove the local GTK+ copy (if we're not just upgrading)
+- ${GetParameters} $R0
+- ClearErrors
+- ${GetOptions} "$R0" "/UPGRADE=" $R1
+- IfErrors +2
+- StrCmp $R1 "1" upgrade_done
+- RMDir /r "$INSTDIR\Gtk"
+- ; Remove the downloaded spellcheck dictionaries (if we're not just upgrading)
+- RMDir /r "$INSTDIR\spellcheck"
+- upgrade_done:
+-
+- ;Try to remove Pidgin install dir (only if empty)
+- RMDir "$INSTDIR"
+-
+- ; Shortcuts..
+- Delete "$DESKTOP\Pidgin.lnk"
+- Delete "$SMPROGRAMS\Pidgin.lnk"
+-
+- Goto done
+-
+- cant_uninstall:
+- MessageBox MB_OK $(PIDGINUNINSTALLERROR1) /SD IDOK
+- Quit
+-
+- no_rights:
+- MessageBox MB_OK $(PIDGINUNINSTALLERROR2) /SD IDOK
+- Quit
+-
+- done:
+-SectionEnd ; end of uninstall section
+-
+-;--------------------------------
+-;Descriptions
+-!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecPidgin} \
+- $(PIDGINSECTIONDESCRIPTION)
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecGtk} \
+- $(GTKSECTIONDESCRIPTION)
+-
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecShortcuts} \
+- $(PIDGINSHORTCUTSSECTIONDESCRIPTION)
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecDesktopShortcut} \
+- $(PIDGINDESKTOPSHORTCUTDESC)
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecStartMenuShortcut} \
+- $(PIDGINSTARTMENUSHORTCUTDESC)
+-
+- !insertmacro MUI_DESCRIPTION_TEXT ${SecSpellCheck} \
+- $(PIDGINSPELLCHECKSECTIONDESCRIPTION)
+-
+-!insertmacro MUI_FUNCTION_DESCRIPTION_END
+-
+-;--------------------------------
+-;Functions
+-
+-; Default the URI handler checkboxes if Pidgin is the current handler or if there is no handler
+-Function SelectURIHandlerSelections
+- Push $R0
+- Push $R1
+- Push $R2
+- Push $R3
+-
+- ; Start with the first URI handler
+- IntOp $R0 ${SecURIHandlers} + 1
+-
+- start:
+- ; If it is the end of the section group, stop
+- SectionGetFlags $R0 $R1
+- IntOp $R2 $R1 & ${SF_SECGRPEND}
+- IntCmp $R2 ${SF_SECGRPEND} done
+-
+- SectionGetText $R0 $R2
+- ;Strip the trailing ':'
+- StrLen $R3 $R2
+- IntOp $R3 $R3 - 1
+- StrCpy $R2 $R2 $R3
+-
+- ClearErrors
+- ReadRegStr $R3 HKCR "$R2" ""
+- IfErrors default_on ;there is no current handler
+-
+- Push $R2
+- Call CheckIfPidginIsCurrentURIHandler
+- Pop $R3
+-
+- ; If Pidgin isn't the current handler, we don't steal it automatically
+- IntCmp $R3 0 end_loop
+-
+- ;We default the URI handler checkbox on
+- default_on:
+- IntOp $R1 $R1 | ${SF_SELECTED} ; Select
+- SectionSetFlags $R0 $R1
+-
+- end_loop:
+- IntOp $R0 $R0 + 1 ;Advance to the next section
+- Goto start
+-
+- done:
+- Pop $R3
+- Pop $R2
+- Pop $R1
+- Pop $R0
+-FunctionEnd ;SelectURIHandlerSections
+-
+-; Check if Pidgin is the current handler
+-; Returns a boolean on the stack
+-!macro CheckIfPidginIsCurrentURIHandlerMacro UN
+-Function ${UN}CheckIfPidginIsCurrentURIHandler
+- Exch $R0
+- ClearErrors
+-
+- ReadRegStr $R0 HKCR "$R0\shell\Open\command" ""
+- IfErrors 0 +3
+- IntOp $R0 0 + 0
+- Goto done
+-
+- !ifdef __UNINSTALL__
+- ${un.WordFind} "$R0" "pidgin.exe" "E+1{" $R0
+- !else
+- ${WordFind} "$R0" "pidgin.exe" "E+1{" $R0
+- !endif
+- IntOp $R0 0 + 1
+- IfErrors 0 +2
+- IntOp $R0 0 + 0
+-
+- done:
+- Exch $R0
+-FunctionEnd
+-!macroend
+-!insertmacro CheckIfPidginIsCurrentURIHandlerMacro ""
+-!insertmacro CheckIfPidginIsCurrentURIHandlerMacro "un."
+-
+-; If Pidgin is the current URI handler for the specified protocol, remove it.
+-Function un.UnregisterURIHandler
+- Exch $R0
+- Push $R1
+-
+- Push $R0
+- Call un.CheckIfPidginIsCurrentURIHandler
+- Pop $R1
+-
+- ; If Pidgin isn't the current handler, leave it as-is
+- IntCmp $R1 0 done
+-
+- ;Unregister the URI handler
+- DetailPrint "Unregistering $R0 URI Handler"
+- DeleteRegKey HKCR "$R0"
+-
+- done:
+- Pop $R1
+- Pop $R0
+-FunctionEnd
+-
+-Function RegisterURIHandler
+- Exch $R0
+- DetailPrint "Registering $R0 URI Handler"
+- DeleteRegKey HKCR "$R0"
+- WriteRegStr HKCR "$R0" "" "URL:$R0"
+- WriteRegStr HKCR "$R0" "URL Protocol" ""
+- WriteRegStr HKCR "$R0\DefaultIcon" "" "$INSTDIR\pidgin.exe"
+- WriteRegStr HKCR "$R0\shell" "" ""
+- WriteRegStr HKCR "$R0\shell\Open" "" ""
+- WriteRegStr HKCR "$R0\shell\Open\command" "" "$INSTDIR\pidgin.exe --protocolhandler=%1"
+- Pop $R0
+-FunctionEnd
+-
+-
+-!macro CheckUserInstallRightsMacro UN
+-Function ${UN}CheckUserInstallRights
+- Push $0
+- Push $1
+- ClearErrors
+- UserInfo::GetName
+- IfErrors Win9x
+- Pop $0
+- UserInfo::GetAccountType
+- Pop $1
+-
+- StrCmp $1 "Admin" 0 +3
+- StrCpy $1 "HKLM"
+- Goto done
+- StrCmp $1 "Power" 0 +3
+- StrCpy $1 "HKLM"
+- Goto done
+- StrCmp $1 "User" 0 +3
+- StrCpy $1 "HKCU"
+- Goto done
+- StrCmp $1 "Guest" 0 +3
+- StrCpy $1 "NONE"
+- Goto done
+- ; Unknown error
+- StrCpy $1 "NONE"
+- Goto done
+-
+- Win9x:
+- StrCpy $1 "HKLM"
+-
+- done:
+- Exch $1
+- Exch
+- Pop $0
+-FunctionEnd
+-!macroend
+-!insertmacro CheckUserInstallRightsMacro ""
+-!insertmacro CheckUserInstallRightsMacro "un."
+-
+-;
+-; Usage:
+-; Push $0 ; Path string
+-; Call VerifyDir
+-; Pop $0 ; 0 - Bad path 1 - Good path
+-;
+-Function VerifyDir
+- Exch $0
+- Push $1
+- Push $2
+- Loop:
+- IfFileExists $0 dir_exists
+- StrCpy $1 $0 ; save last
+- ${GetParent} $0 $0
+- StrLen $2 $0
+- ; IfFileExists "C:" on xp returns true and on win2k returns false
+- ; So we're done in such a case..
+- IntCmp $2 2 loop_done
+- ; GetParent of "C:" returns ""
+- IntCmp $2 0 loop_done
+- Goto Loop
+-
+- loop_done:
+- StrCpy $1 "$0\GaImFooB"
+- ; Check if we can create dir on this drive..
+- ClearErrors
+- CreateDirectory $1
+- IfErrors DirBad DirGood
+-
+- dir_exists:
+- ClearErrors
+- FileOpen $1 "$0\pidginfoo.bar" w
+- IfErrors PathBad PathGood
+-
+- DirGood:
+- RMDir $1
+- Goto PathGood1
+-
+- DirBad:
+- RMDir $1
+- Goto PathBad1
+-
+- PathBad:
+- FileClose $1
+- Delete "$0\pidginfoo.bar"
+- PathBad1:
+- StrCpy $0 "0"
+- Push $0
+- Goto done
+-
+- PathGood:
+- FileClose $1
+- Delete "$0\pidginfoo.bar"
+- PathGood1:
+- StrCpy $0 "1"
+- Push $0
+-
+- done:
+- Exch 3 ; The top of the stack contains the output variable
+- Pop $0
+- Pop $2
+- Pop $1
+-FunctionEnd
+-
+-Function .onVerifyInstDir
+- Push $0
+- Push $INSTDIR
+- Call VerifyDir
+- Pop $0
+- StrCmp $0 "0" 0 dir_good
+- Pop $0
+- Abort
+-
+- dir_good:
+- Pop $0
+-FunctionEnd
+-
+-;
+-; Usage:
+-; Call DoWeNeedGtk
+-; First Pop:
+-; 0 - We have the correct version
+-; 1 - We have an old version that should work, prompt user for optional upgrade
+-; 2 - We have an old version that needs to be upgraded
+-; 3 - We don't have Gtk+ at all
+-;
+-Function DoWeNeedGtk
+- Push $0
+- Push $1
+-
+- IfFileExists "$INSTDIR\Gtk\CONTENTS" +3
+- Push "3"
+- Goto done
+-
+- ClearErrors
+- ${ConfigRead} "$INSTDIR\Gtk\CONTENTS" "Bundle Version " $0
+- IfErrors 0 +3
+- Push "3"
+- Goto done
+-
+- ${VersionCompare} ${GTK_INSTALL_VERSION} $0 $1
+- IntCmp $1 1 +3
+- Push "0" ; Have a good version
+- Goto done
+-
+- ${VersionCompare} ${GTK_MIN_VERSION} $0 $1
+- IntCmp $1 1 +3
+- Push "1" ; Optional Upgrade
+- Goto done
+- Push "2" ; Mandatory Upgrade
+- Goto done
+-
+- done:
+- ; The item on the stack is what we want to return
+- Exch
+- Pop $1
+- Exch
+- Pop $0
+-FunctionEnd
+-
+-
+-!macro RunCheckMacro UN
+-Function ${UN}RunCheck
+- Push $R0
+- Push $R1
+-
+- IntOp $R1 0 + 0
+- retry_runcheck:
+- ; Close the Handle (needed if we're retrying)
+- IntCmp $R1 0 +2
+- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
+- System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_is_running") i .R1 ?e'
+- Pop $R0
+- IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume
+- MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(PIDGINISRUNNING) /SD IDCANCEL IDRETRY retry_runcheck
+- Abort
+-
+- ; Close the Handle (If we don't do this, the uninstaller called from within will fail)
+- ; This is not optimal because there is a (small) window of time when a new process could start
+- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
+-
+- Pop $R1
+- Pop $R0
+-FunctionEnd
+-!macroend
+-!insertmacro RunCheckMacro ""
+-!insertmacro RunCheckMacro "un."
+-
+-Function .onInit
+- Push $R0
+- Push $R1
+- Push $R2
+- Push $R3 ; This is only used for the Parameters throughout the function
+-
+- ${GetParameters} $R3
+-
+- IntOp $R1 0 + 0
+- retry_runcheck:
+- ; Close the Handle (needed if we're retrying)
+- IntCmp $R1 0 +2
+- System::Call 'kernel32::CloseHandle(i $R1) i .R1'
+- System::Call 'kernel32::CreateMutexA(i 0, i 0, t "pidgin_installer_running") i .R1 ?e'
+- Pop $R0
+- IntCmp $R0 0 +3 ;This could check for ERROR_ALREADY_EXISTS(183), but lets just assume
+- MessageBox MB_RETRYCANCEL|MB_ICONEXCLAMATION $(INSTALLERISRUNNING) /SD IDCANCEL IDRETRY retry_runcheck
+- Abort
+-
+- ; Allow installer to run even if pidgin is running via "/NOPIDGINRUNCHECK=1"
+- ; This is useful for testing
+- ClearErrors
+- ${GetOptions} "$R3" "/NOPIDGINRUNCHECK=" $R1
+- IfErrors 0 +2
+- Call RunCheck
+-
+- StrCpy $name "Pidgin ${PIDGIN_VERSION}"
+-
+- ;Try to copy the old Gaim installer Lang Reg. key
+- ;(remove it after we're done to prevent this being done more than once)
+- ClearErrors
+- ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+- IfErrors 0 +5
+- ClearErrors
+- ReadRegStr $R0 HKCU "${OLD_GAIM_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+- IfErrors +3
+- DeleteRegValue HKCU "${OLD_GAIM_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+- WriteRegStr HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}" "$R0"
+-
+- ${MementoSectionRestore}
+-
+- ;Preselect the URI handlers as appropriate
+- Call SelectURIHandlerSelections
+-
+- ;Preselect the "shortcuts" checkboxes according to the previous installation
+- ClearErrors
+- ;Make sure that there was a previous installation
+- ReadRegStr $R0 HKCU "${PIDGIN_REG_KEY}" "${MUI_LANGDLL_REGISTRY_VALUENAME}"
+- IfErrors done_preselecting_shortcuts
+- ;Does the Desktop shortcut exist?
+- GetFileTime "$DESKTOP\Pidgin.lnk" $R0 $R0
+- IfErrors +1 +5
+- ClearErrors
+- SetShellVarContext "all"
+- GetFileTime "$DESKTOP\Pidgin.lnk" $R0 $R0
+- IfErrors preselect_startmenu_shortcut ;Desktop Shortcut if off by default
+- !insertmacro SelectSection ${SecDesktopShortcut}
+- preselect_startmenu_shortcut:
+- ;Reset ShellVarContext because we may have changed it
+- SetShellVarContext "current"
+- ClearErrors
+- ;Does the StartMenu shortcut exist?
+- GetFileTime "$SMPROGRAMS\Pidgin.lnk" $R0 $R0
+- IfErrors +1 done_preselecting_shortcuts ;StartMenu Shortcut is on by default
+- ClearErrors
+- SetShellVarContext "all"
+- GetFileTime "$SMPROGRAMS\Pidgin.lnk" $R0 $R0
+- IfErrors +1 done_preselecting_shortcuts ;StartMenu Shortcut is on by default
+- !insertmacro UnselectSection ${SecStartMenuShortcut}
+- done_preselecting_shortcuts:
+- ;Reset ShellVarContext because we may have changed it
+- SetShellVarContext "current"
+-
+- ClearErrors
+- ${GetOptions} "$R3" "/L=" $R1
+- IfErrors +3
+- StrCpy $LANGUAGE $R1
+- Goto skip_lang
+-
+- ; Select Language
+- ; Display Language selection dialog
+- !define MUI_LANGDLL_ALWAYSSHOW
+- !insertmacro MUI_LANGDLL_DISPLAY
+- skip_lang:
+-
+- ClearErrors
+- ${GetOptions} "$R3" "/DS=" $R1
+- IfErrors +8
+- SectionGetFlags ${SecDesktopShortcut} $R2
+- StrCmp "1" $R1 0 +2
+- IntOp $R2 $R2 | ${SF_SELECTED}
+- StrCmp "0" $R1 0 +3
+- IntOp $R1 ${SF_SELECTED} ~
+- IntOp $R2 $R2 & $R1
+- SectionSetFlags ${SecDesktopShortcut} $R2
+-
+- ClearErrors
+- ${GetOptions} "$R3" "/SMS=" $R1
+- IfErrors +8
+- SectionGetFlags ${SecStartMenuShortcut} $R2
+- StrCmp "1" $R1 0 +2
+- IntOp $R2 $R2 | ${SF_SELECTED}
+- StrCmp "0" $R1 0 +3
+- IntOp $R1 ${SF_SELECTED} ~
+- IntOp $R2 $R2 & $R1
+- SectionSetFlags ${SecStartMenuShortcut} $R2
+-
+- ; If install path was set on the command, use it.
+- StrCmp $INSTDIR "" 0 instdir_done
+-
+- ; If pidgin or gaim is currently installed, we should default to where it is currently installed
+- ClearErrors
+- ReadRegStr $INSTDIR HKCU "${PIDGIN_REG_KEY}" ""
+- IfErrors +2
+- StrCmp $INSTDIR "" 0 instdir_done
+- ClearErrors
+- ReadRegStr $INSTDIR HKLM "${PIDGIN_REG_KEY}" ""
+- IfErrors +2
+- StrCmp $INSTDIR "" 0 instdir_done
+-
+- Call CheckUserInstallRights
+- Pop $R0
+-
+- StrCmp $R0 "HKLM" 0 user_dir
+- StrCpy $INSTDIR "$PROGRAMFILES\Pidgin"
+- Goto instdir_done
+- user_dir:
+- Push $SMPROGRAMS
+- ${GetParent} $SMPROGRAMS $R2
+- ${GetParent} $R2 $R2
+- StrCpy $INSTDIR "$R2\Pidgin"
+-
+- instdir_done:
+-;LogSet on
+-
+- ; Try to select a translation and a dictionary for the currently selected Language
+- Call SelectTranslationForCurrentLanguage
+-
+- ;Mark the dictionaries that are already installed as readonly
+- Call SelectAndDisableInstalledDictionaries
+-
+- Pop $R3
+- Pop $R2
+- Pop $R1
+- Pop $R0
+-FunctionEnd
+-
+-Function .onInstSuccess
+-
+- ${MementoSectionSave}
+-
+-FunctionEnd
+-
+-
+-Function un.onInit
+-
+- Call un.RunCheck
+- StrCpy $name "Pidgin ${PIDGIN_VERSION}"
+-;LogSet on
+-
+- ; Get stored language preference
+- !insertmacro MUI_UNGETLANGUAGE
+-
+-FunctionEnd
+-
+-; Page enter and exit functions..
+-
+-Function preWelcomePage
+- Push $R0
+- Push $R1
+-
+-!ifdef OFFLINE_INSTALLER
+- !insertmacro SelectSection ${SecDebugSymbols}
+-!endif
+-
+- Call DoWeNeedGtk
+- Pop $CURRENT_GTK_STATE
+- StrCpy $WARNED_GTK_STATE "0"
+- IntCmp $CURRENT_GTK_STATE 1 done gtk_not_mandatory
+- ; Make the GTK+ Section RO if it is required. (it is required only if you have an existing version that is too old)
+- StrCmp $CURRENT_GTK_STATE "2" 0 done
+- !insertmacro SetSectionFlag ${SecGtk} ${SF_RO}
+- Goto done
+- gtk_not_mandatory:
+- ; Don't select the GTK+ section if we already have this version or newer installed
+- !insertmacro UnselectSection ${SecGtk}
+-
+- done:
+- Pop $R1
+- Pop $R0
+-FunctionEnd
+-
+-; If the GTK+ Section has been unselected and there isn't a compatible GTK+ already, confirm
+-Function .onSelChange
+- Push $R0
+-
+- SectionGetFlags ${SecGtk} $R0
+- IntOp $R0 $R0 & ${SF_SELECTED}
+- ; If the Gtk Section is currently selected, reset the "Warned" flag
+- StrCmp $R0 "${SF_SELECTED}" 0 +3
+- StrCpy $WARNED_GTK_STATE "0"
+- Goto done
+-
+- ; If we've already warned the user, don't warn them again
+- StrCmp $WARNED_GTK_STATE "1" done
+- IntCmp $CURRENT_GTK_STATE 1 done done 0
+- StrCpy $WARNED_GTK_STATE "1"
+- MessageBox MB_YESNO $(PIDGINPROMPTFORCENOGTK) /SD IDNO IDYES done
+- !insertmacro SelectSection ${SecGtk}
+-
+- done:
+- Pop $R0
+-FunctionEnd
+-
+-Function SelectTranslationForCurrentLanguage
+-!insertmacro SELECT_TRANSLATION_FUNCTION
+-FunctionEnd
+-
+-; SpellChecker Related Functions
+-;-------------------------------
+-
+-; Select and Disable any Sections that have currently installed dictionaries
+-!macro CHECK_SPELLCHECK_SECTION lang
+- ;Advance to the next (correct) section index
+- IntOp $R0 $R0 + 1
+- IfFileExists "$INSTDIR\spellcheck\share\enchant\myspell\${lang}.dic" 0 done_${lang}
+- SectionGetFlags $R0 $R1
+- IntOp $R1 $R1 | ${SF_RO} ; Mark Readonly
+- IntOp $R1 $R1 | ${SF_SELECTED} ; Select
+- SectionSetFlags $R0 $R1
+- done_${lang}:
+-!macroend
+-Function SelectAndDisableInstalledDictionaries
+- Push $R0
+- Push $R1
+-
+- !insertmacro SetSectionFlag ${SecSpellCheck} ${SF_RO}
+- !insertmacro UnselectSection ${SecSpellCheck}
+-
+- IntOp $R0 ${SecSpellCheck} + 0
+- !include "pidgin-spellcheck-preselect.nsh"
+-
+- Pop $R1
+- Pop $R0
+-FunctionEnd
+-
+-Function InstallDict
+- Push $R0
+- Exch
+- Pop $R0 ;This is the language code
+- Push $R1
+- Exch 2
+- Pop $R1 ;This is the language file
+- Push $R2
+- Push $R3
+- Push $R4
+-
+- ClearErrors
+- IfFileExists "$INSTDIR\spellcheck\share\enchant\myspell\$R0.dic" installed
+-
+- InitPluginsDir
+-
+- ; We need to download and install dictionary
+- StrCpy $R2 "$PLUGINSDIR\$R1"
+- StrCpy $R3 "${DOWNLOADER_URL}&dl_pkg=oo_dict&lang=$R1&lang_file=$R1"
+- DetailPrint "Downloading the $R0 Dictionary... ($R3)"
+- retry:
+- NSISdl::download /TIMEOUT=10000 "$R3" "$R2"
+- Pop $R4
+- StrCmp $R4 "cancel" done
+- StrCmp $R4 "success" +3
+- MessageBox MB_RETRYCANCEL "$(PIDGINSPELLCHECKERROR)" /SD IDCANCEL IDRETRY retry IDCANCEL done
+- Goto done
+- SetOutPath "$INSTDIR\spellcheck\share\enchant\myspell"
+- nsisunz::UnzipToLog "$R2" "$OUTDIR"
+- SetOutPath "$INSTDIR"
+- Pop $R3
+- StrCmp $R3 "success" installed
+- DetailPrint "$R3" ;print error message to log
+- Goto done
+-
+- installed: ;The dictionary is currently installed, no error message
+- DetailPrint "$R0 Dictionary is installed"
+-
+- done:
+- Pop $R4
+- Pop $R3
+- Pop $R2
+- Pop $R0
+- Exch $R1
+-FunctionEnd
+-
+-!ifndef OFFLINE_INSTALLER
+-; Input Stack: Filename, SHA1sum
+-; Output Return Code: 0=Match; 1=FileSum error; 2=Mismatch
+-Function CheckSHA1Sum
+- Push $R0
+- Exch
+- Pop $R0 ;Filename
+- Push $R2
+- Exch 2
+- Pop $R2 ;SHA1sum
+- Push $R1
+-
+- SHA1Plugin::FileSum "$R0"
+- Pop $R1
+- Pop $R0
+-
+- StrCmp "$R1" "0" +4
+- DetailPrint "SHA1Sum calculation error: $R0"
+- IntOp $R1 0 + 1
+- Goto done
+-
+- ; Compare the SHA1Sums
+- StrCmp $R2 $R0 +4
+- DetailPrint "SHA1Sum mismatch... Expected $R2; got $R0"
+- IntOp $R1 0 + 2
+- Goto done
+-
+- IntOp $R1 0 + 0
+-
+- done:
+- Pop $R2
+- Pop $R0
+- Exch $R1 ;$R1 has the return code
+-FunctionEnd
+-!endif
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/pidgin-plugin.nsh pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-plugin.nsh
+--- pidgin-2.10.7/pidgin/win32/nsis/pidgin-plugin.nsh 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/pidgin-plugin.nsh 1969-12-31 21:00:00.000000000 -0300
+@@ -1,181 +0,0 @@
+-;;
+-;; Windows Pidgin NSIS installer plugin helper utilities
+-;; Copyright 2005, Daniel Atallah <daniel_atallah@yahoo.com>
+-;;
+-;; Include in plugin installer scripts using:
+-;; !addincludedir "${PATH_TO_PIDGIN_SRC}\pidgin\win32\nsis"
+-;; !include "pidgin-plugin.nsh"
+-;;
+-
+-!define PIDGIN_REG_KEY "SOFTWARE\pidgin"
+-
+-!define PIDGIN_VERSION_OK 0
+-!define PIDGIN_VERSION_INCOMPATIBLE 1
+-!define PIDGIN_VERSION_UNDEFINED 2
+-
+-; Extract the Pidgin Version from the registry
+-; This will set the Error flag if unable to determine the value
+-; Pop the value of the stack after calling this to get the value (unless Error Flag is set)
+-Function GetPidginVersion
+- Push $R0
+-
+- ; Read the pidgin version
+- ClearErrors
+- ReadRegStr $R0 HKLM ${PIDGIN_REG_KEY} "Version"
+- IfErrors +1 GetPidginVersion_found
+- ; fall back to the HKCU registry key
+- ReadRegStr $R0 HKCU ${PIDGIN_REG_KEY} "Version"
+- IfErrors GetPidginVersion_done ; Keep the error flag set
+-
+- GetPidginVersion_found:
+- Push $R0 ; Push the value onto the stack
+- Exch
+-
+- GetPidginVersion_done:
+- ; restore $R0
+- Pop $R0
+-FunctionEnd
+-
+-; Check that the currently installed Pidgin version is compatible
+-; with the plugin version we are installing
+-; Push the Plugin's Pidgin Version onto the Stack before calling
+-; After calling, the top of the Stack will contain the result of the check:
+-; PIDGIN_VERSION_OK - If the installed Pidgin version is compatible w/ the version specified
+-; PIDGIN_VERSION_INCOMPATIBLE - If the installed Pidgin version isn't compatible w/ the version specified
+-; PIDGIN_VERSION_UNDEFINED - If the installed Pidgin version can't be determined
+-Function CheckPidginVersion
+- ; Save the Variable values that we will use in the stack
+- Push $R4
+- Exch
+- Pop $R4 ; Get the plugin's Pidgin Version
+- Push $R0
+- Push $R1
+- Push $R2
+-
+- ; Read the pidgin version
+- Call GetPidginVersion
+- IfErrors checkPidginVersion_noPidginInstallFound
+- Pop $R0
+-
+- ;If they are exactly the same, we don't need to look at anything else
+- StrCmp $R0 $R4 checkPidginVersion_VersionOK
+-
+- ; Versions are in the form of X.Y.Z
+- ; If X is different or plugin's Y > pidgin's Y, then we shouldn't install
+-
+- ;Check the Major Version
+- Push $R0
+- Push 0
+- Call GetVersionComponent
+- IfErrors checkPidginVersion_noPidginInstallFound ;We couldn't extract 'X' from the installed pidgin version
+- Pop $R2
+- Push $R4
+- Push 0
+- Call GetVersionComponent
+- IfErrors checkPidginVersion_BadVersion ; this isn't a valid version, so don't bother even checking
+- Pop $R1
+- ;Check that both versions' X is the same
+- StrCmp $R1 $R2 +1 checkPidginVersion_BadVersion
+-
+- ;Check the Minor Version
+- Push $R0
+- Push 1
+- Call GetVersionComponent
+- IfErrors checkPidginVersion_noPidginInstallFound ;We couldn't extract 'Y' from the installed pidgin version
+- Pop $R2
+- Push $R4
+- Push 1
+- Call GetVersionComponent
+- IfErrors checkPidginVersion_BadVersion ; this isn't a valid version, so don't bother even checking
+- Pop $R1
+- ;Check that plugin's Y <= pidgin's Y
+- IntCmp $R1 $R2 checkPidginVersion_VersionOK checkPidginVersion_VersionOK checkPidginVersion_BadVersion
+-
+- checkPidginVersion_BadVersion:
+- Push ${PIDGIN_VERSION_INCOMPATIBLE}
+- goto checkPidginVersion_done
+- checkPidginVersion_noPidginInstallFound:
+- Push ${PIDGIN_VERSION_UNDEFINED}
+- goto checkPidginVersion_done
+- checkPidginVersion_VersionOK:
+- Push ${PIDGIN_VERSION_OK}
+-
+- checkPidginVersion_done:
+- ; Restore the Variables that we used
+- Exch
+- Pop $R2
+- Exch
+- Pop $R1
+- Exch
+- Pop $R0
+- Exch
+- Pop $R4
+-FunctionEnd
+-
+-; Extract the part of a string prior to "." (or the whole string if there is no ".")
+-; If no "." was found, the ErrorFlag will be set
+-; Before this is called, Push ${VERSION_STRING} must be called, and then Push 0 for Major, 1 for Minor, etc
+-; Pop should be called after to retrieve the new value
+-Function GetVersionComponent
+- ClearErrors
+-
+- ; Save the Variable values that we will use in the stack
+- Push $1
+- Exch
+- Pop $1 ;The version component which we want to extract (0, 1, 2)
+- Exch
+- Push $0
+- Exch
+- Pop $0 ;The string from which to extract the version component
+-
+- Push $2
+- Push $3
+- Push $4
+- Push $5
+- Push $6
+- Push $7
+-
+- StrCpy $2 "0" ;Initialize our string index counter
+- StrCpy $7 "0" ;Index of last "."
+- StrCpy $3 "0" ;Initialize our version index counter
+-
+- startGetVersionComponentLoop:
+- ;avoid infinite loop (if we have gotten the whole initial string, exit the loop and set the error flag)
+- StrCmp $6 $0 GetVersionComponentSetErrorFlag
+- IntOp $2 $2 + 1
+- StrCpy $6 $0 $2 ;Update the infinite loop preventing string
+- ;Determine the correct substring (only the current index component)
+- IntOp $5 $2 - $7
+- StrCpy $4 $0 $5 $7 ;Append the current character in $0 to $4
+- StrCpy $5 $0 1 $2 ;store the next character in $5
+-
+- ;if the next character is ".", $4 will contain the version component prior to "."
+- StrCmp $5 "." +1 startGetVersionComponentLoop
+- StrCmp $3 $1 doneGetVersionComponent ;If it is the version component we're looking for, stop
+- IntOp $3 $3 + 1 ;Increment the version index counter
+- IntOp $2 $2 + 1 ;Increment the version string index to "." (so it will be skipped)
+- StrCpy $7 $2 ;Keep track of the index of the last "."
+- StrCpy $6 $0 $2 ;Update the infinite loop preventing string
+- goto startGetVersionComponentLoop
+-
+- GetVersionComponentSetErrorFlag:
+- SetErrors
+-
+- doneGetVersionComponent:
+- ; Restore the Variables that we used
+- Pop $7
+- Pop $6
+- Pop $5
+- Push $4 ;This is the value we're returning
+- Exch
+- Pop $4
+- Exch
+- Pop $3
+- Exch
+- Pop $2
+- Exch
+- Pop $0
+- Exch
+- Pop $1
+-FunctionEnd
+-
+Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-header.bmp and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-header.bmp differ
+Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-install.ico and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-install.ico differ
+Binary files pidgin-2.10.7/pidgin/win32/nsis/pixmaps/pidgin-intro.bmp and pidgin-2.10.7-nonprism/pidgin/win32/nsis/pixmaps/pidgin-intro.bmp differ
+diff -Nur pidgin-2.10.7/pidgin/win32/nsis/rpm2zip.sh pidgin-2.10.7-nonprism/pidgin/win32/nsis/rpm2zip.sh
+--- pidgin-2.10.7/pidgin/win32/nsis/rpm2zip.sh 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/nsis/rpm2zip.sh 1969-12-31 21:00:00.000000000 -0300
+@@ -1,65 +0,0 @@
+-#!/bin/sh
+-
+-here=`pwd`
+-for F in $*; do
+- case $F in
+- mingw32-*.noarch.rpm|mingw64-*.noarch.rpm|*/mingw32-*.noarch.rpm|*/mingw64-*.noarch.rpm)
+- package=`rpm -qp $F 2>/dev/null`
+- case $package in
+- mingw32-*|mingw64-*)
+- case $package in
+- mingw32-*)
+- cpu=i686
+- bits=32
+- ;;
+- mingw64-*)
+- cpu=x86_64
+- bits=64
+- ;;
+- esac
+- origname=`rpm -qp --queryformat='%{NAME}' $F 2>/dev/null`
+- name=$origname
+- case $name in
+- *-devel)
+- name=${name%el}
+- ;;
+- esac
+- shortpackage="$name"_`rpm -qp --queryformat='%{VERSION}-%{RELEASE}'_win${bits} $F 2>/dev/null`
+- shortpackage=${shortpackage#mingw32-}
+- shortpackage=${shortpackage#mingw64-}
+- shortname=$name
+- shortname=${shortname#mingw32-}
+- shortname=${shortname#mingw64-}
+- tmp=`mktemp -d`
+- #rpm2cpio $F | lzcat | (cd $tmp && cpio --quiet -id)
+- rpm2cpio $F | (cd $tmp && cpio --quiet -id)
+- (
+- cd $tmp
+- zipfile="$here/$shortpackage.zip"
+- rm -f $zipfile
+- (cd usr/${cpu}-pc-mingw32/sys-root/mingw && zip -q -r -D $zipfile .)
+- if [ -d usr/share/doc/packages/$origname ] ; then
+- mv usr/share/doc/packages/$origname usr/share/doc/packages/$shortname
+- (cd usr && zip -q -r -D $zipfile share/doc/packages/$shortname)
+- fi
+- mkdir -p manifest
+- unzip -l $zipfile >manifest/$shortpackage.mft
+- zip -q $zipfile manifest/$shortpackage.mft
+- N=`unzip -l $zipfile | wc -l | sed -e 's/^ *\([0-9]*\).*/\1/'`
+- Nm1=`expr $N - 1`
+- unzip -l $zipfile | sed -e "1,3 d" -e "$Nm1,$N d" | awk '{print $4}' | grep -v -E '/$' >manifest/$shortpackage.mft
+- zip -q $zipfile manifest/$shortpackage.mft
+- echo $zipfile
+- )
+- rm -rf $tmp
+- ;;
+- *)
+- echo $F is not a mingw32/64 RPM package >&2
+- ;;
+- esac
+- ;;
+- *)
+- echo $F is not a mingw32/64 RPM package >&2
+- ;;
+- esac
+-done
+diff -Nur pidgin-2.10.7/pidgin/win32/pidgin_dll_rc.rc.in pidgin-2.10.7-nonprism/pidgin/win32/pidgin_dll_rc.rc.in
+--- pidgin-2.10.7/pidgin/win32/pidgin_dll_rc.rc.in 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/pidgin_dll_rc.rc.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,41 +0,0 @@
+-#include <winver.h>
+-#include "version.h"
+-#include "resource.h"
+-
+-VS_VERSION_INFO VERSIONINFO
+- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- FILEFLAGSMASK 0
+- FILEFLAGS 0
+- FILEOS VOS__WINDOWS32
+- FILETYPE VFT_DLL
+- FILESUBTYPE VFT2_UNKNOWN
+- BEGIN
+- BLOCK "StringFileInfo"
+- BEGIN
+- BLOCK "040904B0"
+- BEGIN
+- VALUE "CompanyName", "The Pidgin developer community"
+- VALUE "FileDescription", "GTK+ Pidgin Library"
+- VALUE "FileVersion", "@PIDGIN_VERSION@"
+- VALUE "InternalName", "libpidgin"
+- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
+- VALUE "OriginalFilename", "pidgin.dll"
+- VALUE "ProductName", "Pidgin"
+- VALUE "ProductVersion", "@PIDGIN_VERSION@"
+- END
+- END
+- BLOCK "VarFileInfo"
+- BEGIN
+- VALUE "Translation", 0x409, 1200
+- END
+- END
+-
+-PIDGIN_TRAY_AVAILABLE_4BIT ICON "pixmaps/tray/16/available_4bit.ico"
+-PIDGIN_TRAY_AWAY_4BIT ICON "pixmaps/tray/16/away_4bit.ico"
+-PIDGIN_TRAY_BUSY_4BIT ICON "pixmaps/tray/16/busy_4bit.ico"
+-PIDGIN_TRAY_XA_4BIT ICON "pixmaps/tray/16/extended-away_4bit.ico"
+-PIDGIN_TRAY_OFFLINE_4BIT ICON "pixmaps/tray/16/offline_4bit.ico"
+-PIDGIN_TRAY_CONNECTING_4BIT ICON "pixmaps/tray/16/connecting_4bit.ico"
+-PIDGIN_TRAY_PENDING_4BIT ICON "pixmaps/tray/16/message_4bit.ico"
+-PIDGIN_TRAY_INVISIBLE_4BIT ICON "pixmaps/tray/16/invisible_4bit.ico"
+diff -Nur pidgin-2.10.7/pidgin/win32/pidgin_exe_rc.rc.in pidgin-2.10.7-nonprism/pidgin/win32/pidgin_exe_rc.rc.in
+--- pidgin-2.10.7/pidgin/win32/pidgin_exe_rc.rc.in 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/pidgin_exe_rc.rc.in 1969-12-31 21:00:00.000000000 -0300
+@@ -1,34 +0,0 @@
+-#include <winver.h>
+-#include "resource.h"
+-#include "version.h"
+-
+-VS_VERSION_INFO VERSIONINFO
+- FILEVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- PRODUCTVERSION PURPLE_MAJOR_VERSION,PURPLE_MINOR_VERSION,PURPLE_MICRO_VERSION,0
+- FILEFLAGSMASK 0
+- FILEFLAGS 0
+- FILEOS VOS__WINDOWS32
+- FILETYPE VFT_APP
+- FILESUBTYPE VFT2_UNKNOWN
+- BEGIN
+- BLOCK "StringFileInfo"
+- BEGIN
+- BLOCK "040904B0"
+- BEGIN
+- VALUE "CompanyName", "The Pidgin developer community"
+- VALUE "FileDescription", "Pidgin"
+- VALUE "FileVersion", "@PIDGIN_VERSION@"
+- VALUE "InternalName", "pidgin"
+- VALUE "LegalCopyright", "Copyright (C) 1998-2010 The Pidgin developer community (See the COPYRIGHT file in the source distribution)."
+- VALUE "OriginalFilename", "@ORIGINAL_FILENAME@"
+- VALUE "ProductName", "Pidgin"
+- VALUE "ProductVersion", "@PIDGIN_VERSION@"
+- END
+- END
+- BLOCK "VarFileInfo"
+- BEGIN
+- VALUE "Translation", 0x409, 1200
+- END
+- END
+-
+-PIDGIN_ICON ICON "pixmaps/pidgin.ico"
+diff -Nur pidgin-2.10.7/pidgin/win32/resource.h pidgin-2.10.7-nonprism/pidgin/win32/resource.h
+--- pidgin-2.10.7/pidgin/win32/resource.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/resource.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,9 +0,0 @@
+-#define PIDGIN_ICON 104
+-#define PIDGIN_TRAY_AVAILABLE_4BIT 105
+-#define PIDGIN_TRAY_AWAY_4BIT 106
+-#define PIDGIN_TRAY_BUSY_4BIT 107
+-#define PIDGIN_TRAY_XA_4BIT 108
+-#define PIDGIN_TRAY_OFFLINE_4BIT 109
+-#define PIDGIN_TRAY_CONNECTING_4BIT 110
+-#define PIDGIN_TRAY_PENDING_4BIT 111
+-#define PIDGIN_TRAY_INVISIBLE_4BIT 112
+diff -Nur pidgin-2.10.7/pidgin/win32/untar.c pidgin-2.10.7-nonprism/pidgin/win32/untar.c
+--- pidgin-2.10.7/pidgin/win32/untar.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/untar.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,633 +0,0 @@
+-/* untar.c */
+-
+-/*#define VERSION "1.4"*/
+-
+-/* DESCRIPTION:
+- * Untar extracts files from an uncompressed tar archive, or one which
+- * has been compressed with gzip. Usually such archives will have file
+- * names that end with ".tar" or ".tgz" respectively, although untar
+- * doesn't depend on any naming conventions. For a summary of the
+- * command-line options, run untar with no arguments.
+- *
+- * HOW TO COMPILE:
+- * Untar doesn't require any special libraries or compile-time flags.
+- * A simple "cc untar.c -o untar" (or the local equivalent) is
+- * sufficient. Even "make untar" works, without needing a Makefile.
+- * For Microsoft Visual C++, the command is "cl /D_WEAK_POSIX untar.c"
+- * (for 32 bit compilers) or "cl /F 1400 untar.c" (for 16-bit).
+- *
+- * IF YOU SEE COMPILER WARNINGS, THAT'S NORMAL; you can ignore them.
+- * Most of the warnings could be eliminated by adding #include <string.h>
+- * but that isn't portable -- some systems require <strings.h> and
+- * <malloc.h>, for example. Because <string.h> isn't quite portable,
+- * and isn't really necessary in the context of this program, it isn't
+- * included.
+- *
+- * PORTABILITY:
+- * Untar only requires the <stdio.h> header. It uses old-style function
+- * definitions. It opens all files in binary mode. Taken together,
+- * this means that untar should compile & run on just about anything.
+- *
+- * If your system supports the POSIX chmod(2), utime(2), link(2), and
+- * symlink(2) calls, then you may wish to compile with -D_POSIX_SOURCE,
+- * which will enable untar to use those system calls to restore the
+- * timestamp and permissions of the extracted files, and restore links.
+- * (For Linux, _POSIX_SOURCE is always defined.)
+- *
+- * For systems which support some POSIX features but not enough to support
+- * -D_POSIX_SOURCE, you might be able to use -D_WEAK_POSIX. This allows
+- * untar to restore time stamps and file permissions, but not links.
+- * This should work for Microsoft systems, and hopefully others as well.
+- *
+- * AUTHOR & COPYRIGHT INFO:
+- * Written by Steve Kirkendall, kirkenda@cs.pdx.edu
+- * Placed in public domain, 6 October 1995
+- *
+- * Portions derived from inflate.c -- Not copyrighted 1992 by Mark Adler
+- * version c10p1, 10 January 1993
+- *
+- * Altered by Herman Bloggs <hermanator12002@yahoo.com>
+- * April 4, 2003
+- * Changes: Stripped out gz compression code, added better interface for
+- * untar.
+- */
+-#include <windows.h>
+-#include <stdio.h>
+-#include <io.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#ifndef SEEK_SET
+-# define SEEK_SET 0
+-#endif
+-
+-#ifdef _WEAK_POSIX
+-# ifndef _POSIX_SOURCE
+-# define _POSIX_SOURCE
+-# endif
+-#endif
+-
+-#ifdef _POSIX_SOURCE
+-# include <sys/types.h>
+-# include <sys/stat.h>
+-# include <sys/utime.h>
+-# ifdef _WEAK_POSIX
+-# define mode_t int
+-# else
+-# include <unistd.h>
+-# endif
+-#endif
+-#include "debug.h"
+-#include "untar.h"
+-#include <glib.h>
+-
+-#include <glib/gstdio.h>
+-
+-#define untar_error( error, args... ) purple_debug(PURPLE_DEBUG_ERROR, "untar", error, ## args )
+-#define untar_warning( warning, args... ) purple_debug(PURPLE_DEBUG_WARNING, "untar", warning, ## args )
+-#define untar_verbose( args... ) purple_debug(PURPLE_DEBUG_INFO, "untar", ## args )
+-
+-#define WSIZE 32768 /* size of decompression buffer */
+-#define TSIZE 512 /* size of a "tape" block */
+-#define CR 13 /* carriage-return character */
+-#define LF 10 /* line-feed character */
+-
+-typedef unsigned char Uchar_t;
+-typedef unsigned short Ushort_t;
+-typedef unsigned long Ulong_t;
+-
+-typedef struct
+-{
+- char filename[100]; /* 0 name of next file */
+- char mode[8]; /* 100 Permissions and type (octal digits) */
+- char owner[8]; /* 108 Owner ID (ignored) */
+- char group[8]; /* 116 Group ID (ignored) */
+- char size[12]; /* 124 Bytes in file (octal digits) */
+- char mtime[12]; /* 136 Modification time stamp (octal digits)*/
+- char checksum[8]; /* 148 Header checksum (ignored) */
+- char type; /* 156 File type (see below) */
+- char linkto[100]; /* 157 Linked-to name */
+- char brand[8]; /* 257 Identifies tar version (ignored) */
+- char ownername[32]; /* 265 Name of owner (ignored) */
+- char groupname[32]; /* 297 Name of group (ignored) */
+- char devmajor[8]; /* 329 Device major number (ignored) */
+- char defminor[8]; /* 337 Device minor number (ignored) */
+- char prefix[155]; /* 345 Prefix of name (optional) */
+- char RESERVED[12]; /* 500 Pad header size to 512 bytes */
+-} tar_t;
+-#define ISREGULAR(hdr) ((hdr).type < '1' || (hdr).type > '6')
+-
+-Uchar_t slide[WSIZE];
+-
+-static const char *inname = NULL; /* name of input archive */
+-static FILE *infp = NULL; /* input byte stream */
+-static FILE *outfp = NULL; /* output stream, for file currently being extracted */
+-static Ulong_t outsize = 0; /* number of bytes remainin in file currently being extracted */
+-static char **only = NULL; /* array of filenames to extract/list */
+-static int nonlys = 0; /* number of filenames in "only" array; 0=extract all */
+-static int didabs = 0; /* were any filenames affected by the absence of -p? */
+-
+-static untar_opt untarops = 0; /* Untar options */
+-
+-/* Options checked during untar process */
+-#define LISTING (untarops & UNTAR_LISTING) /* 1 if listing, 0 if extracting */
+-#define QUIET (untarops & UNTAR_QUIET) /* 1 to write nothing to stdout, 0 for normal chatter */
+-#define VERBOSE (untarops & UNTAR_VERBOSE) /* 1 to write extra information to stdout */
+-#define FORCE (untarops & UNTAR_FORCE) /* 1 to overwrite existing files, 0 to skip them */
+-#define ABSPATH (untarops & UNTAR_ABSPATH) /* 1 to allow leading '/', 0 to strip leading '/' */
+-#define CONVERT (untarops & UNTAR_CONVERT) /* 1 to convert newlines, 0 to leave unchanged */
+-
+-/*----------------------------------------------------------------------------*/
+-
+-/* create a file for writing. If necessary, create the directories leading up
+- * to that file as well.
+- */
+-static FILE *createpath(name)
+- char *name; /* pathname of file to create */
+-{
+- FILE *fp;
+- int i;
+-
+- /* if we aren't allowed to overwrite and this file exists, return NULL */
+- if (!FORCE && access(name, 0) == 0)
+- {
+- untar_warning("%s: exists, will not overwrite without \"FORCE option\"\n", name);
+- return NULL;
+- }
+-
+- /* first try creating it the easy way */
+- fp = g_fopen(name, CONVERT ? "w" : "wb");
+- if (fp)
+- return fp;
+-
+- /* Else try making all of its directories, and then try creating
+- * the file again.
+- */
+- for (i = 0; name[i]; i++)
+- {
+- /* If this is a slash, then temporarily replace the '/'
+- * with a '\0' and do a mkdir() on the resulting string.
+- * Ignore errors for now.
+- */
+- if (name[i] == '/')
+- {
+- name[i] = '\0';
+- (void)g_mkdir(name, 0777);
+- name[i] = '/';
+- }
+- }
+- fp = g_fopen(name, CONVERT ? "w" : "wb");
+- if (!fp)
+- untar_error("Error opening: %s\n", name);
+- return fp;
+-}
+-
+-/* Create a link, or copy a file. If the file is copied (not linked) then
+- * give a warning.
+- */
+-static void linkorcopy(src, dst, sym)
+- char *src; /* name of existing source file */
+- char *dst; /* name of new destination file */
+- int sym; /* use symlink instead of link */
+-{
+- FILE *fpsrc;
+- FILE *fpdst;
+- int c;
+-
+- /* Open the source file. We do this first to make sure it exists */
+- fpsrc = g_fopen(src, "rb");
+- if (!fpsrc)
+- {
+- untar_error("Error opening: %s\n", src);
+- return;
+- }
+-
+- /* Create the destination file. On POSIX systems, this is just to
+- * make sure the directory path exists.
+- */
+- fpdst = createpath(dst);
+- if (!fpdst) {
+- /* error message already given */
+- fclose(fpsrc);
+- return;
+- }
+-
+-#ifdef _POSIX_SOURCE
+-# ifndef _WEAK_POSIX
+- /* first try to link it over, instead of copying */
+- fclose(fpdst);
+- g_unlink(dst);
+- if (sym)
+- {
+- if (symlink(src, dst))
+- {
+- perror(dst);
+- }
+- fclose(fpsrc);
+- return;
+- }
+- if (!link(src, dst))
+- {
+- /* This story had a happy ending */
+- fclose(fpsrc);
+- return;
+- }
+-
+- /* Dang. Reopen the destination again */
+- fpdst = g_fopen(dst, "wb");
+- /* This *can't* fail */
+-
+-# endif /* _WEAK_POSIX */
+-#endif /* _POSIX_SOURCE */
+-
+- /* Copy characters */
+- while ((c = getc(fpsrc)) != EOF)
+- putc(c, fpdst);
+-
+- /* Close the files */
+- fclose(fpsrc);
+- fclose(fpdst);
+-
+- /* Give a warning */
+- untar_warning("%s: copy instead of link\n", dst);
+-}
+-
+-/* This calls fwrite(), possibly after converting CR-LF to LF */
+-static void cvtwrite(blk, size, fp)
+- Uchar_t *blk; /* the block to be written */
+- Ulong_t size; /* number of characters to be written */
+- FILE *fp; /* file to write to */
+-{
+- int i, j;
+- static Uchar_t mod[TSIZE];
+-
+- if (CONVERT)
+- {
+- for (i = j = 0; i < size; i++)
+- {
+- /* convert LF to local newline convention */
+- if (blk[i] == LF)
+- mod[j++] = '\n';
+- /* If CR-LF pair, then delete the CR */
+- else if (blk[i] == CR && (i+1 >= size || blk[i+1] == LF))
+- ;
+- /* other characters copied literally */
+- else
+- mod[j++] = blk[i];
+- }
+- size = j;
+- blk = mod;
+- }
+-
+- fwrite(blk, (size_t)size, sizeof(Uchar_t), fp);
+-}
+-
+-
+-/* Compute the checksum of a tar header block, and return it as a long int.
+- * The checksum can be computed using either POSIX rules (unsigned bytes)
+- * or Sun rules (signed bytes).
+- */
+-static long checksum(tblk, sunny)
+- tar_t *tblk; /* buffer containing the tar header block */
+- int sunny; /* Boolean: Sun-style checksums? (else POSIX) */
+-{
+- long sum;
+- char *scan;
+-
+- /* compute the sum of the first 148 bytes -- everything up to but not
+- * including the checksum field itself.
+- */
+- sum = 0L;
+- for (scan = (char *)tblk; scan < tblk->checksum; scan++)
+- {
+- sum += (*scan) & 0xff;
+- if (sunny && (*scan & 0x80) != 0)
+- sum -= 256;
+- }
+-
+- /* for the 8 bytes of the checksum field, add blanks to the sum */
+- sum += ' ' * sizeof tblk->checksum;
+- scan += sizeof tblk->checksum;
+-
+- /* finish counting the sum of the rest of the block */
+- for (; scan < (char *)tblk + sizeof *tblk; scan++)
+- {
+- sum += (*scan) & 0xff;
+- if (sunny && (*scan & 0x80) != 0)
+- sum -= 256;
+- }
+-
+- return sum;
+-}
+-
+-
+-
+-/* list files in an archive, and optionally extract them as well */
+-static int untar_block(Uchar_t *blk) {
+- static char nbuf[256];/* storage space for prefix+name, combined */
+- static char *name,*n2;/* prefix and name, combined */
+- static int first = 1;/* Boolean: first block of archive? */
+- long sum; /* checksum for this block */
+- int i;
+- tar_t tblk[1];
+-
+-#ifdef _POSIX_SOURCE
+- static mode_t mode; /* file permissions */
+- static struct utimbuf timestamp; /* file timestamp */
+-#endif
+-
+- /* make a local copy of the block, and treat it as a tar header */
+- tblk[0] = *(tar_t *)blk;
+-
+- /* process each type of tape block differently */
+- if (outsize > TSIZE)
+- {
+- /* data block, but not the last one */
+- if (outfp)
+- cvtwrite(blk, (Ulong_t)TSIZE, outfp);
+- outsize -= TSIZE;
+- }
+- else if (outsize > 0)
+- {
+- /* last data block of current file */
+- if (outfp)
+- {
+- cvtwrite(blk, outsize, outfp);
+- fclose(outfp);
+- outfp = NULL;
+-#ifdef _POSIX_SOURCE
+- utime(nbuf, &timestamp);
+- chmod(nbuf, mode);
+-#endif
+- }
+- outsize = 0;
+- }
+- else if ((tblk)->filename[0] == '\0')
+- {
+- /* end-of-archive marker */
+- if (didabs)
+- untar_warning("Removed leading slashes because \"ABSPATH option\" wasn't given.\n");
+- return 1;
+- }
+- else
+- {
+- /* file header */
+-
+- /* half-assed verification -- does it look like header? */
+- if ((tblk)->filename[99] != '\0'
+- || ((tblk)->size[0] < '0'
+- && (tblk)->size[0] != ' ')
+- || (tblk)->size[0] > '9')
+- {
+- if (first)
+- {
+- untar_error("%s: not a valid tar file\n", inname);
+- return 0;
+- }
+- else
+- {
+- untar_error("Garbage detected; preceding file may be damaged\n");
+- return 0;
+- }
+- }
+-
+- /* combine prefix and filename */
+- memset(nbuf, 0, sizeof nbuf);
+- name = nbuf;
+- if ((tblk)->prefix[0])
+- {
+- strncpy(name, (tblk)->prefix, sizeof (tblk)->prefix);
+- strcat(name, "/");
+- strncat(name + strlen(name), (tblk)->filename,
+- sizeof (tblk)->filename);
+- }
+- else
+- {
+- strncpy(name, (tblk)->filename,
+- sizeof (tblk)->filename);
+- }
+-
+- /* Convert any backslashes to forward slashes, and guard
+- * against doubled-up slashes. (Some DOS versions of "tar"
+- * get this wrong.) Also strip off leading slashes.
+- */
+- if (!ABSPATH && (*name == '/' || *name == '\\'))
+- didabs = 1;
+- for (n2 = nbuf; *name; name++)
+- {
+- if (*name == '\\')
+- *name = '/';
+- if (*name != '/'
+- || (ABSPATH && n2 == nbuf)
+- || (n2 != nbuf && n2[-1] != '/'))
+- *n2++ = *name;
+- }
+- if (n2 == nbuf)
+- *n2++ = '/';
+- *n2 = '\0';
+-
+- /* verify the checksum */
+- for (sum = 0L, i = 0; i < sizeof((tblk)->checksum); i++)
+- {
+- if ((tblk)->checksum[i] >= '0'
+- && (tblk)->checksum[i] <= '7')
+- sum = sum * 8 + (tblk)->checksum[i] - '0';
+- }
+- if (sum != checksum(tblk, 0) && sum != checksum(tblk, 1))
+- {
+- if (!first)
+- untar_error("Garbage detected; preceding file may be damaged\n");
+- untar_error("%s: header has bad checksum for %s\n", inname, nbuf);
+- return 0;
+- }
+-
+- /* From this point on, we don't care whether this is the first
+- * block or not. Might as well reset the "first" flag now.
+- */
+- first = 0;
+-
+- /* if last character of name is '/' then assume directory */
+- if (*nbuf && nbuf[strlen(nbuf) - 1] == '/')
+- (tblk)->type = '5';
+-
+- /* convert file size */
+- for (outsize = 0L, i = 0; i < sizeof((tblk)->size); i++)
+- {
+- if ((tblk)->size[i] >= '0' && (tblk)->size[i] <= '7')
+- outsize = outsize * 8 + (tblk)->size[i] - '0';
+- }
+-
+-#ifdef _POSIX_SOURCE
+- /* convert file timestamp */
+- for (timestamp.modtime=0L, i=0; i < sizeof((tblk)->mtime); i++)
+- {
+- if ((tblk)->mtime[i] >= '0' && (tblk)->mtime[i] <= '7')
+- timestamp.modtime = timestamp.modtime * 8
+- + (tblk)->mtime[i] - '0';
+- }
+- timestamp.actime = timestamp.modtime;
+-
+- /* convert file permissions */
+- for (mode = i = 0; i < sizeof((tblk)->mode); i++)
+- {
+- if ((tblk)->mode[i] >= '0' && (tblk)->mode[i] <= '7')
+- mode = mode * 8 + (tblk)->mode[i] - '0';
+- }
+-#endif
+-
+- /* If we have an "only" list, and this file isn't in it,
+- * then skip it.
+- */
+- if (nonlys > 0)
+- {
+- for (i = 0;
+- i < nonlys
+- && strcmp(only[i], nbuf)
+- && (strncmp(only[i], nbuf, strlen(only[i]))
+- || nbuf[strlen(only[i])] != '/');
+- i++)
+- {
+- }
+- if (i >= nonlys)
+- {
+- outfp = NULL;
+- return 1;
+- }
+- }
+-
+- /* list the file */
+- if (VERBOSE)
+- untar_verbose("%c %s",
+- ISREGULAR(*tblk) ? '-' : ("hlcbdp"[(tblk)->type - '1']),
+- nbuf);
+- else if (!QUIET)
+- untar_verbose("%s\n", nbuf);
+-
+- /* if link, then do the link-or-copy thing */
+- if (tblk->type == '1' || tblk->type == '2')
+- {
+- if (VERBOSE)
+- untar_verbose(" -> %s\n", tblk->linkto);
+- if (!LISTING)
+- linkorcopy(tblk->linkto, nbuf, tblk->type == '2');
+- outsize = 0L;
+- return 1;
+- }
+-
+- /* If directory, then make a weak attempt to create it.
+- * Ideally we would do the "create path" thing, but that
+- * seems like more trouble than it's worth since traditional
+- * tar archives don't contain directories anyway.
+- */
+- if (tblk->type == '5')
+- {
+- if (LISTING)
+- n2 = " directory";
+-#ifdef _POSIX_SOURCE
+- else if (mkdir(nbuf, mode) == 0)
+-#else
+- else if (g_mkdir(nbuf, 0755) == 0)
+-#endif
+- n2 = " created";
+- else
+- n2 = " ignored";
+- if (VERBOSE)
+- untar_verbose("%s\n", n2);
+- return 1;
+- }
+-
+- /* if not a regular file, then skip it */
+- if (!ISREGULAR(*tblk))
+- {
+- if (VERBOSE)
+- untar_verbose(" ignored\n");
+- outsize = 0L;
+- return 1;
+- }
+-
+- /* print file statistics */
+- if (VERBOSE)
+- {
+- untar_verbose(" (%ld byte%s, %ld tape block%s)\n",
+- outsize,
+- outsize == 1 ? "" : "s",
+- (outsize + TSIZE - 1) / TSIZE,
+- (outsize > 0 && outsize <= TSIZE) ? "" : "s");
+- }
+-
+- /* if extracting, then try to create the file */
+- if (!LISTING)
+- outfp = createpath(nbuf);
+- else
+- outfp = NULL;
+-
+- /* if file is 0 bytes long, then we're done already! */
+- if (outsize == 0 && outfp)
+- {
+- fclose(outfp);
+-#ifdef _POSIX_SOURCE
+- utime(nbuf, &timestamp);
+- chmod(nbuf, mode);
+-#endif
+- }
+- }
+- return 1;
+-}
+-
+-/* Process an archive file. This involves reading the blocks one at a time
+- * and passing them to a untar() function.
+- */
+-int untar(const char *filename, const char* destdir, untar_opt options) {
+- int ret=1;
+- wchar_t curdir[_MAX_PATH];
+- wchar_t *w_destdir;
+- untarops = options;
+- /* open the archive */
+- inname = filename;
+- infp = g_fopen(filename, "rb");
+- if (!infp)
+- {
+- untar_error("Error opening: %s\n", filename);
+- return 0;
+- }
+-
+- w_destdir = g_utf8_to_utf16(destdir, -1, NULL, NULL, NULL);
+-
+- /* Set current directory */
+- if(!GetCurrentDirectoryW(_MAX_PATH, curdir)) {
+- untar_error("Could not get current directory (error %lu).\n", GetLastError());
+- fclose(infp);
+- return 0;
+- }
+- if(!SetCurrentDirectoryW(w_destdir)) {
+- untar_error("Could not set current directory to (error %lu): %s\n", GetLastError(), destdir);
+- fclose(infp);
+- return 0;
+- } else {
+- /* UNCOMPRESSED */
+- /* send each block to the untar_block() function */
+- while (fread(slide, 1, TSIZE, infp) == TSIZE) {
+- if(!untar_block(slide)) {
+- untar_error("untar failure: %s\n", filename);
+- fclose(infp);
+- ret=0;
+- }
+- }
+- if (outsize > 0 && ret) {
+- untar_warning("Last file might be truncated!\n");
+- fclose(outfp);
+- outfp = NULL;
+- }
+- if(!SetCurrentDirectoryW(curdir)) {
+- untar_error("Could not set current dir back to original (error %lu).\n", GetLastError());
+- ret=0;
+- }
+- }
+-
+- g_free(w_destdir);
+-
+- /* close the archive file. */
+- fclose(infp);
+-
+- return ret;
+-}
+-
+diff -Nur pidgin-2.10.7/pidgin/win32/untar.h pidgin-2.10.7-nonprism/pidgin/win32/untar.h
+--- pidgin-2.10.7/pidgin/win32/untar.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/untar.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,30 +0,0 @@
+-/*
+- * untar.h
+- *
+- * Author: Herman Bloggs <hermanator12002@yahoo.com>
+- * Date: April, 2003
+- * Description: untar.c header
+- */
+-#ifndef _UNTAR_H_
+-#define _UNTAR_H_
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-typedef enum _untar_opt {
+- UNTAR_LISTING = (1 << 0),
+- UNTAR_QUIET = (1 << 1),
+- UNTAR_VERBOSE = (1 << 2),
+- UNTAR_FORCE = (1 << 3),
+- UNTAR_ABSPATH = (1 << 4),
+- UNTAR_CONVERT = (1 << 5)
+-} untar_opt;
+-
+-int untar(const char *filename, const char *destdir, untar_opt options);
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif
+diff -Nur pidgin-2.10.7/pidgin/win32/winpidgin.c pidgin-2.10.7-nonprism/pidgin/win32/winpidgin.c
+--- pidgin-2.10.7/pidgin/win32/winpidgin.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/winpidgin.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,834 +0,0 @@
+-/*
+- * winpidgin.c
+- *
+- * Date: June, 2002
+- * Description: Entry point for win32 pidgin, and various win32 dependant
+- * routines.
+- *
+- * Pidgin 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.
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-/* This is for ATTACH_PARENT_PROCESS */
+-#ifndef _WIN32_WINNT
+-#define _WIN32_WINNT 0x501
+-#endif
+-#include <windows.h>
+-#include <fcntl.h>
+-#include <stdlib.h>
+-#include <string.h>
+-#include <stdio.h>
+-#include <sys/types.h>
+-#include <sys/stat.h>
+-#include "config.h"
+-
+-typedef int (__cdecl* LPFNPIDGINMAIN)(HINSTANCE, int, char**);
+-typedef void (WINAPI* LPFNSETDLLDIRECTORY)(LPCWSTR);
+-typedef BOOL (WINAPI* LPFNATTACHCONSOLE)(DWORD);
+-typedef BOOL (WINAPI* LPFNSETPROCESSDEPPOLICY)(DWORD);
+-
+-static BOOL portable_mode = FALSE;
+-
+-/*
+- * PROTOTYPES
+- */
+-static LPFNPIDGINMAIN pidgin_main = NULL;
+-static LPFNSETDLLDIRECTORY MySetDllDirectory = NULL;
+-
+-static const wchar_t *get_win32_error_message(DWORD err) {
+- static wchar_t err_msg[512];
+-
+- FormatMessageW(
+- FORMAT_MESSAGE_FROM_SYSTEM,
+- NULL, err,
+- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+- (LPWSTR) &err_msg, sizeof(err_msg) / sizeof(wchar_t), NULL);
+-
+- return err_msg;
+-}
+-
+-static BOOL read_reg_string(HKEY key, wchar_t *sub_key, wchar_t *val_name, LPBYTE data, LPDWORD data_len) {
+- HKEY hkey;
+- BOOL ret = FALSE;
+- LONG retv;
+-
+- if (ERROR_SUCCESS == (retv = RegOpenKeyExW(key, sub_key, 0,
+- KEY_QUERY_VALUE, &hkey))) {
+- if (ERROR_SUCCESS == (retv = RegQueryValueExW(hkey, val_name,
+- NULL, NULL, data, data_len)))
+- ret = TRUE;
+- else {
+- const wchar_t *err_msg = get_win32_error_message(retv);
+-
+- wprintf(L"Could not read reg key '%s' subkey '%s' value: '%s'.\nMessage: (%ld) %s\n",
+- (key == HKEY_LOCAL_MACHINE) ? L"HKLM"
+- : ((key == HKEY_CURRENT_USER) ? L"HKCU" : L"???"),
+- sub_key, val_name, retv, err_msg);
+- }
+- RegCloseKey(hkey);
+- }
+- else {
+- wchar_t szBuf[80];
+-
+- FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM, NULL, retv, 0,
+- (LPWSTR) &szBuf, sizeof(szBuf) / sizeof(wchar_t), NULL);
+- wprintf(L"Could not open reg subkey: %s\nError: (%ld) %s\n",
+- sub_key, retv, szBuf);
+- }
+-
+- return ret;
+-}
+-
+-static BOOL common_dll_prep(const wchar_t *path) {
+- HMODULE hmod;
+- HKEY hkey;
+- struct _stat stat_buf;
+- wchar_t test_path[MAX_PATH + 1];
+-
+- _snwprintf(test_path, sizeof(test_path) / sizeof(wchar_t),
+- L"%s\\libgtk-win32-2.0-0.dll", path);
+- test_path[sizeof(test_path) / sizeof(wchar_t) - 1] = L'\0';
+-
+- if (_wstat(test_path, &stat_buf) != 0) {
+- printf("Unable to determine GTK+ path. \n"
+- "Assuming GTK+ is in the PATH.\n");
+- return FALSE;
+- }
+-
+-
+- wprintf(L"GTK+ path found: %s\n", path);
+-
+- if ((hmod = GetModuleHandleW(L"kernel32.dll"))) {
+- MySetDllDirectory = (LPFNSETDLLDIRECTORY) GetProcAddress(
+- hmod, "SetDllDirectoryW");
+- if (!MySetDllDirectory)
+- printf("SetDllDirectory not supported\n");
+- } else
+- printf("Error getting kernel32.dll module handle\n");
+-
+- /* For Windows XP SP1+ / Server 2003 we use SetDllDirectory to avoid dll hell */
+- if (MySetDllDirectory) {
+- printf("Using SetDllDirectory\n");
+- MySetDllDirectory(path);
+- }
+-
+- /* For the rest, we set the current directory and make sure
+- * SafeDllSearch is set to 0 where needed. */
+- else {
+- OSVERSIONINFOW osinfo;
+-
+- printf("Setting current directory to GTK+ dll directory\n");
+- SetCurrentDirectoryW(path);
+- /* For Windows 2000 (SP3+) / WinXP (No SP):
+- * If SafeDllSearchMode is set to 1, Windows system directories are
+- * searched for dlls before the current directory. Therefore we set it
+- * to 0.
+- */
+- osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFOW);
+- GetVersionExW(&osinfo);
+- if ((osinfo.dwMajorVersion == 5
+- && osinfo.dwMinorVersion == 0
+- && wcscmp(osinfo.szCSDVersion, L"Service Pack 3") >= 0)
+- ||
+- (osinfo.dwMajorVersion == 5
+- && osinfo.dwMinorVersion == 1
+- && wcscmp(osinfo.szCSDVersion, L"") >= 0)
+- ) {
+- DWORD regval = 1;
+- DWORD reglen = sizeof(DWORD);
+-
+- printf("Using Win2k (SP3+) / WinXP (No SP)... Checking SafeDllSearch\n");
+- read_reg_string(HKEY_LOCAL_MACHINE,
+- L"System\\CurrentControlSet\\Control\\Session Manager",
+- L"SafeDllSearchMode",
+- (LPBYTE) &regval,
+- &reglen);
+-
+- if (regval != 0) {
+- printf("Trying to set SafeDllSearchMode to 0\n");
+- regval = 0;
+- if (RegOpenKeyExW(HKEY_LOCAL_MACHINE,
+- L"System\\CurrentControlSet\\Control\\Session Manager",
+- 0, KEY_SET_VALUE, &hkey
+- ) == ERROR_SUCCESS) {
+- if (RegSetValueExW(hkey,
+- L"SafeDllSearchMode", 0,
+- REG_DWORD, (LPBYTE) &regval,
+- sizeof(DWORD)
+- ) != ERROR_SUCCESS)
+- printf("Error writing SafeDllSearchMode. Error: %u\n",
+- (UINT) GetLastError());
+- RegCloseKey(hkey);
+- } else
+- printf("Error opening Session Manager key for writing. Error: %u\n",
+- (UINT) GetLastError());
+- } else
+- printf("SafeDllSearchMode is set to 0\n");
+- }/*end else*/
+- }
+-
+- return TRUE;
+-}
+-
+-static BOOL dll_prep(const wchar_t *pidgin_dir) {
+- wchar_t path[MAX_PATH + 1];
+- path[0] = L'\0';
+-
+- if (*pidgin_dir) {
+- _snwprintf(path, sizeof(path) / sizeof(wchar_t), L"%s\\Gtk\\bin", pidgin_dir);
+- path[sizeof(path) / sizeof(wchar_t) - 1] = L'\0';
+- }
+-
+- return common_dll_prep(path);
+-}
+-
+-static void portable_mode_dll_prep(const wchar_t *pidgin_dir) {
+- /* need to be able to fit MAX_PATH + "PURPLEHOME=" in path2 */
+- wchar_t path[MAX_PATH + 1];
+- wchar_t path2[MAX_PATH + 12];
+- const wchar_t *prev = NULL;
+-
+- /* We assume that GTK+ is installed under \\path\to\Pidgin\..\GTK
+- * First we find \\path\to
+- */
+- if (*pidgin_dir)
+- /* pidgin_dir points to \\path\to\Pidgin */
+- prev = wcsrchr(pidgin_dir, L'\\');
+-
+- if (prev) {
+- int cnt = (prev - pidgin_dir);
+- wcsncpy(path, pidgin_dir, cnt);
+- path[cnt] = L'\0';
+- } else {
+- printf("Unable to determine current executable path. \n"
+- "This will prevent the settings dir from being set.\n"
+- "Assuming GTK+ is in the PATH.\n");
+- return;
+- }
+-
+- /* Set $HOME so that the GTK+ settings get stored in the right place */
+- _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"HOME=%s", path);
+- _wputenv(path2);
+-
+- /* Set up the settings dir base to be \\path\to
+- * The actual settings dir will be \\path\to\.purple */
+- _snwprintf(path2, sizeof(path2) / sizeof(wchar_t), L"PURPLEHOME=%s", path);
+- wprintf(L"Setting settings dir: %s\n", path2);
+- _wputenv(path2);
+-
+- if (!dll_prep(pidgin_dir)) {
+- /* set the GTK+ path to be \\path\to\GTK\bin */
+- wcscat(path, L"\\GTK\\bin");
+- common_dll_prep(path);
+- }
+-}
+-
+-static wchar_t* winpidgin_lcid_to_posix(LCID lcid) {
+- wchar_t *posix = NULL;
+- int lang_id = PRIMARYLANGID(lcid);
+- int sub_id = SUBLANGID(lcid);
+-
+- switch (lang_id) {
+- case LANG_AFRIKAANS: posix = L"af"; break;
+- case LANG_ARABIC: posix = L"ar"; break;
+- case LANG_AZERI: posix = L"az"; break;
+- case LANG_BENGALI: posix = L"bn"; break;
+- case LANG_BULGARIAN: posix = L"bg"; break;
+- case LANG_CATALAN: posix = L"ca"; break;
+- case LANG_CZECH: posix = L"cs"; break;
+- case LANG_DANISH: posix = L"da"; break;
+- case LANG_ESTONIAN: posix = L"et"; break;
+- case LANG_PERSIAN: posix = L"fa"; break;
+- case LANG_GERMAN: posix = L"de"; break;
+- case LANG_GREEK: posix = L"el"; break;
+- case LANG_ENGLISH:
+- switch (sub_id) {
+- case SUBLANG_ENGLISH_UK:
+- posix = L"en_GB"; break;
+- case SUBLANG_ENGLISH_AUS:
+- posix = L"en_AU"; break;
+- case SUBLANG_ENGLISH_CAN:
+- posix = L"en_CA"; break;
+- default:
+- posix = L"en"; break;
+- }
+- break;
+- case LANG_SPANISH: posix = L"es"; break;
+- case LANG_BASQUE: posix = L"eu"; break;
+- case LANG_FINNISH: posix = L"fi"; break;
+- case LANG_FRENCH: posix = L"fr"; break;
+- case LANG_GALICIAN: posix = L"gl"; break;
+- case LANG_GUJARATI: posix = L"gu"; break;
+- case LANG_HEBREW: posix = L"he"; break;
+- case LANG_HINDI: posix = L"hi"; break;
+- case LANG_HUNGARIAN: posix = L"hu"; break;
+- case LANG_ICELANDIC: break;
+- case LANG_INDONESIAN: posix = L"id"; break;
+- case LANG_ITALIAN: posix = L"it"; break;
+- case LANG_JAPANESE: posix = L"ja"; break;
+- case LANG_GEORGIAN: posix = L"ka"; break;
+- case LANG_KANNADA: posix = L"kn"; break;
+- case LANG_KOREAN: posix = L"ko"; break;
+- case LANG_LITHUANIAN: posix = L"lt"; break;
+- case LANG_MACEDONIAN: posix = L"mk"; break;
+- case LANG_DUTCH: posix = L"nl"; break;
+- case LANG_NEPALI: posix = L"ne"; break;
+- case LANG_NORWEGIAN:
+- switch (sub_id) {
+- case SUBLANG_NORWEGIAN_BOKMAL:
+- posix = L"nb"; break;
+- case SUBLANG_NORWEGIAN_NYNORSK:
+- posix = L"nn"; break;
+- }
+- break;
+- case LANG_PUNJABI: posix = L"pa"; break;
+- case LANG_POLISH: posix = L"pl"; break;
+- case LANG_PASHTO: posix = L"ps"; break;
+- case LANG_PORTUGUESE:
+- switch (sub_id) {
+- case SUBLANG_PORTUGUESE_BRAZILIAN:
+- posix = L"pt_BR"; break;
+- default:
+- posix = L"pt"; break;
+- }
+- break;
+- case LANG_ROMANIAN: posix = L"ro"; break;
+- case LANG_RUSSIAN: posix = L"ru"; break;
+- case LANG_SLOVAK: posix = L"sk"; break;
+- case LANG_SLOVENIAN: posix = L"sl"; break;
+- case LANG_ALBANIAN: posix = L"sq"; break;
+- /* LANG_CROATIAN == LANG_SERBIAN == LANG_BOSNIAN */
+- case LANG_SERBIAN:
+- switch (sub_id) {
+- case SUBLANG_SERBIAN_LATIN:
+- posix = L"sr@Latn"; break;
+- case SUBLANG_SERBIAN_CYRILLIC:
+- posix = L"sr"; break;
+- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_CYRILLIC:
+- case SUBLANG_BOSNIAN_BOSNIA_HERZEGOVINA_LATIN:
+- posix = L"bs"; break;
+- case SUBLANG_CROATIAN_BOSNIA_HERZEGOVINA_LATIN:
+- posix = L"hr"; break;
+- }
+- break;
+- case LANG_SWEDISH: posix = L"sv"; break;
+- case LANG_TAMIL: posix = L"ta"; break;
+- case LANG_TELUGU: posix = L"te"; break;
+- case LANG_THAI: posix = L"th"; break;
+- case LANG_TURKISH: posix = L"tr"; break;
+- case LANG_UKRAINIAN: posix = L"uk"; break;
+- case LANG_VIETNAMESE: posix = L"vi"; break;
+- case LANG_XHOSA: posix = L"xh"; break;
+- case LANG_CHINESE:
+- switch (sub_id) {
+- case SUBLANG_CHINESE_SIMPLIFIED:
+- posix = L"zh_CN"; break;
+- case SUBLANG_CHINESE_TRADITIONAL:
+- posix = L"zh_TW"; break;
+- default:
+- posix = L"zh"; break;
+- }
+- break;
+- case LANG_URDU: break;
+- case LANG_BELARUSIAN: break;
+- case LANG_LATVIAN: break;
+- case LANG_ARMENIAN: break;
+- case LANG_FAEROESE: break;
+- case LANG_MALAY: break;
+- case LANG_KAZAK: break;
+- case LANG_KYRGYZ: break;
+- case LANG_SWAHILI: break;
+- case LANG_UZBEK: break;
+- case LANG_TATAR: break;
+- case LANG_ORIYA: break;
+- case LANG_MALAYALAM: break;
+- case LANG_ASSAMESE: break;
+- case LANG_MARATHI: break;
+- case LANG_SANSKRIT: break;
+- case LANG_MONGOLIAN: break;
+- case LANG_KONKANI: break;
+- case LANG_MANIPURI: break;
+- case LANG_SINDHI: break;
+- case LANG_SYRIAC: break;
+- case LANG_KASHMIRI: break;
+- case LANG_DIVEHI: break;
+- }
+-
+- /* Deal with exceptions */
+- if (posix == NULL) {
+- switch (lcid) {
+- case 0x0455: posix = L"my_MM"; break; /* Myanmar (Burmese) */
+- case 9999: posix = L"ku"; break; /* Kurdish (from NSIS) */
+- }
+- }
+-
+- return posix;
+-}
+-
+-/* Determine and set Pidgin locale as follows (in order of priority):
+- - Check PIDGINLANG env var
+- - Check NSIS Installer Language reg value
+- - Use default user locale
+-*/
+-static const wchar_t *winpidgin_get_locale() {
+- const wchar_t *locale = NULL;
+- LCID lcid;
+- wchar_t data[10];
+- DWORD datalen = sizeof(data) / sizeof(wchar_t);
+-
+- /* Check if user set PIDGINLANG env var */
+- if ((locale = _wgetenv(L"PIDGINLANG")))
+- return locale;
+-
+- if (!portable_mode && read_reg_string(HKEY_CURRENT_USER, L"SOFTWARE\\pidgin",
+- L"Installer Language", (LPBYTE) &data, &datalen)) {
+- if ((locale = winpidgin_lcid_to_posix(_wtoi(data))))
+- return locale;
+- }
+-
+- lcid = GetUserDefaultLCID();
+- if ((locale = winpidgin_lcid_to_posix(lcid)))
+- return locale;
+-
+- return L"en";
+-}
+-
+-static void winpidgin_set_locale() {
+- const wchar_t *locale;
+- wchar_t envstr[25];
+-
+- locale = winpidgin_get_locale();
+-
+- _snwprintf(envstr, sizeof(envstr) / sizeof(wchar_t), L"LANG=%s", locale);
+- wprintf(L"Setting locale: %s\n", envstr);
+- _wputenv(envstr);
+-}
+-
+-
+-static void winpidgin_add_stuff_to_path() {
+- wchar_t perl_path[MAX_PATH + 1];
+- wchar_t *ppath = NULL;
+- wchar_t mit_kerberos_path[MAX_PATH + 1];
+- wchar_t *mpath = NULL;
+- DWORD plen;
+-
+- printf("%s", "Looking for Perl... ");
+-
+- plen = sizeof(perl_path) / sizeof(wchar_t);
+- if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Perl", L"",
+- (LPBYTE) &perl_path, &plen)) {
+- /* We *could* check for perl510.dll, but it seems unnecessary. */
+- wprintf(L"found in '%s'.\n", perl_path);
+-
+- if (perl_path[wcslen(perl_path) - 1] != L'\\')
+- wcscat(perl_path, L"\\");
+- wcscat(perl_path, L"bin");
+-
+- ppath = perl_path;
+- } else
+- printf("%s", "not found.\n");
+-
+- printf("%s", "Looking for MIT Kerberos... ");
+-
+- plen = sizeof(mit_kerberos_path) / sizeof(wchar_t);
+- if (read_reg_string(HKEY_LOCAL_MACHINE, L"SOFTWARE\\MIT\\Kerberos", L"InstallDir",
+- (LPBYTE) &mit_kerberos_path, &plen)) {
+- /* We *could* check for gssapi32.dll */
+- wprintf(L"found in '%s'.\n", mit_kerberos_path);
+-
+- if (mit_kerberos_path[wcslen(mit_kerberos_path) - 1] != L'\\')
+- wcscat(mit_kerberos_path, L"\\");
+- wcscat(mit_kerberos_path, L"bin");
+-
+- mpath = mit_kerberos_path;
+- } else
+- printf("%s", "not found.\n");
+-
+- if (ppath != NULL || mpath != NULL) {
+- const wchar_t *path = _wgetenv(L"PATH");
+- BOOL add_ppath = ppath != NULL && (path == NULL || !wcsstr(path, ppath));
+- BOOL add_mpath = mpath != NULL && (path == NULL || !wcsstr(path, mpath));
+- wchar_t *newpath;
+- int newlen;
+-
+- if (add_ppath || add_mpath) {
+- /* Enough to add "PATH=" + path + ";" + ppath + ";" + mpath + \0 */
+- newlen = 6 + (path ? wcslen(path) + 1 : 0);
+- if (add_ppath)
+- newlen += wcslen(ppath) + 1;
+- if (add_mpath)
+- newlen += wcslen(mpath) + 1;
+- newpath = malloc(newlen * sizeof(wchar_t));
+-
+- _snwprintf(newpath, newlen, L"PATH=%s%s%s%s%s%s",
+- path ? path : L"",
+- path ? L";" : L"",
+- add_ppath ? ppath : L"",
+- add_ppath ? L";" : L"",
+- add_mpath ? mpath : L"",
+- add_mpath ? L";" : L"");
+-
+- wprintf(L"New PATH: %s\n", newpath);
+-
+- _wputenv(newpath);
+- free(newpath);
+- }
+- }
+-}
+-
+-#define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
+-#define PIDGIN_WM_PROTOCOL_HANDLE (WM_APP + 14)
+-
+-static BOOL winpidgin_set_running(BOOL fail_if_running) {
+- HANDLE h;
+-
+- if ((h = CreateMutexW(NULL, FALSE, L"pidgin_is_running"))) {
+- DWORD err = GetLastError();
+- if (err == ERROR_ALREADY_EXISTS) {
+- if (fail_if_running) {
+- HWND msg_win;
+-
+- printf("An instance of Pidgin is already running.\n");
+-
+- if((msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL)))
+- if(SendMessage(msg_win, PIDGIN_WM_FOCUS_REQUEST, (WPARAM) NULL, (LPARAM) NULL))
+- return FALSE;
+-
+- /* If we get here, the focus request wasn't successful */
+-
+- MessageBoxW(NULL,
+- L"An instance of Pidgin is already running",
+- NULL, MB_OK | MB_TOPMOST);
+-
+- return FALSE;
+- }
+- } else if (err != ERROR_SUCCESS)
+- printf("Error (%u) accessing \"pidgin_is_running\" mutex.\n", (UINT) err);
+- }
+- return TRUE;
+-}
+-
+-#define PROTO_HANDLER_SWITCH L"--protocolhandler="
+-
+-static void handle_protocol(wchar_t *cmd) {
+- char *remote_msg, *utf8msg;
+- wchar_t *tmp1, *tmp2;
+- int len, wlen;
+- SIZE_T len_written;
+- HWND msg_win;
+- DWORD pid;
+- HANDLE process;
+-
+- /* The start of the message */
+- tmp1 = cmd + wcslen(PROTO_HANDLER_SWITCH);
+-
+- /* The end of the message */
+- if ((tmp2 = wcschr(tmp1, L' ')))
+- wlen = (tmp2 - tmp1);
+- else
+- wlen = wcslen(tmp1);
+-
+- if (wlen == 0) {
+- printf("No protocol message specified.\n");
+- return;
+- }
+-
+- if (!(msg_win = FindWindowExW(NULL, NULL, L"WinpidginMsgWinCls", NULL))) {
+- printf("Unable to find an instance of Pidgin to handle protocol message.\n");
+- return;
+- }
+-
+- len = WideCharToMultiByte(CP_UTF8, 0, tmp1,
+- wlen, NULL, 0, NULL, NULL);
+- if (len) {
+- utf8msg = malloc(len);
+- len = WideCharToMultiByte(CP_UTF8, 0, tmp1,
+- wlen, utf8msg, len, NULL, NULL);
+- }
+-
+- if (len == 0) {
+- printf("No protocol message specified.\n");
+- return;
+- }
+-
+- GetWindowThreadProcessId(msg_win, &pid);
+- if (!(process = OpenProcess(PROCESS_VM_OPERATION | PROCESS_VM_WRITE, FALSE, pid))) {
+- DWORD dw = GetLastError();
+- const wchar_t *err_msg = get_win32_error_message(dw);
+- wprintf(L"Unable to open Pidgin process. (%u) %s\n", (UINT) dw, err_msg);
+- return;
+- }
+-
+- wprintf(L"Trying to handle protocol message:\n'%.*s'\n", wlen, tmp1);
+-
+- /* MEM_COMMIT initializes the memory to zero
+- * so we don't need to worry that our section of utf8msg isn't nul-terminated */
+- if ((remote_msg = (char*) VirtualAllocEx(process, NULL, len + 1, MEM_COMMIT, PAGE_READWRITE))) {
+- if (WriteProcessMemory(process, remote_msg, utf8msg, len, &len_written)) {
+- if (!SendMessageA(msg_win, PIDGIN_WM_PROTOCOL_HANDLE, len_written, (LPARAM) remote_msg))
+- printf("Unable to send protocol message to Pidgin instance.\n");
+- } else {
+- DWORD dw = GetLastError();
+- const wchar_t *err_msg = get_win32_error_message(dw);
+- wprintf(L"Unable to write to remote memory. (%u) %s\n", (UINT) dw, err_msg);
+- }
+-
+- VirtualFreeEx(process, remote_msg, 0, MEM_RELEASE);
+- } else {
+- DWORD dw = GetLastError();
+- const wchar_t *err_msg = get_win32_error_message(dw);
+- wprintf(L"Unable to allocate remote memory. (%u) %s\n", (UINT) dw, err_msg);
+- }
+-
+- CloseHandle(process);
+- free(utf8msg);
+-}
+-
+-
+-int _stdcall
+-WinMain (struct HINSTANCE__ *hInstance, struct HINSTANCE__ *hPrevInstance,
+- char *lpszCmdLine, int nCmdShow) {
+- wchar_t errbuf[512];
+- wchar_t pidgin_dir[MAX_PATH];
+- wchar_t *pidgin_dir_start = NULL;
+- wchar_t exe_name[MAX_PATH];
+- HMODULE hmod;
+- wchar_t *wtmp;
+- int pidgin_argc;
+- char **pidgin_argv; /* This is in utf-8 */
+- int i, j, k;
+- BOOL debug = FALSE, help = FALSE, version = FALSE, multiple = FALSE, success;
+- LPWSTR *szArglist;
+- LPWSTR cmdLine;
+-
+- /* If debug or help or version flag used, create console for output */
+- for (i = 1; i < __argc; i++) {
+- if (strlen(__argv[i]) > 1 && __argv[i][0] == '-') {
+- /* check if we're looking at -- or - option */
+- if (__argv[i][1] == '-') {
+- if (strstr(__argv[i], "--debug") == __argv[i])
+- debug = TRUE;
+- else if (strstr(__argv[i], "--help") == __argv[i])
+- help = TRUE;
+- else if (strstr(__argv[i], "--version") == __argv[i])
+- version = TRUE;
+- else if (strstr(__argv[i], "--multiple") == __argv[i])
+- multiple = TRUE;
+- } else {
+- if (strchr(__argv[i], 'd'))
+- debug = TRUE;
+- if (strchr(__argv[i], 'h'))
+- help = TRUE;
+- if (strchr(__argv[i], 'v'))
+- version = TRUE;
+- if (strchr(__argv[i], 'm'))
+- multiple = TRUE;
+- }
+- }
+- }
+-
+- /* Permanently enable DEP if the OS supports it */
+- if ((hmod = GetModuleHandleW(L"kernel32.dll"))) {
+- LPFNSETPROCESSDEPPOLICY MySetProcessDEPPolicy =
+- (LPFNSETPROCESSDEPPOLICY)
+- GetProcAddress(hmod, "SetProcessDEPPolicy");
+- if (MySetProcessDEPPolicy)
+- MySetProcessDEPPolicy(1); //PROCESS_DEP_ENABLE
+- }
+-
+- if (debug || help || version) {
+- /* If stdout hasn't been redirected to a file, alloc a console
+- * (_istty() doesn't work for stuff using the GUI subsystem) */
+- if (_fileno(stdout) == -1 || _fileno(stdout) == -2) {
+- LPFNATTACHCONSOLE MyAttachConsole = NULL;
+- if (hmod)
+- MyAttachConsole =
+- (LPFNATTACHCONSOLE)
+- GetProcAddress(hmod, "AttachConsole");
+- if ((MyAttachConsole && MyAttachConsole(ATTACH_PARENT_PROCESS))
+- || AllocConsole()) {
+- freopen("CONOUT$", "w", stdout);
+- freopen("CONOUT$", "w", stderr);
+- }
+- }
+- }
+-
+- cmdLine = GetCommandLineW();
+-
+- /* If this is a protocol handler invocation, deal with it accordingly */
+- if ((wtmp = wcsstr(cmdLine, PROTO_HANDLER_SWITCH)) != NULL) {
+- handle_protocol(wtmp);
+- return 0;
+- }
+-
+- /* Load exception handler if we have it */
+- if (GetModuleFileNameW(NULL, pidgin_dir, MAX_PATH) != 0) {
+-
+- /* primitive dirname() */
+- pidgin_dir_start = wcsrchr(pidgin_dir, L'\\');
+-
+- if (pidgin_dir_start) {
+- HMODULE hmod;
+- pidgin_dir_start[0] = L'\0';
+-
+- /* tmp++ will now point to the executable file name */
+- wcscpy(exe_name, pidgin_dir_start + 1);
+-
+- wcscat(pidgin_dir, L"\\exchndl.dll");
+- if ((hmod = LoadLibraryW(pidgin_dir))) {
+- typedef void (__cdecl* LPFNSETLOGFILE)(const LPCSTR);
+- LPFNSETLOGFILE MySetLogFile;
+- /* exchndl.dll is built without UNICODE */
+- char debug_dir[MAX_PATH];
+- printf("Loaded exchndl.dll\n");
+- /* Temporarily override exchndl.dll's logfile
+- * to something sane (Pidgin will override it
+- * again when it initializes) */
+- MySetLogFile = (LPFNSETLOGFILE) GetProcAddress(hmod, "SetLogFile");
+- if (MySetLogFile) {
+- if (GetTempPathA(sizeof(debug_dir), debug_dir) != 0) {
+- strcat(debug_dir, "pidgin.RPT");
+- printf(" Setting exchndl.dll LogFile to %s\n",
+- debug_dir);
+- MySetLogFile(debug_dir);
+- }
+- }
+- /* The function signature for SetDebugInfoDir is the same as SetLogFile,
+- * so we can reuse the variable */
+- MySetLogFile = (LPFNSETLOGFILE) GetProcAddress(hmod, "SetDebugInfoDir");
+- if (MySetLogFile) {
+- char *pidgin_dir_ansi = NULL;
+- /* Restore pidgin_dir to point to where the executable is */
+- pidgin_dir_start[0] = L'\0';
+- i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir,
+- -1, NULL, 0, NULL, NULL);
+- if (i != 0) {
+- pidgin_dir_ansi = malloc(i);
+- i = WideCharToMultiByte(CP_ACP, 0, pidgin_dir,
+- -1, pidgin_dir_ansi, i, NULL, NULL);
+- if (i == 0) {
+- free(pidgin_dir_ansi);
+- pidgin_dir_ansi = NULL;
+- }
+- }
+- if (pidgin_dir_ansi != NULL) {
+- _snprintf(debug_dir, sizeof(debug_dir),
+- "%s\\pidgin-%s-dbgsym",
+- pidgin_dir_ansi, VERSION);
+- debug_dir[sizeof(debug_dir) - 1] = '\0';
+- printf(" Setting exchndl.dll DebugInfoDir to %s\n",
+- debug_dir);
+- MySetLogFile(debug_dir);
+- free(pidgin_dir_ansi);
+- }
+- }
+-
+- }
+-
+- /* Restore pidgin_dir to point to where the executable is */
+- pidgin_dir_start[0] = L'\0';
+- }
+- } else {
+- DWORD dw = GetLastError();
+- const wchar_t *err_msg = get_win32_error_message(dw);
+- _snwprintf(errbuf, 512,
+- L"Error getting module filename.\nError: (%u) %s",
+- (UINT) dw, err_msg);
+- wprintf(L"%s\n", errbuf);
+- MessageBoxW(NULL, errbuf, NULL, MB_OK | MB_TOPMOST);
+- pidgin_dir[0] = L'\0';
+- }
+-
+- /* Determine if we're running in portable mode */
+- if (wcsstr(cmdLine, L"--portable-mode")
+- || (exe_name != NULL && wcsstr(exe_name, L"-portable.exe"))) {
+- printf("Running in PORTABLE mode.\n");
+- portable_mode = TRUE;
+- }
+-
+- if (portable_mode)
+- portable_mode_dll_prep(pidgin_dir);
+- else if (!getenv("PIDGIN_NO_DLL_CHECK"))
+- dll_prep(pidgin_dir);
+-
+- winpidgin_set_locale();
+-
+- winpidgin_add_stuff_to_path();
+-
+- /* If help, version or multiple flag used, do not check Mutex */
+- if (!help && !version)
+- if (!winpidgin_set_running(getenv("PIDGIN_MULTI_INST") == NULL && !multiple))
+- return 0;
+-
+- /* Now we are ready for Pidgin .. */
+- wcscat(pidgin_dir, L"\\pidgin.dll");
+- if ((hmod = LoadLibraryW(pidgin_dir)))
+- pidgin_main = (LPFNPIDGINMAIN) GetProcAddress(hmod, "pidgin_main");
+-
+- /* Restore pidgin_dir to point to where the executable is */
+- if (pidgin_dir_start)
+- pidgin_dir_start[0] = L'\0';
+-
+- if (!pidgin_main) {
+- DWORD dw = GetLastError();
+- BOOL mod_not_found = (dw == ERROR_MOD_NOT_FOUND || dw == ERROR_DLL_NOT_FOUND);
+- const wchar_t *err_msg = get_win32_error_message(dw);
+-
+- _snwprintf(errbuf, 512, L"Error loading pidgin.dll.\nError: (%u) %s%s%s",
+- (UINT) dw, err_msg,
+- mod_not_found ? L"\n" : L"",
+- mod_not_found ? L"This probably means that GTK+ can't be found." : L"");
+- wprintf(L"%s\n", errbuf);
+- MessageBoxW(NULL, errbuf, L"Error", MB_OK | MB_TOPMOST);
+-
+- return 0;
+- }
+-
+- /* Convert argv to utf-8*/
+- szArglist = CommandLineToArgvW(cmdLine, &j);
+- pidgin_argc = j;
+- pidgin_argv = malloc(pidgin_argc* sizeof(char*));
+- k = 0;
+- for (i = 0; i < j; i++) {
+- success = FALSE;
+- /* Remove the --portable-mode arg from the args passed to pidgin so it doesn't choke */
+- if (wcsstr(szArglist[i], L"--portable-mode") == NULL) {
+- int len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
+- -1, NULL, 0, NULL, NULL);
+- if (len != 0) {
+- char *arg = malloc(len);
+- len = WideCharToMultiByte(CP_UTF8, 0, szArglist[i],
+- -1, arg, len, NULL, NULL);
+- if (len != 0) {
+- pidgin_argv[k++] = arg;
+- success = TRUE;
+- }
+- }
+- if (!success)
+- wprintf(L"Error converting argument '%s' to UTF-8\n",
+- szArglist[i]);
+- }
+- if (!success)
+- pidgin_argc--;
+- }
+- LocalFree(szArglist);
+-
+-
+- return pidgin_main(hInstance, pidgin_argc, pidgin_argv);
+-}
+diff -Nur pidgin-2.10.7/pidgin/win32/wspell.c pidgin-2.10.7-nonprism/pidgin/win32/wspell.c
+--- pidgin-2.10.7/pidgin/win32/wspell.c 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/wspell.c 1969-12-31 21:00:00.000000000 -0300
+@@ -1,110 +0,0 @@
+-/*
+- * pidgin
+- *
+- * File: wspell.c
+- * Date: March, 2003
+- * Description: Windows Pidgin gtkspell interface.
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-
+-#ifdef HAVE_CONFIG_H
+-#include <config.h>
+-#endif
+-#ifdef USE_GTKSPELL
+-#include <windows.h>
+-#include <string.h>
+-#include <stdlib.h>
+-#include <glib.h>
+-#include <gtk/gtk.h>
+-#include <gtkspell/gtkspell.h>
+-#include "debug.h"
+-#include "win32dep.h"
+-#include "wspell.h"
+-
+-/* Intermediate function so that we can eat Enchant error popups when it doesn't find a DLL
+- * This is fixed upstream, but not released */
+-GtkSpell* (*wpidginspell_new_attach_proxy) (GtkTextView *,
+- const gchar *,
+- GError **) = NULL;
+-
+-/* GTKSPELL DUMMY FUNCS */
+-static GtkSpell* wgtkspell_new_attach(GtkTextView *view, const gchar *lang, GError **error) {
+- GtkSpell *ret = NULL;
+- if (wpidginspell_new_attach_proxy) {
+- UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
+- ret = wpidginspell_new_attach_proxy(view, lang, error);
+- SetErrorMode(old_error_mode);
+- }
+- return ret;
+-}
+-static GtkSpell* wgtkspell_get_from_text_view(GtkTextView *view) {return NULL;}
+-static void wgtkspell_detach(GtkSpell *spell) {}
+-static gboolean wgtkspell_set_language(GtkSpell *spell, const gchar *lang, GError **error) {return FALSE;}
+-static void wgtkspell_recheck_all(GtkSpell *spell) {}
+-
+-/* GTKSPELL PROTOS */
+-GtkSpell* (*wpidginspell_new_attach) (GtkTextView *,
+- const gchar *,
+- GError **) = wgtkspell_new_attach;
+-
+-GtkSpell* (*wpidginspell_get_from_text_view) (GtkTextView*) = wgtkspell_get_from_text_view;
+-
+-void (*wpidginspell_detach) (GtkSpell*) = wgtkspell_detach;
+-
+-gboolean (*wpidginspell_set_language) (GtkSpell*,
+- const gchar*,
+- GError**) = wgtkspell_set_language;
+-
+-void (*wpidginspell_recheck_all) (GtkSpell*) = wgtkspell_recheck_all;
+-
+-#define GTKSPELL_DLL "libgtkspell-0.dll"
+-
+-static void load_gtkspell() {
+- UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
+- gchar *tmp, *tmp2;
+-
+- const char *path = g_getenv("PATH");
+- tmp = g_build_filename(wpurple_install_dir(), "spellcheck", NULL);
+- tmp2 = g_strdup_printf("%s%s%s", tmp,
+- (path ? G_SEARCHPATH_SEPARATOR_S : ""),
+- (path ? path : ""));
+- g_free(tmp);
+- g_setenv("PATH", tmp2, TRUE);
+- g_free(tmp2);
+-
+- tmp = g_build_filename(wpurple_install_dir(), "spellcheck", GTKSPELL_DLL, NULL);
+- /* Suppress error popups */
+- wpidginspell_new_attach_proxy = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_new_attach" );
+- if (wpidginspell_new_attach_proxy) {
+- wpidginspell_get_from_text_view = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_get_from_text_view");
+- wpidginspell_detach = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_detach");
+- wpidginspell_set_language = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_set_language");
+- wpidginspell_recheck_all = (void*) wpurple_find_and_loadproc(tmp, "gtkspell_recheck_all");
+- } else {
+- purple_debug_warning("wspell", "Couldn't load gtkspell (%s) \n", tmp);
+- /*wpidginspell_new_attach = wgtkspell_new_attach;*/
+- }
+- g_free(tmp);
+- SetErrorMode(old_error_mode);
+-}
+-
+-void winpidgin_spell_init() {
+- load_gtkspell();
+-}
+-#endif
+diff -Nur pidgin-2.10.7/pidgin/win32/wspell.h pidgin-2.10.7-nonprism/pidgin/win32/wspell.h
+--- pidgin-2.10.7/pidgin/win32/wspell.h 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin/win32/wspell.h 1969-12-31 21:00:00.000000000 -0300
+@@ -1,57 +0,0 @@
+-/*
+- * pidgin
+- *
+- * File: wspell.h
+- *
+- * Copyright (C) 2002-2003, Herman Bloggs <hermanator12002@yahoo.com>
+- *
+- * This program is free software; you can redistribute it and/or modify
+- * it under the terms of the GNU General Public License as published by
+- * the Free Software Foundation; either version 2 of the License, or
+- * (at your option) any later version.
+- *
+- * This program is distributed in the hope that it will be useful,
+- * but WITHOUT ANY WARRANTY; without even the implied warranty of
+- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+- * GNU General Public License for more details.
+- *
+- * You should have received a copy of the GNU General Public License
+- * along with this program; if not, write to the Free Software
+- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
+- *
+- */
+-#ifndef _WSPELL_H_
+-#define _WSPELL_H_
+-#include <gtkspell/gtkspell.h>
+-
+-#ifdef __cplusplus
+-extern "C" {
+-#endif /* __cplusplus */
+-
+-void winpidgin_spell_init(void);
+-
+-extern GtkSpell* (*wpidginspell_new_attach)(GtkTextView*, const gchar*, GError**);
+-#define gtkspell_new_attach( view, lang, error ) \
+-wpidginspell_new_attach( view, lang, error )
+-
+-extern GtkSpell* (*wpidginspell_get_from_text_view)(GtkTextView*);
+-#define gtkspell_get_from_text_view( view ) \
+-wpidginspell_get_from_text_view( view )
+-
+-extern void (*wpidginspell_detach)(GtkSpell*);
+-#define gtkspell_detach( spell ) \
+-wpidginspell_detach( spell )
+-
+-extern gboolean (*wpidginspell_set_language)(GtkSpell*, const gchar*, GError**);
+-#define gtkspell_set_language( spell, lang, error ) \
+-wpidginspell_set_language( spell, lang, error )
+-
+-extern void (*wpidginspell_recheck_all)(GtkSpell*);
+-#define gtkspell_recheck_all( spell ) \
+-wpidginspell_recheck_all( spell )
+-
+-#ifdef __cplusplus
+-}
+-#endif /* __cplusplus */
+-
+-#endif /* _WSPELL_H_ */
+diff -Nur pidgin-2.10.7/pidgin.apspec.in pidgin-2.10.7-nonprism/pidgin.apspec.in
+--- pidgin-2.10.7/pidgin.apspec.in 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin.apspec.in 2013-08-16 20:53:14.523862926 -0300
+@@ -14,17 +14,13 @@
+
+ [Description]
+ Pidgin allows you to talk to anyone using a variety of messaging protocols,
+-including AIM (Oscar and TOC), ICQ, IRC, Yahoo!, MSN Messenger, XMPP,
+-Gadu-Gadu, and Zephyr. These protocols are implemented using a
++including IRC, XMPP and Zephyr. These protocols are implemented using a
+ modular, easy to use design. To use a protocol, just add an account using the
+ account editor.
+
+ Pidgin supports many common features of other clients, as well as many unique
+ features, such as perl scripting, TCL scripting and C plugins.
+
+-Pidgin is NOT affiliated with or endorsed by America Online, Inc., Microsoft
+-Corporation, Yahoo! Inc., or ICQ Inc.
+-
+ [BuildPrepare]
+ APBUILD_STATIC="Xss startup-notification-1" prepareBuild --enable-nss --enable-gnutls --enable-binreloc --disable-perl --disable-tcl --disable-gtktest --disable-glibtest --disable-vv --disable-fortify
+ #APBUILD_STATIC="Xss startup-notification-1" prepareBuild --enable-nss --enable-gnutls --enable-binreloc --disable-perl --disable-tcl --disable-vv
+diff -Nur pidgin-2.10.7/pidgin.desktop.in pidgin-2.10.7-nonprism/pidgin.desktop.in
+--- pidgin-2.10.7/pidgin.desktop.in 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin.desktop.in 2013-08-16 23:07:34.874212867 -0300
+@@ -1,7 +1,7 @@
+ [Desktop Entry]
+ _Name=Pidgin Internet Messenger
+ _GenericName=Internet Messenger
+-_Comment=Chat over IM. Supports AIM, Google Talk, Jabber/XMPP, MSN, Yahoo and more
++_Comment=Chat over IM. Supports IRC, Jabber/XMPP and more
+ Exec=pidgin
+ Icon=pidgin
+ StartupNotify=true
+diff -Nur pidgin-2.10.7/pidgin.spec pidgin-2.10.7-nonprism/pidgin.spec
+--- pidgin-2.10.7/pidgin.spec 2013-02-11 07:17:59.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin.spec 2013-08-17 00:03:18.474815955 -0300
+@@ -34,7 +34,6 @@
+ %{!?_without_startupnotification:BuildRequires: startup-notification-devel}
+ %{?_with_avahi:BuildRequires: avahi-glib-devel}
+ %{!?_without_gtkspell:BuildRequires: gtkspell-devel}
+-%{?_with_meanwhile:BuildRequires: meanwhile-devel}
+ %{?_with_mono:BuildRequires: mono-devel}
+ %{?_with_sasl:BuildRequires: cyrus-sasl-devel >= 2}
+ %{!?_without_silc:BuildRequires: /usr/include/silc/silcclient.h}
+@@ -105,7 +104,6 @@
+ Group: Applications/Internet
+ Obsoletes: gaim-silc
+ Obsoletes: gaim-tcl
+-Obsoletes: gaim-gadugadu
+ Obsoletes: pidgin-tcl < 2.0.0
+ Obsoletes: pidgin-silc < 2.0.0
+ Obsoletes: libpurple-perl < %{version}
+@@ -131,13 +129,6 @@
+ Requires: libpurple >= %{apiver}
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%package -n libpurple-meanwhile
+-Summary: Lotus Sametime plugin for Pidgin using the Meanwhile library
+-Group: Applications/Internet
+-Requires: libpurple >= %{apiver}
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %package -n libpurple-mono
+ Summary: Mono .NET plugin support for Pidgin
+@@ -161,18 +152,14 @@
+
+ %description
+ Pidgin allows you to talk to anyone using a variety of messaging
+-protocols including AIM, MSN, Yahoo!, XMPP, Bonjour, Gadu-Gadu,
+-ICQ, IRC, Novell Groupwise, QQ, Lotus Sametime, SILC, Simple and
+-Zephyr. These protocols are implemented using a modular, easy to
++protocols including XMPP, Bonjour, IRC, SILC, Simple and Zephyr.
++These protocols are implemented using a modular, easy to
+ use design. To use a protocol, just add an account using the
+ account editor.
+
+ Pidgin supports many common features of other clients, as well as many
+ unique features, such as perl scripting, TCL scripting and C plugins.
+
+-Pidgin is not affiliated with or endorsed by America Online, Inc.,
+-Microsoft Corporation, Yahoo! Inc., or ICQ Inc.
+-
+ %description devel
+ The pidgin-devel package contains the header files, developer
+ documentation, and libraries required for development of Pidgin scripts
+@@ -182,9 +169,8 @@
+ libpurple contains the core IM support for IM clients such as Pidgin
+ and Finch.
+
+-libpurple supports a variety of messaging protocols including AIM, MSN,
+-Yahoo!, XMPP, Bonjour, Gadu-Gadu, ICQ, IRC, Novell Groupwise, QQ,
+-Lotus Sametime, SILC, Simple and Zephyr.
++libpurple supports a variety of messaging protocols including XMPP,
++Bonjour, IRC, SILC, Simple and Zephyr.
+
+ %description -n libpurple-devel
+ The libpurple-devel package contains the header files, developer
+@@ -196,11 +182,6 @@
+ Bonjour plugin for Pidgin.
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%description -n libpurple-meanwhile
+-Lotus Sametime plugin for Pidgin using the Meanwhile library.
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %description -n libpurple-mono
+ Mono plugin loader for Pidgin. This package will allow you to write or
+@@ -236,7 +217,6 @@
+ %{!?_with_vv:--disable-vv} \
+ %{!?_with_dbus:--disable-dbus} \
+ %{!?_with_avahi:--disable-avahi} \
+- %{!?_with_meanwhile:--disable-meanwhile} \
+ %{?_without_gstreamer:--disable-gstreamer} \
+ %{?_without_gtkspell:--disable-gtkspell} \
+ %{?_without_nm:--disable-nm} \
+@@ -258,9 +238,7 @@
+ rm -f $RPM_BUILD_ROOT%{_libdir}/gnt/*.la
+ rm -f $RPM_BUILD_ROOT%{_libdir}/pidgin/*.la
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/*.la
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/liboscar.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libjabber.so
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libymsg.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+ rm -f $RPM_BUILD_ROOT%{perl_archlib}/perllocal.pod
+ find $RPM_BUILD_ROOT -type f -name '*.a' -exec rm -f {} ';'
+@@ -271,10 +249,6 @@
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libbonjour.so
+ %endif
+
+-%if 0%{!?_with_meanwhile:1}
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libsametime.so
+-%endif
+-
+ %if 0%{!?_with_mono:1}
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/mono.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/*.dll
+@@ -299,7 +273,6 @@
+ find $RPM_BUILD_ROOT%{_libdir}/purple-2 -xtype f -print | \
+ sed "s@^$RPM_BUILD_ROOT@@g" | \
+ grep -v /libbonjour.so | \
+- grep -v /libsametime.so | \
+ grep -v /mono.so | \
+ grep -v ".dll$" > %{name}-%{version}-purpleplugins
+
+@@ -435,13 +408,6 @@
+ %{_libdir}/purple-2/libbonjour.*
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%files -n libpurple-meanwhile
+-%defattr(-, root, root)
+-
+-%{_libdir}/purple-2/libsametime.*
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %files -n libpurple-mono
+ %defattr(-, root, root)
+@@ -492,9 +458,6 @@
+ * Sat Jul 11 2009 Stu Tomlinson <stu@nosnilmot.com>
+ - Update to reflect changes in perl module installation directories
+
+-* Mon May 19 2008 Stu Tomlinson <stu@nosnilmot.com>
+-- Fix building without meanwhile support
+-
+ * Fri May 16 2008 Stu Tomlinson <stu@nosnilmot.com>
+ - Add "--without nm" support to build without NetworkManager
+
+@@ -586,8 +549,6 @@
+ - Update to reflect renaming to pidgin/libpurple
+
+ * Sun Oct 1 2006 Stu Tomlinson <stu@nosnilmot.com>
+-- We can build with internal gadu gadu again, so bring it back into the
+- main package
+ - Deal with gconf schame uninstallation on package upgrade and removal
+
+ * Sun Aug 20 2006 Stu Tomlinson <stu@nosnilmot.com>
+@@ -606,19 +567,14 @@
+ - Source RPM uses tar.bz2 now to save space
+ - Update BuildRequires for new intltool dependencies
+ - Add a --with perlmakehack option to allow builds to succeed on RH9
+-- Add a --with gadugadu to build (separate) gaim-gadugadu package
+
+ * Sat Dec 17 2005 Stu Tomlinson <stu@nosnilmot.com>
+ - Add support for beta versions so the subsequent releases are seen as newer
+ by RPM
+-- Split of sametime support to gaim-meanwhile
+ - Use make DESTDIR=... instead of overloading prefix etc. when installing
+ - Default build to include cyrus-sasl support in Jabber
+ - Add --with dbus to build with DBUS support
+
+-* Sun Dec 04 2005 Christopher O'Brien <siege@preoccupied.net>
+-- Added obsoletes gaim-meanwhile
+-
+ * Sun Oct 30 2005 Stu Tomlinson <stu@nosnilmot.com>
+ - Add separate gaim-bonjour package if built with --with-howl
+ - Add separate gaim-mono package if built with --with-mono
+diff -Nur pidgin-2.10.7/pidgin.spec.in pidgin-2.10.7-nonprism/pidgin.spec.in
+--- pidgin-2.10.7/pidgin.spec.in 2013-02-11 07:16:53.000000000 -0200
++++ pidgin-2.10.7-nonprism/pidgin.spec.in 2013-08-17 00:07:12.251996234 -0300
+@@ -34,7 +34,6 @@
+ %{!?_without_startupnotification:BuildRequires: startup-notification-devel}
+ %{?_with_avahi:BuildRequires: avahi-glib-devel}
+ %{!?_without_gtkspell:BuildRequires: gtkspell-devel}
+-%{?_with_meanwhile:BuildRequires: meanwhile-devel}
+ %{?_with_mono:BuildRequires: mono-devel}
+ %{?_with_sasl:BuildRequires: cyrus-sasl-devel >= 2}
+ %{!?_without_silc:BuildRequires: /usr/include/silc/silcclient.h}
+@@ -105,7 +104,6 @@
+ Group: Applications/Internet
+ Obsoletes: gaim-silc
+ Obsoletes: gaim-tcl
+-Obsoletes: gaim-gadugadu
+ Obsoletes: pidgin-tcl < 2.0.0
+ Obsoletes: pidgin-silc < 2.0.0
+ Obsoletes: libpurple-perl < %{version}
+@@ -131,13 +129,6 @@
+ Requires: libpurple >= %{apiver}
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%package -n libpurple-meanwhile
+-Summary: Lotus Sametime plugin for Pidgin using the Meanwhile library
+-Group: Applications/Internet
+-Requires: libpurple >= %{apiver}
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %package -n libpurple-mono
+ Summary: Mono .NET plugin support for Pidgin
+@@ -161,18 +152,14 @@
+
+ %description
+ Pidgin allows you to talk to anyone using a variety of messaging
+-protocols including AIM, MSN, Yahoo!, XMPP, Bonjour, Gadu-Gadu,
+-ICQ, IRC, Novell Groupwise, QQ, Lotus Sametime, SILC, Simple and
+-Zephyr. These protocols are implemented using a modular, easy to
++protocols including XMPP, Bonjour, IRC, SILC, Simple and Zephyr.
++These protocols are implemented using a modular, easy to
+ use design. To use a protocol, just add an account using the
+ account editor.
+
+ Pidgin supports many common features of other clients, as well as many
+ unique features, such as perl scripting, TCL scripting and C plugins.
+
+-Pidgin is not affiliated with or endorsed by America Online, Inc.,
+-Microsoft Corporation, Yahoo! Inc., or ICQ Inc.
+-
+ %description devel
+ The pidgin-devel package contains the header files, developer
+ documentation, and libraries required for development of Pidgin scripts
+@@ -182,9 +169,8 @@
+ libpurple contains the core IM support for IM clients such as Pidgin
+ and Finch.
+
+-libpurple supports a variety of messaging protocols including AIM, MSN,
+-Yahoo!, XMPP, Bonjour, Gadu-Gadu, ICQ, IRC, Novell Groupwise, QQ,
+-Lotus Sametime, SILC, Simple and Zephyr.
++libpurple supports a variety of messaging protocols including XMPP,
++Bonjour, IRC, SILC, Simple and Zephyr.
+
+ %description -n libpurple-devel
+ The libpurple-devel package contains the header files, developer
+@@ -196,11 +182,6 @@
+ Bonjour plugin for Pidgin.
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%description -n libpurple-meanwhile
+-Lotus Sametime plugin for Pidgin using the Meanwhile library.
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %description -n libpurple-mono
+ Mono plugin loader for Pidgin. This package will allow you to write or
+@@ -236,7 +217,6 @@
+ %{!?_with_vv:--disable-vv} \
+ %{!?_with_dbus:--disable-dbus} \
+ %{!?_with_avahi:--disable-avahi} \
+- %{!?_with_meanwhile:--disable-meanwhile} \
+ %{?_without_gstreamer:--disable-gstreamer} \
+ %{?_without_gtkspell:--disable-gtkspell} \
+ %{?_without_nm:--disable-nm} \
+@@ -258,9 +238,7 @@
+ rm -f $RPM_BUILD_ROOT%{_libdir}/gnt/*.la
+ rm -f $RPM_BUILD_ROOT%{_libdir}/pidgin/*.la
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/*.la
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/liboscar.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libjabber.so
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libymsg.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/*.la
+ rm -f $RPM_BUILD_ROOT%{perl_archlib}/perllocal.pod
+ find $RPM_BUILD_ROOT -type f -name '*.a' -exec rm -f {} ';'
+@@ -271,10 +249,6 @@
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libbonjour.so
+ %endif
+
+-%if 0%{!?_with_meanwhile:1}
+-rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/libsametime.so
+-%endif
+-
+ %if 0%{!?_with_mono:1}
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/mono.so
+ rm -f $RPM_BUILD_ROOT%{_libdir}/purple-2/*.dll
+@@ -299,7 +273,6 @@
+ find $RPM_BUILD_ROOT%{_libdir}/purple-2 -xtype f -print | \
+ sed "s@^$RPM_BUILD_ROOT@@g" | \
+ grep -v /libbonjour.so | \
+- grep -v /libsametime.so | \
+ grep -v /mono.so | \
+ grep -v ".dll$" > %{name}-%{version}-purpleplugins
+
+@@ -435,13 +408,6 @@
+ %{_libdir}/purple-2/libbonjour.*
+ %endif
+
+-%if 0%{?_with_meanwhile:1}
+-%files -n libpurple-meanwhile
+-%defattr(-, root, root)
+-
+-%{_libdir}/purple-2/libsametime.*
+-%endif
+-
+ %if 0%{?_with_mono:1}
+ %files -n libpurple-mono
+ %defattr(-, root, root)
+@@ -492,9 +458,6 @@
+ * Sat Jul 11 2009 Stu Tomlinson <stu@nosnilmot.com>
+ - Update to reflect changes in perl module installation directories
+
+-* Mon May 19 2008 Stu Tomlinson <stu@nosnilmot.com>
+-- Fix building without meanwhile support
+-
+ * Fri May 16 2008 Stu Tomlinson <stu@nosnilmot.com>
+ - Add "--without nm" support to build without NetworkManager
+
+@@ -586,8 +549,6 @@
+ - Update to reflect renaming to pidgin/libpurple
+
+ * Sun Oct 1 2006 Stu Tomlinson <stu@nosnilmot.com>
+-- We can build with internal gadu gadu again, so bring it back into the
+- main package
+ - Deal with gconf schame uninstallation on package upgrade and removal
+
+ * Sun Aug 20 2006 Stu Tomlinson <stu@nosnilmot.com>
+@@ -606,19 +567,14 @@
+ - Source RPM uses tar.bz2 now to save space
+ - Update BuildRequires for new intltool dependencies
+ - Add a --with perlmakehack option to allow builds to succeed on RH9
+-- Add a --with gadugadu to build (separate) gaim-gadugadu package
+
+ * Sat Dec 17 2005 Stu Tomlinson <stu@nosnilmot.com>
+ - Add support for beta versions so the subsequent releases are seen as newer
+ by RPM
+-- Split of sametime support to gaim-meanwhile
+ - Use make DESTDIR=... instead of overloading prefix etc. when installing
+ - Default build to include cyrus-sasl support in Jabber
+ - Add --with dbus to build with DBUS support
+
+-* Sun Dec 04 2005 Christopher O'Brien <siege@preoccupied.net>
+-- Added obsoletes gaim-meanwhile
+-
+ * Sun Oct 30 2005 Stu Tomlinson <stu@nosnilmot.com>
+ - Add separate gaim-bonjour package if built with --with-howl
+ - Add separate gaim-mono package if built with --with-mono
+diff -Nur pidgin-2.10.7/po/Makefile.mingw pidgin-2.10.7-nonprism/po/Makefile.mingw
+--- pidgin-2.10.7/po/Makefile.mingw 2013-02-11 07:16:54.000000000 -0200
++++ pidgin-2.10.7-nonprism/po/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,54 +0,0 @@
+-# Makefile.mingw
+-#
+-# Description: Makefile to generate mo files
+-#
+-
+-PIDGIN_TREE_TOP := ..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-PACKAGE = pidgin
+-
+-.SUFFIXES:
+-.SUFFIXES: .po .gmo
+-
+-##
+-## SOURCES, OBJECTS
+-##
+-
+-CATALOGS = $(patsubst %.po,%.gmo,$(wildcard *.po))
+-
+-##
+-## RULES
+-##
+-
+-.po.gmo:
+- rm -f $@ && $(GMSGFMT) --statistics -o $@ $<
+-
+-##
+-## TARGETS
+-##
+-
+-.PHONY: all install clean
+-
+-all: $(CATALOGS)
+-
+-install: all
+- mkdir -p $(PURPLE_INSTALL_PO_DIR)
+- @catalogs='$(CATALOGS)'; \
+- for cat in $$catalogs; do \
+- cat=`basename $$cat`; \
+- lang=`echo $$cat | sed 's/\.gmo$$//'`; \
+- dir=$(PURPLE_INSTALL_PO_DIR)/$$lang/LC_MESSAGES; \
+- mkdir -p $$dir; \
+- if test -r $$cat; then \
+- cp $$cat $$dir/$(PACKAGE).mo; \
+- echo "installing $$cat as $$dir/$(PACKAGE).mo"; \
+- else \
+- cp $(PURPLE_PO_TOP)/$$cat $$dir/$(PACKAGE).mo; \
+- echo "installing $(PURPLE_PO_TOP)/$$cat as" \
+- "$$dir/$(PACKAGE).mo"; \
+- fi; \
+- done
+-
+-clean:
+- rm -f *.gmo
+diff -Nur pidgin-2.10.7/README pidgin-2.10.7-nonprism/README
+--- pidgin-2.10.7/README 2013-02-11 07:16:50.000000000 -0200
++++ pidgin-2.10.7-nonprism/README 2013-08-16 23:06:39.859153182 -0300
+@@ -4,7 +4,7 @@
+
+ libpurple is a library intended to be used by programmers seeking
+ to write an IM client that connects to many IM networks. It supports
+-AIM, ICQ, XMPP, MSN and Yahoo!, among others.
++XMPP, among others.
+
+ Pidgin is a graphical IM client written in C which uses the GTK+
+ toolkit.
+diff -Nur pidgin-2.10.7/share/ca-certs/Makefile.in pidgin-2.10.7-nonprism/share/ca-certs/Makefile.in
+--- pidgin-2.10.7/share/ca-certs/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/share/ca-certs/Makefile.in 2013-08-17 00:03:38.308758187 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/share/ca-certs/Makefile.mingw pidgin-2.10.7-nonprism/share/ca-certs/Makefile.mingw
+--- pidgin-2.10.7/share/ca-certs/Makefile.mingw 2013-02-11 07:16:57.000000000 -0200
++++ pidgin-2.10.7-nonprism/share/ca-certs/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,27 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of Pidgin ca-certs
+-#
+-
+-PIDGIN_TREE_TOP := ../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-datadir := $(PIDGIN_INSTALL_DIR)
+--include ./Makefile.am.mingw
+-cacertsdir := $(PIDGIN_INSTALL_DIR)/ca-certs
+-
+-.PHONY: install clean
+-
+-install: ./Makefile.am.mingw
+- if test '$(cacerts_DATA)'; then \
+- mkdir -p $(cacertsdir); \
+- cp $(cacerts_DATA) $(cacertsdir); \
+- fi;
+-
+-clean:
+- rm -f ./Makefile.am.mingw
+-
+-./Makefile.am.mingw: ./Makefile.am
+- sed -e 's/^if\ INSTALL_SSL_CERTIFICATES/ifeq (\$$(INSTALL_SSL_CERTIFICATES), 1)/' ./Makefile.am > $@
+-
+diff -Nur pidgin-2.10.7/share/sounds/Makefile.in pidgin-2.10.7-nonprism/share/sounds/Makefile.in
+--- pidgin-2.10.7/share/sounds/Makefile.in 2013-02-11 07:17:24.000000000 -0200
++++ pidgin-2.10.7-nonprism/share/sounds/Makefile.in 2013-08-17 00:04:04.366224904 -0300
+@@ -151,8 +151,6 @@
+ FARSTREAM_CFLAGS = @FARSTREAM_CFLAGS@
+ FARSTREAM_LIBS = @FARSTREAM_LIBS@
+ FGREP = @FGREP@
+-GADU_CFLAGS = @GADU_CFLAGS@
+-GADU_LIBS = @GADU_LIBS@
+ GCONFTOOL = @GCONFTOOL@
+ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@
+ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@
+@@ -214,8 +212,6 @@
+ LTLIBOBJS = @LTLIBOBJS@
+ MAKEINFO = @MAKEINFO@
+ MANIFEST_TOOL = @MANIFEST_TOOL@
+-MEANWHILE_CFLAGS = @MEANWHILE_CFLAGS@
+-MEANWHILE_LIBS = @MEANWHILE_LIBS@
+ MKDIR_P = @MKDIR_P@
+ MKINSTALLDIRS = @MKINSTALLDIRS@
+ MONO_CFLAGS = @MONO_CFLAGS@
+diff -Nur pidgin-2.10.7/share/sounds/Makefile.mingw pidgin-2.10.7-nonprism/share/sounds/Makefile.mingw
+--- pidgin-2.10.7/share/sounds/Makefile.mingw 2013-02-11 07:16:57.000000000 -0200
++++ pidgin-2.10.7-nonprism/share/sounds/Makefile.mingw 1969-12-31 21:00:00.000000000 -0300
+@@ -1,20 +0,0 @@
+-#
+-# Makefile.mingw
+-#
+-# Description: Makefile for win32 (mingw) version of Pidgin sounds
+-#
+-
+-PIDGIN_TREE_TOP := ../..
+-include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
+-
+-datadir := $(PIDGIN_INSTALL_DIR)
+-include ./Makefile.am
+-
+-.PHONY: install
+-
+-install:
+- if test '$(sounds_DATA)'; then \
+- mkdir -p $(soundsdir); \
+- cp $(sounds_DATA) $(soundsdir); \
+- fi;
+-
diff --git a/nonprism/pidgin-nonprism/pidgin-2.10.7-link-libirc-to-libsasl2.patch b/nonprism/pidgin-nonprism/pidgin-2.10.7-link-libirc-to-libsasl2.patch
new file mode 100644
index 000000000..abffa20b8
--- /dev/null
+++ b/nonprism/pidgin-nonprism/pidgin-2.10.7-link-libirc-to-libsasl2.patch
@@ -0,0 +1,12 @@
+diff -upr pidgin-2.10.7.orig/libpurple/protocols/irc/Makefile.am pidgin-2.10.7/libpurple/protocols/irc/Makefile.am
+--- pidgin-2.10.7.orig/libpurple/protocols/irc/Makefile.am 2013-02-14 02:44:47.000000000 +0200
++++ pidgin-2.10.7/libpurple/protocols/irc/Makefile.am 2013-02-14 02:49:58.000000000 +0200
+@@ -27,7 +27,7 @@ else
+ st =
+ pkg_LTLIBRARIES = libirc.la
+ libirc_la_SOURCES = $(IRCSOURCES)
+-libirc_la_LIBADD = $(GLIB_LIBS)
++libirc_la_LIBADD = $(GLIB_LIBS) $(SASL_LIBS)
+
+ endif
+
diff --git a/nonprism/pidgin-nonprism/pidgin.install b/nonprism/pidgin-nonprism/pidgin.install
new file mode 100644
index 000000000..1a05f573e
--- /dev/null
+++ b/nonprism/pidgin-nonprism/pidgin.install
@@ -0,0 +1,11 @@
+post_install() {
+ gtk-update-icon-cache -q -t -f usr/share/icons/hicolor
+}
+
+post_upgrade() {
+ post_install
+}
+
+post_remove() {
+ post_install
+}