Mon, 05 Jun 2017 16:36:29 +0300
Merged pidgin/main into default
--- a/.hgignore Sun May 28 13:26:27 2017 +0300 +++ b/.hgignore Mon Jun 05 16:36:29 2017 +0300 @@ -11,10 +11,6 @@ .*/?.*\.pc$ .*/?Makefile(\.in)?$ .*/?Makefile\.am\.mingw$ -.*/perl/common/[^/]+\.c$ -.*/perl/common/blib.* -.*/perl/common/pm_to_blib$ -.*/perl/common/MYMETA\.(json|yml) .*~$ .*\.a$ .*\.asc$ @@ -81,11 +77,6 @@ libpurple/data/purple-url-handler.desktop.in$ libpurple/marshallers.[ch] libpurple/plugins/dbus-example-bindings.c -libpurple/plugins/perl/common/Makefile.PL$ -libpurple/plugins/perl/common/Makefile.old -libpurple/plugins/perl/common/const-c.inc -libpurple/plugins/perl/common/const-xs.inc -libpurple/plugins/perl/common/lib libpurple/protocols/facebook/marshal.[ch] libpurple/purple-client-bindings.[ch] libpurple/purple-client-example @@ -126,8 +117,6 @@ pidgin/pixmaps/emotes/none/theme pidgin/pixmaps/emotes/small/16/theme pidgin/plugins/musicmessaging/music-messaging-bindings.c -pidgin/plugins/perl/common/Makefile.PL$ -pidgin/plugins/perl/common/Makefile.old pidgin/win32/nsis/gtk-runtime-*.*.*.*.zip pidgin/win32/nsis/gtk_runtime_stage$ pidgin/win32/nsis/cacert.pem
--- a/ChangeLog.API Sun May 28 13:26:27 2017 +0300 +++ b/ChangeLog.API Mon Jun 05 16:36:29 2017 +0300 @@ -417,6 +417,7 @@ * purple_account_add_buddies_with_invite * purple_account_add_buddy_with_invite * purple_account_set_current_error + * purple_base64_*. Use g_base64_* instead * purple_blist_load * purple_blist_new * purple_set_blist
--- a/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ b/Makefile.am Mon Jun 05 16:36:29 2017 +0300 @@ -138,12 +138,5 @@ SUBDIRS = . m4macros libpurple $(GNT_DIR) $(GTK_DIR) $(PO_DIR) share/ca-certs share/sounds doc -# perl's MakeMaker uninstall foo doesn't work well with DESTDIR set, which -# breaks "make distcheck" unless we ignore perl things -# TODO drop it when we drop perl wrapper - -distuninstallcheck_listfiles = \ - find . -type f -print | grep -v perl | grep -v Purple.3pm | grep -v Pidgin.3pm - DISTCLEANFILES= intltool-extract intltool-merge intltool-update \ package_revision_raw.txt
--- a/config.h.mingw Sun May 28 13:26:27 2017 +0300 +++ b/config.h.mingw Mon Jun 05 16:36:29 2017 +0300 @@ -180,18 +180,6 @@ /* Define to 1 if you have the <paths.h> header file. */ /* #define HAVE_PATHS_H 1 */ -/* Compile with support for perl */ -#define HAVE_PERL 1 - -/* Define to 1 if you have the `Perl_eval_pv' function. */ -/* #undef HAVE_PERL_EVAL_PV */ - -/* Define to 1 if you have the <perl.h> header file. */ -#define HAVE_PERL_H 1 - -/* Define to 1 if you have the `perl_run' function. */ -/* #define HAVE_PERL_RUN 1 */ - /* Define to 1 if you have the <prio.h> header file. */ /* #undef HAVE_PRIO_H */ @@ -273,9 +261,6 @@ /* Define to 1 if you have the <sys/wait.h> header file. */ /* #define HAVE_SYS_WAIT_H 1 */ -/* Compile with support for the Tcl toolkit */ -/* #define HAVE_TCL 1 */ - /* Define to 1 if you have the <termios.h> header file. */ /* #define HAVE_TERMIOS_H 1 */ @@ -285,9 +270,6 @@ /* Define if you have the external 'timezone' variable. */ #define HAVE_TIMEZONE 1 -/* Compile with support for the Tk toolkit */ -#define HAVE_TK 1 - /* Define if you have a tm_gmtoff member in struct tm */ /* #define HAVE_TM_GMTOFF 1 */ @@ -321,9 +303,6 @@ /* Define to 1 if you don't have wide-character support. */ /* #undef NO_WIDECHAR */ -/* Define if old perl is installed. */ -/* #undef OLD_PERL */ - /* Name of package */ #define PACKAGE "pidgin"
--- a/doc/pidgin.1.in Sun May 28 13:26:27 2017 +0300 +++ b/doc/pidgin.1.in Mon Jun 05 16:36:29 2017 +0300 @@ -520,15 +520,6 @@ configuration options, the \fIConfigure Plugin\fR button will present the plugin's preferences dialog. -.SH PERL -Pidgin allows for plugins to be written in the perl scripting language. See -\fIPerl Scripting HOWTO\fR in the Pidgin documentation for more information -about perl scripting. - -.SH TCL -Pidgin allows for plugins to be written in the Tcl scripting language. See -\fIplugins/tcl/TCL-HOWTO\fR for more information about Tcl scripting. - .SH D-Bus Pidgin allows for interaction via D-Bus. Currently very little documentation about this interaction exists.
--- a/doc/reference/finch/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ b/doc/reference/finch/Makefile.am Mon Jun 05 16:36:29 2017 +0300 @@ -103,6 +103,7 @@ GTKDOC_LIBS = \ $(top_builddir)/finch/libfinch.la \ + $(top_builddir)/libpurple/libpurple.la \ $(DBUS_LIBS) \ $(INTLLIBS) \ $(GLIB_LIBS) \
--- a/doc/reference/libpurple/libpurple-docs.xml Sun May 28 13:26:27 2017 +0300 +++ b/doc/reference/libpurple/libpurple-docs.xml Mon Jun 05 16:36:29 2017 +0300 @@ -111,13 +111,9 @@ <xi:include href="xml/aescipher.xml" /> <xi:include href="xml/descipher.xml" /> <xi:include href="xml/des3cipher.xml" /> - <xi:include href="xml/hmaccipher.xml" /> <xi:include href="xml/pbkdf2cipher.xml" /> <xi:include href="xml/rc4cipher.xml" /> <xi:include href="xml/md4hash.xml" /> - <xi:include href="xml/md5hash.xml" /> - <xi:include href="xml/sha1hash.xml" /> - <xi:include href="xml/sha256hash.xml" /> </chapter> <chapter id="smiley">
--- a/doc/reference/pidgin/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ b/doc/reference/pidgin/Makefile.am Mon Jun 05 16:36:29 2017 +0300 @@ -111,6 +111,7 @@ GTKDOC_LIBS = \ $(top_builddir)/pidgin/libpidgin.la \ + $(top_builddir)/libpurple/libpurple.la \ $(GLIB_LIBS) \ $(GPLUGIN_LIBS) \ $(GCR_LIBS) \
--- a/libpurple/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/Makefile.am Mon Jun 05 16:36:29 2017 +0300 @@ -44,13 +44,9 @@ ciphers/aescipher.c \ ciphers/descipher.c \ ciphers/des3cipher.c \ - ciphers/hmaccipher.c \ ciphers/md4hash.c \ - ciphers/md5hash.c \ ciphers/pbkdf2cipher.c \ ciphers/rc4cipher.c \ - ciphers/sha1hash.c \ - ciphers/sha256hash.c \ cipher.c \ circularbuffer.c \ cmds.c \ @@ -245,13 +241,9 @@ aescipher.h \ descipher.h \ des3cipher.h \ - hmaccipher.h \ md4hash.h \ - md5hash.h \ pbkdf2cipher.h \ - rc4cipher.h \ - sha1hash.h \ - sha256hash.h + rc4cipher.h purple_builtheaders = purple.h version.h enums.h marshallers.h
--- a/libpurple/Makefile.mingw Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/Makefile.mingw Mon Jun 05 16:36:29 2017 +0300 @@ -71,13 +71,9 @@ ciphers/aescipher.c \ ciphers/descipher.c \ ciphers/des3cipher.c \ - ciphers/hmaccipher.c \ ciphers/md4hash.c \ - ciphers/md5hash.c \ ciphers/pbkdf2cipher.c \ ciphers/rc4cipher.c \ - ciphers/sha1hash.c \ - ciphers/sha256hash.c \ cipher.c \ circularbuffer.c \ cmds.c \
--- a/libpurple/ciphers/hmaccipher.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,341 +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 "glibcompat.h" - -#include "hmaccipher.h" - -#include <string.h> - -/******************************************************************************* - * Structs - ******************************************************************************/ -#define PURPLE_HMAC_CIPHER_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherPrivate)) - -typedef struct { - PurpleHash *hash; - guchar *ipad; - guchar *opad; -} PurpleHMACCipherPrivate; - -/****************************************************************************** - * Enums - *****************************************************************************/ -enum { - PROP_NONE, - PROP_HASH, - PROP_LAST, -}; - -/******************************************************************************* - * Globals - ******************************************************************************/ -static GObjectClass *parent_class = NULL; -static GParamSpec *properties[PROP_LAST]; - -/******************************************************************************* - * Helpers - ******************************************************************************/ -static void -purple_hmac_cipher_set_hash(PurpleCipher *cipher, - PurpleHash *hash) -{ - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - priv->hash = g_object_ref(G_OBJECT(hash)); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_HASH]); -} - -/******************************************************************************* - * Cipher Stuff - ******************************************************************************/ -static void -purple_hmac_cipher_reset(PurpleCipher *cipher) { - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - if(PURPLE_IS_HASH(priv->hash)) - purple_hash_reset(priv->hash); - - g_free(priv->ipad); - priv->ipad = NULL; - g_free(priv->opad); - priv->opad = NULL; -} - -static void -purple_hmac_cipher_reset_state(PurpleCipher *cipher) { - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - if(PURPLE_IS_HASH(priv->hash)) { - purple_hash_reset_state(priv->hash); - purple_hash_append(priv->hash, priv->ipad, - purple_hash_get_block_size(priv->hash)); - } -} - -static void -purple_hmac_cipher_append(PurpleCipher *cipher, const guchar *d, size_t l) { - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - g_return_if_fail(PURPLE_IS_HASH(priv->hash)); - - purple_hash_append(priv->hash, d, l); -} - -static gboolean -purple_hmac_cipher_digest(PurpleCipher *cipher, guchar *out, size_t len) -{ - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - guchar *digest = NULL; - size_t hash_len, block_size; - gboolean result = FALSE; - - g_return_val_if_fail(PURPLE_IS_HASH(priv->hash), FALSE); - - hash_len = purple_hash_get_digest_size(priv->hash); - g_return_val_if_fail(hash_len > 0, FALSE); - - block_size = purple_hash_get_block_size(priv->hash); - digest = g_malloc(hash_len); - - /* get the digest of the data */ - result = purple_hash_digest(priv->hash, digest, hash_len); - purple_hash_reset(priv->hash); - - if(!result) { - g_free(digest); - - return FALSE; - } - - /* now append the opad and the digest from above */ - purple_hash_append(priv->hash, priv->opad, block_size); - purple_hash_append(priv->hash, digest, hash_len); - - /* do our last digest */ - result = purple_hash_digest(priv->hash, out, len); - - /* cleanup */ - g_free(digest); - - return result; -} - -static size_t -purple_hmac_cipher_get_digest_size(PurpleCipher *cipher) -{ - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - g_return_val_if_fail(priv->hash != NULL, 0); - - return purple_hash_get_digest_size(priv->hash); -} - -static void -purple_hmac_cipher_set_key(PurpleCipher *cipher, const guchar *key, - size_t key_len) -{ - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - gsize block_size, i; - guchar *full_key; - - g_return_if_fail(priv->hash); - - g_free(priv->ipad); - g_free(priv->opad); - - block_size = purple_hash_get_block_size(priv->hash); - priv->ipad = g_malloc(block_size); - priv->opad = g_malloc(block_size); - - if (key_len > block_size) { - purple_hash_reset(priv->hash); - purple_hash_append(priv->hash, key, key_len); - - key_len = purple_hash_get_digest_size(priv->hash); - full_key = g_malloc(key_len); - purple_hash_digest(priv->hash, full_key, key_len); - } else { - full_key = g_memdup(key, key_len); - } - - if (key_len < block_size) { - full_key = g_realloc(full_key, block_size); - memset(full_key + key_len, 0, block_size - key_len); - } - - for(i = 0; i < block_size; i++) { - priv->ipad[i] = 0x36 ^ full_key[i]; - priv->opad[i] = 0x5c ^ full_key[i]; - } - - g_free(full_key); - - purple_hash_reset(priv->hash); - purple_hash_append(priv->hash, priv->ipad, block_size); -} - -static size_t -purple_hmac_cipher_get_block_size(PurpleCipher *cipher) -{ - PurpleHMACCipherPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), 0); - - priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - return purple_hash_get_block_size(priv->hash); -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ -static void -purple_hmac_cipher_set_property(GObject *obj, guint param_id, - const GValue *value, - GParamSpec *pspec) -{ - PurpleCipher *cipher = PURPLE_CIPHER(obj); - - switch(param_id) { - case PROP_HASH: - purple_hmac_cipher_set_hash(cipher, g_value_get_object(value)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_hmac_cipher_get_property(GObject *obj, guint param_id, GValue *value, - GParamSpec *pspec) -{ - PurpleHMACCipher *cipher = PURPLE_HMAC_CIPHER(obj); - - switch(param_id) { - case PROP_HASH: - g_value_set_object(value, - purple_hmac_cipher_get_hash(cipher)); - break; - default: - G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec); - break; - } -} - -static void -purple_hmac_cipher_finalize(GObject *obj) { - PurpleCipher *cipher = PURPLE_CIPHER(obj); - PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - purple_hmac_cipher_reset(cipher); - - if (priv->hash != NULL) - g_object_unref(priv->hash); - - parent_class->finalize(obj); -} - -static void -purple_hmac_cipher_class_init(PurpleHMACCipherClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleCipherClass *cipher_class = PURPLE_CIPHER_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - g_type_class_add_private(klass, sizeof(PurpleHMACCipherPrivate)); - - obj_class->finalize = purple_hmac_cipher_finalize; - obj_class->get_property = purple_hmac_cipher_get_property; - obj_class->set_property = purple_hmac_cipher_set_property; - - cipher_class->reset = purple_hmac_cipher_reset; - cipher_class->reset_state = purple_hmac_cipher_reset_state; - cipher_class->append = purple_hmac_cipher_append; - cipher_class->digest = purple_hmac_cipher_digest; - cipher_class->get_digest_size = purple_hmac_cipher_get_digest_size; - cipher_class->set_key = purple_hmac_cipher_set_key; - cipher_class->get_block_size = purple_hmac_cipher_get_block_size; - - properties[PROP_HASH] = g_param_spec_object("hash", "hash", "hash", - PURPLE_TYPE_HASH, - G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | - G_PARAM_STATIC_STRINGS); - - g_object_class_install_properties(obj_class, PROP_LAST, properties); -} - -/****************************************************************************** - * PurpleHMACCipher API - *****************************************************************************/ -GType -purple_hmac_cipher_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleHMACCipherClass), - NULL, - NULL, - (GClassInitFunc)purple_hmac_cipher_class_init, - NULL, - NULL, - sizeof(PurpleHMACCipher), - 0, - (GInstanceInitFunc)purple_cipher_reset, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_CIPHER, - "PurpleHMACCipher", - &info, 0); - } - - return type; -} - -PurpleCipher * -purple_hmac_cipher_new(PurpleHash *hash) { - g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); - - return g_object_new(PURPLE_TYPE_HMAC_CIPHER, - "hash", hash, - NULL); -} - -PurpleHash * -purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher) { - PurpleHMACCipherPrivate *priv = NULL; - - g_return_val_if_fail(PURPLE_IS_HMAC_CIPHER(cipher), NULL); - - priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher); - - if(priv && priv->hash) - return priv->hash; - - return NULL; -} -
--- a/libpurple/ciphers/hmaccipher.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +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 PURPLE_HMAC_CIPHER_H -#define PURPLE_HMAC_CIPHER_H -/** - * SECTION:hmaccipher - * @section_id: libpurple-hmaccipher - * @short_description: <filename>ciphers/hmaccipher.h</filename> - * @title: HMAC Cipher - */ - -#include "cipher.h" - -#define PURPLE_TYPE_HMAC_CIPHER (purple_hmac_cipher_get_type()) -#define PURPLE_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipher)) -#define PURPLE_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) -#define PURPLE_IS_HMAC_CIPHER(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) -#define PURPLE_IS_HMAC_CIPHER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_HMAC_CIPHER)) -#define PURPLE_HMAC_CIPHER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherClass)) - -typedef struct _PurpleHMACCipher PurpleHMACCipher; -typedef struct _PurpleHMACCipherClass PurpleHMACCipherClass; - -struct _PurpleHMACCipher { - PurpleCipher gparent; -}; - -struct _PurpleHMACCipherClass { - PurpleCipherClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_hmac_cipher_get_type(void); - -PurpleCipher *purple_hmac_cipher_new(PurpleHash *hash); - -PurpleHash *purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher); - -G_END_DECLS - -#endif /* PURPLE_HMAC_CIPHER_H */
--- a/libpurple/ciphers/md5hash.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +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 "md5hash.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -#define PURPLE_MD5_HASH_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashPrivate)) - -typedef struct { - GChecksum *checksum; -} PurpleMD5HashPrivate; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; - -/****************************************************************************** - * Hash Stuff - *****************************************************************************/ - -static void -purple_md5_hash_reset(PurpleHash *hash) -{ - PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); - PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - g_checksum_reset(priv->checksum); -} - -static void -purple_md5_hash_append(PurpleHash *hash, const guchar *data, - gsize len) -{ - PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); - PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - while (len >= G_MAXSSIZE) { - g_checksum_update(priv->checksum, data, G_MAXSSIZE); - len -= G_MAXSSIZE; - data += G_MAXSSIZE; - } - - if (len) - g_checksum_update(priv->checksum, data, len); -} - -static gboolean -purple_md5_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) -{ - PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); - PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); - - const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_MD5); - gsize digest_len = buff_len; - - g_return_val_if_fail(priv != NULL, FALSE); - g_return_val_if_fail(priv->checksum != NULL, FALSE); - - g_return_val_if_fail(required_len >= 0, FALSE); - g_return_val_if_fail(buff_len >= (gsize)required_len, FALSE); - - g_checksum_get_digest(priv->checksum, digest, &digest_len); - - if (digest_len != (gsize)required_len) - return FALSE; - - purple_md5_hash_reset(hash); - - return TRUE; -} - -static size_t -purple_md5_hash_get_block_size(PurpleHash *hash) -{ - return 64; -} - -static size_t -purple_md5_hash_get_digest_size(PurpleHash *hash) -{ - return g_checksum_type_get_length(G_CHECKSUM_MD5); -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ - -static void -purple_md5_hash_finalize(GObject *obj) -{ - PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(obj); - PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); - - if (priv->checksum) - g_checksum_free(priv->checksum); - - parent_class->finalize(obj); -} - -static void -purple_md5_hash_class_init(PurpleMD5HashClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->finalize = purple_md5_hash_finalize; - - hash_class->reset = purple_md5_hash_reset; - hash_class->reset_state = purple_md5_hash_reset; - hash_class->append = purple_md5_hash_append; - hash_class->digest = purple_md5_hash_digest; - hash_class->get_digest_size = purple_md5_hash_get_digest_size; - hash_class->get_block_size = purple_md5_hash_get_block_size; - - g_type_class_add_private(klass, sizeof(PurpleMD5HashPrivate)); -} - -static void -purple_md5_hash_init(PurpleHash *hash) -{ - PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(hash); - PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash); - - priv->checksum = g_checksum_new(G_CHECKSUM_MD5); - - purple_md5_hash_reset(hash); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_md5_hash_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleMD5HashClass), - NULL, - NULL, - (GClassInitFunc)purple_md5_hash_class_init, - NULL, - NULL, - sizeof(PurpleMD5Hash), - 0, - (GInstanceInitFunc)purple_md5_hash_init, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_HASH, - "PurpleMD5Hash", - &info, 0); - } - - return type; -} - -PurpleHash * -purple_md5_hash_new(void) { - return g_object_new(PURPLE_TYPE_MD5_HASH, NULL); -}
--- a/libpurple/ciphers/md5hash.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +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 PURPLE_MD5_HASH_H -#define PURPLE_MD5_HASH_H -/** - * SECTION:md5hash - * @section_id: libpurple-md5hash - * @short_description: <filename>ciphers/md5hash.h</filename> - * @title: MD5 Hash - */ - -#include "cipher.h" - -#define PURPLE_TYPE_MD5_HASH (purple_md5_hash_get_type()) -#define PURPLE_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5Hash)) -#define PURPLE_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) -#define PURPLE_IS_MD5_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_MD5_HASH)) -#define PURPLE_IS_MD5_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_MD5_HASH)) -#define PURPLE_MD5_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashClass)) - -typedef struct _PurpleMD5Hash PurpleMD5Hash; -typedef struct _PurpleMD5HashClass PurpleMD5HashClass; - -struct _PurpleMD5Hash { - PurpleHash gparent; -}; - -struct _PurpleMD5HashClass { - PurpleHashClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_md5_hash_get_type(void); - -PurpleHash *purple_md5_hash_new(void); - -G_END_DECLS - -#endif /* PURPLE_MD5_HASH_H */
--- a/libpurple/ciphers/pbkdf2cipher.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/ciphers/pbkdf2cipher.c Mon Jun 05 16:36:29 2017 +0300 @@ -25,7 +25,6 @@ #include "glibcompat.h" #include "pbkdf2cipher.h" -#include "hmaccipher.h" #include "debug.h" /* 1024bit */ @@ -38,7 +37,7 @@ (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherPrivate)) typedef struct { - PurpleHash *hash; + GChecksumType hash_type; guint iter_count; size_t out_len; @@ -53,7 +52,7 @@ *****************************************************************************/ enum { PROP_NONE, - PROP_HASH, + PROP_HASH_TYPE, PROP_ITER_COUNT, PROP_OUT_LEN, PROP_LAST, @@ -65,20 +64,6 @@ static GObjectClass *parent_class = NULL; static GParamSpec *properties[PROP_LAST]; -/******************************************************************************* - * Helpers - ******************************************************************************/ -static void -purple_pbkdf2_cipher_set_hash(PurpleCipher *cipher, - PurpleHash *hash) -{ - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - - priv->hash = g_object_ref(G_OBJECT(hash)); - - g_object_notify_by_pspec(G_OBJECT(cipher), properties[PROP_HASH]); -} - /****************************************************************************** * Cipher Stuff *****************************************************************************/ @@ -89,8 +74,6 @@ g_return_if_fail(priv != NULL); - if(PURPLE_IS_HASH(priv->hash)) - purple_hash_reset(priv->hash); priv->iter_count = 1; priv->out_len = 256; @@ -167,17 +150,16 @@ PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); guchar halfkey[PBKDF2_HASH_MAX_LEN], halfkey_hash[PBKDF2_HASH_MAX_LEN]; - guint halfkey_len, halfkey_count, halfkey_pad, halfkey_no; + guint halfkey_count, halfkey_pad, halfkey_no; + gsize halfkey_len; guchar *salt_ext; size_t salt_ext_len; guint iter_no; - PurpleCipher *hash; g_return_val_if_fail(priv != NULL, FALSE); g_return_val_if_fail(digest != NULL, FALSE); g_return_val_if_fail(len >= priv->out_len, FALSE); - g_return_val_if_fail(priv->hash != NULL, FALSE); g_return_val_if_fail(priv->iter_count > 0, FALSE); g_return_val_if_fail(priv->passphrase != NULL || priv->passphrase_len == 0, FALSE); @@ -188,19 +170,10 @@ salt_ext_len = priv->salt_len + 4; - hash = purple_hmac_cipher_new(priv->hash); - if (hash == NULL) { - purple_debug_error("pbkdf2", "Couldn't create new hmac " - "cipher\n"); - return FALSE; - } - purple_cipher_set_key(hash, (const guchar*)priv->passphrase, - priv->passphrase_len); - - halfkey_len = purple_cipher_get_digest_size(hash); + halfkey_len = g_checksum_type_get_length(priv->hash_type); if (halfkey_len <= 0 || halfkey_len > PBKDF2_HASH_MAX_LEN) { purple_debug_error("pbkdf2", "Unsupported hash function. " - "(digest size: %d)\n", halfkey_len); + "(digest size: %" G_GSIZE_FORMAT ")\n", halfkey_len); return FALSE; } @@ -215,9 +188,18 @@ memset(halfkey, 0, halfkey_len); for (iter_no = 1; iter_no <= priv->iter_count; iter_no++) { + GHmac *hmac; guint i; - purple_cipher_reset_state(hash); + hmac = g_hmac_new(priv->hash_type, + (const guchar*)priv->passphrase, + priv->passphrase_len); + if (hmac == NULL) { + purple_debug_error("pbkdf2", + "Couldn't create new hmac cipher\n"); + g_free(salt_ext); + return FALSE; + } if (iter_no == 1) { salt_ext[salt_ext_len - 4] = @@ -229,21 +211,13 @@ salt_ext[salt_ext_len - 1] = (halfkey_no & 0x000000ff) >> 0; - purple_cipher_append(hash, salt_ext, - salt_ext_len); + g_hmac_update(hmac, salt_ext, salt_ext_len); } else - purple_cipher_append(hash, halfkey_hash, - halfkey_len); + g_hmac_update(hmac, halfkey_hash, halfkey_len); - if (!purple_cipher_digest(hash, halfkey_hash, - halfkey_len)) { - purple_debug_error("pbkdf2", - "Couldn't retrieve a digest\n"); - g_free(salt_ext); - g_object_unref(hash); - return FALSE; - } + g_hmac_get_digest(hmac, halfkey_hash, &halfkey_len); + g_hmac_unref(hmac); for (i = 0; i < halfkey_len; i++) halfkey[i] ^= halfkey_hash[i]; @@ -255,7 +229,6 @@ } g_free(salt_ext); - g_object_unref(hash); return TRUE; } @@ -271,8 +244,8 @@ PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); switch(param_id) { - case PROP_HASH: - g_value_set_object(value, purple_pbkdf2_cipher_get_hash(cipher)); + case PROP_HASH_TYPE: + g_value_set_int(value, priv->hash_type); break; case PROP_ITER_COUNT: g_value_set_uint(value, priv->iter_count); @@ -294,8 +267,8 @@ PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); switch(param_id) { - case PROP_HASH: - purple_pbkdf2_cipher_set_hash(cipher, g_value_get_object(value)); + case PROP_HASH_TYPE: + priv->hash_type = g_value_get_int(value); break; case PROP_ITER_COUNT: priv->iter_count = g_value_get_uint(value); @@ -313,13 +286,9 @@ purple_pbkdf2_cipher_finalize(GObject *obj) { PurpleCipher *cipher = PURPLE_CIPHER(obj); - PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); purple_pbkdf2_cipher_reset(cipher); - if (priv->hash != NULL) - g_object_unref(priv->hash); - parent_class->finalize(obj); } @@ -343,8 +312,8 @@ g_type_class_add_private(klass, sizeof(PurplePBKDF2CipherPrivate)); - properties[PROP_HASH] = g_param_spec_object("hash", "hash", "hash", - PURPLE_TYPE_HASH, + properties[PROP_HASH_TYPE] = g_param_spec_int("hash-type", "hash-type", "hash-type", + G_MININT, G_MAXINT, -1, G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS); @@ -364,6 +333,11 @@ static void purple_pbkdf2_cipher_init(PurpleCipher *cipher) { + PurplePBKDF2CipherPrivate *priv = + PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); + + priv->hash_type = -1; + purple_cipher_reset(cipher); } @@ -397,24 +371,22 @@ } PurpleCipher * -purple_pbkdf2_cipher_new(PurpleHash *hash) { - g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL); - +purple_pbkdf2_cipher_new(GChecksumType hash_type) { return g_object_new(PURPLE_TYPE_PBKDF2_CIPHER, - "hash", hash, + "hash-type", hash_type, NULL); } -PurpleHash * -purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher) { +GChecksumType +purple_pbkdf2_cipher_get_hash_type(const PurplePBKDF2Cipher *cipher) { PurplePBKDF2CipherPrivate *priv = NULL; - g_return_val_if_fail(PURPLE_IS_PBKDF2_CIPHER(cipher), NULL); + g_return_val_if_fail(PURPLE_IS_PBKDF2_CIPHER(cipher), -1); priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); - if(priv && priv->hash) - return priv->hash; + if(priv) + return priv->hash_type; - return NULL; + return -1; }
--- a/libpurple/ciphers/pbkdf2cipher.h Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/ciphers/pbkdf2cipher.h Mon Jun 05 16:36:29 2017 +0300 @@ -58,9 +58,9 @@ GType purple_pbkdf2_cipher_get_type(void); -PurpleCipher *purple_pbkdf2_cipher_new(PurpleHash *hash); +PurpleCipher *purple_pbkdf2_cipher_new(GChecksumType hash_type); -PurpleHash *purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher); +GChecksumType purple_pbkdf2_cipher_get_hash_type(const PurplePBKDF2Cipher *cipher); G_END_DECLS
--- a/libpurple/ciphers/sha1hash.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +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 "sha1hash.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -#define PURPLE_SHA1_HASH_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashPrivate)) - -typedef struct { - GChecksum *checksum; -} PurpleSHA1HashPrivate; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; - -/****************************************************************************** - * Hash Stuff - *****************************************************************************/ - -static void -purple_sha1_hash_reset(PurpleHash *hash) -{ - PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); - PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - g_checksum_reset(priv->checksum); -} - -static void -purple_sha1_hash_append(PurpleHash *hash, const guchar *data, - gsize len) -{ - PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); - PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - while (len >= G_MAXSSIZE) { - g_checksum_update(priv->checksum, data, G_MAXSSIZE); - len -= G_MAXSSIZE; - data += G_MAXSSIZE; - } - - if (len) - g_checksum_update(priv->checksum, data, len); -} - -static gboolean -purple_sha1_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) -{ - PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); - PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); - - const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA1); - gsize digest_len = buff_len; - - g_return_val_if_fail(priv != NULL, FALSE); - g_return_val_if_fail(priv->checksum != NULL, FALSE); - - g_return_val_if_fail(required_len >= 0, FALSE); - g_return_val_if_fail(buff_len >= (gsize)required_len, FALSE); - - g_checksum_get_digest(priv->checksum, digest, &digest_len); - - if (digest_len != (gsize)required_len) - return FALSE; - - purple_sha1_hash_reset(hash); - - return TRUE; -} - -static size_t -purple_sha1_hash_get_block_size(PurpleHash *hash) -{ - return 64; -} - -static size_t -purple_sha1_hash_get_digest_size(PurpleHash *hash) -{ - return g_checksum_type_get_length(G_CHECKSUM_SHA1); -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ - -static void -purple_sha1_hash_finalize(GObject *obj) -{ - PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(obj); - PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); - - if (priv->checksum) - g_checksum_free(priv->checksum); - - parent_class->finalize(obj); -} - -static void -purple_sha1_hash_class_init(PurpleSHA1HashClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->finalize = purple_sha1_hash_finalize; - - hash_class->reset = purple_sha1_hash_reset; - hash_class->reset_state = purple_sha1_hash_reset; - hash_class->append = purple_sha1_hash_append; - hash_class->digest = purple_sha1_hash_digest; - hash_class->get_digest_size = purple_sha1_hash_get_digest_size; - hash_class->get_block_size = purple_sha1_hash_get_block_size; - - g_type_class_add_private(klass, sizeof(PurpleSHA1HashPrivate)); -} - -static void -purple_sha1_hash_init(PurpleHash *hash) -{ - PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(hash); - PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash); - - priv->checksum = g_checksum_new(G_CHECKSUM_SHA1); - - purple_sha1_hash_reset(hash); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_sha1_hash_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleSHA1HashClass), - NULL, - NULL, - (GClassInitFunc)purple_sha1_hash_class_init, - NULL, - NULL, - sizeof(PurpleSHA1Hash), - 0, - (GInstanceInitFunc)purple_sha1_hash_init, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_HASH, - "PurpleSHA1Hash", - &info, 0); - } - - return type; -} - -PurpleHash * -purple_sha1_hash_new(void) { - return g_object_new(PURPLE_TYPE_SHA1_HASH, NULL); -}
--- a/libpurple/ciphers/sha1hash.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +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 PURPLE_SHA1_HASH_H -#define PURPLE_SHA1_HASH_H -/** - * SECTION:sha1hash - * @section_id: libpurple-sha1hash - * @short_description: <filename>ciphers/sha1hash.h</filename> - * @title: SHA1 Hash - */ - -#include "cipher.h" - -#define PURPLE_TYPE_SHA1_HASH (purple_sha1_hash_get_type()) -#define PURPLE_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1Hash)) -#define PURPLE_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) -#define PURPLE_IS_SHA1_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) -#define PURPLE_IS_SHA1_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA1_HASH)) -#define PURPLE_SHA1_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashClass)) - -typedef struct _PurpleSHA1Hash PurpleSHA1Hash; -typedef struct _PurpleSHA1HashClass PurpleSHA1HashClass; - -struct _PurpleSHA1Hash { - PurpleHash gparent; -}; - -struct _PurpleSHA1HashClass { - PurpleHashClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_sha1_hash_get_type(void); - -PurpleHash *purple_sha1_hash_new(void); - -G_END_DECLS - -#endif /* PURPLE_SHA1_HASH_H */
--- a/libpurple/ciphers/sha256hash.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,191 +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 "sha256hash.h" - -/******************************************************************************* - * Structs - ******************************************************************************/ -#define PURPLE_SHA256_HASH_GET_PRIVATE(obj) \ - (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashPrivate)) - -typedef struct { - GChecksum *checksum; -} PurpleSHA256HashPrivate; - -/****************************************************************************** - * Globals - *****************************************************************************/ -static GObjectClass *parent_class = NULL; - -/****************************************************************************** - * Hash Stuff - *****************************************************************************/ - -static void -purple_sha256_hash_reset(PurpleHash *hash) -{ - PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); - PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - g_checksum_reset(priv->checksum); -} - -static void -purple_sha256_hash_append(PurpleHash *hash, const guchar *data, - gsize len) -{ - PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); - PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); - - g_return_if_fail(priv != NULL); - g_return_if_fail(priv->checksum != NULL); - - while (len >= G_MAXSSIZE) { - g_checksum_update(priv->checksum, data, G_MAXSSIZE); - len -= G_MAXSSIZE; - data += G_MAXSSIZE; - } - - if (len) - g_checksum_update(priv->checksum, data, len); -} - -static gboolean -purple_sha256_hash_digest(PurpleHash *hash, guchar *digest, size_t buff_len) -{ - PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); - PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); - - const gssize required_len = g_checksum_type_get_length(G_CHECKSUM_SHA256); - gsize digest_len = buff_len; - - g_return_val_if_fail(priv != NULL, FALSE); - g_return_val_if_fail(priv->checksum != NULL, FALSE); - - g_return_val_if_fail(required_len >= 0, FALSE); - g_return_val_if_fail(buff_len >= (gsize)required_len, FALSE); - - g_checksum_get_digest(priv->checksum, digest, &digest_len); - - if (digest_len != (gsize)required_len) - return FALSE; - - purple_sha256_hash_reset(hash); - - return TRUE; -} - -static size_t -purple_sha256_hash_get_block_size(PurpleHash *hash) -{ - return 64; -} - -static size_t -purple_sha256_hash_get_digest_size(PurpleHash *hash) -{ - return g_checksum_type_get_length(G_CHECKSUM_SHA256); -} - -/****************************************************************************** - * Object Stuff - *****************************************************************************/ - -static void -purple_sha256_hash_finalize(GObject *obj) -{ - PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(obj); - PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); - - if (priv->checksum) - g_checksum_free(priv->checksum); - - parent_class->finalize(obj); -} - -static void -purple_sha256_hash_class_init(PurpleSHA256HashClass *klass) { - GObjectClass *obj_class = G_OBJECT_CLASS(klass); - PurpleHashClass *hash_class = PURPLE_HASH_CLASS(klass); - - parent_class = g_type_class_peek_parent(klass); - - obj_class->finalize = purple_sha256_hash_finalize; - - hash_class->reset = purple_sha256_hash_reset; - hash_class->reset_state = purple_sha256_hash_reset; - hash_class->append = purple_sha256_hash_append; - hash_class->digest = purple_sha256_hash_digest; - hash_class->get_digest_size = purple_sha256_hash_get_digest_size; - hash_class->get_block_size = purple_sha256_hash_get_block_size; - - g_type_class_add_private(klass, sizeof(PurpleSHA256HashPrivate)); -} - -static void -purple_sha256_hash_init(PurpleHash *hash) -{ - PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(hash); - PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash); - - priv->checksum = g_checksum_new(G_CHECKSUM_SHA256); - - purple_sha256_hash_reset(hash); -} - -/****************************************************************************** - * API - *****************************************************************************/ -GType -purple_sha256_hash_get_type(void) { - static GType type = 0; - - if(type == 0) { - static const GTypeInfo info = { - sizeof(PurpleSHA256HashClass), - NULL, - NULL, - (GClassInitFunc)purple_sha256_hash_class_init, - NULL, - NULL, - sizeof(PurpleSHA256Hash), - 0, - (GInstanceInitFunc)purple_sha256_hash_init, - NULL, - }; - - type = g_type_register_static(PURPLE_TYPE_HASH, - "PurpleSHA256Hash", - &info, 0); - } - - return type; -} - -PurpleHash * -purple_sha256_hash_new(void) { - return g_object_new(PURPLE_TYPE_SHA256_HASH, NULL); -}
--- a/libpurple/ciphers/sha256hash.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,65 +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 PURPLE_SHA256_HASH_H -#define PURPLE_SHA256_HASH_H -/** - * SECTION:sha256hash - * @section_id: libpurple-sha256hash - * @short_description: <filename>ciphers/sha256hash.h</filename> - * @title: SHA256 Hash - */ - -#include "cipher.h" - -#define PURPLE_TYPE_SHA256_HASH (purple_sha256_hash_get_type()) -#define PURPLE_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256Hash)) -#define PURPLE_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) -#define PURPLE_IS_SHA256_HASH(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) -#define PURPLE_IS_SHA256_HASH_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((obj), PURPLE_TYPE_SHA256_HASH)) -#define PURPLE_SHA256_HASH_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashClass)) - -typedef struct _PurpleSHA256Hash PurpleSHA256Hash; -typedef struct _PurpleSHA256HashClass PurpleSHA256HashClass; - -struct _PurpleSHA256Hash { - PurpleHash gparent; -}; - -struct _PurpleSHA256HashClass { - PurpleHashClass gparent; - - /*< private >*/ - void (*_purple_reserved1)(void); - void (*_purple_reserved2)(void); - void (*_purple_reserved3)(void); - void (*_purple_reserved4)(void); -}; - -G_BEGIN_DECLS - -GType purple_sha256_hash_get_type(void); - -PurpleHash *purple_sha256_hash_new(void); - -G_END_DECLS - -#endif /* PURPLE_SHA256_HASH_H */
--- a/libpurple/http.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/http.c Mon Jun 05 16:36:29 2017 +0300 @@ -859,7 +859,7 @@ tmp = g_strdup_printf("%s:%s", proxy_username, proxy_password); len = strlen(tmp); - proxy_auth = purple_base64_encode((const guchar *)tmp, len); + proxy_auth = g_base64_encode((const guchar *)tmp, len); memset(tmp, 0, len); g_free(tmp);
--- a/libpurple/mime.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/mime.c Mon Jun 05 16:36:29 2017 +0300 @@ -345,7 +345,7 @@ *data = purple_base16_decode(part->data->str, len); } else if(! g_ascii_strcasecmp(enc, "base64")) { - *data = purple_base64_decode(part->data->str, len); + *data = g_base64_decode(part->data->str, len); } else if(! g_ascii_strcasecmp(enc, "quoted-printable")) { *data = purple_quotedp_decode(part->data->str, len);
--- a/libpurple/ntlm.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/ntlm.c Mon Jun 05 16:36:29 2017 +0300 @@ -139,7 +139,7 @@ memcpy(msg + host_off, hostname, hostnamelen); memcpy(msg + dom_off, domain, domainlen); - tmp = purple_base64_encode(msg, sizeof(struct type1_message) + hostnamelen + domainlen); + tmp = g_base64_encode(msg, sizeof(struct type1_message) + hostnamelen + domainlen); g_free(msg); return tmp; @@ -153,7 +153,7 @@ struct type2_message tmsg; static guint8 nonce[8]; - buff = purple_base64_decode(type2, &retlen); + buff = g_base64_decode(type2, &retlen); if (buff != NULL && retlen >= (sizeof(struct type2_message) - 1)) { memcpy(&tmsg, buff, MIN(retlen, sizeof(tmsg))); @@ -397,7 +397,7 @@ /*tmsg->flags2 = 0x0a280105; tmsg->flags3 = 0x0f000000;*/ - tmp = purple_base64_encode((guchar *)tmsg, msglen); + tmp = g_base64_encode((guchar *)tmsg, msglen); g_free(tmsg); return tmp;
--- a/libpurple/plugins/Makefile.mingw Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/plugins/Makefile.mingw Mon Jun 05 16:36:29 2017 +0300 @@ -7,8 +7,6 @@ PIDGIN_TREE_TOP := ../.. include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak -PERL_PLUGIN := ./perl -SSL_PLUGIN := ./ssl KEYRING_PLUGIN := ./keyrings .SUFFIXES: @@ -45,13 +43,9 @@ .PHONY: all clean plugins install all: $(PURPLE_DLL).a plugins - $(MAKE_at) $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) - $(MAKE_at) $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE_at) $(MAKE) -C $(KEYRING_PLUGIN) -f $(MINGW_MAKEFILE) install: all $(PURPLE_INSTALL_PLUGINS_DIR) - $(MAKE_at) $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) install - $(MAKE_at) $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE_at) $(MAKE) -C $(KEYRING_PLUGIN) -f $(MINGW_MAKEFILE) install cp *.dll $(PURPLE_INSTALL_PLUGINS_DIR) @@ -74,8 +68,6 @@ ## clean: rm -f *.o *.dll - $(MAKE_at) $(MAKE) -C $(PERL_PLUGIN) -f $(MINGW_MAKEFILE) clean - $(MAKE_at) $(MAKE) -C $(SSL_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE_at) $(MAKE) -C $(KEYRING_PLUGIN) -f $(MINGW_MAKEFILE) clean include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/plugins/keyrings/internalkeyring.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/plugins/keyrings/internalkeyring.c Mon Jun 05 16:36:29 2017 +0300 @@ -33,7 +33,6 @@ #include "ciphers/aescipher.h" #include "ciphers/pbkdf2cipher.h" -#include "ciphers/sha256hash.h" #define INTKEYRING_NAME N_("Internal keyring") #define INTKEYRING_DESCRIPTION N_("This plugin provides the default password " \ @@ -139,7 +138,7 @@ guchar *data; gsize len; - data = purple_base64_decode(base64, &len); + data = g_base64_decode(base64, &len); return intkeyring_buff_new(data, len); } @@ -152,14 +151,12 @@ intkeyring_derive_key(const gchar *passphrase, intkeyring_buff_t *salt) { PurpleCipher *cipher; - PurpleHash *hash; gboolean succ; intkeyring_buff_t *ret; g_return_val_if_fail(passphrase != NULL, NULL); - hash = purple_sha256_hash_new(); - cipher = purple_pbkdf2_cipher_new(hash); + cipher = purple_pbkdf2_cipher_new(G_CHECKSUM_SHA256); g_object_set(G_OBJECT(cipher), "iter_count", GUINT_TO_POINTER(purple_prefs_get_int(INTKEYRING_PREFS @@ -175,7 +172,6 @@ succ = purple_cipher_digest(cipher, ret->data, ret->len); g_object_unref(cipher); - g_object_unref(hash); if (!succ) { intkeyring_buff_free(ret); @@ -282,7 +278,7 @@ if (encrypted_size < 0) return NULL; - return purple_base64_encode(encrypted_raw, encrypted_size); + return g_base64_encode(encrypted_raw, encrypted_size); } @@ -304,7 +300,7 @@ cipher = purple_aes_cipher_new(); g_return_val_if_fail(cipher != NULL, NULL); - encrypted_raw = purple_base64_decode(str, &encrypted_size); + encrypted_raw = g_base64_decode(str, &encrypted_size); g_return_val_if_fail(encrypted_raw != NULL, NULL); iv_len = purple_cipher_get_block_size(cipher); @@ -378,7 +374,7 @@ * but it's not a problem. */ verifier = intkeyring_encrypt(key, INTKEYRING_VERIFY_STR); - salt_b64 = purple_base64_encode(salt->data, salt->len); + salt_b64 = g_base64_encode(salt->data, salt->len); } if (!verifier || !salt_b64) {
--- a/libpurple/protocols/bonjour/bonjour_ft.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/bonjour/bonjour_ft.c Mon Jun 05 16:36:29 2017 +0300 @@ -28,7 +28,6 @@ #include "buddy.h" #include "bonjour.h" #include "bonjour_ft.h" -#include "ciphers/sha1hash.h" static void bonjour_bytestreams_init(PurpleXfer *xfer); @@ -1014,11 +1013,12 @@ { PurpleBuddy *pb; PurpleAccount *account = NULL; - PurpleHash *hash; + GChecksum *hash; XepXfer *xf; char dstaddr[41]; const gchar *name = NULL; unsigned char hashval[20]; + gsize digest_len = 20; char *p; int i; @@ -1037,10 +1037,10 @@ p = g_strdup_printf("%s%s%s", xf->sid, name, bonjour_get_jid(account)); - hash = purple_sha1_hash_new(); - purple_hash_append(hash, (guchar *)p, strlen(p)); - purple_hash_digest(hash, hashval, sizeof(hashval)); - g_object_unref(G_OBJECT(hash)); + hash = g_checksum_new(G_CHECKSUM_SHA1); + g_checksum_update(hash, (guchar *)p, -1); + g_checksum_get_digest(hash, hashval, &digest_len); + g_checksum_free(hash); g_free(p);
--- a/libpurple/protocols/gg/avatar.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/gg/avatar.c Mon Jun 05 16:36:29 2017 +0300 @@ -353,7 +353,7 @@ } own_data->img = NULL; - img_data = purple_base64_encode(purple_image_get_data(img), + img_data = g_base64_encode(purple_image_get_data(img), purple_image_get_data_size(img)); img_data_e = g_uri_escape_string(img_data, NULL, FALSE); g_free(img_data);
--- a/libpurple/protocols/gg/oauth/oauth.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/gg/oauth/oauth.c Mon Jun 05 16:36:29 2017 +0300 @@ -26,8 +26,6 @@ #include "oauth.h" #include "oauth-parameter.h" -#include "ciphers/hmaccipher.h" -#include "ciphers/sha1hash.h" char *gg_oauth_static_nonce; /* dla unit testów */ char *gg_oauth_static_timestamp; /* dla unit testów */ @@ -49,21 +47,16 @@ static gchar *gg_hmac_sha1(const char *key, const char *message) { - PurpleCipher *cipher; - PurpleHash *hash; + GHmac *hmac; guchar digest[20]; - - hash = purple_sha1_hash_new(); - cipher = purple_hmac_cipher_new(hash); + gsize digest_len = 20; - purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); - purple_cipher_append(cipher, (guchar *)message, strlen(message)); - purple_cipher_digest(cipher, digest, sizeof(digest)); + hmac = g_hmac_new(G_CHECKSUM_SHA1, (guchar *)key, strlen(key)); + g_hmac_update(hmac, (guchar *)message, -1); + g_hmac_get_digest(hmac, digest, &digest_len); + g_hmac_unref(hmac); - g_object_unref(cipher); - g_object_unref(hash); - - return purple_base64_encode(digest, sizeof(digest)); + return g_base64_encode(digest, sizeof(digest)); } static char *
--- a/libpurple/protocols/irc/msgs.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/irc/msgs.c Mon Jun 05 16:36:29 2017 +0300 @@ -1660,7 +1660,7 @@ return; if (arg[0] != '+') - serverin = (char *)purple_base64_decode(arg, &serverinlen); + serverin = (char *)g_base64_decode(arg, &serverinlen); ret = sasl_client_step(irc->sasl_conn, serverin, serverinlen, NULL, &c_out, &clen); @@ -1678,7 +1678,7 @@ } if (clen > 0) - authinfo = purple_base64_encode((const guchar*)c_out, clen); + authinfo = g_base64_encode((const guchar*)c_out, clen); else authinfo = g_strdup("+");
--- a/libpurple/protocols/jabber/auth.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth.c Mon Jun 05 16:36:29 2017 +0300 @@ -38,9 +38,6 @@ #include "iq.h" #include "notify.h" -#include "ciphers/hmaccipher.h" -#include "ciphers/md5hash.h" - static GSList *auth_mechs = NULL; static void auth_old_result_cb(JabberStream *js, const char *from, @@ -266,7 +263,8 @@ x = purple_xmlnode_new_child(query, "digest"); s = g_strdup_printf("%s%s", js->stream_id, pw); - hash = jabber_calculate_data_hash(s, strlen(s), "sha1"); + hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, + s, -1); purple_xmlnode_insert_data(x, hash, -1); g_free(hash); g_free(s); @@ -277,22 +275,15 @@ * to non-SASL authentication. */ const char *challenge; - gchar digest[33]; - PurpleCipher *hmac; - PurpleHash *md5; - gssize diglen; + gchar *digest; /* Calculate the MHAC-MD5 digest */ - md5 = purple_md5_hash_new(); - hmac = purple_hmac_cipher_new(md5); challenge = purple_xmlnode_get_attrib(x, "challenge"); - purple_cipher_set_key(hmac, (guchar *)pw, strlen(pw)); - purple_cipher_append(hmac, (guchar *)challenge, strlen(challenge)); - diglen = purple_cipher_digest_to_str(hmac, digest, 33); - g_object_unref(hmac); - g_object_unref(md5); + digest = g_compute_hmac_for_string(G_CHECKSUM_MD5, + (guchar *)pw, strlen(pw), + challenge, -1); - g_return_if_fail(diglen > 0); + g_return_if_fail(digest != NULL); /* Create the response query */ iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:auth"); @@ -306,6 +297,7 @@ x = purple_xmlnode_new_child(query, "crammd5"); purple_xmlnode_insert_data(x, digest, 32); + g_free(digest); jabber_iq_set_callback(iq, auth_old_result_cb, NULL); jabber_iq_send(iq);
--- a/libpurple/protocols/jabber/auth_cyrus.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth_cyrus.c Mon Jun 05 16:36:29 2017 +0300 @@ -336,7 +336,7 @@ if (coutlen == 0) { purple_xmlnode_insert_data(auth, "=", -1); } else { - enc_out = purple_base64_encode((unsigned char*)clientout, coutlen); + enc_out = g_base64_encode((unsigned char*)clientout, coutlen); purple_xmlnode_insert_data(auth, enc_out, -1); g_free(enc_out); } @@ -458,7 +458,7 @@ unsigned int clen; gsize declen; - dec_in = purple_base64_decode(enc_in, &declen); + dec_in = g_base64_decode(enc_in, &declen); js->sasl_state = sasl_client_step(js->sasl, (char*)dec_in, declen, NULL, &c_out, &clen); @@ -486,10 +486,10 @@ if (!purple_strequal(js->current_mech, "DIGEST-MD5") || strstr(c_out, ",charset=")) /* If we're not using DIGEST-MD5 or Cyrus SASL is fixed */ - enc_out = purple_base64_encode((unsigned char*)c_out, clen); + enc_out = g_base64_encode((unsigned char*)c_out, clen); else { char *tmp = g_strdup_printf("%s,charset=utf-8", c_out); - enc_out = purple_base64_encode((unsigned char*)tmp, clen + 14); + enc_out = g_base64_encode((unsigned char*)tmp, clen + 14); g_free(tmp); } @@ -519,7 +519,7 @@ gsize declen = 0; if(enc_in != NULL) - dec_in = purple_base64_decode(enc_in, &declen); + dec_in = g_base64_decode(enc_in, &declen); js->sasl_state = sasl_client_step(js->sasl, (char*)dec_in, declen, NULL, &c_out, &clen);
--- a/libpurple/protocols/jabber/auth_digest_md5.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth_digest_md5.c Mon Jun 05 16:36:29 2017 +0300 @@ -23,7 +23,6 @@ #include "internal.h" #include "debug.h" -#include "ciphers/md5hash.h" #include "util.h" #include "xmlnode.h" @@ -106,9 +105,8 @@ generate_response_value(JabberID *jid, const char *passwd, const char *nonce, const char *cnonce, const char *a2, const char *realm) { - PurpleHash *hash; - guchar result[16]; - size_t a1len; + GChecksum *hash; + gsize digest_len = 16; gchar *a1, *convnode=NULL, *convpasswd = NULL, *ha1, *ha2, *kd, *x, *z; @@ -121,36 +119,22 @@ convpasswd = g_strdup(passwd); } - hash = purple_md5_hash_new(); + hash = g_checksum_new(G_CHECKSUM_MD5); x = g_strdup_printf("%s:%s:%s", convnode, realm, convpasswd ? convpasswd : ""); - purple_hash_append(hash, (const guchar *)x, strlen(x)); - purple_hash_digest(hash, result, sizeof(result)); + g_checksum_update(hash, (const guchar *)x, -1); a1 = g_strdup_printf("xxxxxxxxxxxxxxxx:%s:%s", nonce, cnonce); - a1len = strlen(a1); - g_memmove(a1, result, 16); - - purple_hash_reset(hash); - purple_hash_append(hash, (const guchar *)a1, a1len); - purple_hash_digest(hash, result, sizeof(result)); - ha1 = purple_base16_encode(result, 16); + g_checksum_get_digest(hash, (guint8 *)a1, &digest_len); + g_checksum_free(hash); - purple_hash_reset(hash); - purple_hash_append(hash, (const guchar *)a2, strlen(a2)); - purple_hash_digest(hash, result, sizeof(result)); - - ha2 = purple_base16_encode(result, 16); + ha1 = g_compute_checksum_for_string(G_CHECKSUM_MD5, a1, -1); + ha2 = g_compute_checksum_for_string(G_CHECKSUM_MD5, a2, -1); kd = g_strdup_printf("%s:%s:00000001:%s:auth:%s", ha1, nonce, cnonce, ha2); - purple_hash_reset(hash); - purple_hash_append(hash, (const guchar *)kd, strlen(kd)); - purple_hash_digest(hash, result, sizeof(result)); - g_object_unref(hash); - - z = purple_base16_encode(result, 16); + z = g_compute_checksum_for_string(G_CHECKSUM_MD5, kd, -1); g_free(convnode); g_free(convpasswd); @@ -171,6 +155,7 @@ char *enc_in = purple_xmlnode_get_data(packet); char *dec_in; char *enc_out; + gsize size = 0; GHashTable *parts; JabberSaslState state = JABBER_SASL_STATE_CONTINUE; @@ -179,10 +164,10 @@ return JABBER_SASL_STATE_FAIL; } - dec_in = (char *)purple_base64_decode(enc_in, NULL); + dec_in = (char *)g_base64_decode(enc_in, &size); purple_debug_misc("jabber", "decoded challenge (%" G_GSIZE_FORMAT "): %s\n", - strlen(dec_in), + size, dec_in); parts = jabber_auth_digest_md5_parse(dec_in); @@ -254,7 +239,7 @@ g_free(auth_resp); g_free(cnonce); - enc_out = purple_base64_encode((guchar *)response->str, response->len); + enc_out = g_base64_encode((guchar *)response->str, response->len); purple_debug_misc("jabber", "decoded response (%" G_GSIZE_FORMAT "): %s\n",
--- a/libpurple/protocols/jabber/auth_plain.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth_plain.c Mon Jun 05 16:36:29 2017 +0300 @@ -50,7 +50,7 @@ response = g_string_append(response, purple_connection_get_password(js->gc)); - enc_out = purple_base64_encode((guchar *)response->str, response->len); + enc_out = g_base64_encode((guchar *)response->str, response->len); purple_xmlnode_set_attrib(auth, "mechanism", "PLAIN"); purple_xmlnode_insert_data(auth, enc_out, -1);
--- a/libpurple/protocols/jabber/auth_scram.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth_scram.c Mon Jun 05 16:36:29 2017 +0300 @@ -25,12 +25,10 @@ #include "auth.h" #include "auth_scram.h" -#include "ciphers/hmaccipher.h" -#include "ciphers/sha1hash.h" #include "debug.h" static const JabberScramHash hashes[] = { - { "-SHA-1", purple_sha1_hash_new, 20 }, + { "-SHA-1", G_CHECKSUM_SHA1 }, }; static const JabberScramHash *mech_to_hash(const char *mech) @@ -80,8 +78,8 @@ guchar *jabber_scram_hi(const JabberScramHash *hash, const GString *str, GString *salt, guint iterations) { - PurpleHash *hasher; - PurpleCipher *cipher; + GHmac *hmac; + gsize digest_len; guchar *result; guint i; guchar *prev, *tmp; @@ -91,40 +89,38 @@ g_return_val_if_fail(salt != NULL && salt->len > 0, NULL); g_return_val_if_fail(iterations > 0, NULL); - prev = g_new0(guint8, hash->size); - tmp = g_new0(guint8, hash->size); - result = g_new0(guint8, hash->size); + digest_len = g_checksum_type_get_length(hash->type); + prev = g_new0(guchar, digest_len); + tmp = g_new0(guchar, digest_len); + result = g_new0(guchar, digest_len); - hasher = hash->new_cipher(); - cipher = purple_hmac_cipher_new(hasher); - g_object_unref(G_OBJECT(hasher)); + hmac = g_hmac_new(hash->type, (guchar *)str->str, str->len); /* Append INT(1), a four-octet encoding of the integer 1, most significant * octet first. */ g_string_append_len(salt, "\0\0\0\1", 4); /* Compute U0 */ - purple_cipher_set_key(cipher, (guchar *)str->str, str->len); - purple_cipher_append(cipher, (guchar *)salt->str, salt->len); - purple_cipher_digest(cipher, result, hash->size); + g_hmac_update(hmac, (guchar *)salt->str, salt->len); + g_hmac_get_digest(hmac, result, &digest_len); + g_hmac_unref(hmac); - memcpy(prev, result, hash->size); + memcpy(prev, result, digest_len); /* Compute U1...Ui */ for (i = 1; i < iterations; ++i) { guint j; - purple_cipher_reset(cipher); - purple_cipher_set_key(cipher, (guchar *)str->str, str->len); - purple_cipher_append(cipher, prev, hash->size); - purple_cipher_digest(cipher, tmp, hash->size); + hmac = g_hmac_new(hash->type, (guchar *)str->str, str->len); + g_hmac_update(hmac, prev, digest_len); + g_hmac_get_digest(hmac, tmp, &digest_len); + g_hmac_unref(hmac); - for (j = 0; j < hash->size; ++j) + for (j = 0; j < digest_len; ++j) result[j] ^= tmp[j]; - memcpy(prev, tmp, hash->size); + memcpy(prev, tmp, digest_len); } - g_object_unref(G_OBJECT(cipher)); g_free(tmp); g_free(prev); return result; @@ -142,33 +138,31 @@ static void hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str) { - PurpleHash *hasher; - PurpleCipher *cipher; + GHmac *hmac; + gsize digest_len = g_checksum_type_get_length(hash->type); - hasher = hash->new_cipher(); - cipher = purple_hmac_cipher_new(hasher); - g_object_unref(G_OBJECT(hasher)); - purple_cipher_set_key(cipher, key, hash->size); - purple_cipher_append(cipher, (guchar *)str, strlen(str)); - purple_cipher_digest(cipher, out, hash->size); - g_object_unref(G_OBJECT(cipher)); + hmac = g_hmac_new(hash->type, key, digest_len); + g_hmac_update(hmac, (guchar *)str, -1); + g_hmac_get_digest(hmac, out, &digest_len); + g_hmac_unref(hmac); } static void hash(const JabberScramHash *hash, guchar *out, const guchar *data) { - PurpleHash *hasher; + GChecksum *checksum; + gsize digest_len = g_checksum_type_get_length(hash->type); - hasher = hash->new_cipher(); - purple_hash_append(hasher, data, hash->size); - purple_hash_digest(hasher, out, hash->size); - g_object_unref(G_OBJECT(hasher)); + checksum = g_checksum_new(hash->type); + g_checksum_update(checksum, data, digest_len); + g_checksum_get_digest(checksum, out, &digest_len); + g_checksum_free(checksum); } gboolean jabber_scram_calc_proofs(JabberScramData *data, GString *salt, guint iterations) { - guint hash_len = data->hash->size; + guint hash_len = g_checksum_type_get_length(data->hash->type); guint i; GString *pass = g_string_new(data->password); @@ -252,7 +246,7 @@ if (token[0] != 's' || token[1] != '=') goto err; - decoded = (gchar *)purple_base64_decode(token + 2, &len); + decoded = (gchar *)g_base64_decode(token + 2, &len); if (!decoded || *decoded == '\0') { g_free(decoded); goto err; @@ -343,7 +337,7 @@ return FALSE; } - proof = purple_base64_encode((guchar *)data->client_proof->str, data->client_proof->len); + proof = g_base64_encode((guchar *)data->client_proof->str, data->client_proof->len); *out = g_strdup_printf("c=%s,r=%s,p=%s", "biws", nonce, proof); g_free(nonce); g_free(proof); @@ -355,7 +349,7 @@ if (!ret) return FALSE; - server_sig = (gchar *)purple_base64_decode(enc_server_sig, &len); + server_sig = (gchar *)g_base64_decode(enc_server_sig, &len); g_free(enc_server_sig); if (server_sig == NULL || len != data->server_signature->len) { @@ -427,7 +421,7 @@ data->channel_binding = TRUE; #endif cnonce = ((guint64)g_random_int() << 32) | g_random_int(); - data->cnonce = purple_base64_encode((guchar *)&cnonce, sizeof(cnonce)); + data->cnonce = g_base64_encode((guchar *)&cnonce, sizeof(cnonce)); data->auth_message = g_string_new(NULL); g_string_printf(data->auth_message, "n=%s,r=%s", @@ -442,7 +436,7 @@ /* TODO: Channel binding */ dec_out = g_strdup_printf("%c,,%s", 'n', data->auth_message->str); - enc_out = purple_base64_encode((guchar *)dec_out, strlen(dec_out)); + enc_out = g_base64_encode((guchar *)dec_out, strlen(dec_out)); purple_debug_misc("jabber", "initial SCRAM message '%s'\n", dec_out); purple_xmlnode_insert_data(reply, enc_out, -1); @@ -473,7 +467,7 @@ goto out; } - dec_in = (gchar *)purple_base64_decode(enc_in, &len); + dec_in = (gchar *)g_base64_decode(enc_in, &len); if (!dec_in || len != strlen(dec_in)) { /* Danger afoot; SCRAM shouldn't contain NUL bytes */ reply = purple_xmlnode_new("abort"); @@ -500,7 +494,7 @@ purple_debug_misc("jabber", "decoded response: %s\n", dec_out ? dec_out : "(null)"); if (dec_out) { - enc_out = purple_base64_encode((guchar *)dec_out, strlen(dec_out)); + enc_out = g_base64_encode((guchar *)dec_out, strlen(dec_out)); purple_xmlnode_insert_data(reply, enc_out, -1); } @@ -546,7 +540,7 @@ return JABBER_SASL_STATE_FAIL; } - dec_in = (gchar *)purple_base64_decode(enc_in, &len); + dec_in = (gchar *)g_base64_decode(enc_in, &len); g_free(enc_in); if (!dec_in || len != strlen(dec_in)) { /* Danger afoot; SCRAM shouldn't contain NUL bytes */
--- a/libpurple/protocols/jabber/auth_scram.h Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/auth_scram.h Mon Jun 05 16:36:29 2017 +0300 @@ -29,15 +29,12 @@ * DO NOT USE ANYTHING HERE OR YOU WILL BE SENT TO THE PIT OF DESPAIR. */ -#include "cipher.h" - /* Per-connection state stored between messages. * This is stored in js->auth_data_mech. */ typedef struct { const char *mech_substr; - PurpleHash *(*new_cipher)(void); - guint size; + GChecksumType type; } JabberScramHash; typedef struct {
--- a/libpurple/protocols/jabber/buddy.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/buddy.c Mon Jun 05 16:36:29 2017 +0300 @@ -472,10 +472,10 @@ g_free(js->initial_avatar_hash); image = purple_buddy_icons_find_account_icon(purple_connection_get_account(gc)); if (image != NULL) { - js->initial_avatar_hash = jabber_calculate_data_hash( + js->initial_avatar_hash = g_compute_checksum_for_data( + G_CHECKSUM_SHA1, purple_image_get_data(image), - purple_image_get_data_size(image), - "sha1" + purple_image_get_data_size(image) ); g_object_unref(image); } else { @@ -528,10 +528,10 @@ type = purple_xmlnode_new_child(photo, "TYPE"); purple_xmlnode_insert_data(type, "image/png", -1); binval = purple_xmlnode_new_child(photo, "BINVAL"); - enc = purple_base64_encode(avatar_data, avatar_len); + enc = g_base64_encode(avatar_data, avatar_len); - js->avatar_hash = - jabber_calculate_data_hash(avatar_data, avatar_len, "sha1"); + js->avatar_hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1, + avatar_data, avatar_len); purple_xmlnode_insert_data(binval, enc, -1); g_free(enc); @@ -957,11 +957,12 @@ gsize size; char *bintext = purple_xmlnode_get_data(binval); if (bintext) { - guchar *data = purple_base64_decode(bintext, &size); + guchar *data = g_base64_decode(bintext, &size); g_free(bintext); if (data) { - vcard_hash = jabber_calculate_data_hash(data, size, "sha1"); + vcard_hash = g_compute_checksum_for_data( + G_CHECKSUM_SHA1, data, size); g_free(data); } } @@ -1200,7 +1201,7 @@ guchar *data; gboolean photo = (strcmp(child->name, "PHOTO") == 0); - data = purple_base64_decode(bintext, &size); + data = g_base64_decode(bintext, &size); if (data) { PurpleImage *img; guint img_id; @@ -1216,7 +1217,7 @@ purple_notify_user_info_add_pair_html(user_info, (photo ? _("Photo") : _("Logo")), img_text); - hash = jabber_calculate_data_hash(data, size, "sha1"); + hash = g_compute_checksum_for_data(G_CHECKSUM_SHA1, data, size); purple_buddy_icons_set_for_user(account, bare_jid, data, size, hash); g_free(hash); g_free(img_text);
--- a/libpurple/protocols/jabber/caps.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/caps.c Mon Jun 05 16:36:29 2017 +0300 @@ -30,9 +30,6 @@ #include "util.h" #include "xdata.h" -#include "ciphers/md5hash.h" -#include "ciphers/sha1hash.h" - #define JABBER_CAPS_FILENAME "xmpp-caps.xml" typedef struct _JabberDataFormField { @@ -457,19 +454,20 @@ /* Only validate if these are v1.5 capabilities */ if (userdata->hash) { gchar *hash = NULL; - PurpleHash *hasher = NULL; - /* - * TODO: If you add *any* hash here, make sure the checksum buffer - * size in jabber_caps_calculate_hash is large enough. The cipher API - * doesn't seem to offer a "Get the hash size" function(?). - */ + GChecksumType hash_type; + gboolean supported_hash = TRUE; + if (g_str_equal(userdata->hash, "sha-1")) { - hasher = purple_sha1_hash_new(); + hash_type = G_CHECKSUM_SHA1; } else if (g_str_equal(userdata->hash, "md5")) { - hasher = purple_md5_hash_new(); + hash_type = G_CHECKSUM_MD5; + } else { + supported_hash = FALSE; } - hash = jabber_caps_calculate_hash(info, hasher); - g_object_unref(hasher); + + if (supported_hash) { + hash = jabber_caps_calculate_hash(info, hash_type); + } if (!hash || !g_str_equal(hash, userdata->ver)) { purple_debug_warning("jabber", "Could not validate caps info from " @@ -818,27 +816,29 @@ } static void -append_escaped_string(PurpleHash *hash, const gchar *str) +append_escaped_string(GChecksum *hash, const gchar *str) { g_return_if_fail(hash != NULL); if (str && *str) { char *tmp = g_markup_escape_text(str, -1); - purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); + g_checksum_update(hash, (const guchar *)tmp, -1); g_free(tmp); } - purple_hash_append(hash, (const guchar *)"<", 1); + g_checksum_update(hash, (const guchar *)"<", -1); } -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash) +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, + GChecksumType hash_type) { + GChecksum *hash; GList *node; - guint8 checksum[20]; - gsize checksum_size = 20; - gboolean success; + guint8 *checksum; + gsize checksum_size; + gchar *ret; - if (!info || !hash) + if (!info) return NULL; /* sort identities, features and x-data forms */ @@ -846,6 +846,12 @@ info->features = g_list_sort(info->features, (GCompareFunc)strcmp); info->forms = g_list_sort(info->forms, jabber_xdata_compare); + hash = g_checksum_new(hash_type); + + if (hash == NULL) { + return NULL; + } + /* Add identities to the hash data */ for (node = info->identities; node; node = node->next) { JabberIdentity *id = (JabberIdentity*)node->data; @@ -863,7 +869,7 @@ tmp = g_strconcat(category, "/", type, "/", lang ? lang : "", "/", name ? name : "", "<", NULL); - purple_hash_append(hash, (const guchar *)tmp, strlen(tmp)); + g_checksum_update(hash, (const guchar *)tmp, -1); g_free(tmp); g_free(category); @@ -912,16 +918,20 @@ } } + checksum_size = g_checksum_type_get_length(hash_type); + checksum = g_new(guint8, checksum_size); + /* generate hash */ - success = purple_hash_digest(hash, checksum, checksum_size); - checksum_size = purple_hash_get_digest_size(hash); + g_checksum_get_digest(hash, checksum, &checksum_size); - return (success ? purple_base64_encode(checksum, checksum_size) : NULL); + ret = g_base64_encode(checksum, checksum_size); + g_free(checksum); + + return ret; } void jabber_caps_calculate_own_hash(JabberStream *js) { JabberCapsClientInfo info; - PurpleHash *hasher; GList *iter = NULL; GList *features = NULL; @@ -952,9 +962,7 @@ info.forms = NULL; g_free(js->caps_hash); - hasher = purple_sha1_hash_new(); - js->caps_hash = jabber_caps_calculate_hash(&info, hasher); - g_object_unref(hasher); + js->caps_hash = jabber_caps_calculate_hash(&info, G_CHECKSUM_SHA1); g_list_free(info.identities); g_list_free(info.features); }
--- a/libpurple/protocols/jabber/caps.h Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/caps.h Mon Jun 05 16:36:29 2017 +0300 @@ -27,7 +27,6 @@ typedef struct _JabberCapsClientInfo JabberCapsClientInfo; #include "jabber.h" -#include "cipher.h" /* Implementation of XEP-0115 - Entity Capabilities */ @@ -96,10 +95,11 @@ * XEP-0115 Version 1.5. * * @param info A JabberCapsClientInfo pointer. - * @param hash Hash cipher to be used. Either sha-1 or md5. + * @param hash_type GChecksumType to be used. Either sha-1 or md5. * @return The base64 encoded SHA-1 hash; must be freed by caller */ -gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, PurpleHash *hash); +gchar *jabber_caps_calculate_hash(JabberCapsClientInfo *info, + GChecksumType hash_type); /** * Calculate SHA1 hash for own featureset.
--- a/libpurple/protocols/jabber/data.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/data.c Mon Jun 05 16:36:29 2017 +0300 @@ -50,7 +50,7 @@ g_return_val_if_fail(type != NULL, NULL); data = g_new0(JabberData, 1); - checksum = jabber_calculate_data_hash(rawdata, size, "sha1"); + checksum = g_compute_checksum_for_data(G_CHECKSUM_SHA1, rawdata, size); g_snprintf(cid, sizeof(cid), "sha1+%s@bob.xmpp.org", checksum); g_free(checksum); @@ -109,7 +109,7 @@ } data = g_new0(JabberData, 1); - data->data = purple_base64_decode(raw_data, &data->size); + data->data = g_base64_decode(raw_data, &data->size); g_free(raw_data); if (data->data == NULL) { @@ -174,7 +174,7 @@ g_return_val_if_fail(data != NULL, NULL); tag = purple_xmlnode_new("data"); - base64data = purple_base64_encode(data->data, data->size); + base64data = g_base64_encode(data->data, data->size); purple_xmlnode_set_namespace(tag, NS_BOB); purple_xmlnode_set_attrib(tag, "cid", data->cid); @@ -238,11 +238,25 @@ if (num_sub_parts == 2) { const gchar *hash_algo = sub_parts[0]; const gchar *hash_value = sub_parts[1]; - gchar *digest = - jabber_calculate_data_hash(jabber_data_get_data(data), - jabber_data_get_size(data), hash_algo); + GChecksumType hash_type; + gboolean valid_hash_type = TRUE; - if (digest) { + if (purple_strequal(hash_algo, "sha1")) + hash_type = G_CHECKSUM_SHA1; + else if (purple_strequal(hash_algo, "sha256")) + hash_type = G_CHECKSUM_SHA256; + else if (purple_strequal(hash_algo, "sha512")) + hash_type = G_CHECKSUM_SHA512; + else if (purple_strequal(hash_algo, "md5")) + hash_type = G_CHECKSUM_MD5; + else + valid_hash_type = FALSE; + + if (valid_hash_type) { + gchar *digest = g_compute_checksum_for_data( + hash_type, jabber_data_get_data(data), + jabber_data_get_size(data)); + ret = purple_strequal(digest, hash_value); if (!ret)
--- a/libpurple/protocols/jabber/ibb.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/ibb.c Mon Jun 05 16:36:29 2017 +0300 @@ -335,7 +335,7 @@ JabberIq *set = jabber_iq_new(jabber_ibb_session_get_js(sess), JABBER_IQ_SET); PurpleXmlNode *data_element = purple_xmlnode_new("data"); - char *base64 = purple_base64_encode(data, size); + char *base64 = g_base64_encode(data, size); char seq[10]; g_snprintf(seq, sizeof(seq), "%u", jabber_ibb_session_get_send_seq(sess)); @@ -415,7 +415,7 @@ if (sess->data_received_cb) { gchar *base64 = purple_xmlnode_get_data(child); gsize size; - gpointer rawdata = purple_base64_decode(base64, &size); + gpointer rawdata = g_base64_decode(base64, &size); g_free(base64);
--- a/libpurple/protocols/jabber/jabber.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/jabber.c Mon Jun 05 16:36:29 2017 +0300 @@ -1135,10 +1135,10 @@ */ image = purple_buddy_icons_find_account_icon(account); if (image != NULL) { - js->initial_avatar_hash = jabber_calculate_data_hash( + js->initial_avatar_hash = g_compute_checksum_for_data( + G_CHECKSUM_SHA1, purple_image_get_data(image), - purple_image_get_data_size(image), - "sha1" + purple_image_get_data_size(image) ); g_object_unref(image); }
--- a/libpurple/protocols/jabber/jutil.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/jutil.c Mon Jun 05 16:36:29 2017 +0300 @@ -32,10 +32,6 @@ #include "presence.h" #include "jutil.h" -#include "ciphers/sha1hash.h" -#include "ciphers/sha256hash.h" -#include "ciphers/md5hash.h" - #ifdef USE_IDN #include <idna.h> #include <stringprep.h> @@ -780,36 +776,3 @@ return NULL; } -char * -jabber_calculate_data_hash(gconstpointer data, size_t len, - const gchar *hash_algo) -{ - PurpleHash *hash = NULL; - static gchar digest[129]; /* 512 bits hex + \0 */ - - if (g_str_equal(hash_algo, "sha1")) - hash = purple_sha1_hash_new(); - else if (g_str_equal(hash_algo, "sha256")) - hash = purple_sha256_hash_new(); - else if (g_str_equal(hash_algo, "md5")) - hash = purple_md5_hash_new(); - - if (hash == NULL) - { - purple_debug_error("jabber", "Unexpected hashing algorithm %s requested\n", hash_algo); - g_return_val_if_reached(NULL); - } - - /* Hash the data */ - purple_hash_append(hash, data, len); - if (!purple_hash_digest_to_str(hash, digest, sizeof(digest))) - { - purple_debug_error("jabber", "Failed to get digest for %s cipher.\n", - hash_algo); - g_return_val_if_reached(NULL); - } - g_object_unref(G_OBJECT(hash)); - - return g_strdup(digest); -} -
--- a/libpurple/protocols/jabber/jutil.h Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/jutil.h Mon Jun 05 16:36:29 2017 +0300 @@ -94,6 +94,4 @@ /* show attr (presence stanza) -> state */ JabberBuddyState jabber_buddy_show_get_state(const char *id); -char *jabber_calculate_data_hash(gconstpointer data, size_t len, - const gchar *hash_algo); #endif /* PURPLE_JABBER_JUTIL_H_ */
--- a/libpurple/protocols/jabber/presence.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/presence.c Mon Jun 05 16:36:29 2017 +0300 @@ -458,11 +458,12 @@ if ((binval = purple_xmlnode_get_child(photo, "BINVAL")) && (text = purple_xmlnode_get_data(binval))) { - data = purple_base64_decode(text, &size); + data = g_base64_decode(text, &size); g_free(text); if (data) - hash = jabber_calculate_data_hash(data, size, "sha1"); + g_compute_checksum_for_data( + G_CHECKSUM_SHA1, data, size); } purple_buddy_icons_set_for_user(purple_connection_get_account(js->gc), from, data, size, hash);
--- a/libpurple/protocols/jabber/si.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/si.c Mon Jun 05 16:36:29 2017 +0300 @@ -301,7 +301,8 @@ jsx->js->user->node, jsx->js->user->domain, jsx->js->user->resource); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); + hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, + dstaddr, -1); account = purple_connection_get_account(jsx->js->gc); jsx->connect_data = purple_proxy_connect_socks5_account(NULL, account, @@ -478,7 +479,7 @@ jsx->js->user->resource, purple_xfer_get_remote_user(xfer)); /* Per XEP-0065, the 'host' must be SHA1(SID + from JID + to JID) */ - hash = jabber_calculate_data_hash(dstaddr, strlen(dstaddr), "sha1"); + hash = g_compute_checksum_for_string(G_CHECKSUM_SHA1, dstaddr, -1); if(strncmp(hash, jsx->rxqueue + 5, 40) || jsx->rxqueue[45] != 0x00 || jsx->rxqueue[46] != 0x00) {
--- a/libpurple/protocols/jabber/tests/test_jabber_caps.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/tests/test_jabber_caps.c Mon Jun 05 16:36:29 2017 +0300 @@ -1,7 +1,6 @@ #include <glib.h> #include "xmlnode.h" -#include "ciphers/sha1hash.h" #include "protocols/jabber/caps.h" static void @@ -24,13 +23,12 @@ } static void -_test_jabber_caps_match(PurpleHash *hash, const gchar *in, const gchar *expected) { +_test_jabber_caps_match(GChecksumType hash_type, const gchar *in, const gchar *expected) { PurpleXmlNode *query = purple_xmlnode_from_str(in, -1); JabberCapsClientInfo *info = jabber_caps_parse_client_info(query); gchar *got = NULL; - got = jabber_caps_calculate_hash(info, hash); - g_object_unref(G_OBJECT(hash)); + got = jabber_caps_calculate_hash(info, hash_type); g_assert_cmpstr(expected, ==, got); g_free(got); @@ -39,7 +37,7 @@ static void test_jabber_caps_calculate_from_xmlnode(void) { _test_jabber_caps_match( - purple_sha1_hash_new(), + G_CHECKSUM_SHA1, "<query xmlns='http://jabber.org/protocol/disco#info' node='http://tkabber.jabber.ru/#GNjxthSckUNvAIoCCJFttjl6VL8='><identity category='client' type='pc' name='Tkabber'/><x xmlns='jabber:x:data' type='result'><field var='FORM_TYPE' type='hidden'><value>urn:xmpp:dataforms:softwareinfo</value></field><field var='software'><value>Tkabber</value></field><field var='software_version'><value> ( 8.5.5 )</value></field><field var='os'><value>ATmega640-16AU</value></field><field var='os_version'><value/></field></x><feature var='games:board'/><feature var='google:mail:notify'/><feature var='http://jabber.org/protocol/activity'/><feature var='http://jabber.org/protocol/bytestreams'/><feature var='http://jabber.org/protocol/chatstates'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/commands'/><feature var='http://jabber.org/protocol/disco#info'/><feature var='http://jabber.org/protocol/disco#items'/><feature var='http://jabber.org/protocol/feature-neg'/><feature var='http://jabber.org/protocol/geoloc'/><feature var='http://jabber.org/protocol/ibb'/><feature var='http://jabber.org/protocol/iqibb'/><feature var='http://jabber.org/protocol/mood'/><feature var='http://jabber.org/protocol/muc'/><feature var='http://jabber.org/protocol/mute#ancestor'/><feature var='http://jabber.org/protocol/mute#editor'/><feature var='http://jabber.org/protocol/rosterx'/><feature var='http://jabber.org/protocol/si'/><feature var='http://jabber.org/protocol/si/profile/file-transfer'/><feature var='http://jabber.org/protocol/tune'/><feature var='jabber:iq:avatar'/><feature var='jabber:iq:browse'/><feature var='jabber:iq:dtcp'/><feature var='jabber:iq:filexfer'/><feature var='jabber:iq:ibb'/><feature var='jabber:iq:inband'/><feature var='jabber:iq:jidlink'/><feature var='jabber:iq:last'/><feature var='jabber:iq:oob'/><feature var='jabber:iq:privacy'/><feature var='jabber:iq:time'/><feature var='jabber:iq:version'/><feature var='jabber:x:data'/><feature var='jabber:x:event'/><feature var='jabber:x:oob'/><feature var='urn:xmpp:ping'/><feature var='urn:xmpp:receipts'/><feature var='urn:xmpp:time'/></query>", "GNjxthSckUNvAIoCCJFttjl6VL8=" );
--- a/libpurple/protocols/jabber/tests/test_jabber_scram.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/tests/test_jabber_scram.c Mon Jun 05 16:36:29 2017 +0300 @@ -4,9 +4,8 @@ #include "util.h" #include "protocols/jabber/auth_scram.h" #include "protocols/jabber/jutil.h" -#include "ciphers/sha1hash.h" -static JabberScramHash sha1_mech = { "-SHA-1", purple_sha1_hash_new, 20 }; +static JabberScramHash sha1_mech = { "-SHA-1", G_CHECKSUM_SHA1 }; #define assert_pbkdf2_equal(password, salt, count, expected) { \ GString *p = g_string_new(password); \
--- a/libpurple/protocols/jabber/useravatar.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/jabber/useravatar.c Mon Jun 05 16:36:29 2017 +0300 @@ -154,10 +154,11 @@ char *lengthstring, *widthstring, *heightstring; /* compute the sha1 hash */ - char *hash = jabber_calculate_data_hash( + char *hash = g_compute_checksum_for_data( + G_CHECKSUM_SHA1, purple_image_get_data(img), - purple_image_get_data_size(img), "sha1"); - char *base64avatar = purple_base64_encode( + purple_image_get_data_size(img)); + char *base64avatar = g_base64_encode( purple_image_get_data(img), purple_image_get_data_size(img)); @@ -314,7 +315,7 @@ if(!b64data) return; - img = purple_base64_decode(b64data, &size); + img = g_base64_decode(b64data, &size); if(!img) { g_free(b64data); return;
--- a/libpurple/protocols/msn/ft.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,256 +0,0 @@ -/** - * @file ft.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 "ft.h" - -/************************************************************************** - * Xfer - **************************************************************************/ - -void -msn_xfer_init(PurpleXfer *xfer) -{ - MsnSlpCall *slpcall; - /* MsnSlpLink *slplink; */ - char *content; - - purple_debug_info("msn", "xfer_init\n"); - - slpcall = purple_xfer_get_protocol_data(xfer); - - /* 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); - - slpcall = purple_xfer_get_protocol_data(xfer); - g_return_if_fail(slpcall != NULL); - - 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_xfer_type(xfer) == PURPLE_XFER_TYPE_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_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND, -1); - - slpcall = purple_xfer_get_protocol_data(xfer); - /* 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, gsize size, 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_xfer_type(xfer) == PURPLE_XFER_TYPE_RECEIVE, -1); - - slpcall = purple_xfer_get_protocol_data(xfer); - /* 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_V2 + 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; -#if 0 - memcpy(tmp, context->unknown1, sizeof(context->unknown1)); - tmp += sizeof(context->unknown1); - msn_push32le(tmp, context->unknown2); -#else - memset(tmp, 0, sizeof(gchar[30])); - tmp += sizeof(gchar[30]); - msn_push32le(tmp, 0xffffffff); -#endif - 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_V0) - return NULL; - - context = g_new(MsnFileContext, 1); - - context->length = msn_pop32le(buf); - context->version = msn_pop32le(buf); - if (context->version == 0) { - if (context->length != MSN_FILE_CONTEXT_SIZE_V0) { - g_free(context); - return NULL; - } - } else if (context->version == 2) { - /* The length field is broken for this version. No check. */ - context->length = MSN_FILE_CONTEXT_SIZE_V2; - if (len < MSN_FILE_CONTEXT_SIZE_V2) { - g_free(context); - return NULL; - } - } else if (context->version == 3) { - if (context->length != MSN_FILE_CONTEXT_SIZE_V3) { - g_free(context); - return NULL; - } else if (len < MSN_FILE_CONTEXT_SIZE_V3) { - 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; - if (context->version > 0) { -#if 0 - memcpy(context->unknown1, buf, sizeof(context->unknown1)); - buf += sizeof(context->unknown1); - context->unknown2 = msn_pop32le(buf); -#else - buf += sizeof(gchar[30]) + sizeof(guint32); -#endif - } - - 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; -} -
--- a/libpurple/protocols/msn/ft.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -/** - * @file ft.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_FT_H -#define MSN_FT_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 */ -#if 0 - gchar unknown1[30]; /*< Used somehow for background sharing */ - guint32 unknown2; /*< Possibly for background sharing as well */ -#endif - gchar *preview; /*< File preview data, 96x96 PNG */ - gsize preview_len; -} MsnFileContext; - -#define MSN_FILE_CONTEXT_SIZE_V0 (4*3 + 1*8 + 2*MAX_FILE_NAME_LEN) -#define MSN_FILE_CONTEXT_SIZE_V2 (MSN_FILE_CONTEXT_SIZE_V0 + 4*1 + 30) -#define MSN_FILE_CONTEXT_SIZE_V3 (MSN_FILE_CONTEXT_SIZE_V2 + 63) - -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, gsize size, 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_FT_H */ -
--- a/libpurple/protocols/mxit/cipher-mxit.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,83 +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 "cipher-mxit.h" - -#include "cipher.h" -#include "ciphers/aescipher.h" -#include "debug.h" -#include "internal.h" - -#define INITIAL_KEY "6170383452343567" -#define SECRET_HEADER "<mxit/>" - -/** - * 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. - */ -gchar * -mxit_encrypt_password(struct MXitSession* session) -{ - guchar key[16]; - size_t clientkey_len, header_len, pass_len, plaintext_len; - const gchar *plaintext_passwd; - guchar *plaintext; - guchar encrypted[64]; /* shouldn't be longer than 17 */ - PurpleCipher *cipher; - ssize_t encrypted_size; - - purple_debug_info(MXIT_PLUGIN_ID, "mxit_encrypt_password"); - - /* build the AES encryption key */ - g_assert(strlen(INITIAL_KEY) == sizeof(key)); - memcpy(key, INITIAL_KEY, sizeof(key)); - clientkey_len = strlen(session->clientkey); - if (clientkey_len > sizeof(key)) - clientkey_len = sizeof(key); - memcpy(key, session->clientkey, clientkey_len); - - /* build the secret data to be encrypted: SECRET_HEADER + password */ - plaintext_passwd = purple_connection_get_password(session->con); - g_return_val_if_fail(plaintext_passwd, NULL); - pass_len = strlen(plaintext_passwd); - header_len = strlen(SECRET_HEADER); - /* Trailing NUL, just to be safe. But PKCS#7 seems to be enough. */ - plaintext_len = header_len + pass_len + 1; - plaintext = g_new0(guchar, plaintext_len); - memcpy(plaintext, SECRET_HEADER, header_len); - memcpy(plaintext + header_len, plaintext_passwd, pass_len); - - /* encrypt */ - cipher = purple_aes_cipher_new(); - purple_cipher_set_key(cipher, key, sizeof(key)); - purple_cipher_set_batch_mode(cipher, PURPLE_CIPHER_BATCH_MODE_ECB); - encrypted_size = purple_cipher_encrypt(cipher, - plaintext, plaintext_len, encrypted, sizeof(encrypted)); - g_return_val_if_fail(encrypted_size > 0, NULL); - - return purple_base64_encode(encrypted, encrypted_size); -}
--- a/libpurple/protocols/mxit/cipher-mxit.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,31 +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 _MXIT_CIPHER_H_ -#define _MXIT_CIPHER_H_ - -#include "mxit.h" - -gchar * -mxit_encrypt_password(struct MXitSession* session); - -#endif /* _MXIT_CIPHER_H_ */
--- a/libpurple/protocols/mxit/client.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,2968 +0,0 @@ -/* - * MXit Protocol libPurple Plugin - * - * -- MXit client protocol implementation -- - * - * Pieter Loubser <libpurple@mxit.com> - * - * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. - * <http://www.mxitlifestyle.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#include "internal.h" -#include "debug.h" -#include "version.h" - -#include "client.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 "cipher.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, 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 = g_malloc0( len + 1 ); - int i; - - for ( i = 0; i < len; i++ ) { - char ch = buf[i]; - - if ( ch == CP_REC_TERM ) /* record terminator */ - msg[i] = '!'; - else if ( ch == CP_FLD_TERM ) /* field terminator */ - msg[i] = '^'; - else if ( ch == CP_PKT_TERM ) /* packet terminator */ - msg[i] = '@'; - else if ( ( ch < 0x20 ) || ( ch > 0x7E ) ) /* non-printable character */ - msg[i] = '_'; - else - msg[i] = ch; - } - - purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg ); - - g_free( 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; -} - - -/*------------------------------------------------------------------------ - * scnprintf - * - * @param string The destination buffer. - * @param size The maximum size of the destination buffer. - * @param format The format string - * @param ... The parameters to the format string. - * @return The number of characters actually stored in the buffer. - */ -static int scnprintf( gchar* string, size_t size, const char *format, ... ) -{ - va_list args; - guint i; - - va_start( args, format ); - i = g_vsnprintf( string, size, format, args ); - va_end( args ); - - if ( i < size ) - return i; - else if ( size > 0 ) /* destination buffer too short - return number of characters actually inserted */ - return size - 1; - else - return 0; -} - - - -/*======================================================================================================================== - * 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 http_conn http api object (see http.h) - * @param response http api object (see http.h) - * @param _session The MXit session object - */ -static void -mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response, - gpointer _session) -{ - struct MXitSession *session = _session; - const gchar *got_data; - size_t got_len; - - if (!purple_http_response_is_successful(response)) { - purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n", - purple_http_response_get_error(response)); - return; - } - - /* convert the HTTP result */ - got_data = purple_http_response_get_data(response, &got_len); - memcpy(session->rx_dbuf, got_data, got_len); - session->rx_i = got_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 packet The packet data - */ -static void -mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet) -{ - PurpleHttpRequest *req; - char *part = NULL; - - if (packet->datalen > 0) { - char *tmp; - - tmp = g_strndup(packet->data, packet->datalen); - part = g_strdup(purple_url_encode(tmp)); - g_free(tmp); - } - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, "%s?%s%s", session->http_server, - purple_url_encode(packet->header), part ? part : ""); - purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); - purple_http_connection_set_add(session->async_http_reqs, - purple_http_request(session->con, req, mxit_cb_http_rx, - session)); - purple_http_request_unref(req); - - g_free(part); -} - - -/** - * TX Step 3: Write the packet data to the HTTP connection (POST style). - * - * @param session The MXit session object - * @param packet The packet data - */ -static void -mxit_write_http_post(struct MXitSession* session, struct tx_packet* packet) -{ - PurpleHttpRequest *req; - - /* strip off the last '&' from the header */ - packet->header[packet->headerlen - 1] = '\0'; - packet->headerlen--; - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, "%s?%s", session->http_server, - purple_url_encode(packet->header)); - purple_http_request_set_method(req, "POST"); - purple_http_request_header_set(req, "User-Agent", MXIT_HTTP_USERAGENT); - purple_http_request_header_set(req, "Content-Type", - "application/octet-stream"); - purple_http_request_set_contents(req, packet->data + MXIT_MS_OFFSET, - packet->datalen - MXIT_MS_OFFSET); - purple_http_connection_set_add(session->async_http_reqs, - purple_http_request(session->con, req, mxit_cb_http_rx, - session)); - purple_http_request_unref(req); -} - - -/*------------------------------------------------------------------------ - * 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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 = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */ - - if ( session->http ) { - /* http connection only */ - hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "s=" ); - if ( session->http_sesid > 0 ) { - hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_sesid, CP_FLD_TERM ); /* http session id */ - } - session->http_seqno++; - hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "%u%c", session->http_seqno, CP_REC_TERM ); /* http request sequence id */ - } - - hlen += scnprintf( header + hlen, sizeof( header ) - hlen, "cm=%i%c", cmd, CP_REC_TERM ); /* packet command */ - - if ( !session->http ) { - /* socket connection only */ - packet->headerlen = scnprintf( packet->header, sizeof( 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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(); - 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; - - 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)\n", session->http_interval, rxdiff ); - - 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 ); - - /* 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 = scnprintf( 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 ); - - /* 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 ) { - if ( parts == NULL || parts[i] == NULL || parts[i + 1] == NULL || parts[i + 2] == NULL ) { - purple_debug_error( MXIT_PLUGIN_ID, "Invalid profile update attributes = '%s' - nbr=%u\n", attributes, nr_attrib ); - g_strfreev( parts ); - return; - } - datalen += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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 = scnprintf( data, sizeof( data ), - "ms=%i%c", /* "ms"=show\1status */ - presence, CP_FLD_TERM - ); - - /* append status message (if one is set) */ - if ( statusmsg ) - datalen += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 = scnprintf( 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 = scnprintf( 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 = scnprintf( 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 = scnprintf( data, sizeof( data ), - "ms=%s", /* "ms"=username */ - username - ); - - /* append reason (if one is set) */ - if ( reason ) - datalen += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 = scnprintf( 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 = scnprintf( 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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 = scnprintf( 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 += scnprintf( data + datalen, sizeof( 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, size_t buflen ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "SENDING FILE '%s' of %zu bytes to user '%s'\n", filename, buflen, username ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_senddirect( chunk_data( chunk ), username, filename, buf, buflen ); - set_chunk_type( chunk, CP_CHUNK_DIRECT_SND ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_reject\n" ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_reject( chunk_data( chunk ), fileid ); - set_chunk_type( chunk, CP_CHUNK_REJECT ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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, size_t filesize, size_t offset ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_accept\n" ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_get( chunk_data(chunk), fileid, filesize, offset ); - set_chunk_type( chunk, CP_CHUNK_GET ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_send_file_received\n" ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_received( chunk_data(chunk), fileid, status ); - set_chunk_type( chunk, CP_CHUNK_RECEIVED ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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, size_t avatarlen ) -{ - char data[CP_MAX_PACKET]; - int datalen = 0; - gchar* chunk; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_set_avatar: %zu bytes\n", avatarlen ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_set_avatar( chunk_data(chunk), avatar, avatarlen ); - set_chunk_type( chunk, CP_CHUNK_SET_AVATAR ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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; - size_t chunksize; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_get_avatar: %s\n", mxitId ); - - /* convert the packet to a byte stream */ - datalen = scnprintf( data, sizeof( data ), "ms=" ); - - /* map chunk header over data buffer */ - chunk = &data[datalen]; - - /* encode chunk */ - chunksize = mxit_chunk_create_get_avatar( chunk_data(chunk), mxitId, avatarId ); - set_chunk_type( chunk, CP_CHUNK_GET_AVATAR ); - set_chunk_length( chunk, chunksize ); - datalen += MXIT_CHUNK_HEADER_SIZE + chunksize; - - /* 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_CONNECTION_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 ); - - /* 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_blist_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. We don't support - * it anymore, because original client doesn't look like it was. */ - purple_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 ) && ( *rec->fields[4]->data ) ) - 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 ); - } -} - - -/*------------------------------------------------------------------------ - * Parse the received presence value, and ensure that it is supported. - * - * @param value The received presence value. - * @return A valid presence value. - */ -static short mxit_parse_presence( const char* value ) -{ - short presence = atoi( value ); - - /* ensure that the presence value is valid */ - switch ( presence ) { - case MXIT_PRESENCE_OFFLINE : - case MXIT_PRESENCE_ONLINE : - case MXIT_PRESENCE_AWAY : - case MXIT_PRESENCE_DND : - return presence; - - default : - return MXIT_PRESENCE_ONLINE; - } -} - - -/*------------------------------------------------------------------------ - * Parse the received mood value, and ensure that it is supported. - * - * @param value The received mood value. - * @return A valid mood value. - */ -static short mxit_parse_mood( const char* value ) -{ - short mood = atoi( value ); - - /* ensure that the mood value is valid */ - if ( ( mood >= MXIT_MOOD_NONE ) && ( mood <= MXIT_MOOD_STRESSED ) ) - return mood; - - return MXIT_MOOD_NONE; -} - - -/*------------------------------------------------------------------------ - * 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 = mxit_parse_presence( rec->fields[3]->data ); - contact->type = atoi( rec->fields[4]->data ); - contact->mood = mxit_parse_mood( 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, mxit_parse_presence( rec->fields[1]->data ), mxit_parse_mood( 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 ); - - /* ensure the packet has the correct number of fields */ - if ( records[0]->fcount < ( 2 + ( count * 3 ) ) ) { - purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in extprofile response. fields=%i records=%i", records[0]->fcount, count ); - return; - } - - 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 = g_ascii_strtoll( fvalue, NULL, 10 ); - } - else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) { - /* last seen online */ - profile->lastonline = g_ascii_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 ) && ( *statusMsg ) ) { - /* update the status message */ - g_free(contact->statusMsg); - contact->statusMsg = strdup( statusMsg ); - } - else - contact->statusMsg = NULL; - g_free(contact->profile); - contact->profile = profile; - if ( ( avatarId ) && ( *avatarId ) ) { - /* avatar must be requested for this invite before we can display it */ - mxit_get_avatar( session, mxitId, 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 ) && ( *statusMsg ) ) { - /* update the status message */ - PurpleBuddy* buddy = NULL; - - buddy = purple_blist_find_buddy( session->acc, mxitId ); - if ( buddy ) { - contact = purple_buddy_get_protocol_data( buddy ); - if ( contact ) { - 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 - */ - - /* ensure that record[0] contacts the minumum number of fields */ - if ( records[0]->fcount < 4 ) { - purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i", records[0]->fcount ); - return; - } - - /* 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 ); - - /* ensure that record[0] contains the specified number of attributes */ - if ( records[0]->fcount < ( 4 + count ) ) { - purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", records[0]->fcount, count ); - return; - } - - for ( i = 1; i < rcount; i ++ ) { - struct record* rec = records[i]; - struct MXitProfile* profile = g_new0( struct MXitProfile, 1 ); - int j; - - /* ensure that each result contains the specified number of attributes */ - if ( rec->fcount != ( 2 + count ) ) { - purple_debug_error( MXIT_PLUGIN_ID, "Insufficient number of fields in suggest contacts response. fields=%i attributes=%i", rec->fcount, count ); - g_free( profile ); - continue; - } - - 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 */ - purple_serv_got_typing( session->con, records[0]->fields[0]->data, 0, PURPLE_IM_TYPING ); - break; - - case CP_MSGEVENT_STOPPED : /* user has stopped typing */ - purple_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 ); - } -} - - -/*------------------------------------------------------------------------ - * 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 ) -{ - guint chunktype; - guint32 chunksize; - gchar* chunkdata; - - /* received packet is too short to even contain a chunk header */ - if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE ) - return; - - /* decode the chunk header */ - chunktype = chunk_type( records[0]->fields[0]->data ); - chunksize = chunk_length( records[0]->fields[0]->data ); - chunkdata = chunk_data( records[0]->fields[0]->data ); - - /* check chunk size against length of received data */ - if ( MXIT_CHUNK_HEADER_SIZE + chunksize > records[0]->fields[0]->len ) - return; - - purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize ); - - /* supported chunked data types */ - switch ( chunktype ) { - case CP_CHUNK_CUSTOM : /* custom resource */ - { - struct cr_chunk chunk; - - /* decode the chunked data */ - if ( mxit_chunk_parse_cr( chunkdata, chunksize, &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 */ - if ( mxit_chunk_parse_offer( chunkdata, chunksize, &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 */ - if ( mxit_chunk_parse_get( chunkdata, chunksize, &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 */ - if ( mxit_chunk_parse_get_avatar( chunkdata, chunksize, &chunk ) ) { - /* update avatar image */ - 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) */ - if (contact->image) - g_object_unref(contact->image); - contact->image = purple_image_new_from_data( - g_memdup(chunk.data, chunk.length), chunk.length); - /* 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_REJECT : - /* this is a reply packet to a reject file request. no action is required */ - break; - - case CP_CHUNK_DIRECT_SND : - /* this is a ack for a file send. */ - { - struct sendfile_chunk chunk; - - if ( mxit_chunk_parse_sendfile( chunkdata, chunksize, &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", chunktype ); - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( 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 { - g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode ); - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg ); - return -1; - } - case CP_CMD_LOGOUT : - g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode ); - purple_connection_error( 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=%zu) '%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 */ - if ( packet.records[0]->fcount > 0 ) - 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 = chunk_length( 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) ); - return; - } - else if ( len == 0 ) { - /* connection closed */ - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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 <= 0 ) || ( session->rx_res > CP_MAX_PACKET ) ) { - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x03)" ) ); - return; - } - 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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) ); - return; - } - else if ( len == 0 ) { - /* connection closed */ - purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "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 all outstanding async calls */ - purple_http_connection_set_destroy(session->async_http_reqs); - session->async_http_reqs = NULL; - - /* remove the input cb function */ - if ( session->inpa ) { - purple_input_remove( session->inpa ); - session->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 ); - - g_free(contact->msg); - g_free(contact->statusMsg); - g_free(contact->profile); - if (contact->image) - g_object_unref(contact->image); - g_free( contact ); - } - g_list_free( session->invites ); - session->invites = NULL; - - free( session->profile ); - mxit_free_emoticon_cache( session ); - g_free( session->uid ); - g_free( session->encpwd ); - session->encpwd = NULL; - - /* flush all the commands still in the queue */ - flush_queue( session ); -} -
--- a/libpurple/protocols/mxit/client.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,352 +0,0 @@ -/* - * MXit Protocol libPurple Plugin - * - * -- MXit client protocol implementation -- - * - * Pieter Loubser <libpurple@mxit.com> - * - * (C) Copyright 2009 MXit Lifestyle (Pty) Ltd. - * <http://www.mxitlifestyle.com> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _MXIT_PROTO_H_ -#define _MXIT_PROTO_H_ - - -/* Client protocol constants */ -#define CP_SOCK_REC_TERM '\x00' /* socket record terminator */ -#define CP_HTTP_REC_TERM '\x26' /* http record terminator '&' */ -#define CP_FLD_TERM '\x01' /* field terminator */ -#define CP_PKT_TERM '\x02' /* packet terminator */ - - -#define CP_MAX_PACKET ( 1 * 1000 * 1000 ) /* maximum client protocol packet size (1 MB) */ -#define CP_MAX_FILESIZE ( CP_MAX_PACKET - 1000 ) /* maximum file size (reserve some space for packet headers) */ -#define MXIT_EMOTICON_SIZE 18 /* icon size for custom emoticons */ -#define CP_MAX_STATUS_MSG 250 /* maximum status message length (in characters) */ - -/* Avatars */ -#define MXIT_AVATAR_SIZE 96 /* default avatar image size 96x96 */ -#define MXIT_AVATAR_TYPE "PNG" /* request avatars in this file type (only a suggestion) */ -#define MXIT_AVATAR_BITDEPT 24 /* request avatars with this bit depth (only a suggestion) */ - -/* Protocol error codes */ -#define MXIT_ERRCODE_SUCCESS 0 -#define MXIT_ERRCODE_REDIRECT 16 -#define MXIT_ERRCODE_LOGGEDOUT 42 - -/* MXit client features */ -#define MXIT_CF_NONE 0x000000 -#define MXIT_CF_FORMS 0x000001 -#define MXIT_CF_FILE_TRANSFER 0x000002 -#define MXIT_CF_CAMERA 0x000004 -#define MXIT_CF_COMMANDS 0x000008 -#define MXIT_CF_SMS 0x000010 -#define MXIT_CF_FILE_ACCESS 0x000020 -#define MXIT_CF_MIDP2 0x000040 -#define MXIT_CF_SKINS 0x000080 -#define MXIT_CF_AUDIO 0x000100 -#define MXIT_CF_ENCRYPTION 0x000200 -#define MXIT_CF_VOICE_REC 0x000400 -#define MXIT_CF_VECTOR_GFX 0x000800 -#define MXIT_CF_IMAGES 0x001000 -#define MXIT_CF_MARKUP 0x002000 -#define MXIT_CF_VIBES 0x004000 -#define MXIT_CF_SELECT_CONTACT 0x008000 -#define MXIT_CF_CUSTOM_EMO 0x010000 -#define MXIT_CF_ALERT_PROFILES 0x020000 -#define MXIT_CF_EXT_MARKUP 0x040000 -#define MXIT_CF_PLAIN_PWD 0x080000 -#define MXIT_CF_NO_GATEWAYS 0x100000 -#define MXIT_CF_NO_AVATARS 0x200000 -#define MXIT_CF_GAMING 0x400000 -#define MXIT_CF_GAMING_UPDATE 0x800000 -#define MXIT_CF_VOICE 0x1000000 -#define MXIT_CF_VIDEO 0x2000000 -#define MXIT_CF_TOUCHSCREEN 0x4000000 -#define MXIT_CF_SVC_CONNECTION 0x8000000 -#define MXIT_CF_MXML 0x10000000 -#define MXIT_CF_TYPING_NOTIFY 0x20000000 - -/* Client features supported by this implementation */ -#define MXIT_CP_FEATURES ( MXIT_CF_FILE_TRANSFER | MXIT_CF_FILE_ACCESS | MXIT_CF_AUDIO | MXIT_CF_MARKUP | MXIT_CF_EXT_MARKUP | MXIT_CF_NO_GATEWAYS | MXIT_CF_IMAGES | MXIT_CF_COMMANDS | MXIT_CF_VIBES | MXIT_CF_MIDP2 | MXIT_CF_TYPING_NOTIFY ) - - -#define MXIT_PING_INTERVAL ( 5 * 60 ) /* ping the server after X seconds of being idle (5 minutes) */ -#define MXIT_ACK_TIMEOUT ( 30 ) /* timeout after waiting X seconds for an ack from the server (30 seconds) */ -#define MXIT_TX_DELAY ( 100 ) /* delay between sending consecutive packets (100 ms) */ - -/* MXit client version */ -#define MXIT_CP_DISTCODE 'P' /* client distribution code (magic, do not touch!) */ -#define MXIT_CP_ARCH "Y" /* client architecture series (Y not for Yoda but for PC-client) */ -#define MXIT_CLIENT_ID "LP" /* client ID as specified by MXit */ -#define MXIT_CP_PLATFORM "PURPLE" /* client platform */ -#define MXIT_CP_PROTO_VESION 63 /* client protocol version */ - -/* set operating system name */ -#if defined( __APPLE__ ) -#define MXIT_CP_OS "apple" -#elif defined( _WIN32 ) -#define MXIT_CP_OS "windows" -#elif defined( __linux__ ) -#define MXIT_CP_OS "linux" -#else -#define MXIT_CP_OS "unknown" -#endif - -/* Client capabilities */ -#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID - -/* Client settings */ -#define MAX_QUEUE_SIZE ( 1 << 5 ) /* tx queue size (32 packets) */ -#define MXIT_POPUP_WIN_NAME "MXit Notification" /* popup window name */ -#define MXIT_DEFAULT_LOCALE "en" /* default locale setting */ -#define MXIT_DEFAULT_LOC "planetpurple" /* the default location for registration */ - -/* Client protocol commands */ -#define CP_CMD_LOGIN 0x0001 /* (1) login */ -#define CP_CMD_LOGOUT 0x0002 /* (2) logout */ -#define CP_CMD_CONTACT 0x0003 /* (3) get contacts */ -#define CP_CMD_UPDATE 0x0005 /* (5) update contact information */ -#define CP_CMD_INVITE 0x0006 /* (6) subscribe to new contact */ -#define CP_CMD_PRESENCE 0x0007 /* (7) get presence */ -#define CP_CMD_REMOVE 0x0008 /* (8) remove contact */ -#define CP_CMD_RX_MSG 0x0009 /* (9) get new messages */ -#define CP_CMD_TX_MSG 0x000A /* (10) send new message */ -#define CP_CMD_REGISTER 0x000B /* (11) register */ -//#define CP_CMD_PROFILE_SET 0x000C /* (12) set profile (DEPRECATED see CP_CMD_EXTPROFILE_SET) */ -#define CP_CMD_SUGGESTCONTACTS 0x000D /* (13) suggest contacts */ -#define CP_CMD_POLL 0x0011 /* (17) poll the HTTP server for an update */ -//#define CP_CMD_PROFILE_GET 0x001A /* (26) get profile (DEPRECATED see CP_CMD_EXTPROFILE_GET) */ -#define CP_CMD_MEDIA 0x001B /* (27) get multimedia message */ -#define CP_CMD_SPLASHCLICK 0x001F /* (31) splash-screen clickthrough */ -#define CP_CMD_STATUS 0x0020 /* (32) set shown presence & status */ -#define CP_CMD_MSGEVENT 0x0023 /* (35) Raise message event */ -#define CP_CMD_GOT_MSGEVENT 0x0024 /* (36) Get message event */ -#define CP_CMD_MOOD 0x0029 /* (41) set mood */ -#define CP_CMD_KICK 0x002B /* (43) login kick */ -#define CP_CMD_GRPCHAT_CREATE 0x002C /* (44) create new groupchat */ -#define CP_CMD_GRPCHAT_INVITE 0x002D /* (45) add new groupchat member */ -#define CP_CMD_NEW_SUB 0x0033 /* (51) get new subscription */ -#define CP_CMD_ALLOW 0x0034 /* (52) allow subscription */ -#define CP_CMD_DENY 0x0037 /* (55) deny subscription */ -#define CP_CMD_EXTPROFILE_GET 0x0039 /* (57) get extended profile */ -#define CP_CMD_EXTPROFILE_SET 0x003A /* (58) set extended profile */ -#define CP_CMD_PING 0x03E8 /* (1000) ping (keepalive) */ - -/* HTTP connection */ -#define MXIT_HTTP_POLL_MIN 7 /* minimum time between HTTP polls (seconds) */ -#define MXIT_HTTP_POLL_MAX ( 10 * 60 ) /* maximum time between HTTP polls (seconds) */ - -/* receiver states */ -#define RX_STATE_RLEN 0x01 /* reading packet length section */ -#define RX_STATE_DATA 0x02 /* reading packet data section */ -#define RX_STATE_PROC 0x03 /* process read data */ - -/* message flags */ -#define CP_MSG_NOTIFY_DELIVERY 0x0002 /* request delivery notification */ -#define CP_MSG_NOTIFY_READ 0x0004 /* request read notification */ -#define CP_MSG_PWD_ENCRYPTED 0x0010 /* message is password encrypted */ -#define CP_MSG_TL_ENCRYPTED 0x0020 /* message is transport encrypted */ -#define CP_MSG_RPLY_PWD_ENCRYPT 0x0040 /* reply should be password encrypted */ -#define CP_MSG_RPLY_TL_ENCRYPT 0x0080 /* reply should be transport encrypted */ -#define CP_MSG_MARKUP 0x0200 /* message may contain markup */ -#define CP_MSG_EMOTICON 0x0400 /* message may contain custom emoticons */ -#define CP_MSG_FAREWELL 0x0800 /* this is a farewell message */ - -/* redirect types */ -#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */ -#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */ - -/* message tx types */ -#define CP_MSGTYPE_NORMAL 0x01 /* normal message */ -#define CP_MSGTYPE_CHAT 0x02 /* chat message */ -#define CP_MSGTYPE_HEADLINE 0x03 /* headline message */ -#define CP_MSGTYPE_ERROR 0x04 /* error message */ -#define CP_MSGTYPE_GROUPCHAT 0x05 /* groupchat message */ -#define CP_MSGTYPE_FORM 0x06 /* mxit custom form */ -#define CP_MSGTYPE_COMMAND 0x07 /* mxit command */ - -/* message event types */ -#define CP_MSGEVENT_DELIVERED 0x02 /* message was delivered */ -#define CP_MSGEVENT_DISPLAYED 0x04 /* message was viewed */ -#define CP_MSGEVENT_TYPING 0x10 /* user is typing */ -#define CP_MSGEVENT_STOPPED 0x20 /* user has stopped typing */ -#define CP_MSGEVENT_ANGRY 0x40 /* user is typing angrily */ -#define CP_MSGEVENT_ERASING 0x80 /* user is erasing text */ - -/* extended profile attribute fields */ -#define CP_PROFILE_BIRTHDATE "birthdate" /* Birthdate (String - ISO 8601 format) */ -#define CP_PROFILE_GENDER "gender" /* Gender (Boolean - 0=female, 1=male) */ -// #define CP_PROFILE_HIDENUMBER "hidenumber" /* Hide Number (Boolean - 0=false, 1=true) (DEPRECATED) */ -#define CP_PROFILE_FULLNAME "fullname" /* Fullname (UTF8 String) */ -#define CP_PROFILE_STATUS "statusmsg" /* Status Message (UTF8 String) */ -#define CP_PROFILE_PREVSTATUS "prevstatusmsgs" /* Previous Status Messages (UTF8 String) */ -#define CP_PROFILE_AVATAR "avatarid" /* Avatar ID (String) */ -#define CP_PROFILE_MODIFIED "lastmodified" /* Last-Modified timestamp */ -#define CP_PROFILE_TITLE "title" /* Title (UTF8 String) */ -#define CP_PROFILE_FIRSTNAME "firstname" /* First name (UTF8 String) */ -#define CP_PROFILE_LASTNAME "lastname" /* Last name (UTF8 String) */ -#define CP_PROFILE_EMAIL "email" /* Email address (UTF8 String) */ -#define CP_PROFILE_MOBILENR "mobilenumber" /* Mobile Number (UTF8 String) */ -#define CP_PROFILE_REGCOUNTRY "registeredcountry" /* Registered Country Code (UTF8 String) */ -#define CP_PROFILE_FLAGS "flags" /* Profile flags (Bitset) */ -#define CP_PROFILE_LASTSEEN "lastseen" /* Last-Online timestamp */ -#define CP_PROFILE_WHEREAMI "whereami" /* Where am I / Where I live */ -#define CP_PROFILE_ABOUTME "aboutme" /* About me */ -#define CP_PROFILE_RELATIONSHIP "relationship" /* Relationship Status */ - -/* extended profile field types */ -#define CP_PROFILE_TYPE_BOOL 0x02 /* boolean (0 or 1) */ -#define CP_PROFILE_TYPE_SHORT 0x04 /* short (16-bit) */ -#define CP_PROFILE_TYPE_INT 0x05 /* integer (32-bit) */ -#define CP_PROFILE_TYPE_LONG 0x06 /* long (64-bit) */ -#define CP_PROFILE_TYPE_UTF8 0x0A /* UTF8 string */ -#define CP_PROFILE_TYPE_DATE 0x0B /* date-time (ISO 8601 format) */ - -/* profile flags */ -#define CP_PROF_NOT_SEARCHABLE 0x02 /* user cannot be searched for */ -#define CP_PROF_NOT_SUGGESTABLE 0x08 /* user cannot be suggested as friend */ -#define CP_PROF_DOBLOCKED 0x40 /* date-of-birth cannot be changed */ - -/* suggestion types */ -#define CP_SUGGEST_ADDRESSBOOK 0 /* address book search */ -#define CP_SUGGEST_FRIENDS 1 /* suggested friends */ -#define CP_SUGGEST_SEARCH 2 /* free-text search */ -#define CP_SUGGEST_MXITID 3 /* MXitId search */ - -/* define this to enable protocol debugging (very verbose logging) */ -#define DEBUG_PROTOCOL - - -/* ======================================================================================= */ - -struct MXitSession; - -/*------------------------------------------*/ - -struct field { - char* data; - size_t 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, size_t buflen ); -void mxit_send_file_reject( struct MXitSession* session, const char* fileid ); -void mxit_send_file_accept( struct MXitSession* session, const char* fileid, size_t filesize, size_t 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, size_t 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_ */ -
--- a/libpurple/protocols/oscar/clientlogin.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/oscar/clientlogin.c Mon Jun 05 16:36:29 2017 +0300 @@ -40,9 +40,6 @@ #include "oscarcommon.h" #include "core.h" -#include "ciphers/hmaccipher.h" -#include "ciphers/sha256hash.h" - #define AIM_LOGIN_HOST "api.screenname.aol.com" #define ICQ_LOGIN_HOST "api.login.icq.net" @@ -122,19 +119,16 @@ */ static gchar *hmac_sha256(const char *key, const char *message) { - PurpleCipher *cipher; - PurpleHash *hash; + GHmac *hmac; guchar digest[32]; + gsize digest_len = 32; - hash = purple_sha256_hash_new(); - cipher = purple_hmac_cipher_new(hash); - purple_cipher_set_key(cipher, (guchar *)key, strlen(key)); - purple_cipher_append(cipher, (guchar *)message, strlen(message)); - purple_cipher_digest(cipher, digest, sizeof(digest)); - g_object_unref(cipher); - g_object_unref(hash); + hmac = g_hmac_new(G_CHECKSUM_SHA256, (guchar *)key, strlen(key)); + g_hmac_update(hmac, (guchar *)message, -1); + g_hmac_get_digest(hmac, digest, &digest_len); + g_hmac_unref(hmac); - return purple_base64_encode(digest, sizeof(digest)); + return g_base64_encode(digest, sizeof(digest)); } /** @@ -345,7 +339,7 @@ if (!parse_start_oscar_session_response(gc, got_data, got_len, &host, &port, &cookie, &tls_certname)) return; - cookiedata = purple_base64_decode(cookie, &cookiedata_len); + cookiedata = g_base64_decode(cookie, &cookiedata_len); oscar_connect_to_bos(gc, od, host, port, cookiedata, cookiedata_len, tls_certname); g_free(cookiedata);
--- a/libpurple/protocols/oscar/family_auth.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/oscar/family_auth.c Mon Jun 05 16:36:29 2017 +0300 @@ -31,8 +31,6 @@ #include <ctype.h> -#include "ciphers/md5hash.h" - /* #define USE_XOR_FOR_ICQ */ #ifdef USE_XOR_FOR_ICQ @@ -75,14 +73,15 @@ static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleHash *hash; + GChecksum *hash; + gsize digest_len = 16; - hash = purple_md5_hash_new(); - purple_hash_append(hash, (const guchar *)key, strlen(key)); - purple_hash_append(hash, (const guchar *)password, password_len); - purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_hash_digest(hash, 16, digest, NULL); - g_object_unref(hash); + hash = g_checksum_new(G_CHECKSUM_MD5); + g_checksum_update(hash, (const guchar *)key, -1); + g_checksum_update(hash, (const guchar *)password, password_len); + g_checksum_update(hash, (const guchar *)AIM_MD5_STRING, -1); + g_checksum_get_digest(hash, digest, &digest_len); + g_checksum_free(hash); return 0; } @@ -90,19 +89,20 @@ static int aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest) { - PurpleHash *hash; + GChecksum *hash; guchar passdigest[16]; + gsize digest_len = 16; - hash = purple_md5_hash_new(); - purple_hash_append(hash, (const guchar *)password, password_len); - purple_hash_digest(hash, passdigest, sizeof(passdigest)); - purple_hash_reset(hash); + hash = g_checksum_new(G_CHECKSUM_MD5); + g_checksum_update(hash, (const guchar *)password, password_len); + g_checksum_get_digest(hash, passdigest, &digest_len); + g_checksum_reset(hash); - purple_hash_append(hash, (const guchar *)key, strlen(key)); - purple_hash_append(hash, passdigest, 16); - purple_hash_append(hash, (const guchar *)AIM_MD5_STRING, strlen(AIM_MD5_STRING)); - purple_hash_digest(hash, digest, 16); - g_object_unref(hash); + g_checksum_update(hash, (const guchar *)key, -1); + g_checksum_update(hash, passdigest, digest_len); + g_checksum_update(hash, (const guchar *)AIM_MD5_STRING, -1); + g_checksum_get_digest(hash, digest, &digest_len); + g_checksum_free(hash); return 0; }
--- a/libpurple/protocols/oscar/oscar.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/oscar/oscar.c Mon Jun 05 16:36:29 2017 +0300 @@ -33,7 +33,6 @@ #include "account.h" #include "accountopt.h" #include "buddyicon.h" -#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -5238,15 +5237,16 @@ if (img == NULL) { aim_ssi_delicon(od); } else { - PurpleHash *hash; + GChecksum *hash; guchar md5[16]; + gsize digest_len = 16; gconstpointer data = purple_image_get_data(img); size_t len = purple_image_get_data_size(img); - hash = purple_md5_hash_new(); - purple_hash_append(hash, data, len); - purple_hash_digest(hash, md5, sizeof(md5)); - g_object_unref(hash); + hash = g_checksum_new(G_CHECKSUM_MD5); + g_checksum_update(hash, data, len); + g_checksum_get_digest(hash, md5, &digest_len); + g_checksum_free(hash); aim_ssi_seticon(od, md5, 16); }
--- a/libpurple/protocols/sametime/sametime.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/protocols/sametime/sametime.c Mon Jun 05 16:36:29 2017 +0300 @@ -3879,7 +3879,7 @@ /* obtain and base64 encode the image data, and put it in the mime part */ size = purple_image_get_data_size(img); - data = purple_base64_encode(purple_image_get_data(img), size); + data = g_base64_encode(purple_image_get_data(img), size); purple_mime_part_set_data(part, data); g_free(data);
--- a/libpurple/protocols/yahoo/tests/.hgignore Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -syntax: regexp -^test_yahoo_util$ - -syntax: glob -*.log -*.trs -
--- a/libpurple/protocols/yahoo/tests/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -include $(top_srcdir)/glib-tap.mk - -COMMON_LIBS=\ - $(top_builddir)/libpurple/libpurple.la \ - $(top_builddir)/libpurple/protocols/yahoo/libyahoo.la \ - $(GLIB_LIBS) \ - $(GPLUGIN_LIBS) - -test_programs=\ - test_yahoo_util - -test_yahoo_util_SOURCES=test_yahoo_util.c -test_yahoo_util_LDADD=$(COMMON_LIBS) - -AM_CPPFLAGS = \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - $(DEBUG_CFLAGS) \ - $(GLIB_CFLAGS) \ - $(GPLUGIN_CFLAGS) \ - $(PLUGIN_CFLAGS) \ - $(DBUS_CFLAGS) \ - $(NSS_CFLAGS)
--- a/libpurple/protocols/yahoo/tests/test_yahoo_util.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,250 +0,0 @@ -#include <glib.h> - -#include "../ymsg.h" - -typedef struct { - gchar *input; - gchar *output; -} YahooStringTestData; - -static void -test_codes_to_html(void) { - YahooStringTestData data[] = { - { - "", - "", - }, { - "\x1B[12345m", - "", - }, { - "plain", - "plain", - }, { - "unknown \x1B[12345m ansi code", - "unknown ansi code", - }, { - "plain <peanut>", - "plain <peanut>", - }, { - "plain <peanut", - "plain <peanut", - }, { - "plain> peanut", - "plain> peanut", - }, { - "<font face='inva>lid'>test", - "<font face='inva>lid'>test</font>", - }, { - "<font face='inva>lid", - "<font face='inva>lid", - }, { - "\x1B[1mbold", - "<b>bold</b>", - }, { - "\x1B[2mitalic", - "<i>italic</i>", - }, { - "\x1B[4munderline", - "<u>underline</u>", - }, { - "no\x1B[x4m markup", - "no markup", - }, { - /* bold italic underline */ - "\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline", - "<b>bold</b> <i>italic</i> <u>underline</u>", - }, { - "\x1B[1mbold \x1B[2mbolditalic\x1B[x1m italic", - "<b>bold <i>bolditalic</i></b><i> italic</i>", - }, { - "\x1B[1mbold \x1B[2mbolditalic\x1B[x1m \x1B[4mitalicunderline", - "<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>", - }, { - "\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x2m boldunderline", - "<b>bold <i>bolditalic <u>bolditalicunderline</u></i><u> boldunderline</u></b>", - }, { - "\x1B[1mbold \x1B[2mbolditalic \x1B[4mbolditalicunderline\x1B[x1m italicunderline", - "<b>bold <i>bolditalic <u>bolditalicunderline</u></i></b><i><u> italicunderline</u></i>", - }, { - /* links */ - "\x1B[lmhttps://pidgin.im/\x1B[xlm", - "https://pidgin.im/", - }, { - /* font color */ - "\x1B[31mblue", - "<font color='#0000FF'>blue</font>", - }, { - "\x1B[#70ea15mcustom color", - "<font color='#70ea15'>custom color</font>", - }, { - "<ALT #ff0000,#00ff00,#0000ff>test</ALT>", - "test", - }, { - /* font face */ - "<font face='Georgia'>test", - "<font face='Georgia'>test</font>", - }, { - /* font size */ - "<font size='15'>test", - "<font size='4' absz='15'>test</font>", - }, { - "<font size='32'>size 32", - "<font size='6' absz='32'>size 32</font>", - }, { - /* combinations */ - "<font face='Georgia' size='32'>test", - "<font face='Georgia' size='6' absz='32'>test</font>", - }, { - "\x1B[35m<font size='15'>test", - "<font color='#FF0080'><font size='4' absz='15'>test</font></font>", - }, { - "<FADE #ff0000,#00ff00,#0000ff>:<</FADE>", - ":<", - }, { - NULL, - NULL, - } - }; - gint i; - - yahoo_init_colorht(); - - for(i = 0; data[i].input; i++) { - gchar *result = yahoo_codes_to_html(data[i].input); - - g_assert_cmpstr(result, ==, data[i].output); - - g_free(result); - } - - yahoo_dest_colorht(); -} - -static void -test_html_to_codes(void) { - YahooStringTestData data[] = { - { - "plain", - "plain", - }, { - "plain <peanut>", - "plain <peanut>", - }, { - "plain <peanut", - "plain <peanut", - }, { - "plain> peanut", - "plain> peanut", - }, { - "plain >", - "plain >", - }, { - "plain > ", - "plain > ", - }, { - "plain <", - "plain <", - }, { - "plain < ", - "plain < ", - }, { - "plain <", - "plain <", - }, { - "plain &", - "plain &", - }, { - /* bold/italic/underline */ - "<b>bold</b>", - "\x1B[1mbold\x1B[x1m", - }, { - "<i>italic</i>", - "\x1B[2mitalic\x1B[x2m", - }, { - "<u>underline</u>", - "\x1B[4munderline\x1B[x4m", - }, { - "no</u> markup", - "no markup", - }, { - "<b>bold</b> <i>italic</i> <u>underline</u>", - "\x1B[1mbold\x1B[x1m \x1B[2mitalic\x1B[x2m \x1B[4munderline\x1B[x4m", - }, { - "<b>bold <i>bolditalic</i></b><i> italic</i>", - "\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m italic\x1B[x2m", - }, { - "<b>bold <i>bolditalic</i></b><i> <u>italicunderline</u></i>", - "\x1B[1mbold \x1B[2mbolditalic\x1B[x2m\x1B[x1m\x1B[2m \x1B[4mitalicunderline\x1B[x4m\x1B[x2m", - }, { - /* link */ - "<A HREF=\"https://pidgin.im/\">https://pidgin.im/</A>", - "https://pidgin.im/", - }, { - "<A HREF=\"mailto:mark@example.com\">mark@example.com</A>", - "mark@example.com", - }, { - /* font nothing */ - "<font>nothing</font>", - "nothing", - }, { - /* font color */ - "<font color=\"#E71414\">red</font>", - "\x1B[#E71414mred\x1B[#000000m", - }, { - "<font color=\"#FF0000\">red</font> <font color=\"#0000FF\">blue</font> black", - "\x1B[#FF0000mred\x1B[#000000m \x1B[#0000FFmblue\x1B[#000000m black", - }, { - /* font size */ - "<font size=\"2\">test</font>", - "<font size=\"10\">test</font>", - }, { - "<font size=\"6\">test</font>", - "<font size=\"30\">test</font>", - }, { - /* combinations */ - "<font color=\"#FF0000\"><font size=\"1\">redsmall</font> rednormal</font>", - "\x1B[#FF0000m<font size=\"8\">redsmall</font> rednormal\x1B[#000000m", - }, { - "<font color=\"#FF0000\"><font size=\"1\">redsmall</font> <font color=\"#00FF00\">greennormal</font> rednormal</font>", - "\x1B[#FF0000m<font size=\"8\">redsmall</font> \x1B[#00FF00mgreennormal\x1B[#FF0000m rednormal\x1B[#000000m", - }, { - "<b>bold <font color=\"#FF0000\">red <font face=\"Comic Sans MS\" size=\"5\">larger <font color=\"#000000\">backtoblack <font size=\"3\">normalsize</font></font></font></font></b>", - "\x1B[1mbold \x1B[#FF0000mred <font face=\"Comic Sans MS\" size=\"20\">larger \x1B[#000000mbacktoblack <font size=\"12\">normalsize</font>\x1B[#FF0000m</font>\x1B[#000000m\x1B[x1m", - }, { - /* buzz/unknown tags */ - "<ding>", - "<ding>", - }, { - "Unknown <tags>", - "Unknown <tags>", - }, { - NULL, - NULL, - } - }; - gint i; - - yahoo_init_colorht(); - - for(i = 0; data[i].input; i++) { - gchar *result = yahoo_html_to_codes(data[i].input); - - g_assert_cmpstr(result, ==, data[i].output); - - g_free(result); - } - - yahoo_dest_colorht(); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/yahoo/format/network to html", - test_codes_to_html); - g_test_add_func("/yahoo/format/html to network", - test_html_to_codes); - - return g_test_run(); -}
--- a/libpurple/protocols/yahoo/yahoo.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,415 +0,0 @@ -/* - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - * - */ - -#include "internal.h" - -#include <account.h> -#include <core.h> -#include <plugins.h> - -#include "ymsg.h" -#include "yahoo.h" -#include "yahoochat.h" -#include "yahoo_aliases.h" -#include "yahoo_doodle.h" -#include "yahoo_filexfer.h" -#include "yahoo_picture.h" - -static PurpleProtocol *yahoo_protocol = NULL; - -static GSList *cmds = NULL; - -static void yahoo_register_commands(void) -{ - PurpleCmdId id; - - id = purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoo", yahoopurple_cmd_chat_join, - _("join <room>: Join a chat room on the Yahoo network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoo", yahoopurple_cmd_chat_list, - _("list: List rooms on the Yahoo network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoo", yahoopurple_cmd_buzz, - _("buzz: Buzz a user to get their attention"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoo", yahoo_doodle_purple_cmd_start, - _("doodle: Request user to start a Doodle session"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); -} - -static void yahoo_unregister_commands(void) -{ - while (cmds) { - PurpleCmdId id = GPOINTER_TO_UINT(cmds->data); - purple_cmd_unregister(id); - cmds = g_slist_delete_link(cmds, cmds); - } -} - -static PurpleAccount *find_acct(const char *protocol, const char *acct_id) -{ - PurpleAccount *acct = NULL; - - /* If we have a specific acct, use it */ - if (acct_id) { - acct = purple_accounts_find(acct_id, protocol); - 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(protocol, 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_protocol_get_id(yahoo_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"); - - PurpleIMConversation *im = purple_conversations_find_im_with_account( - sname, acct); - if (im == NULL) - im = purple_im_conversation_new(acct, sname); - purple_conversation_present(PURPLE_CONVERSATION(im)); - - if (message) { - /* Spaces are encoded as '+' */ - g_strdelimit(message, "+", ' '); - purple_conversation_send_confirm(PURPLE_CONVERSATION(im), 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")); - purple_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 PurpleWhiteboardOps yahoo_whiteboard_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 void -yahoo_protocol_init(PurpleProtocol *protocol) -{ - PurpleAccountOption *option; - - protocol->id = "prpl-yahoo"; - protocol->name = "Yahoo"; - protocol->options = OPT_PROTO_MAIL_CHECK | OPT_PROTO_CHAT_TOPIC | - OPT_PROTO_AUTHORIZATION_DENIED_MESSAGE; - protocol->icon_spec = purple_buddy_icon_spec_new("png,gif,jpeg", - 96, 96, 96, 96, 0, - PURPLE_ICON_SCALE_SEND); - - protocol->whiteboard_ops = &yahoo_whiteboard_ops; - - option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOO_XFER_HOST); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOO_ROOMLIST_LOCALE); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8"); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE); - protocol->account_options = g_list_append(protocol->account_options, option); - -#if 0 - option = purple_account_option_bool_new(_("Use account proxy for HTTP and HTTPS connections"), "proxy_ssl", FALSE); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Chat room list URL"), "room_list", YAHOO_ROOMLIST_URL); - protocol->account_options = g_list_append(protocol->account_options, option); -#endif -} - -static void -yahoo_protocol_class_init(PurpleProtocolClass *klass) -{ - klass->login = yahoo_login; - klass->close = yahoo_close; - klass->status_types = yahoo_status_types; - klass->list_icon = yahoo_list_icon; -} - -static void -yahoo_protocol_client_iface_init(PurpleProtocolClientIface *client_iface) -{ - client_iface->get_actions = yahoo_get_actions; - client_iface->list_emblem = yahoo_list_emblem; - client_iface->status_text = yahoo_status_text; - client_iface->tooltip_text = yahoo_tooltip_text; - client_iface->blist_node_menu = yahoo_blist_node_menu; - client_iface->normalize = purple_normalize_nocase; - client_iface->offline_message = yahoo_offline_message; - client_iface->get_account_text_table = yahoo_get_account_text_table; - client_iface->get_max_message_size = yahoo_get_max_message_size; -} - -static void -yahoo_protocol_server_iface_init(PurpleProtocolServerIface *server_iface) -{ - server_iface->get_info = yahoo_get_info; - server_iface->set_status = yahoo_set_status; - server_iface->set_idle = yahoo_set_idle; - server_iface->add_buddy = yahoo_add_buddy; - server_iface->remove_buddy = yahoo_remove_buddy; - server_iface->keepalive = yahoo_keepalive; - server_iface->alias_buddy = yahoo_update_alias; - server_iface->group_buddy = yahoo_change_buddys_group; - server_iface->rename_group = yahoo_rename_group; - server_iface->set_buddy_icon = yahoo_set_buddy_icon; -} - -static void -yahoo_protocol_im_iface_init(PurpleProtocolIMIface *im_iface) -{ - im_iface->send = yahoo_send_im; - im_iface->send_typing = yahoo_send_typing; -} - -static void -yahoo_protocol_chat_iface_init(PurpleProtocolChatIface *chat_iface) -{ - chat_iface->info = yahoo_c_info; - chat_iface->info_defaults = yahoo_c_info_defaults; - chat_iface->join = yahoo_c_join; - chat_iface->get_name = yahoo_get_chat_name; - chat_iface->invite = yahoo_c_invite; - chat_iface->leave = yahoo_c_leave; - chat_iface->send = yahoo_c_send; -} - -static void -yahoo_protocol_privacy_iface_init(PurpleProtocolPrivacyIface *privacy_iface) -{ - privacy_iface->add_deny = yahoo_add_deny; - privacy_iface->rem_deny = yahoo_rem_deny; - privacy_iface->set_permit_deny = yahoo_set_permit_deny; -} - -static void -yahoo_protocol_roomlist_iface_init(PurpleProtocolRoomlistIface *roomlist_iface) -{ - roomlist_iface->get_list = yahoo_roomlist_get_list; - roomlist_iface->cancel = yahoo_roomlist_cancel; - roomlist_iface->expand_category = yahoo_roomlist_expand_category; -} - -static void -yahoo_protocol_attention_iface_init(PurpleProtocolAttentionIface *attention_iface) -{ - attention_iface->send = yahoo_send_attention; - attention_iface->get_types = yahoo_attention_types; -} - -static void -yahoo_protocol_xfer_iface_init(PurpleProtocolXferIface *xfer_iface) -{ - xfer_iface->can_receive = yahoo_can_receive_file; - xfer_iface->send = yahoo_send_file; - xfer_iface->new_xfer = yahoo_new_xfer; -} - -PURPLE_DEFINE_TYPE_EXTENDED( - YahooProtocol, yahoo_protocol, PURPLE_TYPE_PROTOCOL, 0, - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CLIENT_IFACE, - yahoo_protocol_client_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_SERVER_IFACE, - yahoo_protocol_server_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_IM_IFACE, - yahoo_protocol_im_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CHAT_IFACE, - yahoo_protocol_chat_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_PRIVACY_IFACE, - yahoo_protocol_privacy_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ROOMLIST_IFACE, - yahoo_protocol_roomlist_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_ATTENTION_IFACE, - yahoo_protocol_attention_iface_init) - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_XFER_IFACE, - yahoo_protocol_xfer_iface_init) -); - -static PurplePluginInfo * -plugin_query(GError **error) -{ - return purple_plugin_info_new( - "id", "prpl-yahoo", - "name", "Yahoo Protocols", - "version", DISPLAY_VERSION, - "category", N_("Protocol"), - "summary", N_("Yahoo! and Yahoo! JAPAN Protocols Plugin"), - "description", N_("Yahoo! and Yahoo! JAPAN Protocols Plugin"), - "website", PURPLE_WEBSITE, - "abi-version", PURPLE_ABI_VERSION, - "flags", PURPLE_PLUGIN_INFO_FLAGS_INTERNAL | - PURPLE_PLUGIN_INFO_FLAGS_AUTO_LOAD, - NULL - ); -} - -static gboolean -plugin_load(PurplePlugin *plugin, GError **error) -{ - yahoo_protocol_register_type(plugin); - - yahoo_protocol = purple_protocols_add(YAHOO_TYPE_PROTOCOL, error); - if (!yahoo_protocol) - return FALSE; - - yahoo_init_colorht(); - - yahoo_register_commands(); - - purple_signal_connect(purple_get_core(), "uri-handler", yahoo_protocol, - PURPLE_CALLBACK(yahoo_uri_handler), NULL); - - return TRUE; -} - -static gboolean -plugin_unload(PurplePlugin *plugin, GError **error) -{ - yahoo_unregister_commands(); - - yahoo_dest_colorht(); - - if (!purple_protocols_remove(yahoo_protocol, error)) - return FALSE; - - return TRUE; -} - -PURPLE_PLUGIN_INIT(yahoo, plugin_query, plugin_load, plugin_unload);
--- a/libpurple/protocols/yahoo/yahoo.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,51 +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_H_ -#define _YAHOO_H_ - -#include <gmodule.h> - -#include "protocol.h" - -#define YAHOO_TYPE_PROTOCOL (yahoo_protocol_get_type()) -#define YAHOO_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), YAHOO_TYPE_PROTOCOL, YahooProtocol)) -#define YAHOO_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), YAHOO_TYPE_PROTOCOL, YahooProtocolClass)) -#define YAHOO_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), YAHOO_TYPE_PROTOCOL)) -#define YAHOO_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), YAHOO_TYPE_PROTOCOL)) -#define YAHOO_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), YAHOO_TYPE_PROTOCOL, YahooProtocolClass)) - -typedef struct _YahooProtocol -{ - PurpleProtocol parent; -} YahooProtocol; - -typedef struct _YahooProtocolClass -{ - PurpleProtocolClass parent_class; -} YahooProtocolClass; - -/** - * Returns the GType for the YahooProtocol object. - */ -G_MODULE_EXPORT GType yahoo_protocol_get_type(void); - -#endif /* _YAHOO_H_ */
--- a/libpurple/protocols/yahoo/yahoojp.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,131 +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 <plugins.h> - -#include "yahoojp.h" -#include "ymsg.h" -#include "yahoochat.h" -#include "yahoo_aliases.h" -#include "yahoo_doodle.h" -#include "yahoo_filexfer.h" -#include "yahoo_picture.h" - -static GSList *cmds = NULL; - -void yahoojp_register_commands(void) -{ - PurpleCmdId id; - - id = purple_cmd_register("join", "s", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoojp", yahoopurple_cmd_chat_join, - _("join <room>: Join a chat room on the Yahoo network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("list", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_CHAT | - PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoojp", yahoopurple_cmd_chat_list, - _("list: List rooms on the Yahoo network"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("buzz", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoojp", yahoopurple_cmd_buzz, - _("buzz: Buzz a user to get their attention"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); - - id = purple_cmd_register("doodle", "", PURPLE_CMD_P_PROTOCOL, - PURPLE_CMD_FLAG_IM | PURPLE_CMD_FLAG_PROTOCOL_ONLY, - "prpl-yahoojp", yahoo_doodle_purple_cmd_start, - _("doodle: Request user to start a Doodle session"), NULL); - cmds = g_slist_prepend(cmds, GUINT_TO_POINTER(id)); -} - -void yahoojp_unregister_commands(void) -{ - while (cmds) { - PurpleCmdId id = GPOINTER_TO_UINT(cmds->data); - purple_cmd_unregister(id); - cmds = g_slist_delete_link(cmds, cmds); - } -} - -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 void -yahoojp_protocol_init(PurpleProtocol *protocol) -{ - PurpleAccountOption *option; - - protocol->id = "prpl-yahoojp"; - protocol->name = "Yahoo JAPAN"; - - /* delete yahoo's protocol options */ - purple_protocol_override(protocol, PURPLE_PROTOCOL_OVERRIDE_PROTOCOL_OPTIONS); - - option = purple_account_option_int_new(_("Pager port"), "port", YAHOO_PAGER_PORT); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("File transfer server"), "xfer_host", YAHOOJP_XFER_HOST); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Chat room locale"), "room_list_locale", YAHOOJP_ROOMLIST_LOCALE); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_string_new(_("Encoding"), "local_charset", "UTF-8"); - protocol->account_options = g_list_append(protocol->account_options, option); - - option = purple_account_option_bool_new(_("Ignore conference and chatroom invitations"), "ignore_invites", FALSE); - protocol->account_options = g_list_append(protocol->account_options, option); -} - -static void -yahoojp_protocol_class_init(PurpleProtocolClass *klass) -{ -} - -static void -yahoojp_protocol_client_iface_init(PurpleProtocolClientIface *client_iface) -{ - client_iface->get_account_text_table = yahoojp_get_account_text_table; -} - -PURPLE_DEFINE_TYPE_EXTENDED( - YahooJPProtocol, yahoojp_protocol, YAHOO_TYPE_PROTOCOL, 0, - - PURPLE_IMPLEMENT_INTERFACE_STATIC(PURPLE_TYPE_PROTOCOL_CLIENT_IFACE, - yahoojp_protocol_client_iface_init) -);
--- a/libpurple/protocols/yahoo/yahoojp.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,57 +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 _YAHOOJP_H_ -#define _YAHOOJP_H_ - -#include "yahoo.h" - -#define YAHOOJP_TYPE_PROTOCOL (yahoojp_protocol_get_type()) -#define YAHOOJP_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj), YAHOOJP_TYPE_PROTOCOL, YahooJPProtocol)) -#define YAHOOJP_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass), YAHOOJP_TYPE_PROTOCOL, YahooJPProtocolClass)) -#define YAHOOJP_IS_PROTOCOL(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj), YAHOOJP_TYPE_PROTOCOL)) -#define YAHOOJP_IS_PROTOCOL_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass), YAHOOJP_TYPE_PROTOCOL)) -#define YAHOOJP_PROTOCOL_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS((obj), YAHOOJP_TYPE_PROTOCOL, YahooJPProtocolClass)) - -typedef struct _YahooJPProtocol -{ - YahooProtocol parent; -} YahooJPProtocol; - -typedef struct _YahooJPProtocolClass -{ - YahooProtocolClass parent_class; -} YahooJPProtocolClass; - -/** - * Registers the YahooJPProtocol type in the type system. - */ -void yahoojp_protocol_register_type(PurplePlugin *plugin); - -/** - * Returns the GType for the YahooJPProtocol object. - */ -G_MODULE_EXPORT GType yahoojp_protocol_get_type(void); - -void yahoojp_register_commands(void); -void yahoojp_unregister_commands(void); - -#endif /* _YAHOOJP_H_ */
--- a/libpurple/protocols/yahoo/ymsg.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4989 +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 - * - */ - -/* - * Note: When handling the list of struct yahoo_pair's from an incoming - * packet the value might not be UTF-8. You should either validate that - * it is UTF-8 using g_utf8_validate() or use yahoo_string_decode(). - */ - -#include "internal.h" - -#include "account.h" -#include "accountopt.h" -#include "buddylist.h" -#include "ciphers/md5hash.h" -#include "cmds.h" -#include "core.h" -#include "debug.h" -#include "http.h" -#include "network.h" -#include "notify.h" -#include "protocol.h" -#include "proxy.h" -#include "request.h" -#include "server.h" -#include "util.h" -#include "version.h" -#include "xmlnode.h" - -#include "ymsg.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 */ - -/* It doesn't look like it is working (the previously used host is down, another - * one doesn't send us back cookies). - */ -#define TRY_WEBMESSENGER_LOGIN 0 - -/* One hour */ -#define PING_TIMEOUT 3600 - -/* One minute */ -#define KEEPALIVE_TIMEOUT 60 - -#if TRY_WEBMESSENGER_LOGIN -static void -yahoo_login_page_cb(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _unused); -#endif /* TRY_WEBMESSENGER_LOGIN */ - -static void yahoo_update_status(PurpleConnection *gc, const char *name, YahooFriend *f) -{ - char *status = NULL; - - if (!gc || !name || !f || !purple_blist_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_protocol_got_user_status(purple_connection_get_account(gc), name, status, "message", - yahoo_friend_get_status_message(f), NULL); - else - purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, NULL); - } - - if (f->idle != 0) - purple_protocol_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle); - else - purple_protocol_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0); - - if (f->sms) - purple_protocol_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL); - else - purple_protocol_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; - - if (pkt->service == YAHOO_SERVICE_LOGOFF && pkt->status == -1) { - if (!purple_account_get_remember_password(account)) - purple_account_set_password(account, NULL, NULL, NULL); - purple_connection_error(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)) { - name = pair->value; - f = yahoo_friend_find_or_new(gc, name); - } - 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_protocol_got_user_status(account, name, "offline", NULL); - purple_protocol_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_blist_find_buddy(purple_connection_get_account(gc), name); - - if (!cksum || (cksum == -1)) { - if (f) - yahoo_friend_set_buddy_icon_need_request(f, TRUE); - purple_buddy_icons_set_for_user(purple_connection_get_account(gc), 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, - purple_request_cpar_from_connection(gc)); - 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; - 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); - } -} - -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_blist_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_blist_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') { - g_free(yd->cookie_y); - yd->cookie_y = _getcookie(c); - } else if (c[0] == '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 = purple_connection_get_protocol_data(gc); - 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? */ - 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) { - norm_bud = g_strdup(temp); - - if (yd->current_list15_grp) { - /* This buddy is in a group */ - f = yahoo_friend_find_or_new(gc, norm_bud); - if (!purple_blist_find_buddy(account, norm_bud)) { - PurpleBuddy *b; - PurpleGroup *g; - if (!(g = purple_blist_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(stealth == 2) - f->presence = YAHOO_PRESENCE_PERM_OFFLINE; - - yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED); - f->p2p_packet_sent = 0; - } 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", purple_account_get_username(account), norm_bud); - purple_account_privacy_deny_add(account, norm_bud, 1); - } - - g_free(norm_bud); - norm_bud=NULL; - 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 */ - if (g_utf8_validate(pair->value, -1, NULL)) { - g_free(temp); - temp = g_strdup(purple_normalize(account, pair->value)); - } else { - purple_debug_warning("yahoo", "yahoo_process_list_15 " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 59: /* somebody told cookies come here too, but im not sure */ - if (g_utf8_validate(pair->value, -1, NULL)) { - yahoo_process_cookie(yd, pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_process_list_15 " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 317: /* Stealth Setting */ - stealth = strtol(pair->value, NULL, 10); - 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_CONNECTION_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 got_serv_list = FALSE; - YahooFriend *f = NULL; - PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = purple_connection_get_protocol_data(gc); - 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 (g_utf8_validate(pair->value, -1, NULL)) { - if (!yd->tmp_serv_ilist) - yd->tmp_serv_ilist = g_string_new(pair->value); - else - g_string_append(yd->tmp_serv_ilist, pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_process_list " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 89: - if (g_utf8_validate(pair->value, -1, NULL)) { - yd->profiles = g_strsplit(pair->value, ",", -1); - } else { - purple_debug_warning("yahoo", "yahoo_process_list " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 59: /* cookies, yum */ - if (g_utf8_validate(pair->value, -1, NULL)) { - yahoo_process_cookie(yd, pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_process_list " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case YAHOO_SERVICE_PRESENCE_PERM: - if (g_utf8_validate(pair->value, -1, NULL)) { - if (!yd->tmp_serv_plist) - yd->tmp_serv_plist = g_string_new(pair->value); - else - g_string_append(yd->tmp_serv_plist, pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_process_list " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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++) { - if (!g_utf8_validate(*bud, -1, NULL)) { - purple_debug_warning("yahoo", "yahoo_process_list " - "got non-UTF-8 string for bud\n"); - continue; - } - - norm_bud = g_strdup(purple_normalize(account, *bud)); - f = yahoo_friend_find_or_new(gc, norm_bud); - - if (!purple_blist_find_buddy(account, norm_bud)) { - PurpleBuddy *b; - PurpleGroup *g; - if (!(g = purple_blist_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); - } - - 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_account_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 && - ((purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST) && - (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_DENY_ALL) && - (purple_account_get_privacy_type(account) != PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS))) - { - purple_account_set_privacy_type(account, PURPLE_ACCOUNT_PRIVACY_DENY_USERS); - purple_debug_info("yahoo", "%s privacy defaulting to PURPLE_ACCOUNT_PRIVACY_DENY_USERS.\n", - purple_account_get_username(account)); - } - - 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", - purple_account_get_username(account), *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 = purple_connection_get_protocol_data(gc); - - account = purple_connection_get_account(gc); - - while (l) { - struct yahoo_pair *pair = l->data; - if (pair->key == 4 || pair->key == 1) { - if (g_utf8_validate(pair->value, -1, NULL)) { - from = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_notify " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 49) { - msg = pair->value; - } else if (pair->key == 13) { - stat = pair->value; - } else if (pair->key == 14) { - if (g_utf8_validate(pair->value, -1, NULL)) { - game = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_notify " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 11) { - val_11 = 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_account_privacy_check(account, from))) - { - - if (stat && *stat == '1') - purple_serv_got_typing(gc, from, 0, PURPLE_IM_TYPING); - else - purple_serv_got_typing_stopped(gc, from); - - } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) { - PurpleBuddy *bud = purple_blist_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"))) { - PurpleIMConversation *im = purple_conversations_find_im_with_account(from, account); - char *buf = g_strdup_printf(_("%s has sent you a webcam invite, which is not yet supported."), from); - purple_conversation_write_system_message(PURPLE_CONVERSATION(im), - buf, PURPLE_MESSAGE_NOTIFY); - g_free(buf); - } -} - - -struct _yahoo_im { - char *from; - char *active_id; - int time; - int utf8; - int buddy_icon; - char *id; - char *msg; -}; - -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 = purple_connection_get_protocol_data(gc); - account = purple_connection_get_account(gc); - - while (l != NULL) { - struct yahoo_pair *pair = l->data; - if (pair->key == 4) { - if (g_utf8_validate(pair->value, -1, NULL)) { - sms = g_new0(struct _yahoo_im, 1); - sms->from = g_strdup_printf("+%s", pair->value); - sms->time = time(NULL); - sms->utf8 = TRUE; - } else { - purple_debug_warning("yahoo", "yahoo_process_sms_message " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 14) { - if (sms) - sms->msg = pair->value; - } else if (pair->key == 68) { - if(sms) - g_hash_table_insert(yd->sms_carrier, g_strdup(sms->from), g_strdup(pair->value)); - } else if (pair->key == 16) { - if (g_utf8_validate(pair->value, -1, NULL)) { - server_msg = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_sms_message " - "got non-UTF-8 string for key %d\n", pair->key); - } - } - l = l->next; - } - - if(!sms) { - purple_debug_info("yahoo", "Received a malformed SMS packet!\n"); - return; - } - - if ((int)pkt->status < 0) - pkt->status = YAHOO_STATUS_DISCONNECTED; - if (pkt->status == YAHOO_STATUS_DISCONNECTED) { - if (server_msg) { - PurpleIMConversation *im; - im = purple_conversations_find_im_with_account(sms->from, account); - if (im == NULL) - im = purple_im_conversation_new(account, sms->from); - purple_conversation_write_system_message(PURPLE_CONVERSATION(im), - server_msg, 0); - } - else { - purple_notify_error(gc, NULL, - _("Your SMS was not delivered"), NULL, - purple_request_cpar_from_connection(gc)); - } - - 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); - purple_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 = purple_connection_get_protocol_data(gc); - 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) { - if (g_utf8_validate(pair->value, -1, NULL)) { - im = g_new0(struct _yahoo_im, 1); - list = g_slist_append(list, im); - im->from = pair->value; - im->time = time(NULL); - im->utf8 = TRUE; - } else { - purple_debug_warning("yahoo", "yahoo_process_message " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (im && pair->key == 5) { - im->active_id = pair->value; - } else if (pair->key == 97) { - if (im) - im->utf8 = strtol(pair->value, NULL, 10); - } else if (pair->key == 15) { - if (im) - im->time = strtol(pair->value, NULL, 10); - } else if (pair->key == 206) { - if (im) - im->buddy_icon = strtol(pair->value, NULL, 10); - } else if (pair->key == 14) { - if (im) - im->msg = pair->value; - } else if (im && (pair->key == 11)) { - /* peer session id */ - /* disconnect the peer if connected through p2p and sends wrong value for session id */ - if( (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->from); - /* remove from p2p connection lists, also calls yahoo_p2p_disconnect_destroy_data */ - g_hash_table_remove(yd->peers, im->from); - g_free(im); - return; /* Not sure whether we should process remaining IMs in this packet */ - } - - } else if (im && pair->key == 63 && g_utf8_validate(pair->value, -1, NULL)) { - /* IMV key */ - /* Check for the Doodle IMV */ - if (im->from != NULL) - { - g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value)); - - if (strstr(pair->value, "doodle;") != NULL) - { - PurpleWhiteboard *wb; - - if (!purple_account_privacy_check(account, im->from)) { - purple_debug_info("yahoo", "Doodle request from %s dropped.\n", - im->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_new(account, im->from, - DOODLE_STATE_REQUESTED); - ds = purple_whiteboard_get_protocol_data(wb); - 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); - } - } - } - } else 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, - purple_request_cpar_from_connection(gc)); - } - - for (l = list; l; l = l->next) { - char *m, *m2; - im = l->data; - - if (!im->msg) { - g_free(im); - continue; - } - - if (!purple_account_privacy_check(account, im->from)) { - purple_debug_info("yahoo", "Message from %s dropped.\n", im->from); - return; - } - - /* - * TODO: Is there anything else we should check when determining whether - * we should send an acknowledgement? - */ - if (im->id != NULL) { - /* Send acknowledgement. If we don't do this then the official - * Yahoo Messenger client for Windows will send us the same - * message 7 seconds later as an offline message. This is true - * for at least version 9.0.0.2162 on Windows XP. */ - struct yahoo_packet *pkt2; - pkt2 = yahoo_packet_new(YAHOO_SERVICE_MESSAGE_ACK, - YAHOO_STATUS_AVAILABLE, pkt->id); - yahoo_packet_hash(pkt2, "ssisii", - 1, im->active_id, /* May not always be the connection's display name */ - 5, im->from, - 302, 430, - 430, im->id, - 303, 430, - 450, 0); - yahoo_packet_send_and_free(pkt2, yd); - } - - m = yahoo_string_decode(gc, im->msg, im->utf8); - /* This may actually not be necessary, but it appears - * that at least at one point some clients were sending - * "\r\n" as line delimiters, so we want to avoid double - * lines. */ - m2 = purple_strreplace(m, "\r\n", "\n"); - g_free(m); - m = m2; - purple_util_chrreplace(m, '\r', '\n'); - if (!strcmp(m, "<ding>")) { - char *username; - - username = g_markup_escape_text(im->from, -1); - purple_protocol_got_attention(gc, username, YAHOO_BUZZ); - g_free(username); - g_free(m); - g_free(im); - continue; - } - - m2 = yahoo_codes_to_html(m); - g_free(m); - - purple_serv_got_im(gc, im->from, m2, 0, im->time); - g_free(m2); - 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) { - if (g_utf8_validate(pair->value, -1, NULL)) { - me = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_sysmessage " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 14) { - if (g_utf8_validate(pair->value, -1, NULL)) { - msg = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_sysmessage " - "got non-UTF-8 string for key %d\n", pair->key); - } - } - - 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, - purple_request_cpar_from_connection(gc)); - g_free(prim); -} - -struct yahoo_add_request { - PurpleConnection *gc; - char *id; - char *who; -}; - -static void -yahoo_buddy_add_authorize_cb(const char *message, gpointer data) -{ - struct yahoo_add_request *add_req = data; - struct yahoo_packet *pkt; - YahooData *yd = purple_connection_get_protocol_data(add_req->gc); - const char *who = add_req->who; - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, YAHOO_STATUS_AVAILABLE, yd->session_id); - 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(const char *msg, gpointer data) -{ - struct yahoo_add_request *add_req = data; - YahooData *yd = purple_connection_get_protocol_data(add_req->gc); - 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, FALSE); - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH_REQ_15, - YAHOO_STATUS_AVAILABLE, yd->session_id); - - yahoo_packet_hash(pkt, "ssiiis", - 1, add_req->id, - 5, who, - 13, 2, - 334, 0, - 97, 1, /* UTF-8 */ - 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_denied_our_add(PurpleConnection *gc, const char *who, const char *reason) -{ - char *notify_msg; - YahooData *yd = purple_connection_get_protocol_data(gc); - - 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, - purple_request_cpar_from_connection(gc)); - g_free(notify_msg); - - g_hash_table_remove(yd->friends, who); - purple_protocol_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 *who = NULL; - int response = 0; - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - break; - case 13: - response = strtol(pair->value, NULL, 10); - break; - case 14: - msg = pair->value; - break; - } - l = l->next; - } - - 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; - - 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 4: - break; - case 5: - if (g_utf8_validate(pair->value, -1, NULL)) { - add_req->id = g_strdup(pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 14: - msg = pair->value; - break; - case 216: - if (g_utf8_validate(pair->value, -1, NULL)) { - firstname = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 254: - if (g_utf8_validate(pair->value, -1, NULL)) { - lastname = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - - } - l = l->next; - } - - if (add_req->id && add_req->who) { - char *alias = NULL, *dec_msg = NULL; - - if (!purple_account_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(NULL, add_req); - 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_blist_find_buddy(account, add_req->who) != NULL, - yahoo_buddy_add_authorize_cb, - yahoo_buddy_add_deny_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: - if (g_utf8_validate(pair->value, -1, NULL)) { - add_req->id = g_strdup(pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_buddy_added_us " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 3: - if (g_utf8_validate(pair->value, -1, NULL)) { - add_req->who = g_strdup(pair->value); - } else { - purple_debug_warning("yahoo", "yahoo_buddy_added_us " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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_account_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(NULL, add_req); - 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_blist_find_buddy(account,add_req->who) != NULL, - yahoo_buddy_add_authorize_cb, - yahoo_buddy_add_deny_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: - if (g_utf8_validate(pair->value, -1, NULL)) { - who = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 14: - if (g_utf8_validate(pair->value, -1, NULL)) { - msg = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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'; - - /* XXX: Is this related to Yahoo! Japan? If so, it should be removed. -mmcco */ - 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); - const char *who = NULL; - const char *email = NULL; - const char *subj = NULL; - const char *yahoo_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) { - if (g_utf8_validate(pair->value, -1, NULL)) { - who = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_mail " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 42) { - if (g_utf8_validate(pair->value, -1, NULL)) { - email = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_mail " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else if (pair->key == 18) { - if (g_utf8_validate(pair->value, -1, NULL)) { - subj = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_mail " - "got non-UTF-8 string for key %d\n", pair->key); - } - } - 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 = purple_connection_get_protocol_data(gc); - PurpleAccount *account = purple_connection_get_account(gc); - const char *name = purple_normalize(account, purple_account_get_username(account)); - PurpleHash *md5_hash; - guchar md5_digest[16]; - gchar base64_string[25]; - struct yahoo_packet *pkt; - - purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage3\n"); - - g_return_if_fail(crypt != NULL); - - md5_hash = purple_md5_hash_new(); - purple_hash_append(md5_hash, (guchar *)crypt, strlen(crypt)); - purple_hash_digest(md5_hash, md5_digest, sizeof(md5_digest)); - - 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, YAHOO_CLIENT_VERSION_ID, - 2, name, - 2, "1", - 59, yd->cookie_b, - 98, purple_account_get_string(account, "room_list_locale", "us"), - 135, 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, YAHOO_CLIENT_VERSION_ID, - 2, name, - 2, "1", - 98, purple_account_get_string(account, "room_list_locale", "us"), - 135, YAHOO_CLIENT_VERSION); - } - - if (yd->picture_checksum) - yahoo_packet_hash_int(pkt, 192, yd->picture_checksum); - yahoo_packet_send_and_free(pkt, yd); - - g_object_unref(md5_hash); -} - -static void yahoo_auth16_stage2(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _auth_data) -{ - struct yahoo_auth_data *auth_data = _auth_data; - PurpleConnection *gc = auth_data->gc; - YahooData *yd = purple_connection_get_protocol_data(gc); - - int i; - gchar **splits; - int response_no = -1; - char *crumb = NULL; - char *crypt = NULL; - PurpleHttpCookieJar *cookiejar; - - purple_debug_info("yahoo","Authentication: In yahoo_auth16_stage2\n"); - - if (!purple_http_response_is_successful(response)) { - const gchar *error_message = purple_http_response_get_error(response); - purple_debug_error("yahoo", "Login Failed, unable to retrieve stage 2 url: %s\n", error_message); - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); - g_free(auth_data->seed); - g_free(auth_data); - return; - } - - splits = g_strsplit(purple_http_response_get_data(response, NULL), - "\r\n", -1); - - cookiejar = purple_http_conn_get_cookie_jar(http_conn); - yd->cookie_b = purple_http_cookie_jar_get(cookiejar, "B"); - yd->cookie_t = purple_http_cookie_jar_get(cookiejar, "T"); - yd->cookie_y = purple_http_cookie_jar_get(cookiejar, "Y"); - - i = 0; - while (splits[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 (i == 0 && g_ascii_isdigit(splits[i][0])) { - response_no = strtol(splits[i], NULL, 10); - purple_debug_info("yahoo", "Got auth16 stage 2 response code: %d\n", - response_no); - } else if (strncmp(splits[i], "crumb=", 6) == 0) { - crumb = g_strdup(&splits[i][6]); - - if (purple_debug_is_unsafe()) - purple_debug_info("yahoo", "Got crumb: %s\n", crumb); - } - i++; - } - - g_strfreev(splits); - - if (crumb == NULL) - response_no = -1; - - 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)) { -#if 0 - try_login_on_error = TRUE; -#endif - 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(gc, error, error_reason); - g_free(error_reason); - g_free(crumb); - 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(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _auth_data) -{ - struct yahoo_auth_data *auth_data = _auth_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"); - - if (!purple_http_response_is_successful(response)) { - const gchar *error_message = purple_http_response_get_error(response); - purple_debug_error("yahoo", "Login Failed, unable to retrieve login url: %s\n", error_message); - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, error_message); - g_free(auth_data->seed); - g_free(auth_data); - return; - } else { - PurpleAccount *account = purple_connection_get_account(gc); - gchar **split_data = g_strsplit(purple_http_response_get_data( - response, NULL), "\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, NULL, 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(gc, error, error_reason); - g_free(error_reason); - g_free(auth_data->seed); - g_free(auth_data); - g_free(token); - } - else { - PurpleHttpRequest *req; - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, YAHOO_LOGIN_URL, token); - purple_http_request_header_set(req, "User-Agent", - YAHOO_CLIENT_USERAGENT); - purple_http_connection_set_add(yd->http_reqs, - purple_http_request(gc, req, - yahoo_auth16_stage2, auth_data)); - purple_http_request_unref(req); - - g_free(token); - } - } -} - -static void yahoo_auth16_stage1(PurpleConnection *gc, const char *seed) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleHttpRequest *req; - struct yahoo_auth_data *auth_data = NULL; - char *encoded_username; - char *encoded_password; - - purple_debug_info("yahoo", "Authentication: In yahoo_auth16_stage1\n"); - - 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))); - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, YAHOO_TOKEN_URL, - encoded_username, encoded_password, purple_url_encode(seed)); - purple_http_request_header_set(req, "User-Agent", YAHOO_CLIENT_USERAGENT); - purple_http_connection_set_add(yd->http_reqs, purple_http_request(gc, - req, yahoo_auth16_stage1_cb, auth_data)); - purple_http_request_unref(req); - - purple_str_wipe(encoded_password); - g_free(encoded_username); -} - -static void yahoo_process_auth(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - char *seed = NULL; - GSList *l = pkt->hash; - int m = 0; - gchar *buf; - - while (l) { - struct yahoo_pair *pair = l->data; - /* (pair->key == 1) -> sn */ - if (pair->key == 94) { - if (g_utf8_validate(pair->value, -1, NULL)) { - seed = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_auth " - "got non-UTF-8 string for key %d\n", pair->key); - } - } else 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, - purple_request_cpar_from_connection(gc)); - 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); - - purple_serv_add_deny(purple_account_get_connection(account), name); - - g_free(name); -} - -static void keep_buddy(PurpleBuddy *b) -{ - purple_account_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 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: - if (g_utf8_validate(pair->value, -1, NULL)) { - who = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_ignore " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - /* 1 -> me */ - 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_blist_find_buddy(purple_connection_get_account(gc), 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, - purple_request_cpar_from_connection(gc), - 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; - } -} - -#if TRY_WEBMESSENGER_LOGIN - -static gboolean -yahoo_try_webmessenger_login(PurpleConnection *gc) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleHttpRequest *req; - - if (yd->wm) - return FALSE; - - yd->wm = TRUE; - if (yd->fd >= 0) - close(yd->fd); - if (yd->inpa) { - purple_input_remove(yd->inpa); - yd->inpa = 0; - } - - req = purple_http_request_new(WEBMESSENGER_URL); - purple_http_request_header_set(req, "User-Agent", "Purple/" VERSION); - purple_http_connection_set_add(yd->http_reqs, purple_http_request(gc, - req, yahoo_login_page_cb, NULL)); - purple_http_request_unref(req); - - return TRUE; -} - -#endif /* TRY_WEBMESSENGER_LOGIN */ - -static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt) -{ - GSList *l = pkt->hash; - int err = 0; - char *msg; - char *url = NULL; - char *fullmsg; - PurpleAccount *account = purple_connection_get_account(gc); - 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) { - if (g_utf8_validate(pair->value, -1, NULL)) { - url = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_authresp " - "got non-UTF-8 string for key %d\n", pair->key); - } - } - - 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: -#if TRY_WEBMESSENGER_LOGIN - if (yahoo_try_webmessenger_login(gc)) - return; -#else - purple_debug_info("yahoo", "Web messenger login is disabled\n"); -#endif /* TRY_WEBMESSENGER_LOGIN */ - if (!purple_account_get_remember_password(account)) - purple_account_set_password(account, NULL, NULL, 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(_("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(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 = purple_connection_get_protocol_data(gc); - - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 66: - err = strtol(pair->value, NULL, 10); - break; - case 7: - if (g_utf8_validate(pair->value, -1, NULL)) { - temp = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_addbuddy " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 65: - group = pair->value; - break; - } - - l = l->next; - } - - if (!temp) - return; - if (!group) - group = ""; - - who = g_strdup(temp); - - 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); - - if( !g_hash_table_lookup(yd->peers, who) ) { - /* we are not connected as client, so set friend to not connected */ - 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_conversation_present_error(who, purple_connection_get_account(gc), buf)) - purple_notify_error(gc, NULL, _("Unable to add buddy to server list"), buf, - purple_request_cpar_from_connection(gc)); - 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; - gssize written; - guchar *raw_packet; - - /*build the raw packet and send it to the host*/ - pkt_len = yahoo_packet_build(pkt, 0, 0, &raw_packet); - written = write(source, raw_packet, pkt_len); - if (written < 0 || (gsize)written != 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 = purple_connection_get_protocol_data(gc); - - 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 = purple_connection_get_protocol_data(gc); - - 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 = purple_connection_get_protocol_data(p2p_data->gc); - - /* lets see whats in the packet */ - while (l) { - struct yahoo_pair *pair = l->data; - - switch (pair->key) { - case 4: - if (g_utf8_validate(pair->value, -1, NULL)) { - 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; - } - } else { - purple_debug_warning("yahoo", "yahoo_p2p_process_p2pfilexfer " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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; - struct yahoo_p2p_data *p2p_data; - YahooData *yd; - - if(!(p2p_data = data)) - return ; - yd = purple_connection_get_protocol_data(p2p_data->gc); - - 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; - } - - /* TODO: It looks like there's a bug here (and above) where an incorrect - * assumtion is being made that the buffer will be added to when this - * is next called, but that's not really the case! */ - if(len < YAHOO_PACKET_HDRLEN) - return; - - if(strncmp((char *)buf, "YMSG", 4) != 0) { - /* Not a YMSG packet */ - purple_debug_warning("yahoo", "p2p: Got something other than YMSG packet\n"); - - start = (guchar *) g_strstr_len((char *) buf + 1, len - 1 ,"YMSG"); - if (start == NULL) { - /* 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; - } - purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n"); - - len -= (start - buf); - g_memmove(buf, start, len); - } - - pos += 4; /* YMSG */ - pos += 2; - pos += 2; - - pktlen = yahoo_get16(buf + pos); pos += 2; - if (len < (YAHOO_PACKET_HDRLEN + pktlen)) { - purple_debug_error("yahoo", "p2p: packet length(%d) > buffer length(%d)\n", - pktlen, (len - pos)); - /* 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; - } else - purple_debug_misc("yahoo", "p2p: %d bytes to read\n", pktlen); - - 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 = purple_connection_get_protocol_data(p2p_data->gc); - - 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 = purple_connection_get_protocol_data(p2p_data->gc); - - 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 = purple_connection_get_protocol_data(p2p_data->gc); - 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 = purple_connection_get_protocol_data(gc); - 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; - - /* 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, AF_UNSPEC, SOCK_STREAM, TRUE, 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 = purple_connection_get_protocol_data(p2p_data->gc); - - 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: - if (g_utf8_validate(pair->value, -1, NULL)) { - who = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_p2p " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 1: - /* who again, the master identity this time? */ - break; - case 12: - if (g_utf8_validate(pair->value, -1, NULL)) { - 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?*/ - } else { - purple_debug_warning("yahoo", "yahoo_process_p2p " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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: - if (g_utf8_validate(pair->value, -1, NULL)) { - who = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_audible " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 5: - /* us */ - break; - case 230: - /* the audible, in foo.locale.bar.baz format - eg: base.tw.smiley.smiley43 */ - if (g_utf8_validate(pair->value, -1, NULL)) { - id = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_audible " - "got non-UTF-8 string for key %d\n", pair->key); - } - break; - case 231: - /* the text of the audible */ - if (g_utf8_validate(pair->value, -1, NULL)) { - msg = pair->value; - } else { - purple_debug_warning("yahoo", "yahoo_process_audible " - "got non-UTF-8 string for key %d\n", pair->key); - } - 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_account_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); - - purple_serv_got_im(gc, who, buf, 0, time(NULL)); - g_free(buf); - } else - purple_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: - purple_debug_error("yahoo", "Legacy file transfers are not " - "supported anymore.\n"); - 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 = purple_connection_get_protocol_data(gc); - 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(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); - return; - } else if (len == 0) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Server closed the connection")); - return; - } - purple_connection_update_last_received(gc); - 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(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); - return; - } - - yd = purple_connection_get_protocol_data(gc); - yd->fd = source; - - pkt = yahoo_packet_new(YAHOO_SERVICE_AUTH, yd->current_status, yd->session_id); - - yahoo_packet_hash_str(pkt, 1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc)))); - yahoo_packet_send_and_free(pkt, yd); - - yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); -} - -#if 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(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp); - g_free(tmp); - return; - } - - yd = purple_connection_get_protocol_data(gc); - yd->fd = source; - - pkt = yahoo_packet_new(YAHOO_SERVICE_WEBLOGIN, YAHOO_STATUS_WEBLOGIN, yd->session_id); - - yahoo_packet_hash(pkt, "sss", 0, - purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))), - 1, purple_normalize(purple_connection_get_account(gc), purple_account_get_username(purple_connection_get_account(gc))), - 6, yd->auth); - yahoo_packet_send_and_free(pkt, yd); - - g_free(yd->auth); - yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc); -} - -static void -yahoo_login_page_got(PurpleHttpConnection *hc, PurpleHttpResponse *resp, - gpointer _unused) -{ - PurpleConnection *gc = purple_http_conn_get_purple_connection(hc); - YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleAccount *account = purple_connection_get_account(gc); - PurpleHttpCookieJar *cjar; - GString *auth_s; - gchar *cookie; - - if (purple_http_response_get_code(resp) != 302) { - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - return; - } - - auth_s = g_string_new(NULL); - cjar = purple_http_conn_get_cookie_jar(hc); - cookie = purple_http_cookie_jar_get(cjar, "B"); - if (cookie) { - g_string_append_printf(auth_s, "B=%s; ", cookie); - g_free(cookie); - } - cookie = purple_http_cookie_jar_get(cjar, "T"); - if (cookie) { - g_string_append_printf(auth_s, "T=%s; ", cookie); - g_free(cookie); - } - cookie = purple_http_cookie_jar_get(cjar, "Y"); - if (cookie) { - g_string_append_printf(auth_s, "Y=%s; ", cookie); - g_free(cookie); - } - - yd->auth = g_string_free(auth_s, FALSE); - /* Now we have our cookies to login with. I'll go get the milk. */ - - /* XXX: wcs2.msg.dcn.yahoo.com is down, so I used - * YAHOO_PAGER_HOST_FALLBACK, but I'm not sure, if it is the correct - * host. - */ - if (purple_proxy_connect(gc, account, YAHOO_PAGER_HOST_FALLBACK, - purple_account_get_int(account, "port", YAHOO_PAGER_PORT), - yahoo_got_web_connected, gc) == NULL) - { - purple_connection_error(gc, - PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - return; - } -} - -static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url) -{ - if (!strcmp(key, "passwd") || !strcmp(key, "login")) - return; - g_string_append_c(url, '&'); - g_string_append(url, key); - g_string_append_c(url, '='); - if (!strcmp(key, ".save") || !strcmp(key, ".js")) - g_string_append_c(url, '1'); - else if (!strcmp(key, ".challenge")) - g_string_append(url, val); - else - g_string_append(url, purple_url_encode(val)); -} - -static GHashTable *yahoo_login_page_hash(const char *buf, size_t len) -{ - GHashTable *hash = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, g_free); - const char *c = buf; - char *d; - char name[64], value[64]; - int count; - int input_len = strlen("<input "); - int name_len = strlen("name=\""); - int value_len = strlen("value=\""); - while ((len > ((c - buf) + input_len)) - && (c = strstr(c, "<input "))) { - if (!(c = g_strstr_len(c, len - (c - buf), "name=\""))) - continue; - c += name_len; - count = sizeof(name)-1; - for (d = name; (len > ((c - buf) + 1)) && *c!='"' - && count; c++, d++, count--) - *d = *c; - *d = '\0'; - count = sizeof(value)-1; - if (!(d = g_strstr_len(c, len - (c - buf), "value=\""))) - continue; - d += value_len; - if (strchr(c, '>') < d) - break; - for (c = d, d = value; (len > ((c - buf) + 1)) - && *c!='"' && count; c++, d++, count--) - *d = *c; - *d = '\0'; - g_hash_table_insert(hash, g_strdup(name), g_strdup(value)); - } - return hash; -} - -static void -yahoo_login_page_cb(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _unused) -{ - PurpleConnection *gc = purple_http_conn_get_purple_connection(http_conn); - PurpleAccount *account = purple_connection_get_account(gc); - YahooData *yd = purple_connection_get_protocol_data(gc); - const char *pass = purple_connection_get_password(gc); - size_t len; - const gchar *got_data; - GHashTable *hash; - GString *url; - char md5[33], *hashp = md5, *chal; - int i; - PurpleCipher *cipher; - guchar digest[16]; - PurpleHttpRequest *req; - - if (!purple_http_response_is_successful(response)) - { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - purple_http_response_get_error(response)); - return; - } - - got_data = purple_http_response_get_data(response, &len); - hash = yahoo_login_page_hash(got_data, len); - - cipher = purple_md5_cipher_new(); - - purple_cipher_append(cipher, (const guchar *)pass, strlen(pass)); - purple_cipher_digest(cipher, digest, sizeof(digest)); - 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_reset(cipher); - purple_cipher_append(cipher, (const guchar *)chal, strlen(chal)); - purple_cipher_digest(cipher, digest, sizeof(digest)); - 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_reset(cipher); - purple_cipher_append(cipher, md5, strlen(md5)); - purple_cipher_digest(cipher, 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_new(NULL); - g_string_printf(url, "http://login.yahoo.com/config/login?login=%s&passwd=%s", purple_account_get_username(account), md5); - g_hash_table_foreach(hash, (GHFunc)yahoo_login_page_hash_iter, url); - url = g_string_append(url, "&.hash=1&.md5=1"); - - g_hash_table_destroy(hash); - g_object_unref(cipher); - - req = purple_http_request_new(g_string_free(url, FALSE)); - purple_http_request_set_max_redirects(req, 0); - purple_http_connection_set_add(yd->http_reqs, - purple_http_request(gc, req, yahoo_login_page_got, NULL)); - purple_http_request_unref(req); -} - -#endif /* TRY_WEBMESSENGER_LOGIN */ - -static void yahoo_picture_check(PurpleAccount *account) -{ - PurpleConnection *gc = purple_account_get_connection(account); - PurpleImage *img = purple_buddy_icons_find_account_icon(account); - - yahoo_set_buddy_icon(gc, img); - - if (img) - g_object_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(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _yd) -{ - YahooData *yd = _yd; - 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; - const gchar *got_data; - - if (!purple_http_response_is_successful(response)) { - purple_debug_error("yahoo", "Unable to retrieve server info: %s\n", - purple_http_response_get_error(response)); - - if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port, - yahoo_got_connected, gc) == NULL) { - purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - } - } else { - got_data = purple_http_response_get_data(response, NULL); - strings = g_strsplit(got_data, "\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(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, - _("Unable to connect")); - } else { - purple_debug_error("yahoo", "No CS address retrieved! Server " - "response:\n%s\n", got_data); - - if(purple_proxy_connect(gc, a, YAHOO_PAGER_HOST_FALLBACK, port, - yahoo_got_connected, gc) == NULL) { - purple_connection_error(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); - PurpleHttpRequest *req; - YahooData *yd = g_new0(YahooData, 1); - PurpleStatus *status = purple_account_get_active_status(account); - - purple_connection_set_protocol_data(gc, yd); - purple_connection_set_flags(gc, PURPLE_CONNECTION_FLAG_HTML | - PURPLE_CONNECTION_FLAG_NO_BGCOLOR | - PURPLE_CONNECTION_FLAG_NO_URLDESC | - PURPLE_CONNECTION_FLAG_NO_IMAGES); - - purple_connection_update_progress(gc, _("Connecting"), 1, 2); - - purple_connection_set_display_name(gc, purple_account_get_username(account)); - - yd->gc = gc; - 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_circular_buffer_new(0); - yd->http_reqs = purple_http_connection_set_new(); - 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. */ - req = purple_http_request_new(YAHOO_PAGER_HOST_REQ_URL); - purple_http_request_header_set(req, "User-Agent", YAHOO_CLIENT_USERAGENT); - purple_http_connection_set_add(yd->http_reqs, purple_http_request(gc, - req, yahoo_got_pager_server, yd)); - purple_http_request_unref(req); - - return; -} - -void yahoo_close(PurpleConnection *gc) { - YahooData *yd = purple_connection_get_protocol_data(gc); - GSList *l; - - if (yd->inpa) { - purple_input_remove(yd->inpa); - yd->inpa = 0; - } - - purple_http_connection_set_destroy(yd->http_reqs); - yd->http_reqs = NULL; - - for (l = yd->confs; l; l = l->next) { - PurpleChatConversation *conv = l->data; - GList *users; - - users = purple_chat_conversation_get_users(conv); - yahoo_conf_leave(yd, - purple_conversation_get_name(PURPLE_CONVERSATION(conv)), - purple_connection_get_display_name(gc), users); - g_list_free(users); - } - g_slist_free(yd->confs); - - g_slist_free_full(yd->cookies, g_free); - - 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); - - g_object_unref(G_OBJECT(yd->txbuf)); - - if (yd->fd >= 0) - close(yd->fd); - - g_free(yd->rxqueue); - yd->rxlen = 0; - g_free(yd->picture_url); - - purple_http_conn_cancel(yd->picture_upload_hc); - 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); - purple_connection_set_protocol_data(gc, 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)) || - !purple_connection_get_protocol_data(gc)) - 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"; - } - 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_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - yd = purple_connection_get_protocol_data(gc); - 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_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; - if (ypd->phone.home && *ypd->phone.home) - purple_notify_user_info_add_pair_plaintext(user_info, _("Home Phone Number"), ypd->phone.home); - if (ypd->phone.work && *ypd->phone.work) - purple_notify_user_info_add_pair_plaintext(user_info, _("Work Phone Number"), ypd->phone.work); - if (ypd->phone.mobile && *ypd->phone.mobile) - purple_notify_user_info_add_pair_plaintext(user_info, _("Mobile Phone Number"), ypd->phone.mobile); - } -} - -static void yahoo_addbuddyfrommenu_cb(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_IS_BUDDY(node)); - - buddy = (PurpleBuddy *) node; - gc = purple_account_get_connection(purple_buddy_get_account(buddy)); - - yahoo_add_buddy(gc, buddy, NULL, NULL); -} - - -static void yahoo_chat_goto_menu(PurpleBlistNode *node, gpointer data) -{ - PurpleBuddy *buddy; - PurpleConnection *gc; - - g_return_if_fail(PURPLE_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 = purple_connection_get_protocol_data(gc); - - 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)); -} - -#if 0 -/* XXX: it doesn't seems to work */ -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); -} -#endif - -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 = purple_connection_get_protocol_data(gc); - 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) { - 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); - - act = purple_menu_action_new(_("Start Doodling"), - PURPLE_CALLBACK(yahoo_doodle_blist_node), - NULL, NULL); - m = g_list_append(m, act); - -#if 0 - /* XXX: it doesn't seems to work */ - act = purple_menu_action_new(_("Set User Info..."), - PURPLE_CALLBACK(yahoo_userinfo_blist_node), - NULL, NULL); - m = g_list_append(m, act); -#endif - } - - return m; -} - -GList *yahoo_blist_node_menu(PurpleBlistNode *node) -{ - if(PURPLE_IS_BUDDY(node)) { - return yahoo_buddy_menu((PurpleBuddy *) node); - } else { - return NULL; - } -} - -static void yahoo_act_id(PurpleConnection *gc, PurpleRequestFields *fields) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - const char *name = yd->profiles[GPOINTER_TO_INT(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(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _unused) -{ - PurpleConnection *gc = - purple_http_conn_get_purple_connection(http_conn); - gchar *url; - - PURPLE_ASSERT_CONNECTION_IS_VALID(gc); - - if (!purple_http_response_is_successful(response)) { - purple_debug_error("yahoo", - "Requesting mail login token failed: %s\n", - purple_http_response_get_error(response)); - url = g_strdup(YAHOO_MAIL_URL); - } else { - /* Should we not be hardcoding the rd url? */ - gchar *token; - token = g_strdup(purple_http_response_get_data(response, NULL)); - g_strstrip(token); - url = g_strdup_printf( - "http://login.yahoo.com/config/reset_cookies_token?" - ".token=%s" - "&.done=http://us.rd.yahoo.com/messenger/client/%%3f" - "http://mail.yahoo.com/", token); - purple_str_wipe(token); - } - - /* Open the mailbox with the parsed url data */ - purple_notify_uri(gc, url); - - g_free(url); -} - - -static void yahoo_show_inbox(PurpleProtocolAction *action) -{ - /* Setup a cookie that can be used by the browser */ - - PurpleConnection *gc = action->connection; - YahooData *yd = purple_connection_get_protocol_data(gc); - PurpleHttpRequest *req; - PurpleHttpCookieJar *cookiejar; - - req = purple_http_request_new( - "https://login.yahoo.com/config/cookie_token"); - purple_http_request_set_method(req, "POST"); - purple_http_request_header_set(req, "User-Agent", - YAHOO_CLIENT_USERAGENT); - cookiejar = purple_http_request_get_cookie_jar(req); - purple_http_cookie_jar_set(cookiejar, "T", yd->cookie_t); - purple_http_cookie_jar_set(cookiejar, "Y", yd->cookie_y); - purple_http_connection_set_add(yd->http_reqs, purple_http_request(gc, - req, yahoo_get_inbox_token_cb, NULL)); - purple_http_request_unref(req); -} - -#if 0 -/* XXX: it doesn't seems to work */ -static void -yahoo_set_userinfo_fn(PurpleProtocolAction *action) -{ - yahoo_set_userinfo(action->connection); -} -#endif - -static void yahoo_show_act_id(PurpleProtocolAction *action) -{ - PurpleRequestFields *fields; - PurpleRequestFieldGroup *group; - PurpleRequestField *field; - PurpleConnection *gc = (PurpleConnection *) action->connection; - 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], GINT_TO_POINTER(iter)); - if (purple_strequal(yd->profiles[iter], name)) - purple_request_field_choice_set_default_value(field, GINT_TO_POINTER(iter)); - } - - purple_request_fields(gc, NULL, _("Select the ID you want to activate"), NULL, - fields, - _("OK"), G_CALLBACK(yahoo_act_id), - _("Cancel"), NULL, - purple_request_cpar_from_connection(gc), gc); -} - -static void yahoo_show_chat_goto(PurpleProtocolAction *action) -{ - PurpleConnection *gc = action->connection; - purple_request_input(gc, NULL, _("Join whom in chat?"), NULL, - "", FALSE, FALSE, NULL, - _("OK"), G_CALLBACK(yahoo_chat_goto), - _("Cancel"), NULL, - purple_request_cpar_from_connection(gc), - gc); -} - -GList *yahoo_get_actions(PurpleConnection *gc) { - GList *m = NULL; - PurpleProtocolAction *act; - -#if 0 - /* XXX: it doesn't seems to work */ - act = purple_protocol_action_new(_("Set User Info..."), - yahoo_set_userinfo_fn); - m = g_list_append(m, act); -#endif - - act = purple_protocol_action_new(_("Activate ID..."), - yahoo_show_act_id); - m = g_list_append(m, act); - - act = purple_protocol_action_new(_("Join User in Chat..."), - yahoo_show_chat_goto); - m = g_list_append(m, act); - - m = g_list_append(m, NULL); - act = purple_protocol_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(PurpleHttpConnection *http_conn, - PurpleHttpResponse *response, gpointer _sms_cb_data) -{ - struct yahoo_sms_carrier_cb_data *sms_cb_data = _sms_cb_data; - PurpleConnection *gc = sms_cb_data->gc; - YahooData *yd = purple_connection_get_protocol_data(gc); - char *status = NULL; - char *carrier = NULL; - PurpleAccount *account = purple_connection_get_account(gc); - PurpleIMConversation *im = purple_conversations_find_im_with_account(sms_cb_data->who, account); - - if (!purple_http_response_is_successful(response)) { - purple_conversation_write_system_message(PURPLE_CONVERSATION(im), - _("Can't send SMS. Unable to obtain mobile carrier."), 0); - - g_free(sms_cb_data->who); - g_free(sms_cb_data->what); - g_free(sms_cb_data); - return ; - } else { - const gchar *got_data = purple_http_response_get_data(response, NULL); - PurpleXmlNode *validate_data_root = purple_xmlnode_from_str(got_data, -1); - PurpleXmlNode *validate_data_child = purple_xmlnode_get_child(validate_data_root, "mobile_no"); - const char *mobile_no = purple_xmlnode_get_attrib(validate_data_child, "msisdn"); - - validate_data_root = purple_xmlnode_copy(validate_data_child); - validate_data_child = purple_xmlnode_get_child(validate_data_root, "status"); - status = purple_xmlnode_get_data(validate_data_child); - - validate_data_child = purple_xmlnode_get_child(validate_data_root, "carrier"); - carrier = purple_xmlnode_get_data(validate_data_child); - - purple_debug_info("yahoo", "SMS validate data: %s\n", got_data); - - 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, purple_message_new_outgoing( - sms_cb_data->who, sms_cb_data->what, 0)); - } else { - g_hash_table_insert(yd->sms_carrier, - g_strdup_printf("+%s", mobile_no), g_strdup("Unknown")); - purple_conversation_write_system_message(PURPLE_CONVERSATION(im), - _("Can't send SMS. Unknown mobile carrier."), 0); - } - - purple_xmlnode_free(validate_data_child); - purple_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 = purple_connection_get_protocol_data(gc); - PurpleHttpRequest *req; - PurpleHttpCookieJar *cookiejar; - struct yahoo_sms_carrier_cb_data *sms_cb_data; - char *validate_request_str = NULL; - PurpleXmlNode *validate_request_root = NULL; - PurpleXmlNode *validate_request_child = NULL; - - if(!(sms_cb_data = data)) - return; - - validate_request_root = purple_xmlnode_new("validate"); - purple_xmlnode_set_attrib(validate_request_root, "intl", "us"); - purple_xmlnode_set_attrib(validate_request_root, "version", YAHOO_CLIENT_VERSION); - purple_xmlnode_set_attrib(validate_request_root, "qos", "0"); - - validate_request_child = purple_xmlnode_new_child(validate_request_root, "mobile_no"); - purple_xmlnode_set_attrib(validate_request_child, "msisdn", sms_cb_data->who + 1); - - validate_request_str = purple_xmlnode_to_str(validate_request_root, NULL); - - purple_xmlnode_free(validate_request_child); - purple_xmlnode_free(validate_request_root); - - req = purple_http_request_new(NULL); - purple_http_request_set_url_printf(req, "http://validate.msg.yahoo.com" - "/mobileno?intl=us&version=%s", YAHOO_CLIENT_VERSION); - purple_http_request_set_method(req, "POST"); - purple_http_request_header_set(req, "User-Agent", - YAHOO_CLIENT_USERAGENT); - cookiejar = purple_http_request_get_cookie_jar(req); - purple_http_cookie_jar_set(cookiejar, "T", yd->cookie_t); - purple_http_cookie_jar_set(cookiejar, "Y", yd->cookie_y); - purple_http_request_set_contents(req, validate_request_str, -1); - purple_http_connection_set_add(yd->http_reqs, purple_http_request(gc, - req, yahoo_get_sms_carrier_cb, data)); - purple_http_request_unref(req); - - g_free(validate_request_str); -} - -int yahoo_send_im(PurpleConnection *gc, PurpleMessage *pmsg) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt = NULL; - char *msg = yahoo_html_to_codes(purple_message_get_contents(pmsg)); - char *msg2; - PurpleWhiteboard *wb; - int ret = 1; - gsize lenb = 0; - glong lenc = 0; - struct yahoo_p2p_data *p2p_data; - const gchar *rcpt = purple_message_get_recipient(pmsg); - - msg2 = yahoo_string_encode(gc, msg, TRUE); - - 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; - } - } - - if (rcpt[0] == '+') { - /* we have an sms to be sent */ - gchar *carrier = NULL; - const char *alias = NULL; - PurpleAccount *account = purple_connection_get_account(gc); - PurpleIMConversation *im = purple_conversations_find_im_with_account(rcpt, account); - - carrier = g_hash_table_lookup(yd->sms_carrier, rcpt); - 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(rcpt); - sms_cb_data->what = g_strdup(purple_message_get_contents(pmsg)); - - purple_conversation_write_system_message(PURPLE_CONVERSATION(im), - _("Getting mobile carrier to send the SMS."), 0); - - 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_system_message(PURPLE_CONVERSATION(im), - _("Can't send SMS. Unknown mobile carrier."), 0); - - g_free(msg); - g_free(msg2); - return -1; - } - - alias = purple_account_get_private_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, rcpt + 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); - yahoo_packet_hash(pkt, "ss", 1, purple_connection_get_display_name(gc), 5, rcpt); - - yahoo_packet_hash_str(pkt, 97, "1"); /* UTF-8 */ - 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(purple_connection_get_account(gc), rcpt); - if (wb) - yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY); - else - { - const char *imv; - imv = g_hash_table_lookup(yd->imvironments, rcpt); - 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, rcpt))) { - yahoo_packet_hash_int(pkt, 11, p2p_data->session_id); - yahoo_p2p_write_pkt(p2p_data->source, pkt); - } - else { - yahoo_packet_send(pkt, yd); - yahoo_send_p2p_pkt(gc, rcpt, 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, PurpleIMTypingState state) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - struct yahoo_p2p_data *p2p_data; - struct yahoo_packet *pkt = NULL; - - /* 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))) { - yahoo_packet_hash(pkt, "sssssis", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_IM_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 */ - - yahoo_packet_hash(pkt, "ssssss", 49, "TYPING", 1, purple_connection_get_display_name(gc), - 14, " ", 13, state == PURPLE_IM_TYPING ? "1" : "0", - 5, who, 1002, "1"); - 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; - - if (!purple_status_is_active(status)) - return; - - gc = purple_account_get_connection(account); - presence = purple_status_get_presence(status); - yd = purple_connection_get_protocol_data(gc); - 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, TRUE); - conv_msg = purple_markup_strip_html(tmp); - g_free(tmp); - } else { - if ((msg == NULL) || (*msg == '\0')) - msg = _("Away"); - tmp = yahoo_string_encode(gc, msg, TRUE); - 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, "1"); /* UTF-8 */ - 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 = purple_connection_get_protocol_data(gc); - 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) { - msg = yahoo_string_encode(gc, tmp, TRUE); - msg2 = purple_markup_strip_html(msg); - yahoo_packet_hash_str(pkt, 97, "1"); /* UTF-8 */ - 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(G_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(G_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(G_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 = purple_connection_get_protocol_data(gc); - 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, const char *message) -{ - YahooData *yd = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt; - const char *group = NULL; - char *group2; - const char *bname = purple_buddy_get_name(buddy); - - if (!yd->logged_in) - return; - - if (!purple_account_privacy_check(purple_connection_get_account(gc), bname)) - return; - - group = purple_group_get_name(purple_buddy_get_group(buddy)); - - group2 = yahoo_string_encode(gc, group, FALSE); - pkt = yahoo_packet_new(YAHOO_SERVICE_ADDBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id); - yahoo_packet_hash(pkt, "ssssssssss", - 14, "", - 65, group2, - 97, "1", /* UTF-8 */ - 1, purple_connection_get_display_name(gc), - 302, "319", - 300, "319", - 7, 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 = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt; - GSList *buddies, *l; - PurpleGroup *g; - gboolean remove = TRUE; - char *cg; - const char *bname, *gname; - YahooFriend *f = NULL; - - bname = purple_buddy_get_name(buddy); - f = yahoo_friend_find(gc, bname); - if (!f) - return; - - gname = purple_group_get_name(group); - buddies = purple_blist_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, FALSE); - pkt = yahoo_packet_new(YAHOO_SERVICE_REMBUDDY, YAHOO_STATUS_AVAILABLE, yd->session_id); - - yahoo_packet_hash(pkt, "sss", 1, purple_connection_get_display_name(gc), - 7, bname, 65, cg); - yahoo_packet_send_and_free(pkt, yd); - g_free(cg); -} - -void yahoo_add_deny(PurpleConnection *gc, const char *who) { - YahooData *yd = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt; - - if (!yd->logged_in) - return; - - if (!who || who[0] == '\0') - return; - - pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); - - 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 = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt; - - if (!yd->logged_in) - return; - - if (!who || who[0] == '\0') - return; - - pkt = yahoo_packet_new(YAHOO_SERVICE_IGNORECONTACT, YAHOO_STATUS_AVAILABLE, yd->session_id); - - 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 (purple_account_get_privacy_type(account)) - { - case PURPLE_ACCOUNT_PRIVACY_ALLOW_ALL: - for (deny = purple_account_privacy_get_denied(account); deny; deny = deny->next) - yahoo_rem_deny(gc, deny->data); - break; - - case PURPLE_ACCOUNT_PRIVACY_ALLOW_BUDDYLIST: - case PURPLE_ACCOUNT_PRIVACY_ALLOW_USERS: - case PURPLE_ACCOUNT_PRIVACY_DENY_USERS: - case PURPLE_ACCOUNT_PRIVACY_DENY_ALL: - for (deny = purple_account_privacy_get_denied(account); 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 = purple_connection_get_protocol_data(gc); - 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; - - 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, FALSE); - gpo = yahoo_string_encode(gc, old_group, FALSE); - 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); - 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 = purple_connection_get_protocol_data(gc); - struct yahoo_packet *pkt; - char *gpn, *gpo; - - gpn = yahoo_string_encode(gc, purple_group_get_name(group), FALSE); - gpo = yahoo_string_encode(gc, old_name, FALSE); - 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_protocol_send_attention(purple_account_get_connection(account), purple_conversation_get_name(c), 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_connection(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) -{ - PurpleIMConversation *im; - - im = purple_conversations_find_im_with_account(username, - purple_connection_get_account(gc)); - - g_return_val_if_fail(im != NULL, FALSE); - - purple_debug_info("yahoo", "Sending <ding> on account %s to buddy %s.\n", - username, purple_conversation_get_name(PURPLE_CONVERSATION(im))); - purple_conversation_send_with_flags(PURPLE_CONVERSATION(im), "<ding>", PURPLE_MESSAGE_INVISIBLE); - - return TRUE; -} - -GList *yahoo_attention_types(PurpleAccount *account) -{ - static GList *list = NULL; - - if (!list) { - /* Yahoo only supports one attention command: the 'buzz'. */ - /* This is index number YAHOO_BUZZ. */ - list = g_list_append(list, purple_attention_type_new("Buzz", _("Buzz"), - _("%s has buzzed you!"), _("Buzzing %s..."))); - } - - return list; -} - -gssize -yahoo_get_max_message_size(PurpleConversation *conv) -{ - return YAHOO_MAX_MESSAGE_LENGTH_CHARS; -}
--- a/libpurple/protocols/yahoo/ymsg.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,363 +0,0 @@ -/** - * @file ymsg.h The Yahoo! Protocol - * - * purple - * - * Purple is the legal property of its developers, whose names are too numerous - * to list here. Please refer to the COPYRIGHT file distributed with this - * source distribution. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA - */ - -#ifndef _YMSG_H_ -#define _YMSG_H_ - -#include "circularbuffer.h" -#include "cmds.h" -#include "http.h" -#include "protocol.h" -#include "network.h" - -#define YAHOO_PAGER_HOST_REQ_URL "http://vcs2.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_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" - -#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 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 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 = -1 /* 0xffffffff; in ymsg 15. doesnt mean the normal sense of 'disconnected' */ -}; - -struct yahoo_buddy_icon_upload_data { - PurpleConnection *gc; - char *filename; - GString *picture_data; -}; - -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; - guint inpa; - guchar *rxqueue; - int rxlen; - PurpleCircularBuffer *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; - char *cookie_y; - char *cookie_t; - char *cookie_b; - int session_id; - 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; - PurpleHttpConnection *picture_upload_hc; - - struct _YchtConn *ycht; - - /** - * This set contains HTTP connections - * for when we lookup people profile or photo information. - */ - PurpleHttpConnectionSet *http_reqs; - - GHashTable *xfer_peer_idstring_map;/* Hey, i dont know, but putting this HashTable next to friends gives a run time fault... */ - GSList *cookies;/* contains all cookies, including _y and _t */ - PurpleNetworkListenData *listen_data; - - /** - * We may receive a list15 in multiple packets with no prior warning as to how many we'll be getting; - * the server expects us to keep track of the group for which it is sending us contact names. - */ - char *current_list15_grp; - time_t last_ping; - time_t last_keepalive; - GHashTable *peers; /* information about p2p data */ - int yahoo_p2p_timer; - int yahoo_local_p2p_server_fd; - int yahoo_p2p_server_watcher; - GHashTable *sms_carrier; /* sms carrier data */ - guint yahoo_p2p_server_timeout_handle; -} YahooData; - -#define YAHOO_MAX_STATUS_MESSAGE_LENGTH (255) - -/* - * Current Maximum Length for Instant Messages - * - * This was found by experiment. - * - * The YMSG protocol allows a message of up to 948 bytes, but the official client - * limits to 800 characters. According to experiments I conducted, it seems that - * the discrepancy is to allow some leeway for messages with mixed single- and - * multi-byte characters, as I was able to send messages of 840 and 932 bytes - * by using some multibyte characters (some random Chinese or Japanese characters, - * to be precise). - rekkanoryo - */ -#define YAHOO_MAX_MESSAGE_LENGTH_BYTES 948 -#define YAHOO_MAX_MESSAGE_LENGTH_CHARS 800 - -/* sometimes i wish prpls could #include things from other prpls. then i could just - * use the routines from libfaim and not have to admit to knowing how they work. */ -#define yahoo_put16(buf, data) ( \ - (*(buf) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+1) = (unsigned char)(data)&0xff), \ - 2) -#define yahoo_get16(buf) ((((*(buf))<<8)&0xff00) + ((*((buf)+1)) & 0xff)) -#define yahoo_put32(buf, data) ( \ - (*((buf)) = (unsigned char)((data)>>24)&0xff), \ - (*((buf)+1) = (unsigned char)((data)>>16)&0xff), \ - (*((buf)+2) = (unsigned char)((data)>>8)&0xff), \ - (*((buf)+3) = (unsigned char)(data)&0xff), \ - 4) -#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \ - (((*((buf)+1))<<16)&0x00ff0000) + \ - (((*((buf)+2))<< 8)&0x0000ff00) + \ - (((*((buf)+3) )&0x000000ff))) - -/* util.c */ -void yahoo_init_colorht(void); -void yahoo_dest_colorht(void); -char *yahoo_codes_to_html(const char *x); - -/** - * This function takes a normal HTML message and converts it to the message - * format used by Yahoo, which uses a frankensteinish combination of ANSI - * escape codes and broken HTML. - * - * It results in slightly different output than would be sent by official - * Yahoo clients. The two main differences are: - * - * 1. We always close all tags, whereas official Yahoo clients leave tags - * dangling open at the end of each message (and the client treats them - * as closed). - * 2. We always close inner tags first before closing outter tags. - * - * For example, if you want to send this message: - * <b> bold <i> bolditalic </i></b><i> italic </i> - * Official Yahoo clients would send: - * ESC[1m bold ESC[2m bolditalic ESC[x1m italic - * But we will send: - * ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m - */ -char *yahoo_html_to_codes(const char *src); - -gboolean -yahoo_account_use_http_proxy(PurpleConnection *conn); - -/** - * Encode some text to send to the yahoo server. - * - * @param gc The connection handle. - * @param str The null terminated utf8 string to encode. - * @param utf8 Whether to return a UTF-8 string. - * @return A g_malloc'ed string in the appropriate encoding. If utf8 - * is true then the string is copied verbatim. Otherwise the - * encoding from account settings is used. - */ -gchar *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); - -/* yahoo_profile.c */ -void yahoo_get_info(PurpleConnection *gc, const char *name); - -/* ymsg.h - these functions were formerly static but need not to be for the - * new two-protocol 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, PurpleMessage *msg); -unsigned int yahoo_send_typing(PurpleConnection *gc, const char *who, PurpleIMTypingState 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, const char *message); -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_get_actions(PurpleConnection *gc); -void yahoopurple_register_commands(void); -gssize yahoo_get_max_message_size(PurpleConversation *conv); - -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 /* _YMSG_H_ */
--- a/libpurple/proxy.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/proxy.c Mon Jun 05 16:36:29 2017 +0300 @@ -27,7 +27,6 @@ #define _PURPLE_PROXY_C_ #include "internal.h" -#include "ciphers/md5hash.h" #include "debug.h" #include "http.h" #include "notify.h"
--- a/libpurple/tag.sh Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/tag.sh Mon Jun 05 16:36:29 2017 +0300 @@ -22,17 +22,6 @@ if [ "$tag" == "auto" ] && [ "$arg" == "-shared" ]; then tag="CCLD" fi - if [ "$tag" == "PERL" ] && [ "${arg%(*}" == "Mkbootstrap" ]; then - object="${arg%;}" - is_final=1 - break - fi - if [ "$tag" == "PERL" ] && [ "${arg%(*}" == "ExtUtils::ParseXS::process_file" ]; then - object="${arg#*output => \"}" - object="${object%\", *}" - is_final=1 - break - fi ext_1=${arg#${arg%??}} if [ "${ext_1}" == ".c" ]; then file_1="$arg" @@ -51,10 +40,6 @@ tag="CC" fi -if [ "$tag" == "PERL" ] && [ "$is_final" == 0 ]; then - object=`echo "$object" | sed -n 's|.*output *=> *"\([^"]*\)".*|\1|p'` -fi - if [ "$object" == "" ] && [ "${file_1}" != "" ]; then object="${file_1}" fi
--- a/libpurple/tests/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/tests/Makefile.am Mon Jun 05 16:36:29 2017 +0300 @@ -8,12 +8,8 @@ test_programs=\ test_des \ test_des3 \ - test_hmac \ test_image \ test_md4 \ - test_md5 \ - test_sha1 \ - test_sha256 \ test_smiley \ test_trie \ test_util \ @@ -25,24 +21,12 @@ test_des3_SOURCES=test_des3.c test_des3_LDADD=$(COMMON_LIBS) -test_hmac_SOURCES=test_hmac.c -test_hmac_LDADD=$(COMMON_LIBS) - test_image_SOURCES=test_image.c test_image_LDADD=$(COMMON_LIBS) test_md4_SOURCES=test_md4.c test_md4_LDADD=$(COMMON_LIBS) -test_md5_SOURCES=test_md5.c -test_md5_LDADD=$(COMMON_LIBS) - -test_sha1_SOURCES=test_sha1.c -test_sha1_LDADD=$(COMMON_LIBS) - -test_sha256_SOURCES=test_sha256.c -test_sha256_LDADD=$(COMMON_LIBS) - test_smiley_SOURCES=test_smiley.c test_smiley_LDADD=$(COMMON_LIBS)
--- a/libpurple/tests/test_hmac.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,401 +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 <glib.h> - -#include <purple.h> - -#include "ciphers/hmaccipher.h" -#include "ciphers/md5hash.h" -#include "ciphers/sha1hash.h" - -/****************************************************************************** - * HMAC Tests - * See RFC2202 and some other NULL tests I made up - *****************************************************************************/ -static void -test_hmac(gchar *data, size_t data_len, - const gchar *key, size_t key_len, - PurpleHash *hash, const gchar *digest) -{ - PurpleCipher *cipher = NULL; - gchar cdigest[41]; - gboolean ret = FALSE; - - cipher = purple_hmac_cipher_new(hash); - purple_cipher_set_key(cipher, (guchar *)key, key_len); - - purple_cipher_append(cipher, (guchar *)data, data_len); - ret = purple_cipher_digest_to_str(cipher, cdigest, sizeof(cdigest)); - - g_assert(ret); - g_assert_cmpstr(digest, ==, cdigest); - - g_object_unref(G_OBJECT(cipher)); - g_object_unref(G_OBJECT(hash)); -} - -static void -test_hmac_md5_hi(void) { - test_hmac( - "Hi There", - 8, - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - 16, - purple_md5_hash_new(), - "9294727a3638bb1c13f48ef8158bfc9d" - ); -} - -static void -test_hmac_md5_what(void) { - test_hmac( - "what do ya want for nothing?", - 28, - "Jefe", - 4, - purple_md5_hash_new(), - "750c783e6ab0b503eaa86e310a5db738" - ); -} - -static void -test_hmac_md5_dd(void) { - test_hmac( - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - 50, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 16, - purple_md5_hash_new(), - "56be34521d144c88dbb8c733f0e8b3f6" - ); -} - -static void -test_hmac_md5_cd(void) { - test_hmac( - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - 50, - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" - "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19", - 25, - purple_md5_hash_new(), - "697eaf0aca3a3aea3a75164746ffaa79" - ); -} - -static void -test_hmac_md5_truncation(void) { - test_hmac( - "Test With Truncation", - 20, - "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - 16, - purple_md5_hash_new(), - "56461ef2342edc00f9bab995690efd4c" - ); -} - -static void -test_hmac_md5_large_key(void) { - test_hmac( - "Test Using Larger Than Block-Size Key - Hash Key First", - 54, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 80, - purple_md5_hash_new(), - "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd" - ); -} - -static void -test_hmac_md5_large_key_and_data(void) { - test_hmac( - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", - 73, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 80, - purple_md5_hash_new(), - "6f630fad67cda0ee1fb1f562db3aa53e" - ); -} - -static void -test_hmac_md5_null_key(void) { - test_hmac( - "Hi There", - 8, - "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" - "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", - 20, - purple_md5_hash_new(), - "597bfd644b797a985561eeb03a169e59" - ); -} - -static void -test_hmac_md5_null_text(void) { - test_hmac( - "Hi\x00There", - 8, - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - 20, - purple_md5_hash_new(), - "70be8e1b7b50dfcc335d6cd7992c564f" - ); -} - -static void -test_hmac_md5_null_key_and_text(void) { - test_hmac( - "Hi\x00Th\x00re", - 8, - "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" - "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", - 20, - purple_md5_hash_new(), - "b31bcbba35a33a067cbba9131cba4889" - ); -} - -static void -test_hmac_sha1_hi(void) { - test_hmac( - "Hi There", - 8, - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - 20, - purple_sha1_hash_new(), - "b617318655057264e28bc0b6fb378c8ef146be00" - ); -} - -static void -test_hmac_sha1_what(void) { - test_hmac( - "what do ya want for nothing?", - 28, - "Jefe", - 4, - purple_sha1_hash_new(), - "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79" - ); -} - -static void -test_hmac_sha1_dd(void) { - test_hmac( - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd" - "\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd\xdd", - 50, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 20, - purple_sha1_hash_new(), - "125d7342b9ac11cd91a39af48aa17b4f63f175d3" - ); -} - -static void -test_hmac_sha1_cd(void) { - test_hmac( - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd" - "\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd\xcd", - 50, - "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a" - "\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14" - "\x15\x16\x17\x18\x19", - 25, - purple_sha1_hash_new(), - "4c9007f4026250c6bc8414f9bf50c86c2d7235da" - ); -} - -static void -test_hmac_sha1_truncation(void) { - test_hmac( - "Test With Truncation", - 20, - "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c" - "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c", - 20, - purple_sha1_hash_new(), - "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04" - ); -} - -static void -test_hmac_sha1_large_key(void) { - test_hmac( - "Test Using Larger Than Block-Size Key - Hash Key First", - 54, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 80, - purple_sha1_hash_new(), - "aa4ae5e15272d00e95705637ce8a3b55ed402112" - ); -} - -static void -test_hmac_sha1_large_key_and_data(void) { - test_hmac( - "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", - 73, - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa" - "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa", - 80, - purple_sha1_hash_new(), - "e8e99d0f45237d786d6bbaa7965c7808bbff1a91" - ); -} - -static void -test_hmac_sha1_null_key(void) { - test_hmac( - "Hi There", - 8, - "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b" - "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", - 20, - purple_sha1_hash_new(), - "eb62a2e0e33d300be669c52aab3f591bc960aac5" - ); -} - -static void -test_hmac_sha1_null_text(void) { - test_hmac( - "Hi\x00There", - 8, - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b" - "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b", - 20, - purple_sha1_hash_new(), - "31ca58d849e971e418e3439de2c6f83144b6abb7" - ); -} - -static void -test_hmac_sha1_null_key_and_text(void) { - test_hmac( - "Hi\x00Th\x00re", - 8, - "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34" - "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b", - 20, - purple_sha1_hash_new(), - "e6b8e2fede87aa09dcb13e554df1435e056eae36" - ); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/hmac/md5/hi", - test_hmac_md5_hi); - g_test_add_func("/hmac/md5/what", - test_hmac_md5_what); - g_test_add_func("/hmac/md5/dd", - test_hmac_md5_dd); - g_test_add_func("/hmac/md5/cd", - test_hmac_md5_cd); - g_test_add_func("/hmac/md5/truncation", - test_hmac_md5_truncation); - g_test_add_func("/hmac/md5/large key", - test_hmac_md5_large_key); - g_test_add_func("/hmac/md5/large key and data", - test_hmac_md5_large_key_and_data); - g_test_add_func("/hmac/md5/null key", - test_hmac_md5_null_key); - g_test_add_func("/hmac/md5/null text", - test_hmac_md5_null_text); - g_test_add_func("/hmac/md5/null key and text", - test_hmac_md5_null_key_and_text); - - g_test_add_func("/hmac/sha1/hi", - test_hmac_sha1_hi); - g_test_add_func("/hmac/sha1/what", - test_hmac_sha1_what); - g_test_add_func("/hmac/sha1/dd", - test_hmac_sha1_dd); - g_test_add_func("/hmac/sha1/cd", - test_hmac_sha1_cd); - g_test_add_func("/hmac/sha1/truncation", - test_hmac_sha1_truncation); - g_test_add_func("/hmac/sha1/large key", - test_hmac_sha1_large_key); - g_test_add_func("/hmac/sha1/large key and data", - test_hmac_sha1_large_key_and_data); - g_test_add_func("/hmac/sha1/null key", - test_hmac_sha1_null_key); - g_test_add_func("/hmac/sha1/null text", - test_hmac_sha1_null_text); - g_test_add_func("/hmac/sha1/null key and text", - test_hmac_sha1_null_key_and_text); - - return g_test_run(); -}
--- a/libpurple/tests/test_md5.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,107 +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 <glib.h> - -#include <purple.h> - -#include "ciphers/md5hash.h" - -static void -test_md5hash(gchar *data, gchar *digest) { - PurpleHash *hash = NULL; - gchar cdigest[33]; - gboolean ret = FALSE; - - hash = purple_md5_hash_new(); - - purple_hash_append(hash, (guchar *)data, strlen(data)); - - ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); - - g_assert(ret); - g_assert_cmpstr(digest, ==, cdigest); -} - -static void -test_md5hash_empty_string(void) { - test_md5hash("", - "d41d8cd98f00b204e9800998ecf8427e"); -} - -static void -test_md5hash_a(void) { - test_md5hash("a", - "0cc175b9c0f1b6a831c399e269772661"); -} - -static void -test_md5hash_abc(void) { - test_md5hash("abc", - "900150983cd24fb0d6963f7d28e17f72"); -} - -static void -test_md5hash_message_digest(void) { - test_md5hash("message digest", - "f96b697d7cb7938d525a2f31aaf161d0"); -} - -static void -test_md5hash_a_to_z(void) { - test_md5hash("abcdefghijklmnopqrstuvwxyz", - "c3fcd3d76192e4007dfb496cca67e13b"); -} - -static void -test_md5hash_A_to_Z_a_to_z_0_to_9(void) { - test_md5hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789", - "d174ab98d277d9f5a5611c2c9f419d9f"); -} - -static void -test_md5hash_1_to_0_eight_times(void) { - test_md5hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890", - "57edf4a22be3c955ac49da2e2107b67a"); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/hash/md5/empty-string", - test_md5hash_empty_string); - g_test_add_func("/hash/md5/a", - test_md5hash_a); - g_test_add_func("/hash/md5/abc", - test_md5hash_abc); - g_test_add_func("/hash/md5/message digest", - test_md5hash_message_digest); - g_test_add_func("/hash/md5/a to z", - test_md5hash_a_to_z); - g_test_add_func("/hash/md5/A to Z, a to z, 0 to 9" , - test_md5hash_A_to_Z_a_to_z_0_to_9); - g_test_add_func("/hash/md5/1 to 0 eight times", - test_md5hash_1_to_0_eight_times); - - return g_test_run(); -}
--- a/libpurple/tests/test_sha1.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +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 <glib.h> - -#include <purple.h> - -#include "ciphers/sha1hash.h" - -static void -test_sha1hash(gchar *data, gchar *digest) { - PurpleHash *hash = NULL; - gchar cdigest[41]; - gboolean ret = FALSE; - - hash = purple_sha1_hash_new(); - - if(data) { - purple_hash_append(hash, (guchar *)data, strlen(data)); - } else { - gint j; - guchar buff[1000]; - - memset(buff, 'a', 1000); - - for(j = 0; j < 1000; j++) - purple_hash_append(hash, buff, 1000); - } - - ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); - - g_assert(ret); - g_assert_cmpstr(digest, ==, cdigest); -} - -static void -test_sha1hash_empty_string(void) { - test_sha1hash("", - "da39a3ee5e6b4b0d3255bfef95601890afd80709"); -} - -static void -test_sha1hash_a(void) { - test_sha1hash("a", - "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8"); -} - -static void -test_sha1hash_abc(void) { - test_sha1hash("abc", - "a9993e364706816aba3e25717850c26c9cd0d89d"); -} - -static void -test_sha1hash_abcd_gibberish(void) { - test_sha1hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "84983e441c3bd26ebaae4aa1f95129e5e54670f1"); -} - -static void -test_sha1hash_1000_as_1000_times(void) { - test_sha1hash(NULL, - "34aa973cd4c4daa4f61eeb2bdbad27316534016f"); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/hash/sha1/empty-string", - test_sha1hash_empty_string); - g_test_add_func("/hash/sha1/a", - test_sha1hash_a); - g_test_add_func("/hash/sha1/abc", - test_sha1hash_abc); - g_test_add_func("/hash/sha1/abcd_gibberish", - test_sha1hash_abcd_gibberish); - g_test_add_func("/hash/sha1/1000 a's 1000 times", - test_sha1hash_1000_as_1000_times); - - return g_test_run(); -}
--- a/libpurple/tests/test_sha256.c Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,101 +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 <glib.h> - -#include <purple.h> - -#include "ciphers/sha256hash.h" - -static void -test_sha256hash(gchar *data, gchar *digest) { - PurpleHash *hash = NULL; - gchar cdigest[65]; - gboolean ret = FALSE; - - hash = purple_sha256_hash_new(); - - if(data) { - purple_hash_append(hash, (guchar *)data, strlen(data)); - } else { - gint j; - guchar buff[1000]; - - memset(buff, 'a', 1000); - - for(j = 0; j < 1000; j++) - purple_hash_append(hash, buff, 1000); - } - - ret = purple_hash_digest_to_str(hash, cdigest, sizeof(cdigest)); - - g_assert(ret); - g_assert_cmpstr(digest, ==, cdigest); -} - -static void -test_sha256hash_empty_string(void) { - test_sha256hash("", - "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855"); -} - -static void -test_sha256hash_a(void) { - test_sha256hash("a", - "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb"); -} - -static void -test_sha256hash_abc(void) { - test_sha256hash("abc", - "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad"); -} - -static void -test_sha256hash_abcd_gibberish(void) { - test_sha256hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq", - "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1"); -} - -static void -test_sha256hash_1000_as_1000_times(void) { - test_sha256hash(NULL, - "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0"); -} - -gint -main(gint argc, gchar **argv) { - g_test_init(&argc, &argv, NULL); - - g_test_add_func("/hash/sha256/empty-string", - test_sha256hash_empty_string); - g_test_add_func("/hash/sha256/a", - test_sha256hash_a); - g_test_add_func("/hash/sha256/abc", - test_sha256hash_abc); - g_test_add_func("/hash/sha256/abcd_gibberish", - test_sha256hash_abcd_gibberish); - g_test_add_func("/hash/sha256/1000 a's 1000 times", - test_sha256hash_1000_as_1000_times); - - return g_test_run(); -}
--- a/libpurple/tests/test_util.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/tests/test_util.c Mon Jun 05 16:36:29 2017 +0300 @@ -43,24 +43,6 @@ } /****************************************************************************** - * base 64 tests - *****************************************************************************/ -static void -test_util_base_64_encode(void) { - gchar *in = purple_base64_encode((const unsigned char *)"forty-two", 10); - g_assert_cmpstr("Zm9ydHktdHdvAA==", ==, in); -} - -static void -test_util_base_64_decode(void) { - gsize sz = 0; - guchar *out = purple_base64_decode("b3d0LXl0cm9mAA==", &sz); - - g_assert_cmpint(sz, ==, 10); - g_assert_cmpstr("owt-ytrof", ==, (gchar *)out); -} - -/****************************************************************************** * filename escape tests *****************************************************************************/ static void @@ -512,11 +494,6 @@ g_test_add_func("/util/base/16/decode", test_util_base_16_decode); - g_test_add_func("/util/base/64/encode", - test_util_base_64_encode); - g_test_add_func("/util/base/64/decode", - test_util_base_64_decode); - g_test_add_func("/util/filename/escape", test_util_filename_escape); g_test_add_func("/util/filename/unescape",
--- a/libpurple/tls-certificate-info.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/tls-certificate-info.c Mon Jun 05 16:36:29 2017 +0300 @@ -23,7 +23,6 @@ #include "internal.h" #include "tls-certificate-info.h" -#include "ciphers/sha1hash.h" #include "debug.h" #include "util.h" @@ -789,7 +788,7 @@ GByteArray * purple_tls_certificate_get_fingerprint_sha1(GTlsCertificate *certificate) { - PurpleHash *hash; + GChecksum *hash; GByteArray *der = NULL; guint8 *data = NULL; gsize buf_size = 0; @@ -800,16 +799,16 @@ g_return_val_if_fail(der != NULL, NULL); - hash = purple_sha1_hash_new(); + hash = g_checksum_new(G_CHECKSUM_SHA1); - buf_size = purple_hash_get_digest_size(hash); + buf_size = g_checksum_type_get_length(G_CHECKSUM_SHA1); data = g_malloc(buf_size); - purple_hash_append(hash, der->data, der->len); + g_checksum_update(hash, der->data, der->len); g_byte_array_unref(der); - purple_hash_digest(hash, data, buf_size); - g_object_unref(hash); + g_checksum_get_digest(hash, data, &buf_size); + g_checksum_free(hash); return g_byte_array_new_take(data, buf_size); }
--- a/libpurple/util.c Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/util.c Mon Jun 05 16:36:29 2017 +0300 @@ -18,7 +18,6 @@ */ #include "internal.h" -#include "ciphers/md5hash.h" #include "conversation.h" #include "core.h" #include "debug.h" @@ -330,34 +329,12 @@ return ascii; } - /************************************************************************** - * Base64 Functions + * Quoted Printable Functions (see RFC 2045). **************************************************************************/ static const char xdigits[] = "0123456789abcdef"; -gchar * -purple_base64_encode(const guchar *data, gsize len) -{ - return g_base64_encode(data, len); -} - -guchar * -purple_base64_decode(const char *str, gsize *ret_len) -{ - /* - * We want to allow ret_len to be NULL for backward compatibility, - * but g_base64_decode() requires a valid length variable. So if - * ret_len is NULL then pass in a dummy variable. - */ - gsize unused; - return g_base64_decode(str, ret_len != NULL ? ret_len : &unused); -} - -/************************************************************************** - * Quoted Printable Functions (see RFC 2045). - **************************************************************************/ guchar * purple_quotedp_decode(const char *str, gsize *ret_len) { @@ -517,7 +494,7 @@ if (g_ascii_strcasecmp(encoding, "Q") == 0) decoded = purple_quotedp_decode(encoded_text, &dec_len); else if (g_ascii_strcasecmp(encoding, "B") == 0) - decoded = purple_base64_decode(encoded_text, &dec_len); + decoded = g_base64_decode(encoded_text, &dec_len); else decoded = NULL; if (decoded) { @@ -1424,8 +1401,7 @@ purple_markup_unescape_entity(const char *text, int *length) { const char *pln; - int len, pound; - char temp[2]; + int len; if (!text || *text != '&') return NULL; @@ -4961,9 +4937,8 @@ const gchar *nonce, const gchar *client_nonce) { - PurpleHash *hasher; - gchar hash[33]; /* We only support MD5. */ - gboolean digest_ok; + GChecksum *hasher; + gchar *hash; g_return_val_if_fail(username != NULL, NULL); g_return_val_if_fail(realm != NULL, NULL); @@ -4976,18 +4951,19 @@ g_ascii_strcasecmp(algorithm, "MD5") || g_ascii_strcasecmp(algorithm, "MD5-sess"), NULL); - hasher = purple_md5_hash_new(); - g_return_val_if_fail(hash != NULL, NULL); - - purple_hash_append(hasher, (guchar *)username, strlen(username)); - purple_hash_append(hasher, (guchar *)":", 1); - purple_hash_append(hasher, (guchar *)realm, strlen(realm)); - purple_hash_append(hasher, (guchar *)":", 1); - purple_hash_append(hasher, (guchar *)password, strlen(password)); + hasher = g_checksum_new(G_CHECKSUM_MD5); + g_return_val_if_fail(hasher != NULL, NULL); + + g_checksum_update(hasher, (guchar *)username, -1); + g_checksum_update(hasher, (guchar *)":", -1); + g_checksum_update(hasher, (guchar *)realm, -1); + g_checksum_update(hasher, (guchar *)":", -1); + g_checksum_update(hasher, (guchar *)password, -1); if (algorithm != NULL && !g_ascii_strcasecmp(algorithm, "MD5-sess")) { guchar digest[16]; + gsize digest_len = 16; if (client_nonce == NULL) { @@ -4996,22 +4972,20 @@ return NULL; } - purple_hash_digest(hasher, digest, sizeof(digest)); - - purple_hash_reset(hasher); - purple_hash_append(hasher, digest, sizeof(digest)); - purple_hash_append(hasher, (guchar *)":", 1); - purple_hash_append(hasher, (guchar *)nonce, strlen(nonce)); - purple_hash_append(hasher, (guchar *)":", 1); - purple_hash_append(hasher, (guchar *)client_nonce, strlen(client_nonce)); + g_checksum_get_digest(hasher, digest, &digest_len); + + g_checksum_reset(hasher); + g_checksum_update(hasher, digest, sizeof(digest)); + g_checksum_update(hasher, (guchar *)":", -1); + g_checksum_update(hasher, (guchar *)nonce, -1); + g_checksum_update(hasher, (guchar *)":", -1); + g_checksum_update(hasher, (guchar *)client_nonce, -1); } - digest_ok = purple_hash_digest_to_str(hasher, hash, sizeof(hash)); - g_object_unref(hasher); - - g_return_val_if_fail(digest_ok, NULL); - - return g_strdup(hash); + hash = g_strdup(g_checksum_get_string(hasher)); + g_checksum_free(hasher); + + return hash; } gchar *purple_http_digest_calculate_response( @@ -5025,9 +4999,8 @@ const gchar *client_nonce, const gchar *session_key) { - PurpleHash *hash; - static gchar hash2[33]; /* We only support MD5. */ - gboolean digest_ok; + GChecksum *hash; + gchar *hash2; g_return_val_if_fail(method != NULL, NULL); g_return_val_if_fail(digest_uri != NULL, NULL); @@ -5046,85 +5019,83 @@ g_ascii_strcasecmp(qop, "auth") || g_ascii_strcasecmp(qop, "auth-int"), NULL); - hash = purple_md5_hash_new(); + hash = g_checksum_new(G_CHECKSUM_MD5); g_return_val_if_fail(hash != NULL, NULL); - purple_hash_append(hash, (guchar *)method, strlen(method)); - purple_hash_append(hash, (guchar *)":", 1); - purple_hash_append(hash, (guchar *)digest_uri, strlen(digest_uri)); + g_checksum_update(hash, (guchar *)method, -1); + g_checksum_update(hash, (guchar *)":", -1); + g_checksum_update(hash, (guchar *)digest_uri, -1); if (qop != NULL && !g_ascii_strcasecmp(qop, "auth-int")) { - PurpleHash *hash2; - gchar entity_hash[33]; + gchar *entity_hash; if (entity == NULL) { - g_object_unref(hash); + g_checksum_free(hash); purple_debug_error("hash", "Required entity missing for auth-int digest calculation.\n"); return NULL; } - hash2 = purple_md5_hash_new(); - purple_hash_append(hash2, (guchar *)entity, strlen(entity)); - digest_ok = purple_hash_digest_to_str(hash2, entity_hash, sizeof(entity_hash)); - g_object_unref(hash2); - - if (!digest_ok) { - g_object_unref(hash); + entity_hash = g_compute_checksum_for_string(G_CHECKSUM_MD5, + entity, -1); + + if (entity_hash == NULL) { + g_checksum_free(hash); g_return_val_if_reached(NULL); } - purple_hash_append(hash, (guchar *)":", 1); - purple_hash_append(hash, (guchar *)entity_hash, strlen(entity_hash)); + g_checksum_update(hash, (guchar *)":", -1); + g_checksum_update(hash, (guchar *)entity_hash, -1); + g_free(entity_hash); } - digest_ok = purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); - purple_hash_reset(hash); - - if (!digest_ok) { - g_object_unref(hash); + hash2 = g_strdup(g_checksum_get_string(hash)); + g_checksum_reset(hash); + + if (hash2 == NULL) { + g_checksum_free(hash); g_return_val_if_reached(NULL); } - purple_hash_append(hash, (guchar *)session_key, strlen(session_key)); - purple_hash_append(hash, (guchar *)":", 1); - purple_hash_append(hash, (guchar *)nonce, strlen(nonce)); - purple_hash_append(hash, (guchar *)":", 1); + g_checksum_update(hash, (guchar *)session_key, -1); + g_checksum_update(hash, (guchar *)":", -1); + g_checksum_update(hash, (guchar *)nonce, -1); + g_checksum_update(hash, (guchar *)":", -1); if (qop != NULL && *qop != '\0') { if (nonce_count == NULL) { - g_object_unref(hash); + g_checksum_free(hash); purple_debug_error("hash", "Required nonce_count missing for digest calculation.\n"); return NULL; } if (client_nonce == NULL) { - g_object_unref(hash); + g_checksum_free(hash); purple_debug_error("hash", "Required client_nonce missing for digest calculation.\n"); return NULL; } - purple_hash_append(hash, (guchar *)nonce_count, strlen(nonce_count)); - purple_hash_append(hash, (guchar *)":", 1); - purple_hash_append(hash, (guchar *)client_nonce, strlen(client_nonce)); - purple_hash_append(hash, (guchar *)":", 1); - - purple_hash_append(hash, (guchar *)qop, strlen(qop)); - - purple_hash_append(hash, (guchar *)":", 1); + g_checksum_update(hash, (guchar *)nonce_count, -1); + g_checksum_update(hash, (guchar *)":", -1); + g_checksum_update(hash, (guchar *)client_nonce, -1); + g_checksum_update(hash, (guchar *)":", -1); + + g_checksum_update(hash, (guchar *)qop, -1); + + g_checksum_update(hash, (guchar *)":", -1); } - purple_hash_append(hash, (guchar *)hash2, strlen(hash2)); - digest_ok = purple_hash_digest_to_str(hash, hash2, sizeof(hash2)); - g_object_unref(hash); - - g_return_val_if_fail(digest_ok, NULL); - - return g_strdup(hash2); + g_checksum_update(hash, (guchar *)hash2, -1); + g_free(hash2); + + hash2 = g_strdup(g_checksum_get_string(hash)); + g_checksum_free(hash); + + return hash2; } int
--- a/libpurple/util.h Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/util.h Mon Jun 05 16:36:29 2017 +0300 @@ -287,43 +287,6 @@ */ gchar *purple_base16_encode_chunked(const guchar *data, gsize len); - -/**************************************************************************/ -/* Base64 Functions */ -/**************************************************************************/ - -/** - * purple_base64_encode: - * @data: The data to convert. - * @len: The length of the data. - * - * Converts a chunk of binary data to its base-64 equivalent. - * - * See purple_base64_decode() - * - * Returns: The base-64 string in the ASCII encoding. Must be - * g_free'd when no longer needed. - */ -gchar *purple_base64_encode(const guchar *data, gsize len); - -/** - * purple_base64_decode: - * @str: The base-64 string to convert to raw data. - * @ret_len: The length of the returned data. You can - * pass in NULL if you're sure that you know - * the length of the decoded data, or if you - * know you'll be able to use strlen to - * determine the length, etc. - * - * Converts an ASCII string of base-64 encoded data to - * the binary equivalent. - * - * See purple_base64_encode() - * - * Returns: The raw data. Must be g_free'd when no longer needed. - */ -guchar *purple_base64_decode(const char *str, gsize *ret_len); - /**************************************************************************/ /* Quoted Printable Functions */ /**************************************************************************/
--- a/libpurple/win32/global.mak Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/win32/global.mak Mon Jun 05 16:36:29 2017 +0300 @@ -25,7 +25,6 @@ LIBXML2_TOP ?= $(WIN32_DEV_TOP)/libxml2-2.9.2_daa1 MEANWHILE_TOP ?= $(WIN32_DEV_TOP)/meanwhile-1.0.2_daa3 NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.24-nspr-4.12 -PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl-5.20.1.1 SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.12 GSTREAMER_TOP ?= $(WIN32_DEV_TOP)/gstreamer-0.10.13 GCC_SSP_TOP ?= $(shell dirname $(shell which $(CC))) @@ -40,15 +39,12 @@ 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 @@ -63,7 +59,6 @@ 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
--- a/libpurple/win32/rules.mak Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/win32/rules.mak Mon Jun 05 16:36:29 2017 +0300 @@ -3,9 +3,6 @@ %.o: %.c $(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $< -%.c: %.xs - $(TAG) "PERL" $(PERL) -MExtUtils::ParseXS -e 'ExtUtils::ParseXS::process_file(filename => "$<", output => "$@", typemap => "$(PURPLE_PERL_TOP)/common/typemap");' - %.o: %.rc @echo -e " GEN\t$@" @$(WINDRES) -I$(PURPLE_TOP) -i $< -o $@
--- a/libpurple/win32/targets.mak Sun May 28 13:26:27 2017 +0300 +++ b/libpurple/win32/targets.mak Mon Jun 05 16:36:29 2017 +0300 @@ -35,9 +35,6 @@ $(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_at) $(MAKE) -C $(PIDGIN_TOP) -f $(MINGW_MAKEFILE) pidgin.dll @@ -48,9 +45,6 @@ $(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) @@ -59,6 +53,3 @@ #$(PURPLE_INSTALL_PLUGINS_DIR): # mkdir -p $(PURPLE_INSTALL_PLUGINS_DIR) - -#$(PURPLE_INSTALL_PERL_DIR): -# mkdir -p $(PURPLE_INSTALL_PERL_DIR)
--- a/pidgin/gtkdialogs.c Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/gtkdialogs.c Mon Jun 05 16:36:29 2017 +0300 @@ -683,25 +683,6 @@ g_string_append(str, "<dt>Network Security Services (NSS):</dt><dd>Disabled</dd>"); #endif -#warning TODO: Check for perl. - if (purple_plugins_find_plugin("core-perl") != NULL) - g_string_append(str, "<dt>Perl:</dt><dd>Enabled</dd>"); - else - g_string_append(str, "<dt>Perl:</dt><dd>Disabled</dd>"); - -#warning TODO: Check for tcl. - if (purple_plugins_find_plugin("core-tcl") != NULL) { - g_string_append(str, "<dt>Tcl:</dt><dd>Enabled</dd>"); -#ifdef HAVE_TK - g_string_append(str, "<dt>Tk:</dt><dd>Enabled</dd>"); -#else - g_string_append(str, "<dt>Tk:</dt><dd>Disabled</dd>"); -#endif - } else { - g_string_append(str, "<dt>Tcl:</dt><dd>Disabled</dd>"); - g_string_append(str, "<dt>Tk:</dt><dd>Disabled</dd>"); - } - #ifdef USE_IDN g_string_append(str, "<dt>UTF-8 DNS (IDN):</dt><dd>Enabled</dd>"); #else
--- a/pidgin/gtkwebview.c Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/gtkwebview.c Mon Jun 05 16:36:29 2017 +0300 @@ -204,8 +204,7 @@ gchar *b64, *src; const gchar *type; - b64 = purple_base64_encode( - purple_image_get_data(img), + b64 = g_base64_encode(purple_image_get_data(img), purple_image_get_data_size(img)); type = purple_image_get_mimetype(img); src = g_strdup_printf("data:%s;base64,%s", type, b64);
--- a/pidgin/plugins/Makefile.mingw Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/plugins/Makefile.mingw Mon Jun 05 16:36:29 2017 +0300 @@ -8,7 +8,6 @@ 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 @@ -66,14 +65,12 @@ all: plugins $(MAKE_at) $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) - $(MAKE_at) $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE_at) $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE_at) $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) $(MAKE_at) $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install: all $(PIDGIN_INSTALL_PLUGINS_DIR) $(MAKE_at) $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) install - $(MAKE_at) $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE_at) $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE_at) $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) install $(MAKE_at) $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) install @@ -106,7 +103,6 @@ clean: rm -f *.o *.dll $(MAKE_at) $(MAKE) -C $(DISCO_PLUGIN) -f $(MINGW_MAKEFILE) clean - $(MAKE_at) $(MAKE) -C $(GTKPERL_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE_at) $(MAKE) -C $(TICKER_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE_at) $(MAKE) -C $(TRANSPARENCY_PLUGIN) -f $(MINGW_MAKEFILE) clean $(MAKE_at) $(MAKE) -C $(WINPREFS_PLUGIN) -f $(MINGW_MAKEFILE) clean
--- a/pidgin/plugins/imgupload.c Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/plugins/imgupload.c Mon Jun 05 16:36:29 2017 +0300 @@ -121,7 +121,7 @@ "Client-ID " IMGUP_IMGUR_CLIENT_ID); /* TODO: make it a plain, multipart/form-data request */ - img_data = purple_base64_encode(purple_image_get_data(image), + img_data = g_base64_encode(purple_image_get_data(image), purple_image_get_data_size(image)); img_data_e = g_uri_escape_string(img_data, NULL, FALSE); g_free(img_data);
--- a/pidgin/plugins/perl/Makefile.am Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,106 +0,0 @@ -perl_dirs = common - -common_sources = \ - common/GtkAccount.xs \ - common/GtkBlist.xs \ - common/GtkConn.xs \ - common/GtkConv.xs \ - common/GtkConvWin.xs \ - common/GtkDebug.xs \ - common/GtkDialogs.xs \ - common/GtkFt.xs \ - common/GtkLog.xs \ - common/GtkMenuTray.xs \ - common/GtkPlugin.xs \ - common/GtkPluginPref.xs \ - common/GtkPounce.xs \ - common/GtkPrefs.xs \ - common/GtkPrivacy.xs \ - common/GtkRoomlist.xs \ - common/GtkSavedStatuses.xs \ - common/GtkSession.xs \ - common/GtkSound.xs \ - common/GtkStatusBox.xs \ - common/GtkUtils.xs \ - common/Makefile.PL.in \ - common/Pidgin.pm \ - common/Pidgin.xs \ - common/gtkmodule.h \ - common/typemap - -EXTRA_DIST = \ - Makefile.mingw \ - common/Makefile.mingw \ - $(common_sources) - -common/Makefile: common/Makefile.PL - $(AM_V_GEN)if test "x${top_srcdir}" != "x${top_builddir}"; then \ - for f in ${common_sources}; do \ - srcloc=${srcdir}; \ - case $$srcloc in /*) ;; *) srcloc=../${srcdir} ;; esac; \ - ${LN_S} -f $$srcloc/$$f $$f; \ - done; \ - fi - $(AM_V_at)cd common && $(perlpath) Makefile.PL > /dev/null - -common/Makefile.PL: common/Makefile.PL.in $(top_builddir)/config.status - cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe) - -all-local: common/Makefile - @for dir in $(perl_dirs); do \ - cd $$dir && \ - if [ ! -f Makefile ]; then \ - $(perlpath) Makefile.PL; \ - fi && \ - ($(MAKE) CC="@$(abs_top_srcdir)/libpurple/tag.sh CC $(CC)" LD="@$(abs_top_srcdir)/libpurple/tag.sh LD $(CC)" PERLRUN="@$(abs_top_srcdir)/libpurple/tag.sh PERL $(PERL)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" CP="@cp" RM_F="@rm -f" CHMOD="@chmod" $(PERL_EXTRA_OPTS) || \ - $(MAKE) CC="@$(abs_top_srcdir)/libpurple/tag.sh CC $(CC)" LD="@$(abs_top_srcdir)/libpurple/tag.sh LD $(CC)" PERLRUN="@$(abs_top_srcdir)/libpurple/tag.sh PERL $(PERL)" CCFLAGS="$(PERL_CFLAGS) $(CFLAGS)" CP="@cp" RM_F="@rm -f" CHMOD="@chmod" $(PERL_EXTRA_OPTS)) && \ - cd ..; \ - done - -install-exec-local: - @for dir in $(perl_dirs); do \ - cd $$dir; \ - $(MAKE) install; \ - cd ..; \ - done - -# Evil Hack (TM) -# ... which doesn't work with DESTDIR installs. FIXME? -uninstall-local: - @for dir in $(perl_dirs); do \ - cd $$dir && \ - `$(MAKE) uninstall | grep unlink | sed -e 's#/usr#${prefix}#' -e 's#unlink#rm -f#'` && \ - cd ..; \ - done - -clean-generic: - @for dir in $(perl_dirs); do \ - cd $$dir; \ - $(MAKE) clean; \ - cd ..; \ - done - cd common ; rm -rf *.c *.o pm_to_blib Pidgin.bs MYMETA.* blib/*/.exists blib/*/auto/Pidgin blib/*/Pidgin.*pm ; cd .. - rm -f *.so - -distclean-generic: - @for dir in $(perl_dirs); do \ - cd $$dir; \ - $(MAKE) realclean; \ - rm -f Makefile.PL; \ - rm -f Makefile.old; \ - rm -f Makefile; \ - cd ..; \ - done - - @rm -f Makefile - -AM_CPPFLAGS = \ - -I$(top_srcdir) \ - -I$(top_srcdir)/libpurple \ - -I$(top_builddir)/libpurple \ - -I$(top_srcdir)/pidgin \ - $(DEBUG_CFLAGS) \ - $(GTK_CFLAGS) \ - $(GPLUGIN_CFLAGS) \ - $(PLUGIN_CFLAGS) \ - $(PERL_CFLAGS)
--- a/pidgin/plugins/perl/Makefile.mingw Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for perl plugin loader plugin. -# - -PIDGIN_TREE_TOP := ../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -#we cannot include win32dep.h, but we need struct sockaddr_in6 definition -CFLAGS += -include ws2tcpip.h - -## -## TARGET DEFINITIONS -## -.PHONY: all install clean - -all: - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) - -install: all $(PIDGIN_INSTALL_PLUGINS_DIR) - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install - -## -## CLEAN RULES -## -clean: - $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) clean
--- a/pidgin/plugins/perl/common/GtkAccount.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Account PACKAGE = Pidgin::Account PREFIX = pidgin_account_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_accounts_get_handle() - -MODULE = Pidgin::Account PACKAGE = Pidgin::Account::Dialog PREFIX = pidgin_account_dialog_ -PROTOTYPES: ENABLE - -void -pidgin_account_dialog_show(type, account) - Pidgin::Account::Dialog::Type type - Purple::Account account - -MODULE = Pidgin::Account PACKAGE = Pidgin::Account::Window PREFIX = pidgin_accounts_window_ -PROTOTYPES: ENABLE - -void -pidgin_accounts_window_show() - -void -pidgin_accounts_window_hide()
--- a/pidgin/plugins/perl/common/GtkBlist.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,71 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::BuddyList PACKAGE = Pidgin::BuddyList PREFIX = pidgin_blist_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_blist_get_handle() - -Pidgin::BuddyList -pidgin_blist_get_default_gtk_blist() - -void -pidgin_blist_refresh(list) - Purple::BuddyList list - -void -pidgin_blist_update_refresh_timeout() - -gboolean -pidgin_blist_node_is_contact_expanded(node) - Purple::BuddyList::Node node - -void -pidgin_blist_toggle_visibility() - -void -pidgin_blist_visibility_manager_add() - -void -pidgin_blist_visibility_manager_remove() - -void -pidgin_blist_get_sort_methods() -PREINIT: - GList *l; -PPCODE: - for (l = pidgin_blist_get_sort_methods(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::BuddyList::SortMethod"))); - } - -void -pidgin_blist_sort_method_reg(id, name, func) - const char * id - const char * name - Pidgin::BuddyList::SortFunction func - -void -pidgin_blist_sort_method_unreg(id) - const char * id - -void -pidgin_blist_sort_method_set(id) - const char * id - -void -pidgin_blist_setup_sort_methods() - -void -pidgin_blist_update_accounts_menu() - -void -pidgin_blist_update_plugin_actions() - -void -pidgin_blist_update_sort_methods() - -gboolean -pidgin_blist_joinchat_is_showable() - -void -pidgin_blist_joinchat_show()
--- a/pidgin/plugins/perl/common/GtkConn.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Connection PACKAGE = Pidgin::Connection PREFIX = pidgin_connection_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_connection_get_handle()
--- a/pidgin/plugins/perl/common/GtkConv.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,67 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Conversation PACKAGE = Pidgin::Conversation PREFIX = pidgin_conv_ -PROTOTYPES: ENABLE - -void -pidgin_conv_update_buddy_icon(im) - Purple::IMConversation im - -void -pidgin_conv_switch_active_conversation(conv) - Purple::Conversation conv - -void -pidgin_conv_update_buttons_by_protocol(conv) - Purple::Conversation conv - -void -pidgin_conv_present_conversation(conv) - Purple::Conversation conv - -Pidgin::Conversation::Window -pidgin_conv_get_window(conv) - Pidgin::Conversation conv - -void -pidgin_conv_new(class, conv) - Purple::Conversation conv - C_ARGS: - conv - -gboolean -pidgin_conv_is_hidden(gtkconv) - Pidgin::Conversation gtkconv - -void -pidgin_conv_get_gtkconv(conv) - Purple::Conversation conv -PPCODE: - if (conv != NULL && PIDGIN_IS_PIDGIN_CONVERSATION(conv)) - XPUSHs(sv_2mortal(purple_perl_bless_object( - PIDGIN_CONVERSATION(conv), - "Pidgin::Conversation"))); - -MODULE = Pidgin::Conversation PACKAGE = Pidgin::Conversations PREFIX = pidgin_conversations_ -PROTOTYPES: ENABLE - -void -pidgin_conversations_get_unseen_all(min_state, hidden_only, max_count) - Pidgin::UnseenState min_state - gboolean hidden_only - guint max_count - -void -pidgin_conversations_get_unseen_ims(min_state, hidden_only, max_count) - Pidgin::UnseenState min_state - gboolean hidden_only - guint max_count - -void -pidgin_conversations_get_unseen_chats(min_state, hidden_only, max_count) - Pidgin::UnseenState min_state - gboolean hidden_only - guint max_count - -Purple::Handle -pidgin_conversations_get_handle()
--- a/pidgin/plugins/perl/common/GtkConvWin.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,139 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Window PREFIX = pidgin_conv_window_ -PROTOTYPES: ENABLE - -Pidgin::Conversation::Window -pidgin_conv_window_new(class) - C_ARGS: /* void */ - -void -pidgin_conv_window_destroy(win) - Pidgin::Conversation::Window win - -void -pidgin_conv_window_show(win) - Pidgin::Conversation::Window win - -void -pidgin_conv_window_hide(win) - Pidgin::Conversation::Window win - -void -pidgin_conv_window_raise(win) - Pidgin::Conversation::Window win - -void -pidgin_conv_window_switch_gtkconv(win, gtkconv) - Pidgin::Conversation::Window win - Pidgin::Conversation gtkconv - -void -pidgin_conv_window_add_gtkconv(win, gtkconv) - Pidgin::Conversation::Window win - Pidgin::Conversation gtkconv - -void -pidgin_conv_window_remove_gtkconv(win, gtkconv) - Pidgin::Conversation::Window win - Pidgin::Conversation gtkconv - -Pidgin::Conversation -pidgin_conv_window_get_gtkconv_at_index(win, index) - Pidgin::Conversation::Window win - int index - -Pidgin::Conversation -pidgin_conv_window_get_active_gtkconv(win) - Pidgin::Conversation::Window win - -Purple::Conversation -pidgin_conv_window_get_active_conversation(win) - Pidgin::Conversation::Window win - -gboolean -pidgin_conv_window_is_active_conversation(conv) - Purple::Conversation conv - -gboolean -pidgin_conv_window_has_focus(win) - Pidgin::Conversation::Window win - -void -pidgin_conv_window_get_gtkconvs(win) - Pidgin::Conversation::Window win -PREINIT: - GList *l; -PPCODE: - for (l = pidgin_conv_window_get_gtkconvs(win); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::Conversation"))); - } - -guint -pidgin_conv_window_get_gtkconv_count(win) - Pidgin::Conversation::Window win - -Pidgin::Conversation::Window -pidgin_conv_window_first_im() - -Pidgin::Conversation::Window -pidgin_conv_window_last_im() - -Pidgin::Conversation::Window -pidgin_conv_window_first_chat() - -Pidgin::Conversation::Window -pidgin_conv_window_last_chat() - -MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Placement PREFIX = pidgin_conv_placement_ -PROTOTYPES: ENABLE - -void -pidgin_conv_placement_get_options() -PREINIT: - GList *l; -PPCODE: - for (l = pidgin_conv_placement_get_options(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::Conversation::Window"))); - } - -void -pidgin_conv_placement_add_fnc(id, name, fnc) - const char * id - const char * name - Pidgin::Conversation::PlacementFunc fnc - -void -pidgin_conv_placement_remove_fnc(id) - const char * id - -const char * -pidgin_conv_placement_get_name(id) - const char * id - -Pidgin::Conversation::PlacementFunc -pidgin_conv_placement_get_fnc(id) - const char * id - -void -pidgin_conv_placement_set_current_func(func) - Pidgin::Conversation::PlacementFunc func - -Pidgin::Conversation::PlacementFunc -pidgin_conv_placement_get_current_func() - -void -pidgin_conv_placement_place(gtkconv) - Pidgin::Conversation gtkconv - -MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Windows PREFIX = pidgin_conv_windows_ -PROTOTYPES: ENABLE - -void -pidgin_conv_windows_get_list() -PREINIT: - GList *l; -PPCODE: - for (l = pidgin_conv_windows_get_list(); l != NULL; l = l->next) { - XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::Conversation::Window"))); - }
--- a/pidgin/plugins/perl/common/GtkDebug.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,16 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Debug PACKAGE = Pidgin::Debug PREFIX = pidgin_debug_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_debug_get_handle() - -MODULE = Pidgin::Debug PACKAGE = Pidgin::Debug::Window PREFIX = pidgin_debug_window_ -PROTOTYPES: ENABLE - -void -pidgin_debug_window_show() - -void -pidgin_debug_window_hide()
--- a/pidgin/plugins/perl/common/GtkDialogs.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,48 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Dialogs PACKAGE = Pidgin::Dialogs PREFIX = pidgin_dialogs_ -PROTOTYPES: ENABLE - -void -pidgin_dialogs_destroy_all() - -void -pidgin_dialogs_about() - -void -pidgin_dialogs_im() - -void -pidgin_dialogs_im_with_user(account, username) - Purple::Account account - const char * username - -void -pidgin_dialogs_info() - -void -pidgin_dialogs_log() - -void -pidgin_dialogs_alias_buddy(buddy) - Purple::BuddyList::Buddy buddy - -void -pidgin_dialogs_alias_chat(chat) - Purple::BuddyList::Chat chat - -void -pidgin_dialogs_remove_buddy(buddy) - Purple::BuddyList::Buddy buddy - -void -pidgin_dialogs_remove_group(group) - Purple::BuddyList::Group group - -void -pidgin_dialogs_remove_chat(chat) - Purple::BuddyList::Chat chat - -void -pidgin_dialogs_remove_contact(contact) - Purple::BuddyList::Contact contact
--- a/pidgin/plugins/perl/common/GtkFt.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,50 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Xfer PACKAGE = Pidgin::Xfer PREFIX = pidgin_ -PROTOTYPES: ENABLE - -void -pidgin_set_xfer_dialog(dialog) - Pidgin::Xfer::Dialog dialog - -Pidgin::Xfer::Dialog -pidgin_get_xfer_dialog() - -MODULE = Pidgin::Xfer PACKAGE = Pidgin::Xfer::Dialog PREFIX = pidgin_xfer_dialog_ -PROTOTYPES: ENABLE - -Pidgin::Xfer::Dialog -pidgin_xfer_dialog_new(class) - C_ARGS: /* void */ - -void -pidgin_xfer_dialog_destroy(dialog) - Pidgin::Xfer::Dialog dialog - -void -pidgin_xfer_dialog_show(dialog = NULL) - Pidgin::Xfer::Dialog dialog - -void -pidgin_xfer_dialog_hide(dialog) - Pidgin::Xfer::Dialog dialog - -void -pidgin_xfer_dialog_add_xfer(dialog, xfer) - Pidgin::Xfer::Dialog dialog - Purple::Xfer xfer - -void -pidgin_xfer_dialog_remove_xfer(dialog, xfer) - Pidgin::Xfer::Dialog dialog - Purple::Xfer xfer - -void -pidgin_xfer_dialog_cancel_xfer(dialog, xfer) - Pidgin::Xfer::Dialog dialog - Purple::Xfer xfer - -void -pidgin_xfer_dialog_update_xfer(dialog, xfer) - Pidgin::Xfer::Dialog dialog - Purple::Xfer xfer
--- a/pidgin/plugins/perl/common/GtkLog.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Log PACKAGE = Pidgin::Log PREFIX = pidgin_log_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_log_get_handle() - -void -pidgin_log_show(type, buddyname, account) - Purple::LogType type - const char * buddyname - Purple::Account account - -void -pidgin_log_show_contact(contact) - Purple::BuddyList::Contact contact - -MODULE = Pidgin::Log PACKAGE = Pidgin::SysLog PREFIX = pidgin_syslog_ -PROTOTYPES: ENABLE - -void -pidgin_syslog_show()
--- a/pidgin/plugins/perl/common/GtkMenuTray.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,33 +0,0 @@ -#include "gtkmodule.h" - -/* This can't work at the moment since I don't have a typemap for Gtk::Widget. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -Gtk::Widget -pidgin_menu_tray_new() - -Gtk::Widget -pidgin_menu_tray_get_box(menu_tray) - Pidgin::MenuTray menu_tray - -void -pidgin_menu_tray_append(menu_tray, widget, tooltip) - Pidgin::MenuTray menu_tray - Gtk::Widget widget - const char * tooltip - -void -pidgin_menu_tray_prepend(menu_tray, widget, tooltip) - Pidgin::MenuTray menu_tray - Gtk::Widget widget - const char * tooltip - -void -pidgin_menu_tray_set_tooltip(menu_tray, widget, tooltip) - Pidgin::MenuTray menu_tray - Gtk::Widget widget - const char * tooltip -*/ - -MODULE = Pidgin::MenuTray PACKAGE = Pidgin::MenuTray PREFIX = pidgin_menu_tray -PROTOTYPES: ENABLE
--- a/pidgin/plugins/perl/common/GtkPlugin.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Plugin PACKAGE = Pidgin::Plugins PREFIX = pidgin_plugins_ -PROTOTYPES: ENABLE - -void -pidgin_plugins_save() - -MODULE = Pidgin::Plugin PACKAGE = Pidgin::Plugin::Dialog PREFIX = pidgin_plugin_dialog_ -PROTOTYPES: ENABLE - -void -pidgin_plugin_dialog_show()
--- a/pidgin/plugins/perl/common/GtkPluginPref.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,4 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::PluginPref PACKAGE = Pidgin::PluginPref PREFIX = pidgin_plugin_pref_ -PROTOTYPES: ENABLE
--- a/pidgin/plugins/perl/common/GtkPounce.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounce PREFIX = pidgin_pounce_ -PROTOTYPES: ENABLE - -void -pidgin_pounce_editor_show(account, name, cur_pounce) - Purple::Account account - const char * name - Purple::Pounce cur_pounce - -MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces PREFIX = pidgin_pounces_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_pounces_get_handle() - -MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces::Manager PREFIX = pidgin_pounces_manager_ -PROTOTYPES: ENABLE - -void -pidgin_pounces_manager_show() - -void -pidgin_pounces_manager_hide()
--- a/pidgin/plugins/perl/common/GtkPrefs.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,7 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Prefs PACKAGE = Pidgin::Prefs PREFIX = pidgin_prefs_ -PROTOTYPES: ENABLE - -void -pidgin_prefs_show()
--- a/pidgin/plugins/perl/common/GtkPrivacy.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,23 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Privacy PACKAGE = Pidgin::Privacy PREFIX = pidgin_ -PROTOTYPES: ENABLE - -void -pidgin_request_add_permit(account, name) - Purple::Account account - const char * name - -void -pidgin_request_add_block(account, name) - Purple::Account account - const char * name - -MODULE = Pidgin::Privacy PACKAGE = Pidgin::Privacy::Dialog PREFIX = pidgin_privacy_dialog_ -PROTOTYPES: ENABLE - -void -pidgin_privacy_dialog_show() - -void -pidgin_privacy_dialog_hide()
--- a/pidgin/plugins/perl/common/GtkRoomlist.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Roomlist PACKAGE = Pidgin::Roomlist PREFIX = pidgin_roomlist_ -PROTOTYPES: ENABLE - -gboolean -pidgin_roomlist_is_showable() - -MODULE = Pidgin::Roomlist PACKAGE = Pidgin::Roomlist::Dialog PREFIX = pidgin_roomlist_dialog_ -PROTOTYPES: ENABLE - -void -pidgin_roomlist_dialog_show() - -void -pidgin_roomlist_dialog_show_with_account(account) - Purple::Account account
--- a/pidgin/plugins/perl/common/GtkSavedStatuses.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,24 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Status PACKAGE = Pidgin::Status PREFIX = pidgin_status_ -PROTOTYPES: ENABLE - -Purple::Handle -pidgin_status_get_handle() - -MODULE = Pidgin::Status PACKAGE = Pidgin::Status::Editor PREFIX = pidgin_status_editor_ -PROTOTYPES: ENABLE - -void -pidgin_status_editor_show(edit, status) - gboolean edit - Purple::SavedStatus status - -MODULE = Pidgin::Status PACKAGE = Pidgin::Status::Window PREFIX = pidgin_status_window_ -PROTOTYPES: ENABLE - -void -pidgin_status_window_show() - -void -pidgin_status_window_hide()
--- a/pidgin/plugins/perl/common/GtkSession.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,13 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Session PACKAGE = Pidgin::Session PREFIX = pidgin_session_ -PROTOTYPES: ENABLE - -void -pidgin_session_init(argv0, previous_id, config_dir) - gchar * argv0 - gchar * previous_id - gchar * config_dir - -void -pidgin_session_end()
--- a/pidgin/plugins/perl/common/GtkSound.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,15 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Sound PACKAGE = Pidgin::Sound PREFIX = pidgin_sound_ -PROTOTYPES: ENABLE - -const char * -pidgin_sound_get_event_option(event) - Purple::SoundEventID event - -const char * -pidgin_sound_get_event_label(event) - Purple::SoundEventID event - -Purple::Handle -pidgin_sound_get_handle()
--- a/pidgin/plugins/perl/common/GtkStatusBox.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,41 +0,0 @@ -#include "gtkmodule.h" - -/* This can't work at the moment since I don't have a typemap for Gtk::Widget. - * I thought about using the one from libgtk2-perl but wasn't sure how to go - * about doing that. -Gtk::Widget -pidgin_status_box_new() - -Gtk::Widget -pidgin_status_box_new_with_account(account) - Purple::Account account - -void -pidgin_status_box_add(status_box, type, pixbuf, text, sec_text, data) - Pidgin::StatusBox status_box - Pidgin::StatusBox::ItemType type - GdkPixbuf pixbuf - const char * text - const char * sec_text - gpointer data -*/ - -MODULE = Pidgin::StatusBox PACKAGE = Pidgin::StatusBox PREFIX = pidgin_status_box_ -PROTOTYPES: ENABLE - -void -pidgin_status_box_add_separator(status_box) - Pidgin::StatusBox status_box - -void -pidgin_status_box_set_connecting(status_box, connecting) - Pidgin::StatusBox status_box - gboolean connecting - -void -pidgin_status_box_pulse_connecting(status_box) - Pidgin::StatusBox status_box - -gchar_own * -pidgin_status_box_get_message(status_box) - Pidgin::StatusBox status_box
--- a/pidgin/plugins/perl/common/GtkUtils.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,17 +0,0 @@ -#include "gtkmodule.h" - -MODULE = Pidgin::Utils PACKAGE = Pidgin::Utils PREFIX = pidgin_ -PROTOTYPES: ENABLE - -gboolean -pidgin_save_accels(data) - gpointer data - -void -pidgin_load_accels() - -gchar_own * -pidgin_convert_buddy_icon(plugin, path, size) - Purple::Plugin plugin - const char * path - size_t *size
--- a/pidgin/plugins/perl/common/MANIFEST Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,25 +0,0 @@ -GtkAccount.xs -GtkBlist.xs -GtkConn.xs -GtkConv.xs -GtkConvWin.xs -GtkDebug.xs -GtkDialogs.xs -GtkFt.xs -GtkLog.xs -GtkMenuTray.xs -GtkPlugin.xs -GtkPluginPref.xs -GtkPounce.xs -GtkPrefs.xs -GtkPrivacy.xs -GtkRoomlist.xs -GtkSavedStatuses.xs -GtkSession.xs -GtkSound.xs -GtkStatusBox.xs -GtkUtils.xs -MANIFEST -Pidgin.pm -Pidgin.xs -typemap
--- a/pidgin/plugins/perl/common/Makefile.PL.in Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,28 +0,0 @@ -use 5.006; -use ExtUtils::MakeMaker; -# See lib/ExtUtils/MakeMaker.pm for details of how to influence the contents -# of the Makefile that is written. -WriteMakefile( - 'NAME' => 'Pidgin', - 'VERSION' => '@VERSION@', - ($] >= 5.005 ? ## Add these new keywords supported since 5.005 - ('ABSTRACT_FROM' => '@srcdir@/Pidgin.pm', # finds $ABSTRACT - 'AUTHOR' => 'Pidgin <https://pidgin.im/>') : ()), - 'DEFINE' => '@DEBUG_CFLAGS@ -Wno-float-equal', - 'dynamic_lib' => { 'OTHERLDFLAGS' => '@LDFLAGS@' }, - 'INC' => '-I. -I@srcdir@ -I@top_srcdir@ -I@top_builddir@ -I@top_srcdir@/libpurple -I@top_srcdir@/pidgin @GTK_CFLAGS@ @WEBKIT_CFLAGS@ -DHAVE_CONFIG_H', - 'OBJECT' => '$(O_FILES)', # link all the C files too - 'TYPEMAPS' => ["@top_srcdir@/libpurple/plugins/perl/common/typemap"], -# 'OPTIMIZE' => '-g', # For debugging. - 'INSTALLDIRS' => 'vendor', - 'INSTALL_BASE' => '$(prefix)', - 'INSTALLVENDORARCH' => '$(libdir)/pidgin-$(PURPLE_MAJOR_VERSION)/perl', - 'INSTALLVENDORMAN3DIR' => '$(mandir)/man3', - 'macro' => { - 'prefix' => '@prefix@', - 'exec_prefix' => '@exec_prefix@', - 'libdir' => '@libdir@', - 'mandir' => '@mandir@', - 'datarootdir' => '@datarootdir@', - }, -);
--- a/pidgin/plugins/perl/common/Makefile.mingw Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,117 +0,0 @@ -# -# Makefile.mingw -# -# Description: Makefile for Pidgin perl module. -# - -PIDGIN_TREE_TOP := ../../../.. -include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak - -#we cannot include win32dep.h, but we need struct sockaddr_in6 definition -CFLAGS += -include ws2tcpip.h - -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)/include/gdk-pixbuf-2.0 \ - -I$(GTK_TOP)/lib/glib-2.0/include \ - -I$(GTK_TOP)/lib/gtk-2.0/include \ - -I$(LIBSOUP_TOP)/include/libsoup-2.4 \ - -I$(WEBKITGTK_TOP)/include/webkitgtk-1.0 \ - -I$(PERL_LIB_TOP)/include - -LIB_PATHS += \ - -L$(PERL_LIB_TOP)/lib \ - -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 \ - GtkLog.xs \ - GtkMenuTray.xs \ - GtkPlugin.xs \ - GtkPluginPref.xs \ - GtkPounce.xs \ - GtkPrefs.xs \ - GtkPrivacy.xs \ - GtkRoomlist.xs \ - GtkSavedStatuses.xs \ - GtkSound.xs \ - GtkStatusBox.xs \ - GtkUtils.xs - - -C_FILES = $(XS_FILES:%.xs=%.c) -OBJECTS = $(C_FILES:%.c=%.o) - -## -## LIBRARIES -## -LIBS = -lperl520 \ - -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)
--- a/pidgin/plugins/perl/common/Pidgin.pm Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,59 +0,0 @@ -package Pidgin; - -use 5.008; -use strict; -use warnings; -use Carp; - -use Purple; - -require XSLoader; -XSLoader::load('Pidgin', $VERSION); - -1; -__END__ - -=head1 NAME - -Pidgin - Perl extension for the Pidgin instant messenger. - -=head1 SYNOPSIS - - use Pidgin; - -=head1 ABSTRACT - - This module provides the interface for using perl scripts as plugins in - Pidgin, with access to the Pidgin Gtk interface functions. - -=head1 DESCRIPTION - -This module provides the interface for using perl scripts as plugins in Pidgin, -with access to the Pidgin Gtk interface functions. With this, developers can -write perl scripts that can be loaded in Pidgin as plugins. The script can -interact with IMs, chats, accounts, the buddy list, pidgin signals, and more. - -The API for the perl interface is very similar to that of the Pidgin C API, -which can be viewed at https://developer.pidgin.im/doxygen/ or in the header files -in the Pidgin source tree. - -=head1 FUNCTIONS - -=over - -=back - -=head1 SEE ALSO -Pidgin C API documentation - https://developer.pidgin.im/doxygen/ - -The Pidgin perl module. - -Pidgin website - https://pidgin.im/ - -=head1 AUTHOR - -Etan Reisner, E<lt>deryni@gmail.comE<gt> - -=head1 COPYRIGHT AND LICENSE - -Copyright 2006 by Etan Reisner
--- a/pidgin/plugins/perl/common/Pidgin.xs Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,60 +0,0 @@ -#define PIDGIN_PERL_BOOT_PROTO(x) \ - void boot_Pidgin__##x(pTHX_ CV *cv) - -#define PIDGIN_PERL_BOOT(x) \ - purple_perl_callXS(boot_Pidgin__##x, cv, mark) - -#include "gtkmodule.h" - -/* Prototypes for the BOOT section below. */ -PIDGIN_PERL_BOOT_PROTO(Account); -PIDGIN_PERL_BOOT_PROTO(BuddyList); -PIDGIN_PERL_BOOT_PROTO(Connection); -PIDGIN_PERL_BOOT_PROTO(Conversation); -PIDGIN_PERL_BOOT_PROTO(Conversation__Window); -PIDGIN_PERL_BOOT_PROTO(Debug); -PIDGIN_PERL_BOOT_PROTO(Dialogs); -PIDGIN_PERL_BOOT_PROTO(Log); -PIDGIN_PERL_BOOT_PROTO(MenuTray); -PIDGIN_PERL_BOOT_PROTO(Plugin); -PIDGIN_PERL_BOOT_PROTO(PluginPref); -PIDGIN_PERL_BOOT_PROTO(Pounce); -PIDGIN_PERL_BOOT_PROTO(Prefs); -PIDGIN_PERL_BOOT_PROTO(Privacy); -PIDGIN_PERL_BOOT_PROTO(Roomlist); -PIDGIN_PERL_BOOT_PROTO(Status); -#ifndef _WIN32 -PIDGIN_PERL_BOOT_PROTO(Session); -#endif -PIDGIN_PERL_BOOT_PROTO(Sound); -PIDGIN_PERL_BOOT_PROTO(StatusBox); -PIDGIN_PERL_BOOT_PROTO(Utils); -PIDGIN_PERL_BOOT_PROTO(Xfer); - -MODULE = Pidgin PACKAGE = Pidgin PREFIX = pidgin_ -PROTOTYPES: ENABLE - -BOOT: - PIDGIN_PERL_BOOT(Account); - PIDGIN_PERL_BOOT(BuddyList); - PIDGIN_PERL_BOOT(Connection); - PIDGIN_PERL_BOOT(Conversation); - PIDGIN_PERL_BOOT(Conversation__Window); - PIDGIN_PERL_BOOT(Debug); - PIDGIN_PERL_BOOT(Dialogs); - PIDGIN_PERL_BOOT(Log); - PIDGIN_PERL_BOOT(MenuTray); - PIDGIN_PERL_BOOT(Plugin); - PIDGIN_PERL_BOOT(PluginPref); - PIDGIN_PERL_BOOT(Pounce); - PIDGIN_PERL_BOOT(Prefs); - PIDGIN_PERL_BOOT(Privacy); - PIDGIN_PERL_BOOT(Roomlist); - PIDGIN_PERL_BOOT(Status); -#ifndef _WIN32 - PIDGIN_PERL_BOOT(Session); -#endif - PIDGIN_PERL_BOOT(Sound); - PIDGIN_PERL_BOOT(StatusBox); - PIDGIN_PERL_BOOT(Utils); - PIDGIN_PERL_BOOT(Xfer);
--- a/pidgin/plugins/perl/common/gtkmodule.h Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,70 +0,0 @@ -/* Allow the Perl code to see deprecated functions, so we can continue to - * export them to Perl plugins. */ -#undef PIDGIN_DISABLE_DEPRECATED - -typedef struct group *Pidgin__Group; - -#define group perl_group - -#include <glib.h> -#include <gtk/gtk.h> -#ifdef _WIN32 -#undef pipe -#endif - -#define SILENT_NO_TAINT_SUPPORT 0 -#define NO_TAINT_SUPPORT 0 - -#include <EXTERN.h> -#include <perl.h> -#include <XSUB.h> - -#undef group - -#include <plugins/perl/common/module.h> - -#include "gtkaccount.h" -#include "gtkblist.h" -#include "gtkconn.h" -#include "gtkconv.h" -#include "gtkconvwin.h" -#include "gtkdebug.h" -#include "gtkdialogs.h" -#include "gtkxfer.h" -#include "gtklog.h" -#include "gtkmenutray.h" -#include "gtkplugin.h" -#include "gtkpluginpref.h" -#include "gtkpounce.h" -#include "gtkprefs.h" -#include "gtkprivacy.h" -#include "gtkroomlist.h" -#include "gtksavedstatuses.h" -#include "gtksession.h" -#include "gtksound.h" -#include "gtkstatusbox.h" -#include "gtkutils.h" - -/* gtkaccount.h */ -typedef PidginAccountDialogType Pidgin__Account__Dialog__Type; - -/* gtkblist.h */ -typedef PidginBuddyList * Pidgin__BuddyList; -typedef pidgin_blist_sort_function Pidgin__BuddyList__SortFunction; - -/* gtkconv.h */ -typedef PidginConversation * Pidgin__Conversation; -typedef PidginUnseenState Pidgin__UnseenState; - -/* gtkconvwin.h */ -typedef PidginConvWindow * Pidgin__Conversation__Window; -typedef PidginConvPlacementFunc Pidgin__Conversation__PlacementFunc; - -/* gtkxfer.h */ -typedef PidginXferDialog * Pidgin__Xfer__Dialog; - -/* gtkmenutray.h */ -typedef PidginMenuTray * Pidgin__MenuTray; - -/* gtkstatusbox.h */ -typedef PidginStatusBox * Pidgin__StatusBox;
--- a/pidgin/plugins/perl/common/typemap Sun May 28 13:26:27 2017 +0300 +++ /dev/null Thu Jan 01 00:00:00 1970 +0000 @@ -1,12 +0,0 @@ -TYPEMAP - -Pidgin::Account::Dialog::Type T_IV -Pidgin::BuddyList T_PurpleObj -Pidgin::BuddyList::SortFunction T_PurpleObj -Pidgin::Conversation T_PurpleObj -Pidgin::Conversation::PlacementFunc T_PurpleObj -Pidgin::Conversation::Window T_PurpleObj -Pidgin::Xfer::Dialog T_PurpleObj -Pidgin::MenuTray T_PurpleObj -Pidgin::StatusBox T_PurpleObj -Pidgin::UnseenState T_IV
--- a/pidgin/plugins/raw.c Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/plugins/raw.c Mon Jun 05 16:36:29 2017 +0300 @@ -119,7 +119,7 @@ "category", N_("Protocol utility"), "summary", N_("Lets you send raw input to text-based protocols."), "description", N_("Lets you send raw input to text-based protocols " - "(XMPP, MSN, IRC, TOC). Hit 'Enter' in the entry " + "(XMPP, IRC, TOC). Hit 'Enter' in the entry " "box to send. Watch the debug window."), "authors", authors, "website", PURPLE_WEBSITE,
--- a/pidgin/win32/nsis/pidgin-installer.nsi Sun May 28 13:26:27 2017 +0300 +++ b/pidgin/win32/nsis/pidgin-installer.nsi Mon Jun 05 16:36:29 2017 +0300 @@ -543,7 +543,6 @@ Delete "$INSTDIR\plugins\gtkbuddynote.dll" Delete "$INSTDIR\plugins\history.dll" Delete "$INSTDIR\plugins\internalkeyring.dll" - Delete "$INSTDIR\plugins\ssl-gnutls.dll" Delete "$INSTDIR\plugins\webkit.dll" Delete "$INSTDIR\plugins\wincred.dll" Delete "$INSTDIR\plugins\iconaway.dll" @@ -564,16 +563,12 @@ Delete "$INSTDIR\plugins\markerline.dll" Delete "$INSTDIR\plugins\newline.dll" Delete "$INSTDIR\plugins\notify.dll" - Delete "$INSTDIR\plugins\nss-prefs.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\ticker.dll" Delete "$INSTDIR\plugins\timestamp.dll" @@ -582,15 +577,6 @@ Delete "$INSTDIR\plugins\winprefs.dll" Delete "$INSTDIR\plugins\xmppconsole.dll" Delete "$INSTDIR\plugins\xmppdisco.dll" - Delete "$INSTDIR\plugins\perl\auto\Pidgin\Pidgin.dll" - RMDir "$INSTDIR\plugins\perl\auto\Pidgin" - Delete "$INSTDIR\plugins\perl\auto\Purple\autosplit.ix" - Delete "$INSTDIR\plugins\perl\auto\Purple\Purple.dll" - RMDir "$INSTDIR\plugins\perl\auto\Purple" - RMDir "$INSTDIR\plugins\perl\auto" - Delete "$INSTDIR\plugins\perl\Pidgin.pm" - Delete "$INSTDIR\plugins\perl\Purple.pm" - RMDir "$INSTDIR\plugins\perl" RMDir "$INSTDIR\plugins" Delete "$INSTDIR\sasl2\libanonymous-3.dll" Delete "$INSTDIR\sasl2\libcrammd5-3.dll"
--- a/po/POTFILES.skip Sun May 28 13:26:27 2017 +0300 +++ b/po/POTFILES.skip Mon Jun 05 16:36:29 2017 +0300 @@ -1,138 +1,6 @@ libpurple/data/purple-url-handler.desktop.in.in -libpurple/plugins/mono/loader/mono.c -libpurple/plugins/perl/common/Account.c -libpurple/plugins/perl/common/AccountOpts.c -libpurple/plugins/perl/common/BuddyIcon.c -libpurple/plugins/perl/common/BuddyList.c -libpurple/plugins/perl/common/Certificate.c -libpurple/plugins/perl/common/Cipher.c -libpurple/plugins/perl/common/Cmds.c -libpurple/plugins/perl/common/Connection.c -libpurple/plugins/perl/common/Conversation.c -libpurple/plugins/perl/common/Core.c -libpurple/plugins/perl/common/Debug.c -libpurple/plugins/perl/common/FT.c -libpurple/plugins/perl/common/Idle.c -libpurple/plugins/perl/common/Log.c -libpurple/plugins/perl/common/Network.c -libpurple/plugins/perl/common/Notify.c -libpurple/plugins/perl/common/Plugin.c -libpurple/plugins/perl/common/PluginPref.c -libpurple/plugins/perl/common/Pounce.c -libpurple/plugins/perl/common/Prefs.c -libpurple/plugins/perl/common/Presence.c -libpurple/plugins/perl/common/Privacy.c -libpurple/plugins/perl/common/Proxy.c -libpurple/plugins/perl/common/Prpl.c -libpurple/plugins/perl/common/Purple.c -libpurple/plugins/perl/common/Request.c -libpurple/plugins/perl/common/Roomlist.c -libpurple/plugins/perl/common/SSLConn.c -libpurple/plugins/perl/common/SavedStatuses.c -libpurple/plugins/perl/common/Server.c -libpurple/plugins/perl/common/Signal.c -libpurple/plugins/perl/common/Smiley.c -libpurple/plugins/perl/common/Sound.c -libpurple/plugins/perl/common/Status.c -libpurple/plugins/perl/common/Stringref.c -libpurple/plugins/perl/common/Util.c -libpurple/plugins/perl/common/Whiteboard.c -libpurple/plugins/perl/common/XMLNode.c -libpurple/plugins/perl/common/Xfer.c -libpurple/plugins/perl/perl.c -libpurple/plugins/tcl/tcl.c libpurple/protocols/null/nullprpl.c pidgin/data/pidgin.desktop.in.in -pidgin/plugins/crazychat/cc_pidgin_plugin.c -pidgin/plugins/perl/common/GtkAccount.c -pidgin/plugins/perl/common/GtkBlist.c -pidgin/plugins/perl/common/GtkConn.c -pidgin/plugins/perl/common/GtkConv.c -pidgin/plugins/perl/common/GtkConvWin.c -pidgin/plugins/perl/common/GtkDebug.c -pidgin/plugins/perl/common/GtkDialogs.c -pidgin/plugins/perl/common/GtkFt.c -pidgin/plugins/perl/common/GtkIMHtml.c -pidgin/plugins/perl/common/GtkIMHtmlToolbar.c -pidgin/plugins/perl/common/GtkLog.c -pidgin/plugins/perl/common/GtkMenuTray.c -pidgin/plugins/perl/common/GtkPlugin.c -pidgin/plugins/perl/common/GtkPluginPref.c -pidgin/plugins/perl/common/GtkPounce.c -pidgin/plugins/perl/common/GtkPrefs.c -pidgin/plugins/perl/common/GtkPrivacy.c -pidgin/plugins/perl/common/GtkRoomlist.c -pidgin/plugins/perl/common/GtkSavedStatuses.c -pidgin/plugins/perl/common/GtkSession.c -pidgin/plugins/perl/common/GtkSound.c -pidgin/plugins/perl/common/GtkStatusBox.c -pidgin/plugins/perl/common/GtkThemes.c -pidgin/plugins/perl/common/GtkUtils.c -pidgin/plugins/perl/common/Pidgin.c sub/libpurple/data/purple-url-handler.desktop.in -sub/libpurple/plugins/perl/common/Account.c -sub/libpurple/plugins/perl/common/AccountOpts.c -sub/libpurple/plugins/perl/common/BuddyIcon.c -sub/libpurple/plugins/perl/common/BuddyList.c -sub/libpurple/plugins/perl/common/Certificate.c -sub/libpurple/plugins/perl/common/Cipher.c -sub/libpurple/plugins/perl/common/Cmds.c -sub/libpurple/plugins/perl/common/Connection.c -sub/libpurple/plugins/perl/common/Conversation.c -sub/libpurple/plugins/perl/common/Core.c -sub/libpurple/plugins/perl/common/Debug.c -sub/libpurple/plugins/perl/common/FT.c -sub/libpurple/plugins/perl/common/Idle.c -sub/libpurple/plugins/perl/common/ImgStore.c -sub/libpurple/plugins/perl/common/Log.c -sub/libpurple/plugins/perl/common/Network.c -sub/libpurple/plugins/perl/common/Notify.c -sub/libpurple/plugins/perl/common/Plugin.c -sub/libpurple/plugins/perl/common/PluginPref.c -sub/libpurple/plugins/perl/common/Pounce.c -sub/libpurple/plugins/perl/common/Prefs.c -sub/libpurple/plugins/perl/common/Privacy.c -sub/libpurple/plugins/perl/common/Proxy.c -sub/libpurple/plugins/perl/common/Prpl.c -sub/libpurple/plugins/perl/common/Purple.c -sub/libpurple/plugins/perl/common/Request.c -sub/libpurple/plugins/perl/common/Roomlist.c -sub/libpurple/plugins/perl/common/SSLConn.c -sub/libpurple/plugins/perl/common/SavedStatuses.c -sub/libpurple/plugins/perl/common/Server.c -sub/libpurple/plugins/perl/common/Signal.c -sub/libpurple/plugins/perl/common/Smiley.c -sub/libpurple/plugins/perl/common/Sound.c -sub/libpurple/plugins/perl/common/Status.c -sub/libpurple/plugins/perl/common/Stringref.c -sub/libpurple/plugins/perl/common/Util.c -sub/libpurple/plugins/perl/common/Whiteboard.c -sub/libpurple/plugins/perl/common/XMLNode.c sub/libpurple/protocols/null/nullprpl.c sub/pidgin/data/pidgin.desktop.in -sub/pidgin/plugins/crazychat/cc_pidgin_plugin.c -sub/pidgin/plugins/perl/common/GtkAccount.c -sub/pidgin/plugins/perl/common/GtkBlist.c -sub/pidgin/plugins/perl/common/GtkConn.c -sub/pidgin/plugins/perl/common/GtkConv.c -sub/pidgin/plugins/perl/common/GtkConvWin.c -sub/pidgin/plugins/perl/common/GtkDebug.c -sub/pidgin/plugins/perl/common/GtkDialogs.c -sub/pidgin/plugins/perl/common/GtkFt.c -sub/pidgin/plugins/perl/common/GtkIMHtml.c -sub/pidgin/plugins/perl/common/GtkIMHtmlToolbar.c -sub/pidgin/plugins/perl/common/GtkLog.c -sub/pidgin/plugins/perl/common/GtkMenuTray.c -sub/pidgin/plugins/perl/common/GtkPlugin.c -sub/pidgin/plugins/perl/common/GtkPluginPref.c -sub/pidgin/plugins/perl/common/GtkPounce.c -sub/pidgin/plugins/perl/common/GtkPrefs.c -sub/pidgin/plugins/perl/common/GtkPrivacy.c -sub/pidgin/plugins/perl/common/GtkRoomlist.c -sub/pidgin/plugins/perl/common/GtkSavedStatuses.c -sub/pidgin/plugins/perl/common/GtkSession.c -sub/pidgin/plugins/perl/common/GtkSound.c -sub/pidgin/plugins/perl/common/GtkStatusBox.c -sub/pidgin/plugins/perl/common/GtkThemes.c -sub/pidgin/plugins/perl/common/GtkUtils.c -sub/pidgin/plugins/perl/common/Pidgin.c