From 63783b026b1d255b8fe78f7a186a2efc418e94c1 Mon Sep 17 00:00:00 2001 From: Márcio Alexandre Silva Delgado Date: Wed, 28 Aug 2013 00:23:33 -0300 Subject: adding pidgin-nonprism to nonprism repo --- nonprism/pidgin-nonprism/PKGBUILD | 131 + nonprism/pidgin-nonprism/nonprism.patch | 171507 ++++++++++++++++++ .../pidgin-2.10.7-link-libirc-to-libsasl2.patch | 12 + nonprism/pidgin-nonprism/pidgin.install | 11 + 4 files changed, 171661 insertions(+) create mode 100644 nonprism/pidgin-nonprism/PKGBUILD create mode 100644 nonprism/pidgin-nonprism/nonprism.patch create mode 100644 nonprism/pidgin-nonprism/pidgin-2.10.7-link-libirc-to-libsasl2.patch create mode 100644 nonprism/pidgin-nonprism/pidgin.install (limited to 'nonprism/pidgin-nonprism') 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 +# Contributor: Ionut Biru +# Contributor: Andrea Scarpino +# Contributor: Alexander Fehr +# Contributor: Lucien Immink + +_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 +-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 +-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 ]], [[ +-#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 ]], [[ +-#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 hello there +-18:34:03 I just wanted to share some bevavior that I think its kinda of +- unsafe when using GAIM with yahoo messenges accounts + 18:34:43 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 +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 " + + +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 +- * +- * 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 +- +-#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 +- * +- * 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 +- * +- * 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 +-#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 +- * +- * 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 +- * +- * Some parts of the code are adapted or taken from the previous implementation +- * of this plugin written by Arkadiusz Miskiewicz +- * Some parts Copyright (C) 2009 Krzysztof Klinikowski +- * +- * 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 +- +-#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, "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("", 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, ""); +- increased_len += 3; +- bold = TRUE; +- } +- } else if (bold) { +- g_string_insert(message, byteoffset, ""); +- increased_len += 4; +- bold = FALSE; +- } +- +- if (actformat->font & GG_FONT_ITALIC) { +- if (italic == FALSE) { +- g_string_insert(message, byteoffset, ""); +- increased_len += 3; +- italic = TRUE; +- } +- } else if (italic) { +- g_string_insert(message, byteoffset, ""); +- increased_len += 4; +- italic = FALSE; +- } +- +- if (actformat->font & GG_FONT_UNDERLINE) { +- if (under == FALSE) { +- g_string_insert(message, byteoffset, ""); +- increased_len += 3; +- under = TRUE; +- } +- } else if (under) { +- g_string_insert(message, byteoffset, ""); +- 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 +- * +- * 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 +-#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 +- * +- * 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 +- * +- * 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 +- * Robert J. Woźny +- * +- * 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 +-# include +-# include +-# include +-# include +-# ifdef sun +-# include +-# endif +-#endif +- +-#include +-#include +-#ifndef _WIN32 +-# include +-#endif +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Robert J. Woźny +- * +- * 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. +- +- +- Copyright (C) +- +- 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. +- +- , 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 +- * Tomasz Chiliński +- * Adam Wysocki +- * Bartłomiej Zimoń +- * +- * Thanks to Jakub Zawadzki +- * +- * 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 +-#include +-#ifndef _WIN32 +-# include +-# include +-# include +-# include +-# ifdef sun +-# include +-# endif +-#endif +-#include +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Tomasz Chiliński +- * Adam Wysocki +- * +- * 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 +-#include +-#ifndef _WIN32 +-# include +-# include +-# include +-# include +-# ifdef sun +-# include +-# endif +-#endif +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Tomasz Chiliński +- * Adam Wysocki +- * +- * 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 +-#include +-#include +-#include +-#include +- +-#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 +- * +- * 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 +-#include +- +-#include "libgadu.h" +-#include "deflate.h" +- +-#ifdef GG_CONFIG_HAVE_ZLIB +-#include +-#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 +- * +- * 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 +- * Wojtek Kaniewski +- * +- * 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 +-#include +-#include +- +-#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 +- * Wojtek Kaniewski +- * +- * 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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Adam Wysocki +- * +- * 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 +-#ifndef _WIN32 +-# include +-# include +-# include +-# include +-#endif +-#include +- +-#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 +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef GG_CONFIG_HAVE_GNUTLS +-# include +-# include +-#endif +-#ifdef GG_CONFIG_HAVE_OPENSSL +-# include +-# include +-#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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Tomasz Chiliński +- * Adam Wysocki +- * +- * 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 +-#ifndef _WIN32 +-# include +-# include +-# include +-#endif +-#include +-#ifndef _WIN32 +-# ifdef sun +-# include +-# 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 +-#ifndef _WIN32 +-# include +-#endif +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef GG_CONFIG_HAVE_OPENSSL +-# include +-# include +-#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 +- * +- * 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 +-#ifndef _WIN32 +-# include +-# include +-# include +-#endif +- +-#include "compat.h" +-#include "libgadu.h" +-#include "resolver.h" +- +-#include +-#include +-#ifndef _WIN32 +-# include +-#endif +-#include +-#include +-#include +-#include +-#include +-#include +- +-/** +- * 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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Tomasz Chiliński +- * Adam Wysocki +- * +- * 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 +-#ifdef _WIN32 +-# include +-# include +-# include +-# define SHUT_RDWR SD_BOTH +-#else +-# include +-# include +-# include +-# ifdef sun +-# include +-# 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 /* on Win32 this is included above */ +-# include +-#endif +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#ifdef GG_CONFIG_HAVE_GNUTLS +-# include +-#endif +-#ifdef GG_CONFIG_HAVE_OPENSSL +-# include +-# include +-#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 +-#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 +- * +- * 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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Tomasz Chiliński +- * Piotr Wysocki +- * Dawid Jarosz +- * Jakub Zawadzki +- * +- * 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 +-#include +-#include +- +-/** \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 . */ +-#undef GG_CONFIG_HAVE_STDINT_H +- +-/* Defined if uintX_t types are defined in . */ +-#undef GG_CONFIG_HAVE_INTTYPES_H +- +-/* Defined if uintX_t types are defined in . */ +-#undef GG_CONFIG_HAVE_SYS_INTTYPES_H +- +-/* Defined if uintX_t types are defined in . */ +-#undef GG_CONFIG_HAVE_SYS_INT_TYPES_H +- +-/* Defined if uintX_t types are defined in . */ +-#undef GG_CONFIG_HAVE_SYS_TYPES_H +- +-#ifdef GG_CONFIG_HAVE_OPENSSL +-#include +-#endif +- +-#ifdef GG_CONFIG_HAVE_STDINT_H +-#include +-#else +-# ifdef GG_CONFIG_HAVE_INTTYPES_H +-# include +-# else +-# ifdef GG_CONFIG_HAVE_SYS_INTTYPES_H +-# include +-# else +-# ifdef GG_CONFIG_HAVE_SYS_INT_TYPES_H +-# include +-# else +-# ifdef GG_CONFIG_HAVE_SYS_TYPES_H +-# include +-# else +- +-#ifndef __AC_STDINT_H +-#define __AC_STDINT_H +- +-/* ISO C 9X: 7.18 Integer types */ +- +-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 +- * +- * 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 +- * +- * 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 +-#include +-#include +-#include +-#include +- +-#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[] = ""; +- const int span_len = 75; +- const char img_fmt[] = ""; +- 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ć . */ +- +- 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, "", 4); +- +- if ((old_attr & GG_FONT_ITALIC) != 0) +- gg_append(dst, &len, "", 4); +- +- if ((old_attr & GG_FONT_BOLD) != 0) +- gg_append(dst, &len, "", 4); +- +- if (src[i] != 0) +- gg_append(dst, &len, "", 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, "", 3); +- +- if ((attr & GG_FONT_ITALIC) != 0) +- gg_append(dst, &len, "", 3); +- +- if ((attr & GG_FONT_UNDERLINE) != 0) +- gg_append(dst, &len, "", 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, "&", 5); +- break; +- case '<': +- gg_append(dst, &len, "<", 4); +- break; +- case '>': +- gg_append(dst, &len, ">", 4); +- break; +- case '\'': +- gg_append(dst, &len, "'", 6); +- break; +- case '\"': +- gg_append(dst, &len, """, 6); +- break; +- case '\n': +- gg_append(dst, &len, "
", 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, "
", 4); +- +- if ((old_attr & GG_FONT_ITALIC) != 0) +- gg_append(dst, &len, "
", 4); +- +- if ((old_attr & GG_FONT_BOLD) != 0) +- gg_append(dst, &len, "
", 4); +- +- if (src[0] != 0) +- gg_append(dst, &len, "
", 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, " +- * +- * 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 +-#include +-#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 +- * +- * 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 +- +-#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 +- * Bartłomiej Zimoń +- * Wojtek Kaniewski +- * +- * 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 +- * +- * 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 +-#include +-#include +-#include +- +-#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 +- * Dawid Jarosz +- * Adam Wysocki +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +- +-#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 +- * Robert J. Woźny +- * Arkadiusz Miśkiewicz +- * Tomasz Chiliński +- * Adam Wysocki +- * +- * 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 +-# include +-#endif +-#include +-#include +-#include +-#include +-#ifndef _WIN32 +-# include +-# include +-# include +-#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 +- +-/** +- * \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" — wskaźnik na zmienną, gdzie zostanie umieszczony deskryptor potoku +- * - \c "void **priv_data" — wskaźnik na zmienną, gdzie można umieścić wskaźnik do prywatnych danych na potrzeby rozwiązywania nazwy +- * - \c "const char *name" — nazwa serwera do rozwiązania +- * +- * Parametry funkcji zwalniającej zasoby wyglądają następująco: +- * - \c "void **priv_data" — wskaźnik na zmienną przechowującą wskaźnik do prywatnych danych, należy go ustawić na \c NULL po zakończeniu +- * - \c "int force" — 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 +- * +- * 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 +-#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 +- * +- * 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 +-#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 +- * +- * Public domain SHA-1 implementation by Steve Reid +- * +- * 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 +-#include +-#include +- +-#include "libgadu.h" +- +-/** \cond ignore */ +- +-#ifdef GG_CONFIG_HAVE_OPENSSL +- +-#include +- +-#else +- +-/* +-SHA-1 in C +-By Steve Reid +-100% Public Domain +- +-Modified by Wojtek Kaniewski 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 +- +-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 +- * +- * 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 +- +-#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 +- * +- * 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 +-#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): +- * . +- */ +- 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 to the ) 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 to the ) 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 to the ) 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, ""); +- in_bold = FALSE; +- bold_count--; +- } else if (preceding_space && bold_count > 1 && !g_unichar_isspace(*(p+1))) { +- str = g_string_append(str, ""); +- 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, ""); +- italic_count--; +- in_italic = FALSE; +- } else if (preceding_space && italic_count > 1 && !g_unichar_isspace(*(p+1))) { +- str = g_string_append(str, ""); +- 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(¶ms[next_index].value, G_TYPE_STRING); + g_value_set_string(¶ms[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 +- */ +- +-#include "utsname.h" +-#include +-#include +- +-#include +- +-/* 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 +-#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 +- * +- * 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: +- * +- * Need to do full sync. Can't sync deltas Client +- * has too old a copy for us to do a delta sync +- * +- * 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 +- * 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 \ +- "Full"\ +- "true"\ +- "%s" +- +-#define MSN_GET_CONTACT_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "%s"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "Messenger"\ +- "Invitation"\ +- "SocialNetwork"\ +- "Space"\ +- "Profile"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +-"" +- +-/************************************************ +- * 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 ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Initial"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "0"\ +- "%s"\ +- "true"\ +- ""\ +- ""\ +- ""\ +-"" +- +-/* 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 \ +- ""\ +- "true"\ +- "%s"\ +- "" +- +-#define MSN_GET_GLEAM_UPDATE_XML \ +- "%s"\ +- "Gleam"\ +- "%s" +- +-#define MSN_GET_ADDRESS_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "%s"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "Full"\ +- "AB AllGroups CircleResult"\ +- "%s"\ +- ""\ +- ""\ +-"" +- +- +-/*Gleams SOAP request template*/ +-#define MSN_GET_GLEAMS_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABFindAll" +-#define MSN_GLEAMS_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Initial"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- "Full"\ +- "Gleam"\ +- "0001-01-01T00:00:00.0000000-08:00"\ +- ""\ +- ""\ +-"" +- +- +-/******************************************************* +- * 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 \ +- ""\ +- ""\ +- "LivePending"\ +- "%s"\ +- "true"\ +- ""\ +- "" +- +-#define MSN_CONTACT_XML \ +- ""\ +- ""\ +- "%s"\ +- "false"\ +- "true"\ +- ""\ +- "" +- +-#define MSN_CONTACT_DISPLAYNAME_XML \ +- ""\ +- ""\ +- "%s"\ +- "%s"\ +- "true"\ +- ""\ +- "" +- +-#define MSN_CONTACT_ID_XML \ +- ""\ +- "%s"\ +- "" +- +-#define MSN_CONTACT_EMAIL_XML \ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- "%s"\ +- "true"\ +- "%d"\ +- "false"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "" +- +-#define MSN_CONTACT_INVITE_MESSAGE_XML \ +- ""\ +- ""\ +- ""\ +- "MSN.IM.InviteMessage"\ +- "%s"\ +- ""\ +- ""\ +- "%s"\ +- "" +- +-#define MSN_ADD_CONTACT_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "ContactSave"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- "%s"\ +- ""\ +- "true"\ +- ""\ +- ""\ +- ""\ +-"" +- +-/* 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 ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "ContactSave"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- "true"\ +- "true"\ +- ""\ +- "%s"\ +- ""\ +- ""\ +-"" +- +-/* 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 ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Timer"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- "%s"\ +- ""\ +- ""\ +-"" +- +-/* 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 ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Timer"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- "%s"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +- +-/* Update Contact Information */ +-#define MSN_CONTACT_UPDATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +-#define MSN_CONTACT_UPDATE_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- ""\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-/* Update Contact Annotations */ +-#define MSN_CONTACT_ANNOTATE_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABContactUpdate" +-#define MSN_CONTACT_ANNOTATE_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- ""\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- ""\ +- "Annotation"\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-/******************************************************* +- * 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 \ +- ""\ +- "%s"\ +- "Accepted"\ +- "<%s>%s"\ +- "" +- +-#define MSN_MEMBER_MEMBERSHIPID_XML \ +- ""\ +- "%s"\ +- "%u"\ +- "Accepted"\ +- "" +- +-/* first delete contact from allow list */ +- +-#define MSN_CONTACT_DELETE_FROM_LIST_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "%s"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "0"\ +- "Messenger"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-#define MSN_CONTACT_ADD_TO_LIST_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "%s"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "0"\ +- "Messenger"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +- +- +-/******************************************************* +- * 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 ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "GroupSave"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- "false"\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- "C8529CE2-6EAD-434d-881F-341E17DB3FF8"\ +- "false"\ +- ""\ +- ""\ +- "MSN.IM.Display"\ +- "1"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-/* delete a group */ +-#define MSN_GROUP_DEL_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupDelete" +-#define MSN_GROUP_DEL_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Timer"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-/* change a group's name */ +-#define MSN_GROUP_RENAME_SOAP_ACTION "http://www.msn.com/webservices/AddressBook/ABGroupUpdate" +-#define MSN_GROUP_RENAME_TEMPLATE ""\ +-""\ +- ""\ +- ""\ +- "" MSN_APPLICATION_ID ""\ +- "false"\ +- "Timer"\ +- ""\ +- ""\ +- "false"\ +- "EMPTY"\ +- ""\ +- ""\ +- ""\ +- ""\ +- "00000000-0000-0000-0000-000000000000"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- "%s"\ +- ""\ +- "GroupName "\ +- ""\ +- ""\ +- ""\ +- ""\ +-"" +- +-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. Click here to play it"), +- 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. Click here to play it"), +- 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:
%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
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("", +- 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("%s", 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 %s", 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 "); +- * 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, "
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("%s", +- 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), "
", 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, ""); +- post = g_string_prepend(post, ""); +- } +- +- 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), +- "", +- colors[0], colors[1], colors[2]); +- +- pre = g_string_append(pre, tag); +- post = g_string_prepend(post, ""); +- } +- } +- +- cur = strstr(mime, "RL="); +- +- if (cur && (*(cur = cur + 3) != ';')) +- { +- if (*cur == '1') +- { +- /* RTL text was received */ +- pre = g_string_append(pre, ""); +- post = g_string_prepend(post, ""); +- } +- } +- +- 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 , , , , +- * , , . +- * It ignores and +- */ +-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, "", 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, "<", 4)) +- { +- msg[retcount++] = '<'; +- c += 4; +- } +- else if (!g_ascii_strncasecmp(c, ">", 4)) +- { +- msg[retcount++] = '>'; +- c += 4; +- } +- else if (!g_ascii_strncasecmp(c, " ", 6)) +- { +- msg[retcount++] = ' '; +- c += 6; +- } +- else if (!g_ascii_strncasecmp(c, """, 6)) +- { +- msg[retcount++] = '"'; +- c += 6; +- } +- else if (!g_ascii_strncasecmp(c, "&", 5)) +- { +- msg[retcount++] = '&'; +- c += 5; +- } +- else if (!g_ascii_strncasecmp(c, "'", 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 \ +-""\ +- "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +-"" +- +-#define MSN_SSO_TEMPLATE ""\ +-""\ +- "
"\ +- ""\ +- "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}"\ +- "4"\ +- "1"\ +- ""\ +- "AQAAAAIAAABsYwQAAAAxMDMz"\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- "%s"\ +- ""\ +- ""\ +- "
"\ +- ""\ +- ""\ +- ""\ +- "http://schemas.xmlsoap.org/ws/2004/04/security/trust/Issue"\ +- ""\ +- ""\ +- "http://Passport.NET/tb"\ +- ""\ +- ""\ +- ""\ +- "%s" /* Other RSTn tokens */\ +- ""\ +- ""\ +-"
" +- +-#define MSN_SSO_AUTHINFO_TEMPLATE \ +-""\ +- "{7108E71A-9926-4FCB-BCC9-9A9D3F32E423}"\ +- "4"\ +- "1"\ +- ""\ +- "AQAAAAIAAABsYwQAAAA0MTA1"\ +-"" +-/* 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 \ +-""\ +- "%s"\ +- "%s"\ +-"" +- +-#define MSN_SSO_SIGNEDINFO_TEMPLATE \ +-""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "" MSN_SSO_AUTHINFO_SHA1_BASE64 ""\ +- ""\ +-"" +- +-#define MSN_SSO_TOKEN_UPDATE_TEMPLATE ""\ +-""\ +- "
"\ +- MSN_SSO_AUTHINFO_TEMPLATE /* ps:AuthInfo */ \ +- ""\ +- ""\ +- ""\ +- ""\ +- "http://Passport.NET/STS"\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- "%s" /* wsu:Timestamp */\ +- ""\ +- "%s" /* SignedInfo */\ +- "%s"\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "
"\ +- ""\ +- "%s" /* wst:RequestSecurityToken */ \ +- ""\ +-"" +- +-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 = 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: +- +- +- +- +- +- +- +- +- +- +- +- Message was here +- +- +- +- */ +- +- /* This is the payload if your message was too long: +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- */ +- +- 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
\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; +- +- /* +- Endpoint Name +- true/false +- 1 +- NLN +- +- */ +- 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 '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, "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("", +- 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 +- * 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 +- * 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 ""\ +-""\ +- ""\ +- ""\ +- "EMPTY"\ +- "

EMPTY

"\ +- "
"\ +- "
"\ +- ""\ +- ""\ +- ""\ +-"" +- +-/*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 ""\ +-""\ +- ""\ +- ""\ +- "EMPTY"\ +- "

EMPTY

"\ +- "
"\ +- "
"\ +- ""\ +- ""\ +- "%s"\ +- "false"\ +- ""\ +- ""\ +-"" +- +-/*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 ""\ +-""\ +- ""\ +- ""\ +- "EMPTY"\ +- "

EMPTY

"\ +- "
"\ +- "
"\ +- ""\ +- ""\ +- ""\ +- "%s"\ +- ""\ +- ""\ +- ""\ +-"" +- +-/*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 ""\ +-""\ +- ""\ +- ""\ +- ""\ +- ""\ +- ""\ +- "http://messenger.msn.com"\ +- "%d"\ +- ""\ +- ""\ +- ""\ +- "text"\ +- "%s"\ +- ""\ +-"" +- +-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( +- "%s", +- 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: */ +-#if 0 +- slpcall->remote_user = get_token(body, "From: \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: \r\n" +- "From: \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 +-#if !defined(_WIN32) || !defined(_WINERROR_) +-#include +-#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 +- +-#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: +- * \0Music\01\0{0} - {1}\0Song Title\0Song Artist\0Song Album\0\0\ +- * \0Games\01\0Playing {0}\0Game Name\0\ +- * \0Office\01\0Office Message\0Office App Name\0" +- */ +-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("", 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +-#include +- +-#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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +-#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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 "" +-#define ENCRYPT_HEADER "" +- +- +-/*------------------------------------------------------------------------ +- * 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: */ +- 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: */ +- 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- +-#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 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 map. +- * +- * @param cmd The MXit command string +- * @return The 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 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 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 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, "%s", 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 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), "", 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 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=
|col=:] +- * where: +- * menu ::= { ";" } +- * menuitem ::= { type "," "," "," } +- * colors ::= { ";" } +- * color ::= "," +- * +- * @param session The MXit session object +- * @param from The sender of the message. +- * @param hash The MXit command 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 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 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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, "%s", link, displaytext ); +-#else +- g_string_append_printf( mx->msg, "%s", 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 ); +- 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, "%s Vibe...", 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, "%s: ", 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, "" ); +- else +- g_string_append( mx->msg, "" ); +- 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, "" ); +- else +- g_string_append( mx->msg, "" ); +- 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, "" ); +- else +- g_string_append( mx->msg, "" ); +- 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, "" ); +- i += COLORCODE_LEN; +- } +- else if ( strspn( tmpstr1, "0123456789abcdefABCDEF") == COLORCODE_LEN ) { +- /* definitely a numeric colour code */ +- g_string_append_printf( mx->msg, "", 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++; +- } +- else if ( ( msgflags & CP_MSG_MARKUP ) && ( message[i+1] == '-' ) ) { +- /* decrement text size */ +- font_size--; +- g_string_append_printf( mx->msg, "", 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, "<" ); +- break; +- case '>' : +- g_string_append( mx->msg, ">" ); +- break; +- case '&' : +- g_string_append( mx->msg, "&" ); +- break; +- case '"' : +- g_string_append( mx->msg, """ ); +- 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, "" ); +- g_string_append( mx->msg, "" ); +- } +-} +- +- +-/*------------------------------------------------------------------------ +- * 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: ... +- * Italics: ... +- * Underline: ... +- * Strikethrough: ... (NO MXIT SUPPORT) +- * Font size: ... +- * Font type: ... (NO MXIT SUPPORT) +- * Font colour: ... +- * Links: ... +- * Newline:
+- * Inline image: +- * The following characters are also encoded: +- * & " < > +- */ +- +- /* 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], "" ) || purple_str_has_prefix( &message[i], "" ) ) { +- /* bold */ +- g_string_append_c( mx, '*' ); +- } +- else if ( purple_str_has_prefix( &message[i], "" ) || purple_str_has_prefix( &message[i], "" ) ) { +- /* italics */ +- g_string_append_c( mx, '/' ); +- } +- else if ( purple_str_has_prefix( &message[i], "" ) || purple_str_has_prefix( &message[i], "" ) ) { +- /* underline */ +- g_string_append_c( mx, '_' ); +- } +- else if ( purple_str_has_prefix( &message[i], "
" ) ) { +- /* newline */ +- g_string_append_c( mx, '\n' ); +- } +- else if ( purple_str_has_prefix( &message[i], "" ) ) { +- /* 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], "') */ +- 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 " +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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("%s\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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +-#include +-#include +-#include +-#include +-#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 " +-#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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- +-#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( "", 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- +- +-/* 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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), "", 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 +- * +- * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * (C) Copyright 2010 MXit Lifestyle (Pty) Ltd. +- * +- * +- * 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 +- * +- * 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 ) 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 */ +-#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 (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 . +- */ +- gs_begin = g_string_new(""); +- if (height && !face) { +- guint point_size = msim_height_to_point(session, height); +- g_string_printf(gs_begin, +- "", +- 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, +- "", +- face, msim_point_to_purple_size(session, point_size), +- face, point_size); +- } else { +- g_string_printf(gs_begin, ""); +- } +- +- gs_end = g_string_new(""); +- +- if (decor & MSIM_TEXT_BOLD) { +- g_string_append(gs_begin, ""); +- g_string_prepend(gs_end, ""); +- } +- +- if (decor & MSIM_TEXT_ITALIC) { +- g_string_append(gs_begin, ""); +- g_string_append(gs_end, ""); +- } +- +- if (decor & MSIM_TEXT_UNDERLINE) { +- g_string_append(gs_begin, ""); +- g_string_append(gs_end, ""); +- } +- +- *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 (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("%s", href, href); +- *end = g_strdup(""); +-} +- +-/** +- * Convert the msim markup

(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("

"); +- *end = g_strdup("

"); +-} +- +-/** +- * Convert the msim markup 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: 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("", purple_color); +- *end = g_strdup(""); +-#else +- *begin = g_strdup_printf("", purple_color); +- *end = g_strdup(""); +-#endif +- +- g_free(purple_color); +-} +- +-/** +- * Convert the msim markup 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: 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("", purple_color); +- *end = g_strdup(""); +-#else +- *begin = g_strdup_printf("", purple_color); +- *end = g_strdup(""); +-#endif +- +- g_free(purple_color); +-} +- +-/** +- * Convert the msim markup 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: 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 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("", MSIM_TEXT_BOLD); +- *end = g_strdup(""); +- } else { +- if (!purple_utf8_strcasecmp(root->child->name,"i")) { +- ret++; +- if (root->child->child->type == XMLNODE_TYPE_DATA) { +- *begin = g_strdup_printf("", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC)); +- *end = g_strdup(""); +- } else { +- if (!purple_utf8_strcasecmp(root->child->child->name,"u")) { +- ret++; +- *begin = g_strdup_printf("", (MSIM_TEXT_BOLD + MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE)); +- *end = g_strdup(""); +- } +- } +- } else if (!purple_utf8_strcasecmp(root->child->name,"u")) { +- ret++; +- *begin = g_strdup_printf("", (MSIM_TEXT_BOLD + MSIM_TEXT_UNDERLINE)); +- *end = g_strdup(""); +- } +- } +- } else if (!purple_utf8_strcasecmp(root->name, "i")) { +- if (root->child->type == XMLNODE_TYPE_DATA) { +- *begin = g_strdup_printf("", MSIM_TEXT_ITALIC); +- *end = g_strdup(""); +- } else { +- if (!purple_utf8_strcasecmp(root->child->name,"u")) { +- ret++; +- *begin = g_strdup_printf("", (MSIM_TEXT_ITALIC + MSIM_TEXT_UNDERLINE)); +- *end = g_strdup(""); +- } +- } +- } else if (!purple_utf8_strcasecmp(root->name, "u")) { +- *begin = g_strdup_printf("", MSIM_TEXT_UNDERLINE); +- *end = g_strdup(""); +- } 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: URL +- * Translate to +- * Displayed as text of URL with link to URL +- */ +- *begin = g_strdup_printf("", href); +- } else { +- /* But if we get: text +- * Translate to: text: +- * +- * Because official client only supports self-closed +- * tags; you can't change the link text. +- */ +- *begin = g_strdup_printf("%s: ", link_text, href); +- } +- } else { +- *begin = g_strdup(""); +- } +- +- /* Sorry, kid. MySpace doesn't support you within 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(""); +- +- 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 tag */ +- g_string_append(tmpbegin, ">"); +- +- if (color != NULL) { +- g_string_append_printf(tmpbegin, "", color); +- g_string_prepend(tmpend, ""); +- } +- +- *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("", bgcolor); +- *end = g_strdup(""); +- } +- +- } 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 as +- * a paragraph and will display each on its own line. You actually have +- * to _nest_ 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("", raw, "", 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 markup tags. +- * +- * @param before Original text with ASCII smileys. Will be freed. +- * @return A new string with 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("", 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 +- * +- * 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 +- * +- * 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(""); +- } else { +- debug_str = msim_msg_pack_using(msg, msim_msg_debug_string_element, +- "\n", ""); +- } +- +- 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 +- * +- * 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 +- +-#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 +- * +- * 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 +- * +- * and some constructs also based on existing Purple plugins, which are: +- * Copyright (C) 2003, Robbert Haarman +- * Copyright (C) 2003, Ethan Blanton +- * Copyright (C) 2000-2003, Rob Flynn +- * Copyright (C) 1998-1999, Mark Spencer +- * +- * 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 "" 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 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 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 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_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, ""); +- list = g_list_prepend(list, block ? "b+" : "b-"); +- list = g_list_prepend(list, ""); +- list = g_list_reverse(list); +- +- msg = msim_msg_new( +- "blocklist", MSIM_TYPE_BOOLEAN, TRUE, +- "sesskey", MSIM_TYPE_INTEGER, session->sesskey, +- /* TODO: MsimMessage lists. Currently isn't replaced in lists. */ +- /* "idlist", MSIM_TYPE_STRING, g_strdup("a-||b-|"), */ +- "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(""), +- "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++, +- /* will be replaced by postprocessing */ +- "body", MSIM_TYPE_STRING, g_strdup("ContactID="), +- 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(""), +- "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(""), +- 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 ", /**< 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 +- * +- * 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 +-#include /* for EAGAIN */ +-#include +-#include +- +-#include +- +-#ifdef _WIN32 +-#include "win32dep.h" +-#else +-/* For recv() and send(); needed to match Win32 */ +-#include +-#include +-#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 +- * +- * 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 +- * +- * 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 +- * +- * 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 +- * +- * 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("%s", +- purple_buddy_get_name(user->buddy), _("View web profile")); +- else +- profile = g_strdup_printf("%s", +- 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 +- * +- * 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 +- * +- * 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 +- * +- * 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 +-#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 +-#include +-#include +-#include +-#include +-#include +-#include "nmconn.h" +- +-#ifdef _WIN32 +-#include +-#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 +-#include +-#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 +- +-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 +-#include +-#include +-#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 +- +-/** +- * 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 +-#include +-#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 +- +-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 +-#include +-#include +-#include +-#include +-#include +-#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 +-#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 +-#include +-#include +- +-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 +-#include +-#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 +- +-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. +- +- +- Copyright (C) +- +- 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. +- +- , 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 +- +-#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 +- +-/* 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 +- +-/* +- * 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 +- +-/* 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, ¶ms); +- +- 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, "<title>"); +- if (tmp1 != NULL) { +- tmp1 += 13; +- tmp2 = strstr(tmp1, "</title>"); +- if (tmp2 != NULL) +- g_string_append_len(xstatus, tmp1, tmp2 - tmp1); +- } +- tmp1 = strstr(xml, "<desc>"); +- if (tmp1 != NULL) { +- tmp1 += 12; +- tmp2 = strstr(tmp1, "</desc>"); +- 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 = "<Q><PluginID>srvMng</PluginID></Q><srv><id>cAwaySrv</id><req><id>AwayStat</id><trans>2</trans><senderId>%s</senderId></req></srv>\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 = "<ret event='OnRemoteNotification'><srv><id>cAwaySrv</id><val srv_id='cAwaySrv'><Root><CASXtraSetAwayMessage></CASXtraSetAwayMessage>&l t;uin>%s</uin><index>1</index><title>%s</title><desc>%s</desc></Root></val></srv><srv><id>cRandomizerSrv</id><val srv_id='cRandomizerSrv'>undefined</val></srv></ret>\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: +- * +- * full_phone_without_leading_+ +- * message +- * 1252 +- * self_uin +- * self_name +- * Yes|No +- * +- * +- * +- * 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, "" +- "%s" +- "%s" +- "1252" +- "%s" +- "%s" +- "Yes" +- "" +- "", +- 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 +- */ +- 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 +- +-/* +- * 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 +- +-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 +-#include +-#include +-#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:
%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): +- * +- * +- * +- * This is a really stupid picture:
+- *
+- * Yeah it is
+- * Here is another one:
+- * +- *
+- * +- * +- * datadatadatadata +- * datadatadatadata +- * +- */ +-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 tag! */ +- binary_start = purple_strcasestr(msg, ""); +- if (binary_start == NULL) +- msgend = dataend; +- else +- { +- msgend = binary_start; +- +- /* Move our pointer to immediately after the 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 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 tag */ +- if (g_ascii_strncasecmp(tmp, "", 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, "", 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 +- * Some code copyright (C) 1999-2001, Eric Warmenhoven +- * Some code copyright (C) 2001-2003, Sean Egan +- * Some code copyright (C) 2001-2007, Mark Doliner +- * Some code copyright (C) 2005, Jonathan Clark +- * Some code copyright (C) 2007, ComBOTS Product GmbH (htfv) +- * Some code copyright (C) 2008, Aman Gupta +- * +- * Most libfaim code copyright (C) 1998-2001 Adam Fritzler +- * Some libfaim code copyright (C) 2001-2004 Mark Doliner +- * +- * 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; /* */ +- GData *unused; +- +- /* +- * Find the ending so we can strip off the outer +- * and +- */ +- 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 but not !\n"); +- /* Take everything after */ +- body = g_strdup(start); +- } +- +- ichattextcolor = g_datalist_get_data(&attribs, "ichattextcolor"); +- if (ichattextcolor != NULL) +- { +- tmp2 = g_strdup_printf("%s", ichattextcolor, body); +- g_free(body); +- body = tmp2; +- } +- +- ichatballooncolor = g_datalist_get_data(&attribs, "ichatballooncolor"); +- if (ichatballooncolor != NULL) +- { +- tmp2 = g_strdup_printf("%s", 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: ""); +- g_free(tmp); +- g_free(body); +- +- tmp = tmp2; +- } +- +- /* +- * Are there 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", "
"); +- 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("%s", +- 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; imsg, 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("
", 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("
", 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
%s", 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(""); +- data = g_string_new(""); +- 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, +- "", +- filename, oscar_id, size); +- else +- g_string_append_printf(msg, +- "", +- oscar_id, size); +- +- /* ... and append the data to the binary section ... */ +- g_string_append_printf(data, "", +- oscar_id, size); +- g_string_append_len(data, imgdata, size); +- g_string_append(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, ""); +- +- /* 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, ""); +- } +- 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, "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("%s", 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; istr); +- 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, " 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#ifndef _WIN32 +-#include +-#include +-#include +-#include +-#include +-#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 +-#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 +-#include +-#include +-#include +-#include /* for inet_ntoa */ +-#include /* 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, "", 13) != 0) && +- (g_ascii_strcasecmp(message, "") != 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 +-#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("%s", 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("%s", 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("%s", +- 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 +- +-#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> 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("%s", 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, "
"); +- } +- 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 +- +- 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 +-#include +- +-/* glib includes */ +-#include +- +-/* 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-/* 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 " +-#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, _("Group Title: %s
"), gname); +- g_string_append_printf(str, _("Notes Group ID: %s
"), 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: \n", NSTR(w), NSTR(n)); +- +- } else { +- DEBUG_INFO("%s in conf %s: \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, "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, "", 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, "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)
"), 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 +-#include +- +-#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 <room>: 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 +- +-#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 <room>: 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, "")) { +- 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(" ((c - buf) + input_len)) +- && (c = strstr(c, " ((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 on account %s to buddy %s.\n", +- username, c->name); +- purple_conv_im_send_with_flags(PURPLE_CONV_IM(c), "", 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: +- * bold bolditalic italic +- * 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 +- * (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 +- +-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", ""); /* black */ +- g_hash_table_insert(esc_codes_ht, "31", ""); /* blue */ +- g_hash_table_insert(esc_codes_ht, "32", ""); /* cyan */ /* 00b2b2 */ +- g_hash_table_insert(esc_codes_ht, "33", ""); /* gray */ /* 808080 */ +- g_hash_table_insert(esc_codes_ht, "34", ""); /* green */ /* 00c200 */ +- g_hash_table_insert(esc_codes_ht, "35", ""); /* pink */ /* ffafaf */ +- g_hash_table_insert(esc_codes_ht, "36", ""); /* purple */ /* b200b2 */ +- g_hash_table_insert(esc_codes_ht, "37", ""); /* orange */ /* ffff00 */ +- g_hash_table_insert(esc_codes_ht, "38", ""); /* red */ +- g_hash_table_insert(esc_codes_ht, "39", ""); /* olive */ /* 546b50 */ +-#else +- g_hash_table_insert(esc_codes_ht, "30", ""); /* black */ +- g_hash_table_insert(esc_codes_ht, "31", ""); /* blue */ +- g_hash_table_insert(esc_codes_ht, "32", ""); /* cyan */ /* 00b2b2 */ +- g_hash_table_insert(esc_codes_ht, "33", ""); /* gray */ /* 808080 */ +- g_hash_table_insert(esc_codes_ht, "34", ""); /* green */ /* 00c200 */ +- g_hash_table_insert(esc_codes_ht, "35", ""); /* pink */ /* ffafaf */ +- g_hash_table_insert(esc_codes_ht, "36", ""); /* purple */ /* b200b2 */ +- g_hash_table_insert(esc_codes_ht, "37", ""); /* orange */ /* ffff00 */ +- g_hash_table_insert(esc_codes_ht, "38", ""); /* red */ +- g_hash_table_insert(esc_codes_ht, "39", ""); /* olive */ /* 546b50 */ +-#endif /* !USE_CSS_FORMATTING */ +- +- g_hash_table_insert(esc_codes_ht, "1", ""); +- g_hash_table_insert(esc_codes_ht, "x1", ""); +- g_hash_table_insert(esc_codes_ht, "2", ""); +- g_hash_table_insert(esc_codes_ht, "x2", ""); +- g_hash_table_insert(esc_codes_ht, "4", ""); +- g_hash_table_insert(esc_codes_ht, "x4", ""); +- +- /* 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", ""); +- g_hash_table_insert(tags_ht, "blue", ""); +- g_hash_table_insert(tags_ht, "cyan", ""); +- g_hash_table_insert(tags_ht, "gray", ""); +- g_hash_table_insert(tags_ht, "green", ""); +- g_hash_table_insert(tags_ht, "pink", ""); +- g_hash_table_insert(tags_ht, "purple", ""); +- g_hash_table_insert(tags_ht, "orange", ""); +- g_hash_table_insert(tags_ht, "red", ""); +- g_hash_table_insert(tags_ht, "yellow", ""); +- +- g_hash_table_insert(tags_ht, "/black", ""); +- g_hash_table_insert(tags_ht, "/blue", ""); +- g_hash_table_insert(tags_ht, "/cyan", ""); +- g_hash_table_insert(tags_ht, "/gray", ""); +- g_hash_table_insert(tags_ht, "/green", ""); +- g_hash_table_insert(tags_ht, "/pink", ""); +- g_hash_table_insert(tags_ht, "/purple", ""); +- g_hash_table_insert(tags_ht, "/orange", ""); +- g_hash_table_insert(tags_ht, "/red", ""); +- g_hash_table_insert(tags_ht, "/yellow", ""); +-#else +- g_hash_table_insert(tags_ht, "black", ""); +- g_hash_table_insert(tags_ht, "blue", ""); +- g_hash_table_insert(tags_ht, "cyan", ""); +- g_hash_table_insert(tags_ht, "gray", ""); +- g_hash_table_insert(tags_ht, "green", ""); +- g_hash_table_insert(tags_ht, "pink", ""); +- g_hash_table_insert(tags_ht, "purple", ""); +- g_hash_table_insert(tags_ht, "orange", ""); +- g_hash_table_insert(tags_ht, "red", ""); +- g_hash_table_insert(tags_ht, "yellow", ""); +- +- g_hash_table_insert(tags_ht, "/black", ""); +- g_hash_table_insert(tags_ht, "/blue", ""); +- g_hash_table_insert(tags_ht, "/cyan", ""); +- g_hash_table_insert(tags_ht, "/gray", ""); +- g_hash_table_insert(tags_ht, "/green", ""); +- g_hash_table_insert(tags_ht, "/pink", ""); +- g_hash_table_insert(tags_ht, "/purple", ""); +- g_hash_table_insert(tags_ht, "/orange", ""); +- g_hash_table_insert(tags_ht, "/red", ""); +- g_hash_table_insert(tags_ht, "/yellow", ""); +-#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", ""); +- g_hash_table_insert(tags_ht, "i", ""); +- g_hash_table_insert(tags_ht, "u", ""); +- g_hash_table_insert(tags_ht, "font", ""); +- +- g_hash_table_insert(tags_ht, "/b", ""); +- g_hash_table_insert(tags_ht, "/i", ""); +- g_hash_table_insert(tags_ht, "/u", ""); +- g_hash_table_insert(tags_ht, "/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 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 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: size 8 size 16 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, "")) +- 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 tag. If we don't add anything +- * then we'll pop something that we shouldn't when we hit this +- * corresponding . */ +- *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, "str[dest->len-1] = '>'; +- *tags = g_slist_prepend(*tags, g_strdup("")); +- 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 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(¤t_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: +- * Pidgin +- * with this: +- * Pidgin (http://pidgin.im/) +- * +- * Currently we drop the text within the tag and +- * just show the URL. Doing it the fancy way is +- * complicated when dealing with HTML tags within the +- * 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 tag */ +- end = purple_strcasestr(src + j, ""); +- 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("\n" +- "\n\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("\n" +- "\n\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("\n" +- "\n\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("\n" +- "\n\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 +- * (marv on irc.freenode.net) +- * Some code borrowed from libyahoo2, copyright (C) 2002, Philip +- * S Tellis +- * +- * 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 ", NULL }, +- { DE, "Letzter Update ", NULL }, +- { EL, "Last Updated:", "http://gr.profiles.yahoo.com" }, +- { EN_GB, "Last Update ", "Favourite Quote" }, +- { EN, "Last Update:", NULL }, +- { EN, "Last Update ", NULL }, +- { ES_AR, "\332ltima actualizaci\363n ", NULL }, +- { ES_ES, "Actualizada el ", "http://es.profiles.yahoo.com" }, +- { ES_MX, "Actualizada el  ", "http://mx.profiles.yahoo.com" }, +- { ES_US, "Actualizada el  ", 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 ", NULL }, +- { NO, "Sist oppdatert ", NULL }, +- { PT, "\332ltima atualiza\347\343o ", NULL }, +- { PT_BR, "\332ltima atualiza\347\343o:", NULL }, +- { SV, "Senast uppdaterad ", 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;  '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, " ")) != NULL) { +- *p = ' '; /* Turn  '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("%s

" +- "%s
%s", +- _("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   +- * and · +- */ +- yahoo_remove_nonbreaking_spaces(url_buffer); +-#if 1 +- while ((p = strstr(url_buffer, "·")) != 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 */ +- /* 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, "", "
"); +- /* 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   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("
", 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("%s", +- 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 +- * 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 +- * +- * 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=", +- "urn:xmpp:dataforms:softwareinfoTkabber ( 8.5.5 )ATmega640-16AU"); ++ "urn:xmpp:dataforms:softwareinfoTkabber ( 8.5.5 )ATmega640-16AU"); + } + 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 +- +-#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 +- +-#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 <peanut>", +- yahoo_codes_to_html("plain ")); +- assert_string_equal_free("plain <peanut", +- yahoo_codes_to_html("plain peanut")); +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- assert_string_equal_free("<font face='inva>lid", +- yahoo_codes_to_html("blue
", +- yahoo_codes_to_html("\x1B[31mblue")); +- assert_string_equal_free("custom color", +- yahoo_codes_to_html("\x1B[#70ea15mcustom color")); +- +- /* font face */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- +- /* font size */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- assert_string_equal_free("size 32", +- yahoo_codes_to_html("size 32")); +- +- /* combinations */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- assert_string_equal_free("test", +- yahoo_codes_to_html("\x1B[35mtest")); +-#else +- /* font color */ +- assert_string_equal_free("blue", +- yahoo_codes_to_html("\x1B[31mblue")); +- assert_string_equal_free("custom color", +- yahoo_codes_to_html("\x1B[#70ea15mcustom color")); +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- +- /* font face */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- +- /* font size */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- assert_string_equal_free("size 32", +- yahoo_codes_to_html("size 32")); +- +- /* combinations */ +- assert_string_equal_free("test", +- yahoo_codes_to_html("test")); +- assert_string_equal_free("test", +- yahoo_codes_to_html("\x1B[35mtest")); +- assert_string_equal_free(":<", +- yahoo_codes_to_html(":<")); +-#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 ", +- yahoo_html_to_codes("plain <peanut>")); +- assert_string_equal_free("plain peanut", +- yahoo_html_to_codes("plain> peanut")); +- assert_string_equal_free("plain >", +- yahoo_html_to_codes("plain >")); +- assert_string_equal_free("plain > ", +- yahoo_html_to_codes("plain > ")); +- assert_string_equal_free("plain <", +- yahoo_html_to_codes("plain <")); +- assert_string_equal_free("plain < ", +- yahoo_html_to_codes("plain < ")); +- assert_string_equal_free("plain <", +- yahoo_html_to_codes("plain <")); +- assert_string_equal_free("plain &", +- yahoo_html_to_codes("plain &")); +- +- /* bold/italic/underline */ +- assert_string_equal_free("\x1B[1mbold\x1B[x1m", +- yahoo_html_to_codes("bold")); +- assert_string_equal_free("\x1B[2mitalic\x1B[x2m", +- yahoo_html_to_codes("italic")); +- assert_string_equal_free("\x1B[4munderline\x1B[x4m", +- yahoo_html_to_codes("underline")); +- assert_string_equal_free("no markup", +- yahoo_html_to_codes("no
markup")); +- assert_string_equal_free("\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m", +- yahoo_html_to_codes("bold italic underline")); +- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m", +- yahoo_html_to_codes("bold bolditalic italic")); +- assert_string_equal_free("\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m", +- yahoo_html_to_codes("bold bolditalic italicunderline")); +- +- /* link */ +- assert_string_equal_free("http://pidgin.im/", +- yahoo_html_to_codes("http://pidgin.im/")); +- assert_string_equal_free("mark@example.com", +- yahoo_html_to_codes("mark@example.com")); +-#if 0 +- assert_string_equal_free("Pidgin (http://pidgin.im/)", +- yahoo_html_to_codes("Pidgin")); +-#endif +- +- /* font nothing */ +- assert_string_equal_free("nothing", +- yahoo_html_to_codes("nothing")); +- +- /* font color */ +- assert_string_equal_free("\x1B[#E71414mred\x1B[#000000m", +- yahoo_html_to_codes("red")); +- assert_string_equal_free("\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black", +- yahoo_html_to_codes("red blue black")); +- +- /* font size */ +- assert_string_equal_free("test", +- yahoo_html_to_codes("test")); +- assert_string_equal_free("test", +- yahoo_html_to_codes("test")); +- +- /* combinations */ +- assert_string_equal_free("\x1B[#FF0000mredsmall rednormal\x1B[#000000m", +- yahoo_html_to_codes("redsmall rednormal")); +- +- assert_string_equal_free("\x1B[#FF0000mredsmall \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m", +- yahoo_html_to_codes("redsmall greennormal rednormal")); +- +- assert_string_equal_free("\x1B[1mbold \x1B[#FF0000mred larger \x1B[#000000mbacktoblack normalsize\x1B[#FF0000m\x1B[#000000m\x1B[x1m", +- yahoo_html_to_codes("bold red larger backtoblack normalsize")); +- +- /* buzz/unknown tags */ +- assert_string_equal_free("", +- yahoo_html_to_codes("")); +- assert_string_equal_free("Unknown ", +- yahoo_html_to_codes("Unknown ")); +-} +-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 +- +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +- +-#include +- +-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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include +-#include "config.h" +-#include "debug.h" +-#include "libc_internal.h" +-#include +- +-/** This is redefined here because we can't include internal.h */ +-#ifdef ENABLE_NLS +-# include +-# include +-# define _(String) ((const char *)dgettext(PACKAGE, String)) +-# ifdef gettext_noop +-# define N_(String) gettext_noop (String) +-# else +-# define N_(String) (String) +-# endif +-#else +-# include +-# 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 +- * +- * 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 +-#include +-#include +-#include +-#include "libc_internal.h" +-#include +- +-#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 +- * +- * 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 +- +- +-#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 +-#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 +-#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 +- * +- * 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 +- +-#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, ®_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, ®_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 +- * +- * 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 +-#include +-#include +-#include +-#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 +- * +- * 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, " Gadu-Gadu library (libgadu): Internal
"); +-#else +-#ifdef HAVE_LIBGADU +- g_string_append(str, " Gadu-Gadu library (libgadu): Enabled
"); +-#else +- g_string_append(str, " Gadu-Gadu library (libgadu): Disabled
"); +-#endif +-#endif +- + #ifdef USE_GTKSPELL + g_string_append(str, " GtkSpell: Enabled
"); + #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); + + /* +- marv: The two IM image functions in oscar are purple_odc_send_im and purple_odc_incoming + + + [19:58] 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 / /mn /beauty +-qq.png / /qz /qq +-blowkiss.png / /fw /blow_kiss +-angry.png / /oh /angry +-liquor.png / /bj /baijiu +-can.png / /qsh /soda +-watermelon.png / /xigua /watermelon +-rain.png / /xy /rain +-cloudy.png /<~> /duoy /cloudy +-snowman.png / /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 / /mn /beauty +-qq.png / /qz /qq +-blowkiss.png / /fw /blow_kiss +-angry.png / /oh /angry +-liquor.png / /bj /baijiu +-can.png / /qsh /soda +-watermelon.png / /xigua /watermelon +-rain.png / /xy /rain +-cloudy.png /<~> /duoy /cloudy +-snowman.png / /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 / /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 / /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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- image/svg+xml +- +- Google Talk Icon +- 2006-12-03 +- +- +- Vinicius Scopel Depizzol +- +- +- vdepizzol@gmail.com +- +- +- Google Talk +- GTalk +- VOIP +- Protocol +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +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 @@ +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- +- image/svg+xml +- +- +- +- +- +- +- +- +- +- +- +- +- +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 +- * Copyright (C) 2002-2003, Herman Bloggs +- * Copyright (C) 2005, Daniel Atallah +- * +- * 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 +-#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 ", /**< 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 +- * +- * 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 +-#include +-#include +-#include +-#include +-#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 +- * +- * 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 +-#include +- +-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 +-#include +- +-#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 ", +- 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 +- * Copyright (C) 2003 Herman Bloggs +- * Inspired by a similar plugin by: +- * John (J5) Palmieri +- * +- * 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 +-#include +-#include +- +-#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 +-#include +-#include +-#include +-#include +- +-#include +-#include +-#include +-#include +- +-#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", >kwin32_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 +-#include +-#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 +- */ +-#define _WIN32_WINNT 0x0500 +-#include +-#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 . +-# +- +-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 () { +- 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 () { +- 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>k_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 +-; Updated By: Daniel Atallah +- +-; 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}>k_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 +-;; +-;; 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 +-#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 +-#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 +- * but that isn't portable -- some systems require and +- * , for example. Because isn't quite portable, +- * and isn't really necessary in the context of this program, it isn't +- * included. +- * +- * PORTABILITY: +- * Untar only requires the 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 +- * April 4, 2003 +- * Changes: Stripped out gz compression code, added better interface for +- * untar. +- */ +-#include +-#include +-#include +-#include +-#include +-#ifndef SEEK_SET +-# define SEEK_SET 0 +-#endif +- +-#ifdef _WEAK_POSIX +-# ifndef _POSIX_SOURCE +-# define _POSIX_SOURCE +-# endif +-#endif +- +-#ifdef _POSIX_SOURCE +-# include +-# include +-# include +-# ifdef _WEAK_POSIX +-# define mode_t int +-# else +-# include +-# endif +-#endif +-#include "debug.h" +-#include "untar.h" +-#include +- +-#include +- +-#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, ×tamp); +- 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, ×tamp); +- 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 +- * 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 +-#include +-#include +-#include +-#include +-#include +-#include +-#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) ®val, +- ®len); +- +- 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) ®val, +- 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 +- * +- * 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 +-#endif +-#ifdef USE_GTKSPELL +-#include +-#include +-#include +-#include +-#include +-#include +-#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 +- * +- * 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 +- +-#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 + - Update to reflect changes in perl module installation directories + +-* Mon May 19 2008 Stu Tomlinson +-- Fix building without meanwhile support +- + * Fri May 16 2008 Stu Tomlinson + - 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 +-- 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 +@@ -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 + - 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 +-- Added obsoletes gaim-meanwhile +- + * Sun Oct 30 2005 Stu Tomlinson + - 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 + - Update to reflect changes in perl module installation directories + +-* Mon May 19 2008 Stu Tomlinson +-- Fix building without meanwhile support +- + * Fri May 16 2008 Stu Tomlinson + - 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 +-- 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 +@@ -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 + - 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 +-- Added obsoletes gaim-meanwhile +- + * Sun Oct 30 2005 Stu Tomlinson + - 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 +} -- cgit v1.2.3-54-g00ecf