From f6fdbc4ba29f50f77c6ec1cbce249569551c6cfc Mon Sep 17 00:00:00 2001 From: Márcio Alexandre Silva Delgado Date: Tue, 20 Aug 2013 01:03:50 -0300 Subject: move coherence to nonprism repo --- nonprism/bitlbee-nonprism/PKGBUILD | 62 +++++++++++++++ nonprism/bitlbee-nonprism/bitlbee.install | 15 ++++ nonprism/bitlbee-nonprism/bitlbee.tmpfiles | 1 + nonprism/bitlbee-nonprism/xinetd | 12 +++ nonprism/empathy-nonprism/PKGBUILD | 39 ++++++++++ nonprism/empathy-nonprism/empathy.install | 16 ++++ nonprism/evolution-data-server-nonprism/PKGBUILD | 40 ++++++++++ .../evolution-data-server.install | 11 +++ nonprism/gnome-online-accounts-nonprism/PKGBUILD | 53 +++++++++++++ .../gnome-online-accounts.install | 12 +++ .../gnome-online-accounts-nonprism/imap-smtp.patch | 20 +++++ .../smtp-auth-plain.patch | 88 ++++++++++++++++++++++ nonprism/kdepim-runtime-nonprism/PKGBUILD | 39 ++++++++++ .../kdepim-runtime-nonprism/kdepim-runtime.install | 13 ++++ nonprism/your-privacy/PKGBUILD | 24 ++++++ nonprism/your-privacy/your-coherence.install | 30 ++++++++ 16 files changed, 475 insertions(+) create mode 100644 nonprism/bitlbee-nonprism/PKGBUILD create mode 100644 nonprism/bitlbee-nonprism/bitlbee.install create mode 100644 nonprism/bitlbee-nonprism/bitlbee.tmpfiles create mode 100644 nonprism/bitlbee-nonprism/xinetd create mode 100644 nonprism/empathy-nonprism/PKGBUILD create mode 100644 nonprism/empathy-nonprism/empathy.install create mode 100644 nonprism/evolution-data-server-nonprism/PKGBUILD create mode 100644 nonprism/evolution-data-server-nonprism/evolution-data-server.install create mode 100644 nonprism/gnome-online-accounts-nonprism/PKGBUILD create mode 100644 nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install create mode 100644 nonprism/gnome-online-accounts-nonprism/imap-smtp.patch create mode 100644 nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch create mode 100644 nonprism/kdepim-runtime-nonprism/PKGBUILD create mode 100644 nonprism/kdepim-runtime-nonprism/kdepim-runtime.install create mode 100644 nonprism/your-privacy/PKGBUILD create mode 100644 nonprism/your-privacy/your-coherence.install (limited to 'nonprism') diff --git a/nonprism/bitlbee-nonprism/PKGBUILD b/nonprism/bitlbee-nonprism/PKGBUILD new file mode 100644 index 000000000..f0cfcbf19 --- /dev/null +++ b/nonprism/bitlbee-nonprism/PKGBUILD @@ -0,0 +1,62 @@ + +_pkgname=bitlbee +pkgname=bitlbee-coherence +pkgver=3.2 +pkgrel=1 +pkgdesc='Brings XMPP to IRC (removed support for nonfree, unsafe and dangerous for privacy protocols)' +url='http://www.bitlbee.org/' +license=('GPL') +arch=('i686' 'x86_64') +depends=('gnutls' 'glib2') +makedepends=('asciidoc' 'libotr3') +optdepends=('libotr3: for OTR encryption support' + 'xinetd: to run bitlbee through xinetd') +replaces=$_pkgname +conflicts=$_pkgname +provides=$_pkgname=$pkgver +source=("http://get.bitlbee.org/src/${_pkgname}-${pkgver}.tar.gz" + 'xinetd' + 'bitlbee.tmpfiles') +sha1sums=('21e17f082c776566429603b1e8c966983a75ac9e' + '81c1185b09bee9520b7b58e295a0ffe43a9b0093' + '64b05c7ba522fcdbd0fb57d89ea8320713cc18e9') +backup=('etc/bitlbee/bitlbee.conf' + 'etc/bitlbee/motd.txt' + 'etc/xinetd.d/bitlbee') +install=bitlbee.install + +build() { + cd "$_pkgname-$pkgver" + + ./configure \ + --prefix=/usr \ + --etcdir=/etc/bitlbee \ + --sbindir=/usr/bin \ + --pidfile=/run/bitlbee/bitlbee.pid \ + --ipcsocket=/run/bitlbee/bitlbee.sock \ + --systemdsystemunitdir=/usr/lib/systemd/system \ + --jabber=1 \ + --msn=0 \ + --oscar=0 \ + --yahoo=0 \ + --twitter=0 \ + --purple=0 \ + --ssl=gnutls \ + --strip=0 \ + --otr=plugin \ + --skype=0 + + # hacky: build against libotr3 + sed -i 's,^OTRFLAGS=.*,OTRFLAGS=-lotr3,' Makefile.settings + sed -i 's,#include.*libotr,&3,' otr.h + + make +} + +package() { + make -C "$_pkgname-$pkgver" DESTDIR="$pkgdir" install{,-etc,-dev} + + install -o65 -g65 -dm770 "$pkgdir/var/lib/bitlbee" + install -Dm644 "$srcdir/xinetd" "$pkgdir/etc/xinetd.d/bitlbee" + install -Dm644 "$srcdir/bitlbee.tmpfiles" "$pkgdir/usr/lib/tmpfiles.d/bitlbee.conf" +} \ No newline at end of file diff --git a/nonprism/bitlbee-nonprism/bitlbee.install b/nonprism/bitlbee-nonprism/bitlbee.install new file mode 100644 index 000000000..aa5a81a70 --- /dev/null +++ b/nonprism/bitlbee-nonprism/bitlbee.install @@ -0,0 +1,15 @@ +post_install() { + getent group bitlbee &>/dev/null || groupadd -r -g 65 bitlbee >/dev/null + getent passwd bitlbee &>/dev/null || useradd -r -u 65 -g bitlbee -d /var/lib/bitlbee -s /bin/false -c bitlbee bitlbee >/dev/null + systemd-tmpfiles --create bitlbee.conf +} + +post_upgrade() { + post_install +} + +post_remove() { + getent passwd bitlbee &>/dev/null && userdel bitlbee >/dev/null + getent group bitlbee &>/dev/null && groupdel bitlbee >/dev/null + true +} diff --git a/nonprism/bitlbee-nonprism/bitlbee.tmpfiles b/nonprism/bitlbee-nonprism/bitlbee.tmpfiles new file mode 100644 index 000000000..ebd909675 --- /dev/null +++ b/nonprism/bitlbee-nonprism/bitlbee.tmpfiles @@ -0,0 +1 @@ +d /run/bitlbee 0755 bitlbee bitlbee - - \ No newline at end of file diff --git a/nonprism/bitlbee-nonprism/xinetd b/nonprism/bitlbee-nonprism/xinetd new file mode 100644 index 000000000..169134d2b --- /dev/null +++ b/nonprism/bitlbee-nonprism/xinetd @@ -0,0 +1,12 @@ +service bitlbee +{ + type = UNLISTED + socket_type = stream + protocol = tcp + wait = no + user = bitlbee + group = bitlbee + server = /usr/sbin/bitlbee + port = 6667 + disable = yes +} \ No newline at end of file diff --git a/nonprism/empathy-nonprism/PKGBUILD b/nonprism/empathy-nonprism/PKGBUILD new file mode 100644 index 000000000..de0eca1e9 --- /dev/null +++ b/nonprism/empathy-nonprism/PKGBUILD @@ -0,0 +1,39 @@ + +_pkgname=empathy +pkgname=empathy-coherence +pkgver=3.8.3 +pkgrel=1 +pkgdesc="A GNOME instant messaging client using the Telepathy framework without support for nonfree, unsafe and dangerous for privacy protocols" +arch=(i686 x86_64) +url="http://live.gnome.org/Empathy" +license=(GPL2) +depends=(clutter-gst clutter-gtk folks gcr iso-codes libcanberra libpulse webkitgtk3 telepathy-farstream telepathy-glib telepathy-logger telepathy-mission-control) +makedepends=(intltool itstool docbook-xsl python2) +optdepends=('telepathy-gabble: XMPP/Jabber support' + 'telepathy-idle: IRC support' + 'telepathy-salut: Link-local XMPP support' + 'telepathy-rakia: SIP support') +options=('!libtool' '!makeflags') +groups=(gnome) +install=empathy.install +replaces=$_pkgname +conflicts=$_pkgname +provides=$_pkgname=$pkgver +source=(http://ftp.gnome.org/pub/GNOME/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz) +sha256sums=('61e547c6f0929b3111219349482e2395a32f41bbd0852046405d835acba965c0') + +build() { + cd $_pkgname-$pkgver + PYTHON=/usr/bin/python2 ./configure --prefix=/usr \ + --sysconfdir=/etc \ + --libexecdir=/usr/lib/empathy \ + --disable-static + sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0/g' libtool + make +} + +package() { + cd $_pkgname-$pkgver + make DESTDIR="$pkgdir" install +} + diff --git a/nonprism/empathy-nonprism/empathy.install b/nonprism/empathy-nonprism/empathy.install new file mode 100644 index 000000000..4c5b64313 --- /dev/null +++ b/nonprism/empathy-nonprism/empathy.install @@ -0,0 +1,16 @@ +post_install() { + glib-compile-schemas /usr/share/glib-2.0/schemas + update-desktop-database -q + gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor + echo "To use Empathy you need to install at least one Telepathy connection manager." +} + +post_upgrade() { + glib-compile-schemas /usr/share/glib-2.0/schemas + update-desktop-database -q + gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor +} + +post_remove() { + post_upgrade +} \ No newline at end of file diff --git a/nonprism/evolution-data-server-nonprism/PKGBUILD b/nonprism/evolution-data-server-nonprism/PKGBUILD new file mode 100644 index 000000000..2ba93b16c --- /dev/null +++ b/nonprism/evolution-data-server-nonprism/PKGBUILD @@ -0,0 +1,40 @@ + +_pkgname=evolution-data-server +pkgname=evolution-data-server-coherence +pkgver=3.8.5 +pkgrel=1 +pkgdesc="Centralized access to appointments and contacts without libgdata support" +arch=(i686 x86_64) +depends=(nss krb5 libical db libxml2 libsoup gtk3 libsecret gcr) +makedepends=(intltool gperf gobject-introspection vala python2 gnome-common) +options=('!libtool') +install=$_pkgname.install +url="http://www.gnome.org" +license=(GPL) +replaces=$_pkgname +conflicts=$_pkgname +provides=$_pkgname=$pkgver +source=(http://ftp.gnome.org/pub/gnome/sources/$_pkgname/${pkgver%.*}/$_pkgname-$pkgver.tar.xz) +sha256sums=('73c4ecfed65651cc72966b90081d7b72f9b42573585bc89797efea65ccfdbd2a') + + +build() { + cd "$_pkgname-$pkgver" + autoreconf -fi + ./configure --prefix=/usr --sysconfdir=/etc \ + --localstatedir=/var --with-openldap=yes \ + --libexecdir=/usr/lib/evolution-data-server \ + --with-krb5=/usr --with-libdb=/usr \ + --without-libgdata \ + --disable-goa \ + --disable-google \ + --disable-weather \ + --enable-vala-bindings --disable-uoa PYTHON=python2 + sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0 /g' -e 's/ if test "$export_dynamic" = yes && test -n "$export_dynamic_flag_spec"; then/ func_append compile_command " -Wl,-O1,--as-needed"\n func_append finalize_command " -Wl,-O1,--as-needed"\n\0/' libtool + make +} + +package() { + cd "$_pkgname-$pkgver" + make DESTDIR="$pkgdir" install +} diff --git a/nonprism/evolution-data-server-nonprism/evolution-data-server.install b/nonprism/evolution-data-server-nonprism/evolution-data-server.install new file mode 100644 index 000000000..e75920e11 --- /dev/null +++ b/nonprism/evolution-data-server-nonprism/evolution-data-server.install @@ -0,0 +1,11 @@ +post_install () { + glib-compile-schemas /usr/share/glib-2.0/schemas +} + +post_upgrade () { + post_install +} + +post_remove () { + post_install +} \ No newline at end of file diff --git a/nonprism/gnome-online-accounts-nonprism/PKGBUILD b/nonprism/gnome-online-accounts-nonprism/PKGBUILD new file mode 100644 index 000000000..4f1809e83 --- /dev/null +++ b/nonprism/gnome-online-accounts-nonprism/PKGBUILD @@ -0,0 +1,53 @@ +# $Id$ +# Maintainer: Ionut Biru +# Maintainer (Parabola): Márcio Silva + +_pkgname=gnome-online-accounts +pkgname=gnome-online-accounts-coherence +pkgver=3.8.2 +pkgrel=2 +pkgdesc="GNOME service to access online accounts, without support for nonfree, unsafe and dangerous for privacy protocols" +arch=(i686 x86_64 mips64el) +url="http://www.gnome.org" +license=('GPL') +depends=('webkitgtk3' 'json-glib' 'libnotify' 'rest' 'hicolor-icon-theme' 'libsecret') +makedepends=('intltool' 'libxslt' 'gobject-introspection' 'docbook-xsl') +provides=("$_pkgname=$pkgver") +conflicts=$_pkgname +replaces=$_pkgname +options=(!libtool) +install=$_pkgname.install +source=(http://download.gnome.org/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz + imap-smtp.patch + smtp-auth-plain.patch) +sha256sums=('12611a002043c8acc29e9800ec009e3e19736bdb6237d246e848d7c7909fe826' + '2b413d1f401647bd143b7dc6dd4b6d6660ff47ef9a11ccbc691b7c13de5cba69' + 'e7250be7c078053345699250433b7164751d3e457155bd35508c7d1660f459be') + +prepare() { + cd $_pkgname-$pkgver + # Upstream 3.8 branch + patch -Np1 -i ../imap-smtp.patch + patch -Np1 -i ../smtp-auth-plain.patch +} + +build() { + cd $_pkgname-$pkgver + ./configure --prefix=/usr --libexec=/usr/lib/gnome-online-accounts \ + --disable-google \ + --disable-owncloud \ + --disable-facebook \ + --disable-windows-live \ + --disable-exchange \ + --disable-flickr \ + --enable-imap-smtp \ + --disable-kerberos + make +} + +package() { + cd $_pkgname-$pkgver + make DESTDIR="$pkgdir" install +} + +# vim:set ts=2 sw=2 et: diff --git a/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install b/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install new file mode 100644 index 000000000..ae4eb5fa7 --- /dev/null +++ b/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install @@ -0,0 +1,12 @@ +post_install () { + gtk-update-icon-cache -q -t -f /usr/share/icons/hicolor +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} + diff --git a/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch b/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch new file mode 100644 index 000000000..7213c8d1e --- /dev/null +++ b/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch @@ -0,0 +1,20 @@ +From 034da0871ad78629f9d0df618be494dbb19157e4 Mon Sep 17 00:00:00 2001 +From: Debarshi Ray +Date: Tue, 18 Jun 2013 10:35:42 +0000 +Subject: imap-smtp: Prevent error messages from expanding the dialog + +--- +diff --git a/src/goabackend/goaimapsmtpprovider.c b/src/goabackend/goaimapsmtpprovider.c +index d10a9d8..841327d 100644 +--- a/src/goabackend/goaimapsmtpprovider.c ++++ b/src/goabackend/goaimapsmtpprovider.c +@@ -669,6 +669,7 @@ create_account_details_ui (GoaProvider *provider, + + data->cluebar_label = gtk_label_new (""); + gtk_label_set_line_wrap (GTK_LABEL (data->cluebar_label), TRUE); ++ gtk_label_set_max_width_chars (GTK_LABEL (data->cluebar_label), 36); + gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (data->cluebar))), + data->cluebar_label); + +-- +cgit v0.9.2 diff --git a/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch b/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch new file mode 100644 index 000000000..c6782d0f6 --- /dev/null +++ b/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch @@ -0,0 +1,88 @@ +From 2210bf547dc35adacbc95c0dcf4abe75a73a8368 Mon Sep 17 00:00:00 2001 +From: Debarshi Ray +Date: Tue, 18 Jun 2013 15:27:55 +0000 +Subject: smtp-auth-plain: Handle multiline SMTP greetings + +Fixes: https://bugzilla.gnome.org/702263 +--- +diff --git a/src/goabackend/goasmtpauthplain.c b/src/goabackend/goasmtpauthplain.c +index bb783bd..77324cf 100644 +--- a/src/goabackend/goasmtpauthplain.c ++++ b/src/goabackend/goasmtpauthplain.c +@@ -167,6 +167,40 @@ smtp_auth_plain_check_454 (const gchar *response, GError **error) + + /* ---------------------------------------------------------------------------------------------------- */ + ++static gboolean ++smtp_auth_plain_check_greeting (GDataInputStream *input, GCancellable *cancellable, GError **error) ++{ ++ gboolean ret; ++ gchar *response; ++ ++ response = NULL; ++ ret = FALSE; ++ ++ greeting_again: ++ response = g_data_input_stream_read_line (input, NULL, cancellable, error); ++ if (response == NULL) ++ goto out; ++ g_debug ("< %s", response); ++ if (smtp_auth_plain_check_421 (response, error)) ++ goto out; ++ if (smtp_auth_plain_check_not_220 (response, error)) ++ goto out; ++ ++ if (response[3] == '-') ++ { ++ g_clear_pointer (&response, g_free); ++ goto greeting_again; ++ } ++ ++ ret = TRUE; ++ ++ out: ++ g_free (response); ++ return ret; ++} ++ ++/* ---------------------------------------------------------------------------------------------------- */ ++ + static gchar * + smtp_auth_plain_get_domain (GoaSmtpAuthPlain *auth, + GError **error) +@@ -563,15 +597,8 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth, + + if (!auth->greeting_absent) + { +- response = g_data_input_stream_read_line (input, NULL, cancellable, error); +- if (response == NULL) +- goto out; +- g_debug ("< %s", response); +- if (smtp_auth_plain_check_421 (response, error)) ++ if (!smtp_auth_plain_check_greeting (input, cancellable, error)) + goto out; +- if (smtp_auth_plain_check_not_220 (response, error)) +- goto out; +- g_clear_pointer (&response, g_free); + } + + /* Send EHLO */ +@@ -685,15 +712,8 @@ goa_smtp_auth_plain_starttls_sync (GoaMailAuth *_auth, + + /* Check the greeting */ + +- response = g_data_input_stream_read_line (input, NULL, cancellable, error); +- if (response == NULL) +- goto out; +- g_debug ("< %s", response); +- if (smtp_auth_plain_check_421 (response, error)) ++ if (!smtp_auth_plain_check_greeting (input, cancellable, error)) + goto out; +- if (smtp_auth_plain_check_not_220 (response, error)) +- goto out; +- g_clear_pointer (&response, g_free); + + /* Send EHLO */ + +-- +cgit v0.9.2 diff --git a/nonprism/kdepim-runtime-nonprism/PKGBUILD b/nonprism/kdepim-runtime-nonprism/PKGBUILD new file mode 100644 index 000000000..8bc3de90e --- /dev/null +++ b/nonprism/kdepim-runtime-nonprism/PKGBUILD @@ -0,0 +1,39 @@ +# $Id: PKGBUILD 192541 2013-08-13 18:47:05Z andrea $ +# Maintainer: Andrea Scarpino +# Contributor: Pierre Schmitz +# Maintainer (Parabola): André Silva + +_pkgname=kdepim-runtime +pkgname=kdepim-runtime-coherence +pkgver=4.11.0 +pkgrel=1 +pkgdesc='Extends the functionality of kdepim, without libkgapi support' +arch=('i686' 'x86_64') +url='https://projects.kde.org/projects/kde/kdepim-runtime' +license=('GPL' 'LGPL' 'FDL') +depends=('kdebase-runtime' 'libkolab' 'libkfbapi') +makedepends=('cmake' 'automoc4' 'boost') +install="${_pkgname}.install" +replaces=$_pkgname +conflicts=$_pkgname +provides=$_pkgname=$pkgver +source=("http://download.kde.org/stable/${pkgver}/src/${_pkgname}-${pkgver}.tar.xz") +sha1sums=('ec2a45baf0c2c2ccea633b599a453db52b38dc75') + +prepare() { + mkdir build +} + +build() { + cd build + cmake ../${_pkgname}-${pkgver} \ + -DCMAKE_BUILD_TYPE=Release \ + -DKDE4_BUILD_TESTS=OFF \ + -DCMAKE_INSTALL_PREFIX=/usr + make +} + +package() { + cd build + make DESTDIR="${pkgdir}" install +} diff --git a/nonprism/kdepim-runtime-nonprism/kdepim-runtime.install b/nonprism/kdepim-runtime-nonprism/kdepim-runtime.install new file mode 100644 index 000000000..c77e68041 --- /dev/null +++ b/nonprism/kdepim-runtime-nonprism/kdepim-runtime.install @@ -0,0 +1,13 @@ +post_install() { + xdg-icon-resource forceupdate --theme hicolor &> /dev/null + update-mime-database usr/share/mime &> /dev/null + update-desktop-database -q +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} diff --git a/nonprism/your-privacy/PKGBUILD b/nonprism/your-privacy/PKGBUILD new file mode 100644 index 000000000..c5bfbe5d7 --- /dev/null +++ b/nonprism/your-privacy/PKGBUILD @@ -0,0 +1,24 @@ +# Maintainer: Parabola Project +pkgname=your-coherence +pkgver=$(LC_ALL=C date -u +%Y%m%d) +pkgrel=1 +pkgdesc="This package will remove support for unsafe/dangerous for privacy protocols/services." +arch=('any') +url="https://parabolagnulinux.org" +license=('GPL3') +install=${pkgname}.install +source=(${pkgname}-blacklist-${pkgver}.txt::https://projects.parabolagnulinux.org/blacklist.git/plain/${pkgname}-blacklist.txt) + +package() { + conflicts=($(cut -d: -f1,2 ${pkgname}-blacklist-${pkgver}.txt | \ + sed "s/:$//" | \ + grep -v ":" | \ + grep -v '^#' | \ + sort -u + )) + cd ${srcdir} + install -d ${pkgdir}/usr/share/doc/${pkgname} + install -m644 ${pkgname}-blacklist-${pkgver}.txt ${pkgdir}/usr/share/doc/${pkgname}/ +} + +md5sums=('5fd14982619414fea1882b351607291e') diff --git a/nonprism/your-privacy/your-coherence.install b/nonprism/your-privacy/your-coherence.install new file mode 100644 index 000000000..d5ece49d4 --- /dev/null +++ b/nonprism/your-privacy/your-coherence.install @@ -0,0 +1,30 @@ + +pre_install() { + cat < Date: Tue, 20 Aug 2013 01:05:57 -0300 Subject: rename your-coherence.install to your-privacy.install --- nonprism/your-privacy/your-coherence.install | 30 ---------------------------- nonprism/your-privacy/your-privacy.install | 30 ++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+), 30 deletions(-) delete mode 100644 nonprism/your-privacy/your-coherence.install create mode 100644 nonprism/your-privacy/your-privacy.install (limited to 'nonprism') diff --git a/nonprism/your-privacy/your-coherence.install b/nonprism/your-privacy/your-coherence.install deleted file mode 100644 index d5ece49d4..000000000 --- a/nonprism/your-privacy/your-coherence.install +++ /dev/null @@ -1,30 +0,0 @@ - -pre_install() { - cat < Date: Tue, 20 Aug 2013 01:10:46 -0300 Subject: rename to gnome-online-accounts-nonprism --- nonprism/gnome-online-accounts-nonprism/PKGBUILD | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nonprism') diff --git a/nonprism/gnome-online-accounts-nonprism/PKGBUILD b/nonprism/gnome-online-accounts-nonprism/PKGBUILD index 4f1809e83..5c9172188 100644 --- a/nonprism/gnome-online-accounts-nonprism/PKGBUILD +++ b/nonprism/gnome-online-accounts-nonprism/PKGBUILD @@ -3,10 +3,10 @@ # Maintainer (Parabola): Márcio Silva _pkgname=gnome-online-accounts -pkgname=gnome-online-accounts-coherence +pkgname=gnome-online-accounts-nonprism pkgver=3.8.2 pkgrel=2 -pkgdesc="GNOME service to access online accounts, without support for nonfree, unsafe and dangerous for privacy protocols" +pkgdesc="GNOME service to access online accounts, without support for unsafe and dangerous for privacy protocols" arch=(i686 x86_64 mips64el) url="http://www.gnome.org" license=('GPL') @@ -14,7 +14,7 @@ depends=('webkitgtk3' 'json-glib' 'libnotify' 'rest' 'hicolor-icon-theme' 'libse makedepends=('intltool' 'libxslt' 'gobject-introspection' 'docbook-xsl') provides=("$_pkgname=$pkgver") conflicts=$_pkgname -replaces=$_pkgname +replaces=($_pkgname $pkgname-coherence) options=(!libtool) install=$_pkgname.install source=(http://download.gnome.org/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz -- cgit v1.2.3 From f0728c45baf0ebca5b17e28d8d5cfbbbb4f8fd8d Mon Sep 17 00:00:00 2001 From: Márcio Alexandre Silva Delgado Date: Tue, 20 Aug 2013 02:21:44 -0300 Subject: updating claws-mail-libre and adding claws-mail-libre-nonprism to nonprism repo --- libre/claws-mail-libre/PKGBUILD | 29 +++++------ nonprism/claws-mail-libre-nonprism/PKGBUILD | 76 +++++++++++++++++++++++++++++ 2 files changed, 89 insertions(+), 16 deletions(-) create mode 100644 nonprism/claws-mail-libre-nonprism/PKGBUILD (limited to 'nonprism') diff --git a/libre/claws-mail-libre/PKGBUILD b/libre/claws-mail-libre/PKGBUILD index fdbe6ed19..5ee1fec05 100644 --- a/libre/claws-mail-libre/PKGBUILD +++ b/libre/claws-mail-libre/PKGBUILD @@ -1,23 +1,21 @@ -# $Id: PKGBUILD 192327 2013-08-10 09:48:30Z andyrtr $ +# $Id$ # Maintainer: Andreas Radke # Maintainer (Parabola): Márcio Silva -pkgname=claws-mail-libre -_pkgflag=libre -_pkgname=${pkgname%-$_pkgflag} -pkgver=3.9.2 +_pkgname=claws-mail +pkgname=$_pkgname-libre +pkgver=3.9.1 pkgrel=3 pkgdesc='A GTK+ based e-mail client, without nonfree PalmOS handheld devices support' arch=('i686' 'x86_64' 'mips64el') license=('GPL3') url="http://www.$_pkgname.org" depends=('gtk2' 'gnutls' 'startup-notification' 'enchant' - 'gpgme' 'libetpan>=1.1-4' 'libsm' 'dbus-glib' 'hicolor-icon-theme' 'desktop-file-utils') -makedepends=('compface' 'spamassassin' 'bogofilter' 'valgrind' + 'gpgme' 'libetpan>=1.1' 'libsm' 'db' 'dbus-glib' 'hicolor-icon-theme' 'desktop-file-utils') +makedepends=('compface' 'spamassassin' 'bogofilter' 'valgrind' # dependencies for plugins 'libsoup' 'libgdata' 'webkitgtk2' 'libnotify' 'libcanberra' 'poppler-glib' 'pygtk') #'libchamplain' needed for geolocation plugin, disabled for now - most time it's not compatible with current gnome releases -[ "$CARCH" != "mips64el" ] && makedepends+=('valgrind') optdepends=('python2: needed for some tools and python plugin' 'perl: needed for some tools and perl plugin' 'spamassassin: adds support for spamfiltering' @@ -40,7 +38,7 @@ provides=("$_pkgname=$pkgver" 'claws') options=(!libtool) install=$_pkgname.install source=(http://downloads.sourceforge.net/sourceforge/sylpheed-claws/$_pkgname-$pkgver.tar.bz2{,.asc}) -md5sums=('90de2a265e65fbd9dffdbf428bb0ee28' +md5sums=('8adc734912ff1b83545cb12850100473' 'SKIP') build() { @@ -51,7 +49,7 @@ build() { sed -i 's@^#!.*python.*@#!/usr/bin/python2@' tools/*.py sed -i 's:python -c:python2 -c:g' configure - ./configure --prefix=/usr --disable-static \ + setarch $CARCH ./configure --prefix=/usr --disable-static \ --enable-enchant \ --enable-gnutls \ --enable-ldap \ @@ -59,21 +57,20 @@ build() { --enable-pgpmime-plugin \ --enable-spamassassin-plugin \ --enable-bogofilter-plugin \ - --enable-jpilot \ + --disable-jpilot \ #--help - make + setarch $CARCH make } package() { cd $srcdir/$_pkgname-$pkgver - make DESTDIR=$pkgdir install + setarch $CARCH make DESTDIR=$pkgdir install # build and install extra tools cd tools - make + setarch $CARCH make # all executables and .conf files ; only top directory find -maxdepth 1 -type f -and -perm /111 -or -name '*.conf' | while read i ; do - install -D -m755 $i \ - $pkgdir/usr/lib/$_pkgname/tools/$i + install -D -m755 $i $pkgdir/usr/lib/$_pkgname/tools/$i done } diff --git a/nonprism/claws-mail-libre-nonprism/PKGBUILD b/nonprism/claws-mail-libre-nonprism/PKGBUILD new file mode 100644 index 000000000..42b980a14 --- /dev/null +++ b/nonprism/claws-mail-libre-nonprism/PKGBUILD @@ -0,0 +1,76 @@ +# $Id$ +# Maintainer: Andreas Radke +# Maintainer (Parabola): Márcio Silva + +_pkgname=claws-mail +pkgname=$_pkgname-libre-nonprism +pkgver=3.9.1 +pkgrel=3 +pkgdesc='A GTK+ based e-mail client, without nonfree PalmOS handheld devices support' +arch=('i686' 'x86_64' 'mips64el') +license=('GPL3') +url="http://www.$_pkgname.org" +depends=('gtk2' 'gnutls' 'startup-notification' 'enchant' + 'gpgme' 'libetpan>=1.1' 'libsm' 'db' 'dbus-glib' 'hicolor-icon-theme' 'desktop-file-utils') +makedepends=('compface' 'spamassassin' 'bogofilter' 'valgrind' + # dependencies for plugins + 'libsoup' 'libgdata' 'webkitgtk2' 'libnotify' 'libcanberra' 'poppler-glib' 'pygtk') + #'libchamplain' needed for geolocation plugin, disabled for now - most time it's not compatible with current gnome releases +optdepends=('python2: needed for some tools and python plugin' + 'perl: needed for some tools and perl plugin' + 'spamassassin: adds support for spamfiltering' + 'bogofilter: adds support for spamfiltering' + 'libnotify: for notification plugin' + 'libcanberra: for notification plugin' + 'dbus: for notification plugin' + 'libxml2: for gtkhtml2_viewer and rssyl plugins' + 'curl: for gtkhtml2_viewer, vcalendar, rssyl and spamreport plugins' + 'libarchive: for archive plugin and various other plugins' + 'libytnef: for tnef_parse plugin' + 'webkitgtk2: for the fancy webkit html plugin' + 'libsoup: for the fancy webkit html plugin' + 'poppler-glib: for pdf viewer plugin' + 'ghostscript: for pdf viewer plugin') +replaces=("$_pkgname" "sylpheed-claws" "$_pkgname-extra-plugins" "$_pkgname-libre") +conflicts=("$_pkgname" "$_pkgname-extra-plugins") +provides=("$_pkgname=$pkgver" 'claws') +options=(!libtool) +install=$_pkgname.install +source=(http://downloads.sourceforge.net/sourceforge/sylpheed-claws/$_pkgname-$pkgver.tar.bz2{,.asc}) +md5sums=('8adc734912ff1b83545cb12850100473' + 'SKIP') + +build() { + cd $srcdir/$_pkgname-$pkgver + + # fixes for python2 + export PYTHON="/usr/bin/python2" + sed -i 's@^#!.*python.*@#!/usr/bin/python2@' tools/*.py + sed -i 's:python -c:python2 -c:g' configure + + setarch $CARCH ./configure --prefix=/usr --disable-static \ + --enable-enchant \ + --enable-gnutls \ + --enable-ldap \ + --enable-crash-dialog \ + --enable-pgpmime-plugin \ + --enable-spamassassin-plugin \ + --enable-bogofilter-plugin \ + --disable-jpilot \ + --disable-gdata-plugin + #--help + setarch $CARCH make +} + +package() { + cd $srcdir/$_pkgname-$pkgver + setarch $CARCH make DESTDIR=$pkgdir install + + # build and install extra tools + cd tools + setarch $CARCH make + # all executables and .conf files ; only top directory + find -maxdepth 1 -type f -and -perm /111 -or -name '*.conf' | while read i ; do + install -D -m755 $i $pkgdir/usr/lib/$_pkgname/tools/$i + done +} -- cgit v1.2.3 From 086e7e613ea6526c5cd2922555748e7f9d3a3f6b Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 20 Aug 2013 04:03:31 -0300 Subject: your-privacy: fix some things on install file and PKGBUILD --- nonprism/your-privacy/PKGBUILD | 3 ++- nonprism/your-privacy/your-privacy.install | 6 +++--- 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'nonprism') diff --git a/nonprism/your-privacy/PKGBUILD b/nonprism/your-privacy/PKGBUILD index c5bfbe5d7..3dbc1c733 100644 --- a/nonprism/your-privacy/PKGBUILD +++ b/nonprism/your-privacy/PKGBUILD @@ -1,5 +1,5 @@ # Maintainer: Parabola Project -pkgname=your-coherence +pkgname=your-privacy pkgver=$(LC_ALL=C date -u +%Y%m%d) pkgrel=1 pkgdesc="This package will remove support for unsafe/dangerous for privacy protocols/services." @@ -7,6 +7,7 @@ arch=('any') url="https://parabolagnulinux.org" license=('GPL3') install=${pkgname}.install +replaces=your-coherence source=(${pkgname}-blacklist-${pkgver}.txt::https://projects.parabolagnulinux.org/blacklist.git/plain/${pkgname}-blacklist.txt) package() { diff --git a/nonprism/your-privacy/your-privacy.install b/nonprism/your-privacy/your-privacy.install index d5ece49d4..965fdbf43 100644 --- a/nonprism/your-privacy/your-privacy.install +++ b/nonprism/your-privacy/your-privacy.install @@ -14,11 +14,11 @@ pre_install() { Have in mind that, if you want to retain certain packages that support unsafe/dangerous for privacy protocols/services installed on your system, - you'll have to remove your-coherence :) + you'll have to remove your-privacy :) - Please report any issue to the Coherence Team on the usual channels: + Please report any issue to the Nonprism Team on the usual channels: * https://labs.parabola.nu - * irc://freenode.net/#your-coherence + * irc://freenode.net/#nonprism * mailto:dev@lists.parabolagnulinux.org EOM } -- cgit v1.2.3 From 97161d7676a9268aa73ee18c51fb3d45afad19db Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 20 Aug 2013 04:41:59 -0300 Subject: kdepim-runtime-nonprism: fix package name and features --- nonprism/kdepim-runtime-nonprism/PKGBUILD | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'nonprism') diff --git a/nonprism/kdepim-runtime-nonprism/PKGBUILD b/nonprism/kdepim-runtime-nonprism/PKGBUILD index 8bc3de90e..38a0a1edc 100644 --- a/nonprism/kdepim-runtime-nonprism/PKGBUILD +++ b/nonprism/kdepim-runtime-nonprism/PKGBUILD @@ -4,19 +4,19 @@ # Maintainer (Parabola): André Silva _pkgname=kdepim-runtime -pkgname=kdepim-runtime-coherence +pkgname=kdepim-runtime-nonprism pkgver=4.11.0 pkgrel=1 pkgdesc='Extends the functionality of kdepim, without libkgapi support' arch=('i686' 'x86_64') url='https://projects.kde.org/projects/kde/kdepim-runtime' license=('GPL' 'LGPL' 'FDL') -depends=('kdebase-runtime' 'libkolab' 'libkfbapi') +depends=('kdebase-runtime' 'libkolab') makedepends=('cmake' 'automoc4' 'boost') install="${_pkgname}.install" -replaces=$_pkgname -conflicts=$_pkgname -provides=$_pkgname=$pkgver +replaces=('kdepim-runtime' 'kdepim-runtime-coherence') +conflicts=kdepim-runtime +provides=kdepim-runtime=$pkgver source=("http://download.kde.org/stable/${pkgver}/src/${_pkgname}-${pkgver}.tar.xz") sha1sums=('ec2a45baf0c2c2ccea633b599a453db52b38dc75') -- cgit v1.2.3 From f47d70789def071ce501505d51c90099121aef9c Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 20 Aug 2013 04:42:28 -0300 Subject: kdenetwork-kopete-libre-nonprism: add new package to nonprism repo --- nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD | 71 +++++++++++++ .../kdenetwork-kopete.install | 12 +++ .../kdenetwork.install | 11 +++ .../kdenetwork-kopete-libre-nonprism/libotr3.patch | 71 +++++++++++++ .../libre-nonprism.patch | 110 +++++++++++++++++++++ .../mediastreamer29.patch | 22 +++++ 6 files changed, 297 insertions(+) create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork-kopete.install create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork.install create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/libotr3.patch create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/libre-nonprism.patch create mode 100644 nonprism/kdenetwork-kopete-libre-nonprism/mediastreamer29.patch (limited to 'nonprism') diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD b/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD new file mode 100644 index 000000000..d41efa232 --- /dev/null +++ b/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD @@ -0,0 +1,71 @@ +# $Id: PKGBUILD 192541 2013-08-13 18:47:05Z andrea $ +# Maintainer: Andrea Scarpino +# Maintainer (Parabola): André Silva + +_pkgname=kdenetwork-kopete +pkgname=kdenetwork-kopete-libre-nonprism +pkgver=4.11.0 +pkgrel=1 +pkgdesc='Instant Messenger, without skype and unsafe/dangerous protocols support' +url='http://kde.org/applications/internet/kopete/' +arch=('i686' 'x86_64' 'mips64el') +license=('GPL' 'LGPL' 'FDL') +groups=('kde' 'kdenetwork') +depends=('kdebase-runtime' 'kdepimlibs' 'qca-ossl' 'libotr3' 'libmsn' 'libidn' + 'qimageblitz' 'libgadu' 'mediastreamer' 'jsoncpp') +makedepends=('cmake' 'automoc4' 'boost') +install=${_pkgname}.install +replaces=$_pkgname +conflicts=$_pkgname +provides=$_pkgname=$pkgver +source=("http://download.kde.org/stable/${pkgver}/src/kopete-${pkgver}.tar.xz" + 'libotr3.patch' + 'mediastreamer29.patch' + 'libre-nonprism.patch') +sha1sums=('a67716f14a07cdbacf3df40983db17f594eb768b' + '9c3b0ee15538fbfa36aa0a4748b1f6b5a7905384' + '317683a5c2acd0a0058c5ab42f6006e9db511ef3' + '3c46e5c80ef0cd3f6fe9fb6d5cb8c252c6792208') + +prepare() { + cd kopete-${pkgver} + patch -p2 -i "${srcdir}"/libotr3.patch + patch -p1 -i "${srcdir}"/mediastreamer29.patch + # Based on http://bzr.trisquel.info/package-helpers/trunk/annotate/head%3A/helpers/natty/make-kdenetwork, revision 34. + sed -i 's/Skype protocol" ON/Skype protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/skype + # remove unsafe/dangerous services + sed -i 's/Oscar (ICQ and AIM) protocol" ON/Oscar (ICQ and AIM) protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/oscar + sed -i 's/Yahoo protocol" ON/Yahoo protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/yahoo + sed -i 's/QQ protocol" ON/QQ protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/qq + sed -i 's/Novell GroupWise Messenger protocol" ON/Novell GroupWise Messenger protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/groupwise + sed -i 's/Gadu-Gadu protocol" ON/Gadu-Gadu protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/gadu + sed -i 's/Google Talk support" ON/Google Talk support" OFF/g' protocols/CMakeLists.txt + sed -i 's/Window Live Messenger support" ON/Window Live Messenger support" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/wlm + sed -i 's/Windows Live Messenger voice clip support" ON/Windows Live Messenger voice clip support" OFF/g' protocols/CMakeLists.txt + sed -i 's/meanwhile protocol" ON/meanwhile protocol" OFF/g' protocols/CMakeLists.txt + rm -rf protocols/meanwhile + patch -p1 -i "${srcdir}"/libre-nonprism.patch +} + +build() { + mkdir build + cd build + cmake ../kopete-${pkgver} \ + -DCMAKE_BUILD_TYPE=Release \ + -DKDE4_BUILD_TESTS=OFF \ + -DCMAKE_INSTALL_PREFIX=/usr \ + -DCMAKE_SKIP_RPATH=ON + make +} + +package() { + cd build + make DESTDIR=$pkgdir install +} diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork-kopete.install b/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork-kopete.install new file mode 100644 index 000000000..5495fb1b5 --- /dev/null +++ b/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork-kopete.install @@ -0,0 +1,12 @@ +post_install() { + xdg-icon-resource forceupdate --theme hicolor &> /dev/null + update-desktop-database -q +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork.install b/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork.install new file mode 100644 index 000000000..e70c054ec --- /dev/null +++ b/nonprism/kdenetwork-kopete-libre-nonprism/kdenetwork.install @@ -0,0 +1,11 @@ +post_install() { + xdg-icon-resource forceupdate --theme hicolor &> /dev/null +} + +post_upgrade() { + post_install +} + +post_remove() { + post_install +} diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/libotr3.patch b/nonprism/kdenetwork-kopete-libre-nonprism/libotr3.patch new file mode 100644 index 000000000..1e96c98d6 --- /dev/null +++ b/nonprism/kdenetwork-kopete-libre-nonprism/libotr3.patch @@ -0,0 +1,71 @@ +diff -urN a/kopete/cmake/modules/FindLibOTR.cmake b/kopete/cmake/modules/FindLibOTR.cmake +--- a/kopete/cmake/modules/FindLibOTR.cmake 2012-08-12 18:08:59.000000000 -0600 ++++ b/kopete/cmake/modules/FindLibOTR.cmake 2012-11-09 12:14:24.251450904 -0700 +@@ -13,13 +13,13 @@ + SET(LIBOTR_FIND_QUIETLY TRUE) + ENDIF (LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY) + +-FIND_PATH(LIBOTR_INCLUDE_DIR libotr/version.h) ++FIND_PATH(LIBOTR_INCLUDE_DIR libotr3/version.h) + +-FIND_LIBRARY(LIBOTR_LIBRARY NAMES otr libotr) ++FIND_LIBRARY(LIBOTR_LIBRARY NAMES otr3 libotr3) + +-# Determine version information from libotr/version.h ++# Determine version information from libotr3/version.h + IF( LIBOTR_INCLUDE_DIR AND LIBOTR_LIBRARY ) +- EXECUTE_PROCESS(COMMAND grep "OTRL_VERSION" "${LIBOTR_INCLUDE_DIR}/libotr/version.h" OUTPUT_VARIABLE output) ++ EXECUTE_PROCESS(COMMAND grep "OTRL_VERSION" "${LIBOTR_INCLUDE_DIR}/libotr3/version.h" OUTPUT_VARIABLE output) + STRING(REGEX MATCH "OTRL_VERSION \"[0-9]+\\.[0-9]+\\.[0-9]+" LIBOTR_VERSION "${output}") + STRING(REGEX REPLACE "^OTRL_VERSION \"" "" LIBOTR_VERSION "${LIBOTR_VERSION}") + # Check if version is at least 3.2.0 +diff -urN a/kopete/plugins/otr/authenticationwizard.h b/kopete/plugins/otr/authenticationwizard.h +--- a/kopete/plugins/otr/authenticationwizard.h 2012-08-12 18:09:00.000000000 -0600 ++++ b/kopete/plugins/otr/authenticationwizard.h 2012-11-09 12:15:11.181265336 -0700 +@@ -26,7 +26,7 @@ + */ + + extern "C"{ +-#include "libotr/proto.h" ++#include "libotr3/proto.h" + } + + #include "kopetechatsession.h" +diff -urN a/kopete/plugins/otr/otrlchatinterface.h b/kopete/plugins/otr/otrlchatinterface.h +--- a/kopete/plugins/otr/otrlchatinterface.h 2012-08-12 18:09:00.000000000 -0600 ++++ b/kopete/plugins/otr/otrlchatinterface.h 2012-11-09 12:16:10.141032744 -0700 +@@ -36,10 +36,10 @@ + #include "authenticationwizard.h" + + extern "C" { +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include + } + + +diff -urN a/kopete/plugins/otr/otrlconfinterface.h b/kopete/plugins/otr/otrlconfinterface.h +--- a/kopete/plugins/otr/otrlconfinterface.h 2012-08-12 18:09:00.000000000 -0600 ++++ b/kopete/plugins/otr/otrlconfinterface.h 2012-11-09 12:15:56.961084991 -0700 +@@ -32,11 +32,11 @@ + #include + + extern "C" { +-#include +-#include +-#include +-#include +-#include ++#include ++#include ++#include ++#include ++#include + } + + class KOPETE_OTR_SHARED_EXPORT OtrlConfInterface : public QObject diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/libre-nonprism.patch b/nonprism/kdenetwork-kopete-libre-nonprism/libre-nonprism.patch new file mode 100644 index 000000000..b6915cbb5 --- /dev/null +++ b/nonprism/kdenetwork-kopete-libre-nonprism/libre-nonprism.patch @@ -0,0 +1,110 @@ +diff --git a/doc/index.docbook b/doc/index.docbook +index 1576dc9..daf7170 100644 +--- a/doc/index.docbook ++++ b/doc/index.docbook +@@ -20,7 +20,6 @@ + + + +- + ]> + 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 From 6168f4fb2420b0795734614bc3ff669d33e1026d Mon Sep 17 00:00:00 2001 From: Márcio Alexandre Silva Delgado Date: Wed, 28 Aug 2013 03:45:25 -0300 Subject: pidgin-nonprism: fixing patch --- nonprism/pidgin-nonprism/nonprism-b.patch | 5623 + nonprism/pidgin-nonprism/nonprism.patch | 172633 +-------------------------- 2 files changed, 8651 insertions(+), 169605 deletions(-) create mode 100644 nonprism/pidgin-nonprism/nonprism-b.patch (limited to 'nonprism') diff --git a/nonprism/pidgin-nonprism/nonprism-b.patch b/nonprism/pidgin-nonprism/nonprism-b.patch new file mode 100644 index 000000000..8e64b73d5 --- /dev/null +++ b/nonprism/pidgin-nonprism/nonprism-b.patch @@ -0,0 +1,5623 @@ +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/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/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; +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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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/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 } + }; +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/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.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 --git a/nonprism/pidgin-nonprism/nonprism.patch b/nonprism/pidgin-nonprism/nonprism.patch index 448558a5f..485bef3c8 100644 --- a/nonprism/pidgin-nonprism/nonprism.patch +++ b/nonprism/pidgin-nonprism/nonprism.patch @@ -1157,27 +1157,6 @@ diff -Nur pidgin-2.10.7/doc/funniest_home_convos.txt pidgin-2.10.7-nonprism/doc/ 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 @@ -1194,90 +1173,6 @@ diff -Nur pidgin-2.10.7/doc/pidgin.1.in pidgin-2.10.7-nonprism/doc/pidgin.1.in .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 @@ -1371,17 +1266,6 @@ diff -Nur pidgin-2.10.7/libpurple/blist.c pidgin-2.10.7-nonprism/libpurple/blist 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 @@ -1404,60 +1288,6 @@ diff -Nur pidgin-2.10.7/libpurple/buddyicon.c pidgin-2.10.7-nonprism/libpurple/b } } } -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 @@ -1490,27 +1320,6 @@ diff -Nur pidgin-2.10.7/libpurple/gaim-compat.h pidgin-2.10.7-nonprism/libpurple -#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 @@ -1523,200 +1332,6 @@ diff -Nur pidgin-2.10.7/libpurple/internal.h pidgin-2.10.7-nonprism/libpurple/in */ #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 @@ -1739,138 +1354,44 @@ diff -Nur pidgin-2.10.7/libpurple/media/backend-fs2.c pidgin-2.10.7-nonprism/lib 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 @@ +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/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/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@ @@ -1879,7 +1400,7 @@ diff -Nur pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in pidgin-2.10.7- GCONFTOOL = @GCONFTOOL@ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -@@ -247,8 +245,6 @@ +@@ -223,8 +221,6 @@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -1888,515 +1409,339 @@ diff -Nur pidgin-2.10.7/libpurple/plugins/mono/loader/Makefile.in pidgin-2.10.7- 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/$@ ./ +@@ -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/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) + - --## --## TARGETS --## --.PHONY: all install clean +-def aim(uri): +- protocol = "prpl-aim" +- match = re.match(r"^aim:([^?]*)(\?(.*))", uri) +- if not match: +- print "Invalid aim URI: %s" % uri +- return - --all: $(TARGET).dll $(AUTOSPLIT) +- 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", "") - --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 +- account = findaccount(protocol, accountname) - --$(C_FILES): $(PURPLE_CONFIG_H) +- 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", "")) - --$(AUTOSPLIT): -- mkdir -p ./lib/auto -- cp Purple.pm ./lib -- $(PERL) -MAutoSplit -e 'autosplit("lib/Purple.pm")' +-def gg(uri): +- protocol = "prpl-gg" +- match = re.match(r"^gg:(.*)", uri) +- if not match: +- print "Invalid gg URI: %s" % uri +- return - --$(TARGET).dll: $(PURPLE_DLL).a $(PURPLE_PERL_DLL).a $(FALLBACKS) $(OBJECTS) -- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll +- screenname = urllib.unquote_plus(match.group(1)) +- account = findaccount(protocol) +- goim(account, screenname) - --## --## CLEAN --## --clean: -- rm -rf $(TARGET).dll $(FALLBACKS) lib -- rm -f *.o $(C_FILES) +-def icq(uri): +- protocol = "prpl-icq" +- match = re.match(r"^icq:([^?]*)(\?(.*))", uri) +- if not match: +- print "Invalid icq URI: %s" % uri +- return - --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. --# +- 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", "") - --PIDGIN_TREE_TOP := ../../.. --include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak +- account = findaccount(protocol, accountname) - --DEFINES := $(subst -DWIN32_LEAN_AND_MEAN,,$(DEFINES)) +- 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", "")) - --TARGET = perl + 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 - --# Perl headers with /* /* */ type comments.. Turn off warnings. --GCCWARNINGS += -Wno-comment +- 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", "") - --## --## 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 +- account = findaccount(protocol) - --LIB_PATHS += -L$(GTK_TOP)/lib \ -- -L$(PURPLE_TOP) \ -- -L$(PERL_LIB_TOP) +- if command.lower() == "chat": +- goim(account, screenname) +- elif command.lower() == "add": +- addbuddy(account, screenname) - --## --## SOURCES, OBJECTS --## --C_SRC = perl.c \ -- perl-common.c \ -- perl-handlers.c +-def myim(uri): +- protocol = "prpl-myspace" +- print "TODO: send uri: ", uri +- assert False, "Not implemented" - --OBJECTS = $(C_SRC:%.c=%.o) + 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 - --## --## LIBRARIES --## --LIBS = \ -- -lglib-2.0 \ -- -lgmodule-2.0 \ -- -lgobject-2.0 \ -- -lws2_32 \ -- -lintl \ -- -lpurple \ -- -lperl510 +- 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", "") - --include $(PIDGIN_COMMON_RULES) +- account = findaccount(protocol, accountname) - --## --## TARGET DEFINITIONS --## --.PHONY: all install clean +- if command.lower() == "chat": +- goim(account, jid) +- elif command.lower() == "call": +- # XXX V&V prompt to establish call +- goim(account, jid) - --all: $(TARGET).dll -- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) +-def ymsgr(uri): +- protocol = "prpl-yahoo" +- match = re.match(r"^ymsgr:([^?]*)(\?([^&]*)(&(.*))?)", uri) +- if not match: +- print "Invalid ymsgr URI: %s" % uri +- return - --install: all $(PURPLE_INSTALL_PLUGINS_DIR) -- cp $(TARGET).dll $(PURPLE_INSTALL_PLUGINS_DIR) -- $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install +- 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) - --$(OBJECTS): $(PURPLE_CONFIG_H) +- account = findaccount(protocol) - --## --## 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 +- 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) - --## --## 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 " + 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 @@ -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 @@ + 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@ @@ -2405,7 +1750,7 @@ diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in pidgin-2.10.7-no GCONFTOOL = @GCONFTOOL@ GCONF_SCHEMA_CONFIG_SOURCE = @GCONF_SCHEMA_CONFIG_SOURCE@ GCONF_SCHEMA_FILE_DIR = @GCONF_SCHEMA_FILE_DIR@ -@@ -262,8 +260,6 @@ +@@ -240,8 +234,6 @@ LTLIBOBJS = @LTLIBOBJS@ MAKEINFO = @MAKEINFO@ MANIFEST_TOOL = @MANIFEST_TOOL@ @@ -2414,168560 +1759,2805 @@ diff -Nur pidgin-2.10.7/libpurple/protocols/bonjour/Makefile.in pidgin-2.10.7-no 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) +@@ -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 - --$(TARGET).dll: $(PURPLE_DLL).a $(OBJECTS) -- $(CC) -shared $(OBJECTS) $(LIB_PATHS) $(LIBS) $(DLL_LD_FLAGS) -o $(TARGET).dll +-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` - --## --## CLEAN RULES --## +-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 - --clean: -- rm -f $(OBJECTS) -- rm -f $(TARGET).dll +-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` - --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) + 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/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/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) -{ -- 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, "", ""); +- 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"; - } -- -- ptr = charset_convert(buddylist->str, "UTF-8", "CP1250"); -- g_string_free(buddylist, TRUE); -- return ptr; +- return protocol; -} --/* }}} */ -- -- --/* 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. + 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. - * -- * @return List of buddies. +- * @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. - */ --char * --ggp_buddylist_dump(PurpleAccount *account); -- -- --#endif /* _PURPLE_GG_BUDDYLIST_H */ -- +-const char *_purple_oscar_convert(const char *act, const char *protocol); - --/* 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); + * 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/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"; - -- return purple_find_conversation_with_account(PURPLE_CONV_TYPE_CHAT, name, -- purple_connection_get_account(gc)); --} --/* }}} */ +- 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"; - --/* 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); + /* 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 - -- g_free(str_uin); -- } -- break; + #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); - } --} --/* }}} */ -- --/* 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])); + 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); - -- 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); +- 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); - } -- 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++; +- 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); - -- 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; +- 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); - } -- -- 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; +- 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); - } -- -- 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; +- 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)"); - } - -- 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); + 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; - -- char *buddylist = ggp_buddylist_dump(account); +- pixbuf = pidgin_pixbuf_new_from_file(filename); +- g_free(filename); - -- purple_debug_info("gg", "Saving...\n"); -- purple_debug_info("gg", "file = %s\n", 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 (buddylist == NULL) { -- purple_notify_info(account, _("Save Buddylist..."), -- _("Your buddylist is empty, nothing was written to the file."), -- NULL); -- return; -- } +- if (pixbuf) +- g_object_unref(pixbuf); - -- 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); -- } +- gtalk_name = NULL; +- i++; +- } - -- g_free(buddylist); --} +- 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; - --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; +- pixbuf = pidgin_pixbuf_new_from_file(filename); +- g_free(filename); - -- purple_debug_info("gg", "file_name = %s\n", file); +- 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 (!g_file_get_contents(file, &buddylist, &length, &error)) { -- purple_notify_error(account, -- _("Couldn't load buddylist"), -- _("Couldn't load buddylist"), -- error->message); +- if (pixbuf) +- g_object_unref(pixbuf); - -- purple_debug_error("gg", -- "Couldn't load buddylist. file = %s; error = %s\n", -- file, error->message); +- facebook_name = NULL; +- i++; +- } - -- g_error_free(error); + 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); - -- return; -- } + /* 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 - -- 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); + 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/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-) - -- 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); +-# 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-) - -- 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); --} +-# 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-) - --/* ----- CHANGE PASSWORD ------------------------------------------------ */ +-# Hidden MSN emotes +-cigarette.png (ci) (CI) +-handcuffs.png (%) +-console.png (xx) (XX) +-fingers-crossed.png (yn) (YN) - --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))); +-# 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-) - -- 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); --} +-# 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-) - --static void ggp_change_passwd(PurplePluginAction *action) --{ -- PurpleConnection *gc = (PurpleConnection *)action->context; - -- ggp_token_request(gc, ggp_change_passwd_dialog); --} +-# 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-) - --/* ----- CHANGE STATUS BROADCASTING ------------------------------------------------ */ +-# 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 :-@ - --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; +-# 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 (%) - -- 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); +-# 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 :-(|) :(|) - --out: -- g_free(d->uin); -- g_free(d->avatar_url); -- g_free(d); --} +-# 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 :-@ - --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; +-# 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 (%) - -- 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); +-# 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-) - -- 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; +-# 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/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-) - -- xmlnode_user = xmlnode_get_child(xmlnode_users, "user"); -- if (xmlnode_user == NULL) -- goto out; - -- uin = xmlnode_get_attrib(xmlnode_user, "uin"); +-# 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-) - -- 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; +-# 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-) - -- ggp_update_buddy_avatar(gc, uin); +-# Hidden MSN emotes +-cigarette.png (ci) (CI) +-handcuffs.png (%) +-console.png (xx) (XX) +-fingers-crossed.png (yn) (YN) - -- 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; -- } +-# 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-) - -- 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); --} +-# 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-) - --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); +-# 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-) - -- start = (int)ggp_str_to_uin(gg_pubdir50_get(req, 0, GG_PUBDIR50_START)); -- purple_debug_info("gg", "start = %d\n", start); +-# 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 :-@ - -- for (i = 0; i < res_count; i++) { -- GList *row = NULL; -- char *birth = ggp_search_get_result(req, i, GG_PUBDIR50_BIRTHYEAR); +-# 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 (%) - -- /* 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("-")); +-# 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 :-(|) :(|) - -- purple_notify_searchresults_row_add(results, row); -- } +-# 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 :-@ - -- 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); +-# 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 (%) - -- 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; -- } +-# 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-) - -- 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; --} - +-# 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/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. - --/** -- * 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; -- } +-# 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-) - -- 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); +-# 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 |-) - -- /* 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; +-# Hidden MSN emotes +-cigarette.png (ci) (CI) +-console.png (xx) (XX) - -- 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; +-# 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 - -- 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); +-# 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* - -- /* 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); +-# 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 - -- handlerid = g_strdup_printf("", actimage->crc32); -- g_string_insert(message, byteoffset, handlerid); -- increased_len += strlen(handlerid); -- g_free(handlerid); -- continue; -- } +-# 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 (*) - -- 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); +-# 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 - -- if (got_image) { -- info->pending_richtext_messages = g_list_append(info->pending_richtext_messages, msg); -- return; -- } -- } +-# 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 (*) - -- 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; +-# 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 - -- chat_name = ggp_confer_find_by_participants(gc, -- ev->event.msg.recipients, -- ev->event.msg.recipients_count); +-# 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. - -- 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); +-# 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-) - -- 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); --} +-# 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 |-) - --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))); +-# Hidden MSN emotes +-cigarette.png (ci) (CI) +-console.png (xx) (XX) - -- 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); +-# 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 - -- 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; +-# 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* - -- 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); --} +-# 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 - --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; +-# 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 (*) - -- g_return_val_if_fail(msg != NULL, 0); +-# 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 - -- purple_debug_info("gg", "ggp_to_gg_status: Requested status = %s\n", -- status_id); +-# 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 (*) - -- 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"); +-# 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 - -- 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); +-# 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/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 } + }; +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); - -- 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); -- } -- } +- 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); - -- /* Restore pidgin_dir to point to where the executable is */ -- pidgin_dir_start[0] = L'\0'; +- if (!strcmp(prpl_id, "prpl-msn")) +- { +- mail = g_strdup(purple_normalize(account, +- purple_buddy_get_name(buddy))); - } -- } 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]); +- else if (!strcmp(prpl_id, "prpl-yahoo")) +- { +- mail = g_strdup_printf("%s@yahoo.com", +- purple_normalize(account, +- purple_buddy_get_name(buddy))); - } -- 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_ */ + } + + return mail; +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.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 @@ -171338,170 +4928,3 @@ diff -Nur pidgin-2.10.7/pidgin.spec.in pidgin-2.10.7-nonprism/pidgin.spec.in * 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; -- -- cgit v1.2.3 From 0f01c5850c0915a27a0b20d7f5d65ce88f03dcce Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Mon, 2 Sep 2013 04:18:29 -0300 Subject: gnome-online-accounts-nonprism-3.8.3-1: updating version --- nonprism/gnome-online-accounts-nonprism/PKGBUILD | 21 +++++---------------- .../gnome-online-accounts.install | 1 - 2 files changed, 5 insertions(+), 17 deletions(-) (limited to 'nonprism') diff --git a/nonprism/gnome-online-accounts-nonprism/PKGBUILD b/nonprism/gnome-online-accounts-nonprism/PKGBUILD index 7b541c715..d91e396f5 100644 --- a/nonprism/gnome-online-accounts-nonprism/PKGBUILD +++ b/nonprism/gnome-online-accounts-nonprism/PKGBUILD @@ -1,11 +1,11 @@ -# $Id$ +# $Id: PKGBUILD 193763 2013-08-30 13:15:23Z heftig $ # Maintainer: Ionut Biru # Maintainer (Parabola): Márcio Silva _pkgname=gnome-online-accounts pkgname=gnome-online-accounts-nonprism -pkgver=3.8.2 -pkgrel=2.1 +pkgver=3.8.3 +pkgrel=1 pkgdesc="GNOME service to access online accounts, without support for unsafe and dangerous for privacy protocols" arch=(i686 x86_64 mips64el) url="http://www.gnome.org" @@ -17,19 +17,8 @@ conflicts=$_pkgname replaces=($_pkgname $pkgname-coherence) options=(!libtool) install=$_pkgname.install -source=(http://download.gnome.org/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz - imap-smtp.patch - smtp-auth-plain.patch) -sha256sums=('12611a002043c8acc29e9800ec009e3e19736bdb6237d246e848d7c7909fe826' - '2b413d1f401647bd143b7dc6dd4b6d6660ff47ef9a11ccbc691b7c13de5cba69' - 'e7250be7c078053345699250433b7164751d3e457155bd35508c7d1660f459be') - -prepare() { - cd $_pkgname-$pkgver - # Upstream 3.8 branch - patch -Np1 -i ../imap-smtp.patch - patch -Np1 -i ../smtp-auth-plain.patch -} +source=(http://download.gnome.org/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz) +sha256sums=('9e5e55c5097b8d7c32c0dfb7d94448795c627723b133e8edd0b846adde63a44b') build() { cd $_pkgname-$pkgver diff --git a/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install b/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install index ae4eb5fa7..525ecff63 100644 --- a/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install +++ b/nonprism/gnome-online-accounts-nonprism/gnome-online-accounts.install @@ -9,4 +9,3 @@ post_upgrade() { post_remove() { post_install } - -- cgit v1.2.3 From 1e404c0da87c645c3b6a9667c9b602c5524e56b5 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Mon, 2 Sep 2013 04:20:52 -0300 Subject: gnome-online-accounts-nonprism: remove unnecessaries files --- .../gnome-online-accounts-nonprism/imap-smtp.patch | 20 ----- .../smtp-auth-plain.patch | 88 ---------------------- 2 files changed, 108 deletions(-) delete mode 100644 nonprism/gnome-online-accounts-nonprism/imap-smtp.patch delete mode 100644 nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch (limited to 'nonprism') diff --git a/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch b/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch deleted file mode 100644 index 7213c8d1e..000000000 --- a/nonprism/gnome-online-accounts-nonprism/imap-smtp.patch +++ /dev/null @@ -1,20 +0,0 @@ -From 034da0871ad78629f9d0df618be494dbb19157e4 Mon Sep 17 00:00:00 2001 -From: Debarshi Ray -Date: Tue, 18 Jun 2013 10:35:42 +0000 -Subject: imap-smtp: Prevent error messages from expanding the dialog - ---- -diff --git a/src/goabackend/goaimapsmtpprovider.c b/src/goabackend/goaimapsmtpprovider.c -index d10a9d8..841327d 100644 ---- a/src/goabackend/goaimapsmtpprovider.c -+++ b/src/goabackend/goaimapsmtpprovider.c -@@ -669,6 +669,7 @@ create_account_details_ui (GoaProvider *provider, - - data->cluebar_label = gtk_label_new (""); - gtk_label_set_line_wrap (GTK_LABEL (data->cluebar_label), TRUE); -+ gtk_label_set_max_width_chars (GTK_LABEL (data->cluebar_label), 36); - gtk_container_add (GTK_CONTAINER (gtk_info_bar_get_content_area (GTK_INFO_BAR (data->cluebar))), - data->cluebar_label); - --- -cgit v0.9.2 diff --git a/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch b/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch deleted file mode 100644 index c6782d0f6..000000000 --- a/nonprism/gnome-online-accounts-nonprism/smtp-auth-plain.patch +++ /dev/null @@ -1,88 +0,0 @@ -From 2210bf547dc35adacbc95c0dcf4abe75a73a8368 Mon Sep 17 00:00:00 2001 -From: Debarshi Ray -Date: Tue, 18 Jun 2013 15:27:55 +0000 -Subject: smtp-auth-plain: Handle multiline SMTP greetings - -Fixes: https://bugzilla.gnome.org/702263 ---- -diff --git a/src/goabackend/goasmtpauthplain.c b/src/goabackend/goasmtpauthplain.c -index bb783bd..77324cf 100644 ---- a/src/goabackend/goasmtpauthplain.c -+++ b/src/goabackend/goasmtpauthplain.c -@@ -167,6 +167,40 @@ smtp_auth_plain_check_454 (const gchar *response, GError **error) - - /* ---------------------------------------------------------------------------------------------------- */ - -+static gboolean -+smtp_auth_plain_check_greeting (GDataInputStream *input, GCancellable *cancellable, GError **error) -+{ -+ gboolean ret; -+ gchar *response; -+ -+ response = NULL; -+ ret = FALSE; -+ -+ greeting_again: -+ response = g_data_input_stream_read_line (input, NULL, cancellable, error); -+ if (response == NULL) -+ goto out; -+ g_debug ("< %s", response); -+ if (smtp_auth_plain_check_421 (response, error)) -+ goto out; -+ if (smtp_auth_plain_check_not_220 (response, error)) -+ goto out; -+ -+ if (response[3] == '-') -+ { -+ g_clear_pointer (&response, g_free); -+ goto greeting_again; -+ } -+ -+ ret = TRUE; -+ -+ out: -+ g_free (response); -+ return ret; -+} -+ -+/* ---------------------------------------------------------------------------------------------------- */ -+ - static gchar * - smtp_auth_plain_get_domain (GoaSmtpAuthPlain *auth, - GError **error) -@@ -563,15 +597,8 @@ goa_smtp_auth_plain_run_sync (GoaMailAuth *_auth, - - if (!auth->greeting_absent) - { -- response = g_data_input_stream_read_line (input, NULL, cancellable, error); -- if (response == NULL) -- goto out; -- g_debug ("< %s", response); -- if (smtp_auth_plain_check_421 (response, error)) -+ if (!smtp_auth_plain_check_greeting (input, cancellable, error)) - goto out; -- if (smtp_auth_plain_check_not_220 (response, error)) -- goto out; -- g_clear_pointer (&response, g_free); - } - - /* Send EHLO */ -@@ -685,15 +712,8 @@ goa_smtp_auth_plain_starttls_sync (GoaMailAuth *_auth, - - /* Check the greeting */ - -- response = g_data_input_stream_read_line (input, NULL, cancellable, error); -- if (response == NULL) -- goto out; -- g_debug ("< %s", response); -- if (smtp_auth_plain_check_421 (response, error)) -+ if (!smtp_auth_plain_check_greeting (input, cancellable, error)) - goto out; -- if (smtp_auth_plain_check_not_220 (response, error)) -- goto out; -- g_clear_pointer (&response, g_free); - - /* Send EHLO */ - --- -cgit v0.9.2 -- cgit v1.2.3 From 3d64c0581c214a9f1a8175c9cc715d039df4ef55 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Thu, 5 Sep 2013 16:19:15 -0300 Subject: choqok-nonprism-1.4-1: updating version --- nonprism/choqok-nonprism/PKGBUILD | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'nonprism') diff --git a/nonprism/choqok-nonprism/PKGBUILD b/nonprism/choqok-nonprism/PKGBUILD index abbb4073a..cf5c374b0 100644 --- a/nonprism/choqok-nonprism/PKGBUILD +++ b/nonprism/choqok-nonprism/PKGBUILD @@ -1,4 +1,4 @@ -# $Id$ +# $Id: PKGBUILD 96779 2013-09-04 22:09:55Z andrea $ # Maintainer: Peter Richard Lewis # Contributor: Andrea Scarpino # Contributor: Emanuele Rossi @@ -7,23 +7,25 @@ _pkgname=choqok pkgname=choqok-nonprism -pkgver=1.3 -pkgrel=4.2 +pkgver=1.4 +pkgrel=1 pkgdesc="A status.net client for KDE, without Twitter support" url='http://choqok.gnufolks.org/' license=('GPL') arch=('i686' 'x86_64' 'mips64el') -depends=('kdebase-runtime' 'qjson' 'qoauth' 'qca-ossl') -makedepends=('cmake' 'automoc4') optdepends=('kdebase-konqueror-libre: proxy support') provides=("$_pkgname=$pkgver") conflicts=$_pkgname -replaces=$_pkgname +depends=('kdebase-runtime' 'qjson' 'qoauth' 'qca-ossl') +makedepends=('cmake' 'automoc4') +optdepends=('kdebase-konqueror-libre: proxy support') install="${_pkgname}.install" -source=("http://downloads.sourceforge.net/${_pkgname}/${_pkgname}-${pkgver}.tar.bz2") -md5sums=('87eea4f2c23467fb021e3e6b794eb37d') +source=("http://downloads.sourceforge.net/${_pkgname}/${_pkgname}-${pkgver}.tar.xz") +md5sums=('2efe34ed903b448a21d9233d8033dbdb') prepare() { + mkdir build + cd "${srcdir}/${_pkgname}-${pkgver}" # remove twitter service and keep only twitterapi (choqok software) for status.net and open collaboration services @@ -43,8 +45,6 @@ prepare() { } build() { - cd "${srcdir}" - mkdir build cd build cmake ../${_pkgname}-${pkgver} \ -DCMAKE_BUILD_TYPE=Release \ @@ -53,9 +53,6 @@ build() { } package() { - cd "${srcdir}"/build + cd build make DESTDIR="${pkgdir}" install - - # This is already installed by kdepimlibs >= 4.9.80 - rm "${pkgdir}"/usr/share/apps/cmake/modules/FindQtOAuth.cmake } -- cgit v1.2.3 From 3cfc136cb9eb9c7d9057c3f9f80d0431dc211720 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 10 Sep 2013 18:58:58 -0300 Subject: updating kde packages to 4.11.1 version on nonprism repo --- nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD | 6 +++--- nonprism/kdepim-runtime-nonprism/PKGBUILD | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'nonprism') diff --git a/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD b/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD index 86c23797a..bd4532a4f 100644 --- a/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD +++ b/nonprism/kdenetwork-kopete-libre-nonprism/PKGBUILD @@ -1,10 +1,10 @@ -# $Id: PKGBUILD 192541 2013-08-13 18:47:05Z andrea $ +# $Id: PKGBUILD 194033 2013-09-10 12:51:41Z andrea $ # Maintainer: Andrea Scarpino # Maintainer (Parabola): André Silva _pkgname=kdenetwork-kopete pkgname=kdenetwork-kopete-libre-nonprism -pkgver=4.11.0 +pkgver=4.11.1 pkgrel=1 pkgdesc='Instant Messenger, without skype and support for unsafe and dangerous for privacy protocols' url='http://kde.org/applications/internet/kopete/' @@ -22,7 +22,7 @@ source=("http://download.kde.org/stable/${pkgver}/src/kopete-${pkgver}.tar.xz" 'libotr3.patch' 'mediastreamer29.patch' 'libre-nonprism.patch') -sha1sums=('a67716f14a07cdbacf3df40983db17f594eb768b' +sha1sums=('1dd677e6fd4335e6d0bb906f4c981395ca204e12' '9c3b0ee15538fbfa36aa0a4748b1f6b5a7905384' '317683a5c2acd0a0058c5ab42f6006e9db511ef3' '3c46e5c80ef0cd3f6fe9fb6d5cb8c252c6792208') diff --git a/nonprism/kdepim-runtime-nonprism/PKGBUILD b/nonprism/kdepim-runtime-nonprism/PKGBUILD index 204a69809..79f9b9221 100644 --- a/nonprism/kdepim-runtime-nonprism/PKGBUILD +++ b/nonprism/kdepim-runtime-nonprism/PKGBUILD @@ -1,11 +1,11 @@ -# $Id: PKGBUILD 192541 2013-08-13 18:47:05Z andrea $ +# $Id: PKGBUILD 194033 2013-09-10 12:51:41Z andrea $ # Maintainer: Andrea Scarpino # Contributor: Pierre Schmitz # Maintainer (Parabola): André Silva _pkgname=kdepim-runtime pkgname=kdepim-runtime-nonprism -pkgver=4.11.0 +pkgver=4.11.1 pkgrel=1 pkgdesc='Extends the functionality of kdepim, without libkgapi and libkfbapi support' arch=('i686' 'x86_64') @@ -18,7 +18,7 @@ replaces=('kdepim-runtime' 'kdepim-runtime-coherence') conflicts=kdepim-runtime provides=kdepim-runtime=$pkgver source=("http://download.kde.org/stable/${pkgver}/src/${_pkgname}-${pkgver}.tar.xz") -sha1sums=('ec2a45baf0c2c2ccea633b599a453db52b38dc75') +sha1sums=('a61c1b4cafe16b88213c8cf2f4f64b38a20ed74d') prepare() { mkdir build -- cgit v1.2.3 From ffa02e401d290931439fd16ae2e388af718494e8 Mon Sep 17 00:00:00 2001 From: André Fabian Silva Delgado Date: Tue, 17 Sep 2013 14:18:34 -0300 Subject: empathy-nonprism-3.8.4-1: updating version --- nonprism/empathy-nonprism/PKGBUILD | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'nonprism') diff --git a/nonprism/empathy-nonprism/PKGBUILD b/nonprism/empathy-nonprism/PKGBUILD index 602adb465..50c3fa399 100644 --- a/nonprism/empathy-nonprism/PKGBUILD +++ b/nonprism/empathy-nonprism/PKGBUILD @@ -1,9 +1,11 @@ +# $Id: PKGBUILD 194415 2013-09-16 09:02:51Z jgc $ +# Maintainer: Ionut Biru _pkgname=empathy pkgname=empathy-nonprism -pkgver=3.8.3 +pkgver=3.8.4 pkgrel=1 -pkgdesc="A GNOME instant messaging client using the Telepathy framework, without support for unsafe and dangerous for privacy protocols" +pkgdesc="A GNOME instant messaging client using the Telepathy framework, without telepathy-haze recommendation" arch=(i686 x86_64) url="http://live.gnome.org/Empathy" license=(GPL2) @@ -20,7 +22,7 @@ replaces=("$_pkgname" 'empathy-coherence') conflicts=$_pkgname provides=$_pkgname=$pkgver source=(http://ftp.gnome.org/pub/GNOME/sources/$_pkgname/${pkgver:0:3}/$_pkgname-$pkgver.tar.xz) -sha256sums=('61e547c6f0929b3111219349482e2395a32f41bbd0852046405d835acba965c0') +sha256sums=('cbc4934ce838e3d697616b5c36b070d2fc4fc57f84fd654c2f2cb2b8b650f5c9') build() { cd $_pkgname-$pkgver @@ -36,4 +38,3 @@ package() { cd $_pkgname-$pkgver make DESTDIR="$pkgdir" install } - -- cgit v1.2.3