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 @@
-.*/perl/common/[^/]+\.c$
-.*/perl/common/pm_to_blib$
-.*/perl/common/MYMETA\.(json|yml)
@@ -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 --- 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 \
--- 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 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 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. */
@@ -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. */
-/* Compile with support for the Tk toolkit */
/* 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. */
-/* Define if old perl is installed. */
--- 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.
-Pidgin allows for plugins to be written in the perl scripting language. See
-\fIPerl Scripting HOWTO\fR in the Pidgin documentation for more information
-Pidgin allows for plugins to be written in the Tcl scripting language. See
-\fIplugins/tcl/TCL-HOWTO\fR for more information about Tcl scripting.
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 @@
$(top_builddir)/finch/libfinch.la \
+ $(top_builddir)/libpurple/libpurple.la \ --- 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" />
--- 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 @@
$(top_builddir)/pidgin/libpidgin.la \
+ $(top_builddir)/libpurple/libpurple.la \ --- 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 @@
@@ -245,13 +241,9 @@
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 @@
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/*******************************************************************************
- ******************************************************************************/
-#define PURPLE_HMAC_CIPHER_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_HMAC_CIPHER, PurpleHMACCipherPrivate))
-} PurpleHMACCipherPrivate;
-/******************************************************************************
- *****************************************************************************/
-/*******************************************************************************
- ******************************************************************************/
-static GObjectClass *parent_class = NULL;
-static GParamSpec *properties[PROP_LAST];
-/*******************************************************************************
- ******************************************************************************/
-purple_hmac_cipher_set_hash(PurpleCipher *cipher,
- 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]);
-/*******************************************************************************
- ******************************************************************************/
-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);
-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));
-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);
-purple_hmac_cipher_digest(PurpleCipher *cipher, guchar *out, size_t len)
- PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher);
- 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);
- /* 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);
-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);
-purple_hmac_cipher_set_key(PurpleCipher *cipher, const guchar *key,
- PurpleHMACCipherPrivate *priv = PURPLE_HMAC_CIPHER_GET_PRIVATE(cipher);
- g_return_if_fail(priv->hash);
- 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);
- 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];
- purple_hash_reset(priv->hash);
- purple_hash_append(priv->hash, priv->ipad, block_size);
-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);
-/******************************************************************************
- *****************************************************************************/
-purple_hmac_cipher_set_property(GObject *obj, guint param_id,
- PurpleCipher *cipher = PURPLE_CIPHER(obj);
- purple_hmac_cipher_set_hash(cipher, g_value_get_object(value));
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-purple_hmac_cipher_get_property(GObject *obj, guint param_id, GValue *value,
- PurpleHMACCipher *cipher = PURPLE_HMAC_CIPHER(obj);
- g_value_set_object(value,
- purple_hmac_cipher_get_hash(cipher));
- G_OBJECT_WARN_INVALID_PROPERTY_ID(obj, param_id, pspec);
-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);
-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",
- G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY |
- G_PARAM_STATIC_STRINGS);
- g_object_class_install_properties(obj_class, PROP_LAST, properties);
-/******************************************************************************
- *****************************************************************************/
-purple_hmac_cipher_get_type(void) {
- static const GTypeInfo info = {
- sizeof(PurpleHMACCipherClass),
- (GClassInitFunc)purple_hmac_cipher_class_init,
- sizeof(PurpleHMACCipher),
- (GInstanceInitFunc)purple_cipher_reset,
- type = g_type_register_static(PURPLE_TYPE_CIPHER,
-purple_hmac_cipher_new(PurpleHash *hash) {
- g_return_val_if_fail(PURPLE_IS_HASH(hash), NULL);
- return g_object_new(PURPLE_TYPE_HMAC_CIPHER,
-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);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * 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_id: libpurple-hmaccipher
- * @short_description: <filename>ciphers/hmaccipher.h</filename>
-#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 {
-struct _PurpleHMACCipherClass {
- PurpleCipherClass gparent;
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
-GType purple_hmac_cipher_get_type(void);
-PurpleCipher *purple_hmac_cipher_new(PurpleHash *hash);
-PurpleHash *purple_hmac_cipher_get_hash(const PurpleHMACCipher *cipher);
-#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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/*******************************************************************************
- ******************************************************************************/
-#define PURPLE_MD5_HASH_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_MD5_HASH, PurpleMD5HashPrivate))
-/******************************************************************************
- *****************************************************************************/
-static GObjectClass *parent_class = NULL;
-/******************************************************************************
- *****************************************************************************/
-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);
-purple_md5_hash_append(PurpleHash *hash, const guchar *data,
- 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);
- g_checksum_update(priv->checksum, data, len);
-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)
- purple_md5_hash_reset(hash);
-purple_md5_hash_get_block_size(PurpleHash *hash)
-purple_md5_hash_get_digest_size(PurpleHash *hash)
- return g_checksum_type_get_length(G_CHECKSUM_MD5);
-/******************************************************************************
- *****************************************************************************/
-purple_md5_hash_finalize(GObject *obj)
- PurpleMD5Hash *md5_hash = PURPLE_MD5_HASH(obj);
- PurpleMD5HashPrivate *priv = PURPLE_MD5_HASH_GET_PRIVATE(md5_hash);
- g_checksum_free(priv->checksum);
- parent_class->finalize(obj);
-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));
-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);
-/******************************************************************************
- *****************************************************************************/
-purple_md5_hash_get_type(void) {
- static const GTypeInfo info = {
- sizeof(PurpleMD5HashClass),
- (GClassInitFunc)purple_md5_hash_class_init,
- (GInstanceInitFunc)purple_md5_hash_init,
- type = g_type_register_static(PURPLE_TYPE_HASH,
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * 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_id: libpurple-md5hash
- * @short_description: <filename>ciphers/md5hash.h</filename>
-#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 _PurpleMD5HashClass {
- PurpleHashClass gparent;
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
-GType purple_md5_hash_get_type(void);
-PurpleHash *purple_md5_hash_new(void);
-#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 "pbkdf2cipher.h"
@@ -38,7 +37,7 @@
(G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_PBKDF2_CIPHER, PurplePBKDF2CipherPrivate))
+ GChecksumType hash_type; @@ -53,7 +52,7 @@
*****************************************************************************/
@@ -65,20 +64,6 @@
static GObjectClass *parent_class = NULL;
static GParamSpec *properties[PROP_LAST];
-/*******************************************************************************
- ******************************************************************************/
-purple_pbkdf2_cipher_set_hash(PurpleCipher *cipher,
- 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]);
/******************************************************************************
*****************************************************************************/
@@ -89,8 +74,6 @@
g_return_if_fail(priv != NULL);
- if(PURPLE_IS_HASH(priv->hash))
- purple_hash_reset(priv->hash);
@@ -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;
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);
- purple_debug_error("pbkdf2", "Couldn't create new hmac "
- purple_cipher_set_key(hash, (const guchar*)priv->passphrase,
- 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); @@ -215,9 +188,18 @@
memset(halfkey, 0, halfkey_len);
for (iter_no = 1; iter_no <= priv->iter_count; iter_no++) {
- purple_cipher_reset_state(hash);
+ hmac = g_hmac_new(priv->hash_type, + (const guchar*)priv->passphrase, + purple_debug_error("pbkdf2", + "Couldn't create new hmac cipher\n"); 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,
+ g_hmac_update(hmac, salt_ext, salt_ext_len); - purple_cipher_append(hash, halfkey_hash,
+ g_hmac_update(hmac, halfkey_hash, halfkey_len); - if (!purple_cipher_digest(hash, halfkey_hash,
- purple_debug_error("pbkdf2",
- "Couldn't retrieve a digest\n");
+ g_hmac_get_digest(hmac, halfkey_hash, &halfkey_len); for (i = 0; i < halfkey_len; i++)
halfkey[i] ^= halfkey_hash[i];
@@ -255,7 +229,6 @@
@@ -271,8 +244,8 @@
PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher);
- g_value_set_object(value, purple_pbkdf2_cipher_get_hash(cipher));
+ g_value_set_int(value, priv->hash_type); g_value_set_uint(value, priv->iter_count);
@@ -294,8 +267,8 @@
PurplePBKDF2CipherPrivate *priv = PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher);
- purple_pbkdf2_cipher_set_hash(cipher, g_value_get_object(value));
+ priv->hash_type = g_value_get_int(value); 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",
+ 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 |
@@ -364,6 +333,11 @@
purple_pbkdf2_cipher_init(PurpleCipher *cipher)
+ PurplePBKDF2CipherPrivate *priv = + PURPLE_PBKDF2_CIPHER_GET_PRIVATE(cipher); purple_cipher_reset(cipher);
@@ -397,24 +371,22 @@
-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-type", hash_type,
-purple_pbkdf2_cipher_get_hash(const PurplePBKDF2Cipher *cipher) {
+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);
+ return priv->hash_type;
--- 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); --- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/*******************************************************************************
- ******************************************************************************/
-#define PURPLE_SHA1_HASH_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA1_HASH, PurpleSHA1HashPrivate))
-} PurpleSHA1HashPrivate;
-/******************************************************************************
- *****************************************************************************/
-static GObjectClass *parent_class = NULL;
-/******************************************************************************
- *****************************************************************************/
-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);
-purple_sha1_hash_append(PurpleHash *hash, const guchar *data,
- 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);
- g_checksum_update(priv->checksum, data, len);
-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)
- purple_sha1_hash_reset(hash);
-purple_sha1_hash_get_block_size(PurpleHash *hash)
-purple_sha1_hash_get_digest_size(PurpleHash *hash)
- return g_checksum_type_get_length(G_CHECKSUM_SHA1);
-/******************************************************************************
- *****************************************************************************/
-purple_sha1_hash_finalize(GObject *obj)
- PurpleSHA1Hash *sha1_hash = PURPLE_SHA1_HASH(obj);
- PurpleSHA1HashPrivate *priv = PURPLE_SHA1_HASH_GET_PRIVATE(sha1_hash);
- g_checksum_free(priv->checksum);
- parent_class->finalize(obj);
-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));
-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);
-/******************************************************************************
- *****************************************************************************/
-purple_sha1_hash_get_type(void) {
- static const GTypeInfo info = {
- sizeof(PurpleSHA1HashClass),
- (GClassInitFunc)purple_sha1_hash_class_init,
- sizeof(PurpleSHA1Hash),
- (GInstanceInitFunc)purple_sha1_hash_init,
- type = g_type_register_static(PURPLE_TYPE_HASH,
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * 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_id: libpurple-sha1hash
- * @short_description: <filename>ciphers/sha1hash.h</filename>
-#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 {
-struct _PurpleSHA1HashClass {
- PurpleHashClass gparent;
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
-GType purple_sha1_hash_get_type(void);
-PurpleHash *purple_sha1_hash_new(void);
-#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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/*******************************************************************************
- ******************************************************************************/
-#define PURPLE_SHA256_HASH_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE((obj), PURPLE_TYPE_SHA256_HASH, PurpleSHA256HashPrivate))
-} PurpleSHA256HashPrivate;
-/******************************************************************************
- *****************************************************************************/
-static GObjectClass *parent_class = NULL;
-/******************************************************************************
- *****************************************************************************/
-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);
-purple_sha256_hash_append(PurpleHash *hash, const guchar *data,
- 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);
- g_checksum_update(priv->checksum, data, len);
-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)
- purple_sha256_hash_reset(hash);
-purple_sha256_hash_get_block_size(PurpleHash *hash)
-purple_sha256_hash_get_digest_size(PurpleHash *hash)
- return g_checksum_type_get_length(G_CHECKSUM_SHA256);
-/******************************************************************************
- *****************************************************************************/
-purple_sha256_hash_finalize(GObject *obj)
- PurpleSHA256Hash *sha256_hash = PURPLE_SHA256_HASH(obj);
- PurpleSHA256HashPrivate *priv = PURPLE_SHA256_HASH_GET_PRIVATE(sha256_hash);
- g_checksum_free(priv->checksum);
- parent_class->finalize(obj);
-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));
-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);
-/******************************************************************************
- *****************************************************************************/
-purple_sha256_hash_get_type(void) {
- static const GTypeInfo info = {
- sizeof(PurpleSHA256HashClass),
- (GClassInitFunc)purple_sha256_hash_class_init,
- sizeof(PurpleSHA256Hash),
- (GInstanceInitFunc)purple_sha256_hash_init,
- type = g_type_register_static(PURPLE_TYPE_HASH,
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * 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_id: libpurple-sha256hash
- * @short_description: <filename>ciphers/sha256hash.h</filename>
-#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 {
-struct _PurpleSHA256HashClass {
- PurpleHashClass gparent;
- void (*_purple_reserved1)(void);
- void (*_purple_reserved2)(void);
- void (*_purple_reserved3)(void);
- void (*_purple_reserved4)(void);
-GType purple_sha256_hash_get_type(void);
-PurpleHash *purple_sha256_hash_new(void);
-#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);
- proxy_auth = purple_base64_encode((const guchar *)tmp, len);
+ proxy_auth = g_base64_encode((const guchar *)tmp, len); --- 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); @@ -153,7 +153,7 @@
struct type2_message tmsg;
- 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); --- 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 @@
include $(PIDGIN_TREE_TOP)/libpurple/win32/global.mak
KEYRING_PLUGIN := ./keyrings
@@ -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 @@
- $(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 @@
- 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)
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);
intkeyring_buff_free(ret);
@@ -282,7 +278,7 @@
- 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 "ciphers/sha1hash.h"
bonjour_bytestreams_init(PurpleXfer *xfer);
@@ -1014,11 +1013,12 @@
PurpleAccount *account = NULL;
const gchar *name = NULL;
unsigned char hashval[20];
@@ -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); --- 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 @@
- 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);
--- 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-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)
- hash = purple_sha1_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));
+ 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_object_unref(cipher);
- return purple_base64_encode(digest, sizeof(digest));
+ return g_base64_encode(digest, sizeof(digest)); --- 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 @@
- serverin = (char *)purple_base64_decode(arg, &serverinlen);
+ serverin = (char *)g_base64_decode(arg, &serverinlen); ret = sasl_client_step(irc->sasl_conn, serverin, serverinlen,
@@ -1678,7 +1678,7 @@
- authinfo = purple_base64_encode((const guchar*)c_out, clen);
+ authinfo = g_base64_encode((const guchar*)c_out, clen); 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 "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, purple_xmlnode_insert_data(x, hash, -1);
@@ -277,22 +275,15 @@
* to non-SASL authentication.
/* 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);
+ digest = g_compute_hmac_for_string(G_CHECKSUM_MD5, + (guchar *)pw, strlen(pw), - 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);
jabber_iq_set_callback(iq, auth_old_result_cb, NULL);
--- 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 @@
purple_xmlnode_insert_data(auth, "=", -1);
- 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);
@@ -458,7 +458,7 @@
- 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,
@@ -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); 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); @@ -519,7 +519,7 @@
- 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 "ciphers/md5hash.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)
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);
- 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); - 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));
- z = purple_base16_encode(result, 16);
+ z = g_compute_checksum_for_string(G_CHECKSUM_MD5, kd, -1); @@ -171,6 +155,7 @@
char *enc_in = purple_xmlnode_get_data(packet);
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",
parts = jabber_auth_digest_md5_parse(dec_in);
@@ -254,7 +239,7 @@
- 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 "ciphers/hmaccipher.h"
-#include "ciphers/sha1hash.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)
@@ -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
g_string_append_len(salt, "\0\0\0\1", 4);
- 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); - memcpy(prev, result, hash->size);
+ memcpy(prev, result, digest_len); for (i = 1; i < iterations; ++i) {
- 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); - for (j = 0; j < hash->size; ++j)
+ for (j = 0; j < digest_len; ++j) - memcpy(prev, tmp, hash->size);
+ memcpy(prev, tmp, digest_len); - g_object_unref(G_OBJECT(cipher));
@@ -142,33 +138,31 @@
hmac(const JabberScramHash *hash, guchar *out, const guchar *key, const gchar *str)
+ 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); hash(const JabberScramHash *hash, guchar *out, const guchar *data)
+ 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); 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); GString *pass = g_string_new(data->password);
@@ -252,7 +246,7 @@
if (token[0] != 's' || token[1] != '=')
- decoded = (gchar *)purple_base64_decode(token + 2, &len);
+ decoded = (gchar *)g_base64_decode(token + 2, &len); if (!decoded || *decoded == '\0') {
@@ -343,7 +337,7 @@
- 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);
@@ -355,7 +349,7 @@
- server_sig = (gchar *)purple_base64_decode(enc_server_sig, &len);
+ server_sig = (gchar *)g_base64_decode(enc_server_sig, &len); if (server_sig == NULL || len != data->server_signature->len) {
@@ -427,7 +421,7 @@
data->channel_binding = TRUE;
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 @@
- 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)");
- 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); 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.
/* Per-connection state stored between messages.
* This is stored in js->auth_data_mech.
- PurpleHash *(*new_cipher)(void);
--- 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));
- js->initial_avatar_hash = jabber_calculate_data_hash(
+ js->initial_avatar_hash = g_compute_checksum_for_data( purple_image_get_data(image),
- purple_image_get_data_size(image),
+ purple_image_get_data_size(image) @@ -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);
- 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);
@@ -957,11 +957,12 @@
char *bintext = purple_xmlnode_get_data(binval);
- guchar *data = purple_base64_decode(bintext, &size);
+ guchar *data = g_base64_decode(bintext, &size); - vcard_hash = jabber_calculate_data_hash(data, size, "sha1");
+ vcard_hash = g_compute_checksum_for_data( + G_CHECKSUM_SHA1, data, size); @@ -1200,7 +1201,7 @@
gboolean photo = (strcmp(child->name, "PHOTO") == 0);
- data = purple_base64_decode(bintext, &size);
+ data = g_base64_decode(bintext, &size); @@ -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);
--- 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 "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 */
- 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; + supported_hash = FALSE; - hash = jabber_caps_calculate_hash(info, hasher);
- g_object_unref(hasher);
+ 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 @@
-append_escaped_string(PurpleHash *hash, const gchar *str)
+append_escaped_string(GChecksum *hash, const gchar *str) g_return_if_fail(hash != NULL);
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); - 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)
- gsize checksum_size = 20;
/* 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); /* 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); @@ -912,16 +918,20 @@
+ checksum_size = g_checksum_type_get_length(hash_type); + checksum = g_new(guint8, checksum_size); - 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); void jabber_caps_calculate_own_hash(JabberStream *js) {
JabberCapsClientInfo info;
@@ -952,9 +962,7 @@
- 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;
/* Implementation of XEP-0115 - Entity Capabilities */
@@ -96,10 +95,11 @@
* @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);
@@ -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); 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];
- 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 (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; + valid_hash_type = FALSE; + 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);
--- 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),
PurpleXmlNode *data_element = purple_xmlnode_new("data");
- char *base64 = purple_base64_encode(data, size);
+ char *base64 = g_base64_encode(data, size); 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);
- gpointer rawdata = purple_base64_decode(base64, &size);
+ gpointer rawdata = g_base64_decode(base64, &size); --- 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);
- js->initial_avatar_hash = jabber_calculate_data_hash(
+ js->initial_avatar_hash = g_compute_checksum_for_data( purple_image_get_data(image),
- purple_image_get_data_size(image),
+ purple_image_get_data_size(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 "ciphers/sha1hash.h"
-#include "ciphers/sha256hash.h"
-#include "ciphers/md5hash.h"
@@ -780,36 +776,3 @@
-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();
- purple_debug_error("jabber", "Unexpected hashing algorithm %s requested\n", hash_algo);
- g_return_val_if_reached(NULL);
- 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",
- 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); - 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, 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 "ciphers/sha1hash.h"
#include "protocols/jabber/caps.h"
@@ -24,13 +23,12 @@
-_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);
- 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);
@@ -39,7 +37,7 @@
test_jabber_caps_calculate_from_xmlnode(void) {
- purple_sha1_hash_new(),
"<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 "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( 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 @@
- img = purple_base64_decode(b64data, &size);
+ img = g_base64_decode(b64data, &size); --- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-/**************************************************************************
- **************************************************************************/
-msn_xfer_init(PurpleXfer *xfer)
- /* MsnSlpLink *slplink; */
- purple_debug_info("msn", "xfer_init\n");
- slpcall = purple_xfer_get_protocol_data(xfer);
- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
- msn_slp_send_ok(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
-msn_xfer_cancel(PurpleXfer *xfer)
- 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)
- msn_slpcall_close(slpcall);
- content = g_strdup_printf("SessionID: %lu\r\n\r\n",
- msn_slp_send_decline(slpcall, slpcall->branch, "application/x-msnmsgr-sessionreqbody",
- msn_slplink_send_queued_slpmsgs(slpcall->slplink);
- if (purple_xfer_get_xfer_type(xfer) == PURPLE_XFER_TYPE_SEND)
- slpcall->wasted = TRUE;
- msn_slpcall_destroy(slpcall);
-msn_xfer_write(const guchar *data, gsize len, PurpleXfer *xfer)
- 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);
-msn_xfer_read(guchar **data, gsize size, PurpleXfer *xfer)
- 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();
-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);
-msn_xfer_completed_cb(MsnSlpCall *slpcall, const guchar *body,
- PurpleXfer *xfer = slpcall->xfer;
- purple_xfer_set_completed(xfer, TRUE);
-msn_file_context_to_wire(MsnFileContext *context)
- 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;
- memcpy(tmp, context->unknown1, sizeof(context->unknown1));
- tmp += sizeof(context->unknown1);
- msn_push32le(tmp, context->unknown2);
- memset(tmp, 0, sizeof(gchar[30]));
- tmp += sizeof(gchar[30]);
- msn_push32le(tmp, 0xffffffff);
- if (context->preview) {
- memcpy(tmp, context->preview, context->preview_len);
- tmp[context->preview_len] = '\0';
-msn_file_context_from_wire(const char *buf, gsize len)
- MsnFileContext *context;
- if (!buf || len < MSN_FILE_CONTEXT_SIZE_V0)
- 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) {
- } 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) {
- } else if (context->version == 3) {
- if (context->length != MSN_FILE_CONTEXT_SIZE_V3) {
- } else if (len < MSN_FILE_CONTEXT_SIZE_V3) {
- purple_debug_warning("msn", "Received MsnFileContext with unknown version: %d\n", context->version);
- 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) {
- memcpy(context->unknown1, buf, sizeof(context->unknown1));
- buf += sizeof(context->unknown1);
- context->unknown2 = msn_pop32le(buf);
- buf += sizeof(gchar[30]) + sizeof(guint32);
- if (context->type == 0 && len > context->length) {
- context->preview_len = len - context->length;
- context->preview = g_memdup(buf, context->preview_len);
- context->preview_len = 0;
- context->preview = NULL;
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#define MAX_FILE_NAME_LEN 260 /* MAX_PATH in Windows */
- * The context data for a file transfer request
- guint32 length; /*< Length of header */
- guint32 version; /*< MSN version */
- guint64 file_size; /*< Size of file */
- guint32 type; /*< Transfer type */
- gunichar2 file_name[MAX_FILE_NAME_LEN]; /*< Self-explanatory */
- gchar unknown1[30]; /*< Used somehow for background sharing */
- guint32 unknown2; /*< Possibly for background sharing as well */
- gchar *preview; /*< File preview data, 96x96 PNG */
-#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);
-msn_file_context_to_wire(MsnFileContext *context);
-msn_file_context_from_wire(const char *buf, gsize len);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * 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 "ciphers/aescipher.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
-mxit_encrypt_password(struct MXitSession* session)
- size_t clientkey_len, header_len, pass_len, plaintext_len;
- const gchar *plaintext_passwd;
- guchar encrypted[64]; /* shouldn't be longer than 17 */
- 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);
- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-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 "splashscreen.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 )
- 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
- * @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 len The data length
-void dump_bytes( struct MXitSession* session, const char* buf, int len )
- char* msg = g_malloc0( len + 1 );
- for ( i = 0; i < len; i++ ) {
- if ( ch == CP_REC_TERM ) /* record terminator */
- else if ( ch == CP_FLD_TERM ) /* field terminator */
- else if ( ch == CP_PKT_TERM ) /* packet terminator */
- else if ( ( ch < 0x20 ) || ( ch > 0x7E ) ) /* non-printable character */
- purple_debug_info( MXIT_PLUGIN_ID, "DUMP: '%s'\n", msg );
-/*------------------------------------------------------------------------
- * Determine if we have an active chat with a specific contact
- * @param session The MXit session object
- * @param who The contact name
- * @return Return true if we have an active chat with the contact
-gboolean find_active_chat( const GList* chats, const char* who )
- const GList* list = chats;
- const char* chat = NULL;
- chat = (const char*) list->data;
- if ( strcmp( chat, who ) == 0 )
- list = g_list_next( list );
-/*------------------------------------------------------------------------
- * @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_start( args, format );
- i = g_vsnprintf( string, size, format, args );
- else if ( size > 0 ) /* destination buffer too short - return number of characters actually inserted */
-/*========================================================================================================================
- * 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--;
-/*------------------------------------------------------------------------
- * 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 ) {
- session->queue.packets[session->queue.wr_i] = packet;
- session->queue.wr_i = ( session->queue.wr_i + 1 ) % MAX_QUEUE_SIZE;
- session->queue.count++;
- 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 );
-/*------------------------------------------------------------------------
- * 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 )
- while ( written < pktlen ) {
- res = write( fd, &pktdata[written], pktlen - written );
- purple_debug_error( MXIT_PLUGIN_ID, "Error while writing packet to MXit server (%i)\n", res );
- * 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
-mxit_cb_http_rx(PurpleHttpConnection *http_conn, PurpleHttpResponse *response,
- struct MXitSession *session = _session;
- if (!purple_http_response_is_successful(response)) {
- purple_debug_error(MXIT_PLUGIN_ID, "HTTP response error (%s)\n",
- purple_http_response_get_error(response));
- /* 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
-mxit_write_http_get(struct MXitSession* session, struct tx_packet* packet)
- PurpleHttpRequest *req;
- if (packet->datalen > 0) {
- tmp = g_strndup(packet->data, packet->datalen);
- part = g_strdup(purple_url_encode(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,
- purple_http_request_unref(req);
- * TX Step 3: Write the packet data to the HTTP connection (POST style).
- * @param session The MXit session object
- * @param packet The packet data
-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';
- 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,
- 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 )
- 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" );
- purple_debug_info( MXIT_PLUGIN_ID, "Packet send CMD:%i (%i)\n", packet->cmd, packet->headerlen + packet->datalen );
- dump_bytes( session, packet->header, packet->headerlen );
- dump_bytes( session, packet->data, packet->datalen );
- if ( !session->http ) {
- /* socket connection */
- char data[packet->datalen + packet->headerlen];
- /* 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 );
- /* 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." ) );
- if ( packet->cmd == CP_CMD_MEDIA ) {
- /* multimedia packets must be send with a HTTP POST */
- mxit_write_http_post( session, packet );
- 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;
- /* create a packet for sending */
- packet = g_new0( struct tx_packet, 1 );
- packet->data = g_malloc0( datalen );
- /* create generic packet header */
- hlen = scnprintf( header, sizeof( header ), "id=%s%c", purple_account_get_username( session->acc ), CP_REC_TERM ); /* client mxitid */
- /* 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 */
- 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 */
- memcpy( packet->data, data, datalen );
- packet->datalen = datalen;
- 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 );
- /* 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 );
- 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 */
- 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." ) );
- * 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;
- session->q_fast_timer_id = purple_timeout_add( delay, mxit_manage_queue_fast, session );
- /* 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 );
-/*------------------------------------------------------------------------
- * 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 );
-/*------------------------------------------------------------------------
- * 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;
- gint64 now = mxit_now_milli();
- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
- /* we only poll if we are actually logged in */
- /* 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 */
- /* 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;
- //purple_debug_info( MXIT_PLUGIN_ID, "POLL TIMER: %i (%i)\n", session->http_interval, rxdiff );
- /* send poll request */
- session->http_last_poll = mxit_now_milli();
- mxit_send_poll( session );
-/*========================================================================================================================
- * 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;
- char data[CP_MAX_PACKET];
- 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 )
- char data[CP_MAX_PACKET];
- 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];
- int msgtype = ( is_command ? CP_MSGTYPE_COMMAND : CP_MSGTYPE_NORMAL );
- /* first we need to convert the markup from libPurple to MXit format */
- markuped_msg = mxit_convert_markup_tx( msg, &msgtype );
- 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];
- datalen = scnprintf( data, sizeof( data ),
- "ms=%s%c%i", /* "ms="mxitid\1nr_attributes */
- ( username ? username : "" ), CP_FLD_TERM, nr_attrib
- 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];
- 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
- 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 );
- 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 */
-/*------------------------------------------------------------------------
- * 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];
- /* 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 );
- 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];
- /* 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 );
- 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];
- /* convert the packet to a byte stream */
- datalen = scnprintf( data, sizeof( data ),
- "ms=%i%c", /* "ms"=show\1status */
- /* append status message (if one is set) */
- 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];
- /* convert the packet to a byte stream */
- datalen = scnprintf( data, sizeof( data ),
- "ms=%i", /* "ms"=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];
- /* 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,
- /* 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];
- /* convert the packet to a byte stream */
- datalen = scnprintf( data, sizeof( data ),
- "ms=%s", /* "ms"=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];
- /* 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];
- /* convert the packet to a byte stream */
- datalen = scnprintf( data, sizeof( data ),
- "ms=%s", /* "ms"=username */
- /* append reason (if one is set) */
- 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];
- /* 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];
- /* convert the packet to a byte stream */
- datalen = scnprintf( data, sizeof( data ),
- "ms=%s", /* "ms"=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];
- 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];
- /* 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
- 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];
- /* 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
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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];
- 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 )
- 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 */
- /* 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 );
- /* 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;
- 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 */
- message = records[1]->fields[0]->data;
- msglen = strlen( message );
- /* strip off dummy domain */
- sender = records[0]->fields[0]->data;
- mxit_strip_domain( sender );
- purple_debug_info( MXIT_PLUGIN_ID, "Message received from '%s'\n", sender );
- /* 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 */
- buddy = purple_blist_find_buddy( session->acc, sender );
- name = purple_buddy_get_alias( buddy );
- 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 );
- 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));
- 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->from = g_strdup( sender );
- mx->timestamp = atoi( records[0]->fields[1]->data );
- /* 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 );
- mxit_parse_markup( mx, message, msglen, msgtype, msgflags );
- /* we are now done parsing the message */
- if ( mx->img_count == 0 ) {
- /* we have all the data we need for this message to be displayed now. */
- mxit_show_message( mx );
- /* 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
- if ( msgflags & CP_MSG_TL_ENCRYPTED )
-/*------------------------------------------------------------------------
- * 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;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_new_sub (%i recs)\n", rcount );
- for ( i = 0; i < rcount; i++ ) {
- if ( rec->fcount < 4 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "BAD SUBSCRIPTION RECORD! %i fields\n", rec->fcount );
- /* 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 */
- if ( rec->fcount >= 6 )
- creator = rec->fields[5]->data;
- multimx_invite( session, contact, creator );
- 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 */
- case MXIT_PRESENCE_OFFLINE :
- case MXIT_PRESENCE_ONLINE :
- case MXIT_PRESENCE_AWAY :
- case MXIT_PRESENCE_DND :
- 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 ) )
-/*------------------------------------------------------------------------
- * 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;
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_contact (%i recs)\n", rcount );
- for ( i = 0; i < rcount; i++ ) {
- if ( rec->fcount < 6 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "BAD CONTACT RECORD! %i fields\n", rec->fcount );
- /* 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 );
- 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 )
- 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];
- if ( rec->fcount < 6 ) {
- purple_debug_error( MXIT_PLUGIN_ID, "BAD PRESENCE RECORD! %i fields\n", rec->fcount );
- * 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;
- 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;
- /* 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 );
- for ( i = 0; i < count; i++ ) {
- 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 );
- if ( strcmp( CP_PROFILE_BIRTHDATE, fname ) == 0 ) {
- if ( records[0]->fields[f + 1]->len > 10 ) {
- 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 ) {
- profile->male = ( fvalue[0] == '1' );
- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
- 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 */
- else if ( strcmp( CP_PROFILE_TITLE, fname ) == 0 ) {
- g_strlcpy( profile->title, fvalue, sizeof( profile->title ) );
- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
- else if ( strcmp( CP_PROFILE_EMAIL, fname ) == 0 ) {
- g_strlcpy( profile->email, fvalue, sizeof( profile->email ) );
- else if ( strcmp( CP_PROFILE_MOBILENR, fname ) == 0 ) {
- 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 = g_ascii_strtoll( fvalue, NULL, 10 );
- else if ( strcmp( CP_PROFILE_LASTSEEN, fname ) == 0 ) {
- profile->lastonline = g_ascii_strtoll( fvalue, NULL, 10 );
- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
- else if ( strcmp( CP_PROFILE_ABOUTME, fname ) == 0) {
- g_strlcpy( profile->aboutme, fvalue, sizeof( profile->aboutme ) );
- else if ( strcmp( CP_PROFILE_RELATIONSHIP, fname ) == 0) {
- /* relatinship status */
- profile->relationship = strtol( fvalue, NULL, 10 );
- /* 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 );
- /* this is an invite, so update its profile info */
- if ( ( statusMsg ) && ( *statusMsg ) ) {
- /* update the status message */
- g_free(contact->statusMsg);
- contact->statusMsg = strdup( statusMsg );
- 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 );
- /* display what we have */
- contact->avatarId = NULL;
- mxit_show_profile( session, mxitId, profile );
- /* this is a contact */
- 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 );
- contact = purple_buddy_get_protocol_data( buddy );
- g_free(contact->statusMsg);
- contact->statusMsg = strdup( statusMsg );
- mxit_show_profile( session, mxitId, profile );
-/*------------------------------------------------------------------------
- * 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 )
- * 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 );
- /* 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 );
- for ( i = 1; i < rcount; i ++ ) {
- struct record* rec = records[i];
- struct MXitProfile* profile = g_new0( struct MXitProfile, 1 );
- /* 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_strlcpy( profile->userid, rec->fields[0]->data, sizeof( profile->userid ) );
- // TODO: ContactType - User or Service
- for ( j = 0; j < count; j++ ) {
- 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 ) {
- g_strlcpy( profile->birthday, fvalue, sizeof( profile->birthday ) );
- else if ( strcmp( CP_PROFILE_FIRSTNAME, fname ) == 0 ) {
- g_strlcpy( profile->firstname, fvalue, sizeof( profile->firstname ) );
- else if ( strcmp( CP_PROFILE_LASTNAME, fname ) == 0 ) {
- g_strlcpy( profile->lastname, fvalue, sizeof( profile->lastname ) );
- else if ( strcmp( CP_PROFILE_GENDER, fname ) == 0 ) {
- profile->male = ( fvalue[0] == '1' );
- else if ( strcmp( CP_PROFILE_FULLNAME, fname ) == 0 ) {
- g_strlcpy( profile->nickname, fvalue, sizeof( profile->nickname ) );
- else if ( strcmp( CP_PROFILE_WHEREAMI, fname ) == 0 ) {
- g_strlcpy( profile->whereami, fvalue, sizeof( profile->whereami ) );
- /* ignore other attibutes */
- entries = g_list_append( entries, profile );
- mxit_show_search_results( session, searchType, maxResults, entries );
- 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 )
- * 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 );
- 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 );
- case CP_MSGEVENT_STOPPED : /* user has stopped typing */
- purple_serv_got_typing_stopped( session->con, records[0]->fields[0]->data );
- 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 */
- 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 )
- /* received packet is too short to even contain a chunk header */
- if ( records[0]->fields[0]->len < MXIT_CHUNK_HEADER_SIZE )
- /* 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 )
- purple_debug_info( MXIT_PLUGIN_ID, "mxit_parse_cmd_media (%i records) (%i type) (%i bytes)\n", rcount, chunktype, chunksize );
- /* supported chunked data types */
- case CP_CHUNK_CUSTOM : /* custom resource */
- /* 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
- 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 );
- 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 );
- 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 );
- 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 );
- /* this is an invite (add image to the internal image store) */
- g_object_unref(contact->image);
- contact->image = purple_image_new_from_data(
- g_memdup(chunk.data, chunk.length), chunk.length);
- mxit_show_profile( session, chunk.mxitid, contact->profile );
- /* 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 );
- case CP_CHUNK_SET_AVATAR :
- /* this is a reply packet to a set avatar request. no action is required */
- /* this is a reply packet to a reject file request. no action is required */
- 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 );
- case CP_CHUNK_RECEIVED :
- /* this is a ack for a file received. no action is required */
- purple_debug_error( MXIT_PLUGIN_ID, "Unsupported chunked data packet type received (%i)\n", chunktype );
-/*------------------------------------------------------------------------
- * 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 )
- 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] );
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Cannot perform redirect using the specified protocol" ) );
- /* 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 );
-/*------------------------------------------------------------------------
- * 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
- switch ( packet->cmd ) {
- /* fall through, when registeration successful, MXit will auto login */
- if ( !( session->flags & MXIT_FLAG_LOGGEDIN ) ) {
- mxit_parse_cmd_login( session, &packet->records[2], packet->rcount - 3 );
- session->flags &= ~MXIT_FLAG_LOGGEDIN;
- purple_account_disconnect( session->acc );
- * 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.
- mxit_parse_cmd_contact( session, &packet->records[2], packet->rcount - 3 );
- mxit_parse_cmd_presence( session, &packet->records[2], packet->rcount - 3 );
- /* incoming message (no bogus record) */
- mxit_parse_cmd_message( session, &packet->records[2], packet->rcount - 2 );
- /* new subscription request */
- mxit_parse_cmd_new_sub( session, &packet->records[2], packet->rcount - 3 );
- /* multi-media message */
- mxit_parse_cmd_media( session, &packet->records[2], packet->rcount - 2 );
- case CP_CMD_EXTPROFILE_GET :
- mxit_parse_cmd_extprofile( session, &packet->records[2], packet->rcount - 2 );
- case CP_CMD_SUGGESTCONTACTS :
- mxit_parse_cmd_suggestcontacts( session, &packet->records[2], packet->rcount - 2 );
- case CP_CMD_GOT_MSGEVENT :
- /* received message event */
- mxit_parse_cmd_msgevent( session, &packet->records[2], packet->rcount - 2 );
- /* update contact information */
- /* allow subscription ack */
- /* deny subscription ack */
- /* invite contact ack */
- /* remove contact ack */
- /* outgoing message ack */
- /* presence update ack */
- case CP_CMD_GRPCHAT_CREATE :
- case CP_CMD_GRPCHAT_INVITE :
- case CP_CMD_EXTPROFILE_SET :
- // TODO: Protocol 6.2 indicates status for each attribute, and current value.
- case CP_CMD_SPLASHCLICK :
- /* splash-screen clickthrough */
- purple_debug_error( MXIT_PLUGIN_ID, "Received unknown client packet (cmd = %i)\n", packet->cmd );
-/*------------------------------------------------------------------------
- * 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 )
- /* set the error description to be shown to the user */
- errdesc = packet->errmsg;
- 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 ) );
- switch ( packet->cmd ) {
- if ( packet->errcode == MXIT_ERRCODE_REDIRECT ) {
- mxit_perform_redirect( session, packet->errmsg );
- g_snprintf( errmsg, sizeof( errmsg ), _( "Login error: %s (%i)" ), errdesc, packet->errcode );
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, errmsg );
- g_snprintf( errmsg, sizeof( errmsg ), _( "Logout error: %s (%i)" ), errdesc, packet->errcode );
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NAME_IN_USE, _( errmsg ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Message Sending Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Status Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Mood Error" ), _( errdesc ) );
- * 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
- mxit_send_login( session );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Invitation Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Removal Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Subscription Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Contact Update Error" ), _( errdesc ) );
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "File Transfer Error" ), _( errdesc ) );
- case CP_CMD_GRPCHAT_CREATE :
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Cannot create MultiMx room" ), _( errdesc ) );
- case CP_CMD_GRPCHAT_INVITE :
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "MultiMx Invitation Error" ), _( errdesc ) );
- case CP_CMD_EXTPROFILE_GET :
- case CP_CMD_EXTPROFILE_SET :
- mxit_popup( PURPLE_NOTIFY_MSG_WARNING, _( "Profile Error" ), _( errdesc ) );
- case CP_CMD_SPLASHCLICK :
- mxit_popup( PURPLE_NOTIFY_MSG_ERROR, _( "Error" ), _( errdesc ) );
-/*========================================================================================================================
- * Low-level Packet receive
-/*------------------------------------------------------------------------
- * 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;
- purple_debug_info( MXIT_PLUGIN_ID, "PACKET DUMP: (%i records)\n", p->rcount );
- for ( i = 0; i < p->rcount; i++ ) {
- purple_debug_info( MXIT_PLUGIN_ID, "RECORD: (%i fields)\n", r->fcount );
- for ( j = 0; j < r->fcount; j++ ) {
- purple_debug_info( MXIT_PLUGIN_ID, "\tFIELD: (len=%zu) '%s' \n", f->len, f->data );
-/*------------------------------------------------------------------------
- * 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;
- for ( i = 0; i < p->rcount; i++ ) {
- for ( j = 0; j < r->fcount; j++ ) {
-/*------------------------------------------------------------------------
- * 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 )
- field = g_new0( struct field, 1 );
- r->fields = g_realloc( r->fields, sizeof( struct field* ) * ( r->fcount + 1 ) );
- r->fields[r->fcount] = 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 )
- rec = g_new0( struct record, 1 );
- p->records = g_realloc( p->records, sizeof( struct record* ) * ( p->rcount + 1 ) );
- p->records[p->rcount] = 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;
- purple_debug_info( MXIT_PLUGIN_ID, "Received packet (%i bytes)\n", session->rx_i );
- dump_bytes( session, session->rx_dbuf, session->rx_i );
- while ( i < session->rx_i ) {
- /* create first record and field */
- memset( &packet, 0x00, sizeof( struct rx_packet ) );
- rec = add_record( &packet );
- /* 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 :
- if ( packet.rcount == 1 ) {
- 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 */
- field = add_field( rec );
- field->data = &session->rx_dbuf[i];
- session->rx_dbuf[i] = '\0';
- rec = add_record( &packet );
- session->rx_dbuf[i] = '\0';
- field = add_field( rec );
- field->data = &session->rx_dbuf[i];
- session->rx_dbuf[i] = '\0';
- /* skip non special characters */
- field = add_field( rec );
- field->data = &session->rx_dbuf[i];
- if ( packet.rcount < 2 ) {
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "Invalid packet received from MXit." ) );
- free_rx_packet( &packet );
- 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 );
- dump_packet( &packet );
- /* reset the out ack */
- if ( session->outack == packet.cmd ) {
- /* outstanding ack received from mxit server */
- /* check packet status */
- if ( packet.errcode != MXIT_ERRCODE_SUCCESS ) {
- if ( ( packet.records[1]->fcount > 1 ) && ( packet.records[1]->fields[1]->data ) )
- packet.errmsg = packet.records[1]->fields[1]->data;
- res = process_error_response( session, &packet );
- res = process_success_response( session, &packet );
- /* free up the packet resources */
- free_rx_packet( &packet );
- if ( session->outack == 0 )
- mxit_manage_queue( session );
-/*------------------------------------------------------------------------
- * 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;
- if ( session->rx_state == RX_STATE_RLEN ) {
- /* we are reading in the packet length */
- len = read( session->fd, &ch, 1 );
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x01)" ) );
- /* connection closed */
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x02)" ) );
- 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)" ) );
- session->rx_state = RX_STATE_DATA;
- /* still part of the packet length record */
- session->rx_lbuf[session->rx_i] = ch;
- 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)" ) );
- 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 );
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x05)" ) );
- /* connection closed */
- purple_connection_error( session->con, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, _( "A connection error occurred to MXit. (read stage 0x06)" ) );
- 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 );
- /* we are still logged in */
- session->rx_state = RX_STATE_RLEN;
-/*------------------------------------------------------------------------
- * 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 */
- 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 */
- purple_input_remove( session->inpa );
- /* 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 );
- g_list_free( session->rooms );
- /* 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_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->statusMsg);
- g_free(contact->profile);
- g_object_unref(contact->image);
- 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
-/* 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) */
-#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"
-#define MXIT_CP_OS "windows"
-#elif defined( __linux__ )
-#define MXIT_CP_OS "linux"
-#define MXIT_CP_OS "unknown"
-/* Client capabilities */
-#define MXIT_CP_CAP "utf8=true;cid="MXIT_CLIENT_ID
-#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) */
-#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) */
-#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 */
-#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 */
-#define CP_REDIRECT_PERMANENT 1 /* permanent redirect */
-#define CP_REDIRECT_TEMPORARY 2 /* temporary redirect */
-#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) */
-#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 */
-#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) */
-/* ======================================================================================= */
-/*------------------------------------------*/
- struct record** records;
-/*------------------------------------------*/
- * A received message data object
- 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_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 "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)
- 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);
+ 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); - 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))
- 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);
--- 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 "ciphers/md5hash.h"
/* #define USE_XOR_FOR_ICQ */
@@ -75,14 +73,15 @@
aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
- 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);
+ 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); @@ -90,19 +89,20 @@
aim_encode_password_md5(const char *password, size_t password_len, const char *key, guint8 *digest)
- 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_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); --- 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 "ciphers/md5hash.h"
#include "conversation.h"
@@ -5238,15 +5237,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));
+ hash = g_checksum_new(G_CHECKSUM_MD5); + g_checksum_update(hash, data, len); + g_checksum_get_digest(hash, md5, &digest_len); 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
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);
--- 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 @@
--- 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
- $(top_builddir)/libpurple/libpurple.la \
- $(top_builddir)/libpurple/protocols/yahoo/libyahoo.la \
-test_yahoo_util_SOURCES=test_yahoo_util.c
-test_yahoo_util_LDADD=$(COMMON_LIBS)
- -I$(top_srcdir)/libpurple \
- -I$(top_builddir)/libpurple \
--- 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 @@
-test_codes_to_html(void) {
- YahooStringTestData data[] = {
- "unknown \x1B[12345m ansi code",
- "plain <peanut>",
- "<font face='inva>lid'>test",
- "<font face='inva>lid'>test</font>",
- "<font face='inva>lid",
- "<font face='inva>lid",
- /* 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>",
- "\x1B[lmhttps://pidgin.im/\x1B[xlm",
- "<font color='#0000FF'>blue</font>",
- "\x1B[#70ea15mcustom color",
- "<font color='#70ea15'>custom color</font>",
- "<ALT #ff0000,#00ff00,#0000ff>test</ALT>",
- "<font face='Georgia'>test",
- "<font face='Georgia'>test</font>",
- "<font size='15'>test",
- "<font size='4' absz='15'>test</font>",
- "<font size='32'>size 32",
- "<font size='6' absz='32'>size 32</font>",
- "<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>",
- for(i = 0; data[i].input; i++) {
- gchar *result = yahoo_codes_to_html(data[i].input);
- g_assert_cmpstr(result, ==, data[i].output);
-test_html_to_codes(void) {
- YahooStringTestData data[] = {
- "plain <peanut>",
- /* bold/italic/underline */
- "\x1B[2mitalic\x1B[x2m",
- "\x1B[4munderline\x1B[x4m",
- "<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",
- "<A HREF=\"https://pidgin.im/\">https://pidgin.im/</A>",
- "<A HREF=\"mailto:mark@example.com\">mark@example.com</A>",
- "<font>nothing</font>",
- "<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=\"2\">test</font>",
- "<font size=\"10\">test</font>",
- "<font size=\"6\">test</font>",
- "<font size=\"30\">test</font>",
- "<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 */
- for(i = 0; data[i].input; i++) {
- gchar *result = yahoo_html_to_codes(data[i].input);
- g_assert_cmpstr(result, ==, data[i].output);
-main(gint argc, gchar **argv) {
- g_test_init(&argc, &argv, NULL);
- g_test_add_func("/yahoo/format/network to html",
- g_test_add_func("/yahoo/format/html to network",
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#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)
- 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)
- 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 */
- acct = purple_accounts_find(acct_id, protocol);
- if (acct && !purple_account_is_connected(acct))
- } else { /* Otherwise find an active account for the protocol */
- GList *l = purple_accounts_get_all();
- if (!strcmp(protocol, purple_account_get_protocol_id(l->data))
- && purple_account_is_connected(l->data)) {
-/* 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) {
-static gboolean yahoo_uri_handler(const char *proto, const char *cmd, GHashTable *params)
- char *acct_id = g_hash_table_lookup(params, "account");
- if (g_ascii_strcasecmp(proto, "ymsgr"))
- acct = find_acct(purple_protocol_get_id(yahoo_protocol), acct_id);
- /* ymsgr:SendIM?screename&m=The+Message */
- if (!g_ascii_strcasecmp(cmd, "SendIM")) {
- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &sname);
- char *message = g_hash_table_lookup(params, "m");
- PurpleIMConversation *im = purple_conversations_find_im_with_account(
- im = purple_im_conversation_new(acct, sname);
- purple_conversation_present(PURPLE_CONVERSATION(im));
- /* Spaces are encoded as '+' */
- g_strdelimit(message, "+", ' ');
- purple_conversation_send_confirm(PURPLE_CONVERSATION(im), message);
- **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
- /* ymsgr:Chat?roomname */
- else if (!g_ascii_strcasecmp(cmd, "Chat")) {
- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &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);
- ** Same as above (except that this would have to be re-written using purple_request_*)
- pidgin_blist_joinchat_show(); */
- /* ymsgr:AddFriend?name */
- else if (!g_ascii_strcasecmp(cmd, "AddFriend")) {
- g_hash_table_foreach(params, yahoo_find_uri_novalue_param, &name);
- purple_blist_request_add_buddy(acct, name, NULL, NULL);
-yahoo_get_account_text_table(PurpleAccount *account)
- table = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo ID..."));
-static PurpleWhiteboardOps yahoo_whiteboard_ops =
- yahoo_doodle_get_dimensions,
- yahoo_doodle_get_brush,
- yahoo_doodle_set_brush,
- yahoo_doodle_send_draw_list,
-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",
- 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);
- 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);
-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;
-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;
-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;
-yahoo_protocol_im_iface_init(PurpleProtocolIMIface *im_iface)
- im_iface->send = yahoo_send_im;
- im_iface->send_typing = yahoo_send_typing;
-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;
-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;
-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;
-yahoo_protocol_attention_iface_init(PurpleProtocolAttentionIface *attention_iface)
- attention_iface->send = yahoo_send_attention;
- attention_iface->get_types = yahoo_attention_types;
-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(
- "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,
-plugin_load(PurplePlugin *plugin, GError **error)
- yahoo_protocol_register_type(plugin);
- yahoo_protocol = purple_protocols_add(YAHOO_TYPE_PROTOCOL, error);
- yahoo_register_commands();
- purple_signal_connect(purple_get_core(), "uri-handler", yahoo_protocol,
- PURPLE_CALLBACK(yahoo_uri_handler), NULL);
-plugin_unload(PurplePlugin *plugin, GError **error)
- yahoo_unregister_commands();
- if (!purple_protocols_remove(yahoo_protocol, error))
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#define 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
-typedef struct _YahooProtocolClass
- PurpleProtocolClass parent_class;
- * Returns the GType for the YahooProtocol object.
-G_MODULE_EXPORT GType yahoo_protocol_get_type(void);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#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)
- 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)
- PurpleCmdId id = GPOINTER_TO_UINT(cmds->data);
- purple_cmd_unregister(id);
- cmds = g_slist_delete_link(cmds, cmds);
-yahoojp_get_account_text_table(PurpleAccount *account)
- table = g_hash_table_new(g_str_hash, g_str_equal);
- g_hash_table_insert(table, "login_label", (gpointer)_("Yahoo JAPAN ID..."));
-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);
-yahoojp_protocol_class_init(PurpleProtocolClass *klass)
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#define 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
-typedef struct _YahooJPProtocolClass
- YahooProtocolClass parent_class;
- * 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public 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 "ciphers/md5hash.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"
-/* #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
-#define PING_TIMEOUT 3600
-#define KEEPALIVE_TIMEOUT 60
-#if TRY_WEBMESSENGER_LOGIN
-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)
- if (!gc || !name || !f || !purple_blist_find_buddy(purple_connection_get_account(gc), name))
- case YAHOO_STATUS_OFFLINE:
- status = YAHOO_STATUS_TYPE_OFFLINE;
- case YAHOO_STATUS_AVAILABLE:
- status = YAHOO_STATUS_TYPE_AVAILABLE;
- status = YAHOO_STATUS_TYPE_BRB;
- case YAHOO_STATUS_BUSY:
- status = YAHOO_STATUS_TYPE_BUSY;
- case YAHOO_STATUS_NOTATHOME:
- status = YAHOO_STATUS_TYPE_NOTATHOME;
- case YAHOO_STATUS_NOTATDESK:
- status = YAHOO_STATUS_TYPE_NOTATDESK;
- case YAHOO_STATUS_NOTINOFFICE:
- status = YAHOO_STATUS_TYPE_NOTINOFFICE;
- case YAHOO_STATUS_ONPHONE:
- status = YAHOO_STATUS_TYPE_ONPHONE;
- case YAHOO_STATUS_ONVACATION:
- status = YAHOO_STATUS_TYPE_ONVACATION;
- case YAHOO_STATUS_OUTTOLUNCH:
- status = YAHOO_STATUS_TYPE_OUTTOLUNCH;
- case YAHOO_STATUS_STEPPEDOUT:
- status = YAHOO_STATUS_TYPE_STEPPEDOUT;
- case YAHOO_STATUS_INVISIBLE: /* this should never happen? */
- status = YAHOO_STATUS_TYPE_INVISIBLE;
- case YAHOO_STATUS_CUSTOM:
- case YAHOO_STATUS_IDLE:
- status = YAHOO_STATUS_TYPE_AVAILABLE;
- status = YAHOO_STATUS_TYPE_AWAY;
- purple_debug_warning("yahoo", "Warning, unknown status %d\n", f->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);
- purple_protocol_got_user_status(purple_connection_get_account(gc), name, status, NULL);
- purple_protocol_got_user_idle(purple_connection_get_account(gc), name, TRUE, f->idle);
- purple_protocol_got_user_idle(purple_connection_get_account(gc), name, FALSE, 0);
- purple_protocol_got_user_status(purple_connection_get_account(gc), name, YAHOO_STATUS_TYPE_MOBILE, NULL);
- 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);
- gboolean unicode = FALSE;
- 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"));
- struct yahoo_pair *pair = l->data;
- case 0: /* we won't actually do anything with this */
- case 1: /* we won't actually do anything with this */
- case 8: /* how many online buddies we have */
- case 7: /* the current buddy */
- /* update the previous buddy before changing the variables */
- yahoo_friend_set_status_message(f, yahoo_string_decode(gc, message, unicode));
- yahoo_update_status(gc, name, f);
- if (pair->value && g_utf8_validate(pair->value, -1, NULL)) {
- f = yahoo_friend_find_or_new(gc, name);
- f->status = strtol(pair->value, NULL, 10);
- if ((f->status >= YAHOO_STATUS_BRB) && (f->status <= YAHOO_STATUS_STEPPEDOUT))
- if (f->status == YAHOO_STATUS_IDLE) {
- /* Idle may have already been set in a more precise way in case 137 */
- if(pkt->service == YAHOO_SERVICE_STATUS_15)
- if (f->status != YAHOO_STATUS_CUSTOM)
- yahoo_friend_set_status_message(f, NULL);
- case 19: /* custom message */
- case 11: /* this is the buddy's session id */
- f->session_id = strtol(pair->value, NULL, 10);
- case 17: /* in chat? */
- case 47: /* is custom status away or not? 2=idle*/
- /* I have no idea what it means when this is
- * set when someone's available, but it doesn't
- if (f->status == YAHOO_STATUS_AVAILABLE)
- f->away = strtol(pair->value, NULL, 10);
- /* Idle may have already been set in a more precise way in case 137 */
- if(pkt->service == YAHOO_SERVICE_STATUS_15)
- case 138: /* when value is 1, either we're not idle, or we are but won't say how long */
- if( (strtol(pair->value, NULL, 10) == 1) && (f->idle) )
- case 137: /* usually idle time in seconds, sometimes login time */
- if (f->status != YAHOO_STATUS_AVAILABLE)
- f->idle = time(NULL) - strtol(pair->value, NULL, 10);
- case 13: /* bitmask, bit 0 = pager, bit 1 = chat, bit 2 = game */
- if (strtol(pair->value, NULL, 10) == 0) {
- f->status = YAHOO_STATUS_OFFLINE;
- purple_protocol_got_user_status(account, name, "offline", NULL);
- purple_protocol_got_user_status_deactive(account, name, YAHOO_STATUS_TYPE_MOBILE);
- f->sms = strtol(pair->value, NULL, 10);
- yahoo_update_status(gc, name, f);
- case 197: /* Avatars */
- 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);
- 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;
- b = purple_blist_find_buddy(purple_connection_get_account(gc), name);
- if (!cksum || (cksum == -1)) {
- yahoo_friend_set_buddy_icon_need_request(f, TRUE);
- purple_buddy_icons_set_for_user(purple_connection_get_account(gc), name, NULL, 0, NULL);
- yahoo_friend_set_buddy_icon_need_request(f, FALSE);
- locksum = purple_buddy_icons_get_checksum_for_user(b);
- if (!locksum || (cksum != strtol(locksum, NULL, 10)))
- yahoo_send_picture_request(gc, name);
- 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));
- case 97: /* Unicode status message */
- unicode = !strcmp(pair->value, "1");
- case 244: /* client version number. Yahoo Client Detection */
- if(f && strtol(pair->value, NULL, 10))
- f->version_id = strtol(pair->value, NULL, 10);
- purple_debug_warning("yahoo",
- "Unknown status key %d\n", pair->key);
- if (pkt->service == YAHOO_SERVICE_LOGOFF)
- f->status = YAHOO_STATUS_OFFLINE;
- 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)
- gboolean onlist = FALSE;
- if (g_hash_table_lookup_extended(ht, name, (gpointer *)&oname, (gpointer *)&list))
- g_hash_table_steal(ht, oname);
- list = purple_blist_find_buddies(account, name);
- for (i = list; i; i = i->next) {
- 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);
- 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);
- oname = g_strdup(name);
- g_hash_table_insert(ht, oname, list);
-static void yahoo_do_group_cleanup(gpointer key, gpointer value, gpointer user_data)
- GSList *list = value, *i;
- for (i = list; i; i = i->next) {
- 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)
- if (strlen(rawcookie) < 2)
- tmpcookie = g_strdup(rawcookie+2);
- cookieend = strchr(tmpcookie, ';');
- cookie = g_strdup(tmpcookie);
-static void yahoo_process_cookie(YahooData *yd, char *c)
- yd->cookie_y = _getcookie(c);
- } else if (c[0] == 'T') {
- yd->cookie_t = _getcookie(c);
- 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)
- PurpleAccount *account = purple_connection_get_account(gc);
- YahooData *yd = purple_connection_get_protocol_data(gc);
- YahooFriend *f = NULL; /* It's your friends. They're going to want you to share your StarBursts. */
- /* But what if you had no friends? */
- ht = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, (GDestroyNotify) g_slist_free);
- struct yahoo_pair *pair = l->data;
- /* 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;
- case 301: /* This is 319 before all s/n's in a group after the first. It is followed by an identical 300. */
- 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)) {
- 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);
- f->presence = YAHOO_PRESENCE_PERM_OFFLINE;
- yahoo_friend_set_p2p_status(f, YAHOO_P2PSTATUS_NOT_CONNECTED);
- f->p2p_packet_sent = 0;
- /* 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);
- case 300: /* This is 318 before a group, 319 before any s/n in a group, and 320 before any ignored s/n. */
- case 65: /* This is the group */
- g_free(yd->current_list15_grp);
- yd->current_list15_grp = yahoo_string_decode(gc, pair->value, FALSE);
- case 7: /* buddy's s/n */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- temp = g_strdup(purple_normalize(account, pair->value));
- purple_debug_warning("yahoo", "yahoo_process_list_15 "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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);
- purple_debug_warning("yahoo", "yahoo_process_list_15 "
- "got non-UTF-8 string for key %d\n", pair->key);
- case 317: /* Stealth Setting */
- stealth = strtol(pair->value, NULL, 10);
- 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)));
- 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);
-static void yahoo_process_list(PurpleConnection *gc, struct yahoo_packet *pkt)
- gboolean got_serv_list = FALSE;
- PurpleAccount *account = purple_connection_get_account(gc);
- YahooData *yd = purple_connection_get_protocol_data(gc);
- char **tmp, **bud, *norm_bud;
- yd->session_id = pkt->id;
- struct yahoo_pair *pair = l->data;
- if (!yd->tmp_serv_blist)
- yd->tmp_serv_blist = g_string_new(pair->value);
- g_string_append(yd->tmp_serv_blist, pair->value);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- if (!yd->tmp_serv_ilist)
- yd->tmp_serv_ilist = g_string_new(pair->value);
- g_string_append(yd->tmp_serv_ilist, pair->value);
- purple_debug_warning("yahoo", "yahoo_process_list "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- yd->profiles = g_strsplit(pair->value, ",", -1);
- purple_debug_warning("yahoo", "yahoo_process_list "
- "got non-UTF-8 string for key %d\n", pair->key);
- case 59: /* cookies, yum */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- yahoo_process_cookie(yd, pair->value);
- purple_debug_warning("yahoo", "yahoo_process_list "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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);
- g_string_append(yd->tmp_serv_plist, pair->value);
- purple_debug_warning("yahoo", "yahoo_process_list "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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[0] || !split[1]) {
- 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");
- 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)) {
- 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_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 */
- purple_account_privacy_deny_add(account, *bud, 1);
- g_string_free(yd->tmp_serv_ilist, TRUE);
- yd->tmp_serv_ilist = NULL;
- ((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);
- 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_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;
- YahooData *yd = purple_connection_get_protocol_data(gc);
- account = purple_connection_get_account(gc);
- struct yahoo_pair *pair = l->data;
- if (pair->key == 4 || pair->key == 1) {
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_notify "
- "got non-UTF-8 string for key %d\n", pair->key);
- } else if (pair->key == 49) {
- } else if (pair->key == 13) {
- } else if (pair->key == 14) {
- if (g_utf8_validate(pair->value, -1, NULL)) {
- 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);
- /* 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);
- 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);
- purple_serv_got_typing_stopped(gc, from);
- } else if (!g_ascii_strncasecmp(msg, "GAME", strlen("GAME"))) {
- PurpleBuddy *bud = purple_blist_find_buddy(account, from);
- purple_debug_warning("yahoo",
- "%s is playing a game, and doesn't want you to know.\n", from);
- f = yahoo_friend_find(gc, from);
- 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);
- 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);
-static void yahoo_process_sms_message(PurpleConnection *gc, struct yahoo_packet *pkt)
- PurpleAccount *account;
- struct _yahoo_im *sms = NULL;
- char *server_msg = NULL;
- yd = purple_connection_get_protocol_data(gc);
- account = purple_connection_get_account(gc);
- struct yahoo_pair *pair = l->data;
- 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);
- purple_debug_warning("yahoo", "yahoo_process_sms_message "
- "got non-UTF-8 string for key %d\n", pair->key);
- } else if (pair->key == 14) {
- sms->msg = pair->value;
- } else if (pair->key == 68) {
- 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;
- purple_debug_warning("yahoo", "yahoo_process_sms_message "
- "got non-UTF-8 string for key %d\n", pair->key);
- purple_debug_info("yahoo", "Received a malformed SMS packet!\n");
- if ((int)pkt->status < 0)
- pkt->status = YAHOO_STATUS_DISCONNECTED;
- if (pkt->status == YAHOO_STATUS_DISCONNECTED) {
- PurpleIMConversation *im;
- im = purple_conversations_find_im_with_account(sms->from, account);
- im = purple_im_conversation_new(account, sms->from);
- purple_conversation_write_system_message(PURPLE_CONVERSATION(im),
- purple_notify_error(gc, NULL,
- _("Your SMS was not delivered"), NULL,
- purple_request_cpar_from_connection(gc));
- if (!sms->from || !sms->msg) {
- m = yahoo_string_decode(gc, sms->msg, sms->utf8);
- purple_serv_got_im(gc, sms->from, m, 0, sms->time);
-/* 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);
- 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 */
- 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;
- 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) {
- im->utf8 = strtol(pair->value, NULL, 10);
- } else if (pair->key == 15) {
- im->time = strtol(pair->value, NULL, 10);
- } else if (pair->key == 206) {
- im->buddy_icon = strtol(pair->value, NULL, 10);
- } else if (pair->key == 14) {
- } else if (im && (pair->key == 11)) {
- /* 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);
- 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)) {
- /* Check for the Doodle IMV */
- g_hash_table_replace(yd->imvironments, g_strdup(im->from), g_strdup(pair->value));
- if (strstr(pair->value, "doodle;") != NULL)
- if (!purple_account_privacy_check(account, im->from)) {
- purple_debug_info("yahoo", "Doodle request from %s dropped.\n",
- /* 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 */
- 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) {
- } 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) {
- if (!purple_account_privacy_check(account, im->from)) {
- purple_debug_info("yahoo", "Message from %s dropped.\n", im->from);
- * TODO: Is there anything else we should check when determining whether
- * we should send an acknowledgement?
- /* 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 */
- 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
- m2 = purple_strreplace(m, "\r\n", "\n");
- purple_util_chrreplace(m, '\r', '\n');
- if (!strcmp(m, "<ding>")) {
- username = g_markup_escape_text(im->from, -1);
- purple_protocol_got_attention(gc, username, YAHOO_BUZZ);
- m2 = yahoo_codes_to_html(m);
- purple_serv_got_im(gc, im->from, m2, 0, im->time);
-static void yahoo_process_sysmessage(PurpleConnection *gc, struct yahoo_packet *pkt)
- char *prim, *me = NULL, *msg = NULL;
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- 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)) {
- purple_debug_warning("yahoo", "yahoo_process_sysmessage "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (!msg || !g_utf8_validate(msg, -1, NULL))
- 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));
-struct yahoo_add_request {
-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",
- yahoo_packet_send_and_free(pkt, yd);
-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;
- 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",
- 14, encoded_msg ? encoded_msg : "");
- yahoo_packet_send_and_free(pkt, yd);
-static void yahoo_buddy_denied_our_add(PurpleConnection *gc, const char *who, const char *reason)
- YahooData *yd = purple_connection_get_protocol_data(gc);
- 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);
- 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_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;
- const char *msg = NULL;
- account = purple_connection_get_account(gc);
- /* Buddy authorized/declined our addition */
- if (pkt->status == 1) {
- struct yahoo_pair *pair = l->data;
- response = strtol(pair->value, NULL, 10);
- 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);
- purple_debug_error("yahoo", "Received unknown authorization response of %d from buddy '%s'.\n", response, who ? who : "(Unknown Buddy)");
- /* 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);
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- add_req->id = g_strdup(pair->value);
- purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- firstname = pair->value;
- purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- lastname = pair->value;
- purple_debug_warning("yahoo", "yahoo_buddy_auth_req_15 "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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",
- yahoo_buddy_add_deny_cb(NULL, add_req);
- dec_msg = yahoo_string_decode(gc, msg, FALSE);
- if (firstname && lastname)
- alias = g_strdup_printf("%s %s", firstname, lastname);
- alias = g_strdup(firstname);
- 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,
- purple_blist_find_buddy(account, add_req->who) != NULL,
- yahoo_buddy_add_authorize_cb,
- yahoo_buddy_add_deny_cb,
- 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;
- account = purple_connection_get_account(gc);
- add_req = g_new0(struct yahoo_add_request, 1);
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- add_req->id = g_strdup(pair->value);
- purple_debug_warning("yahoo", "yahoo_buddy_added_us "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- add_req->who = g_strdup(pair->value);
- purple_debug_warning("yahoo", "yahoo_buddy_added_us "
- "got non-UTF-8 string for key %d\n", pair->key);
- case 15: /* time, for when they add us and we're offline */
- if (add_req->id && add_req->who) {
- 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",
- yahoo_buddy_add_deny_cb(NULL, add_req);
- 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,
- purple_blist_find_buddy(account,add_req->who) != NULL,
- yahoo_buddy_add_authorize_cb,
- yahoo_buddy_add_deny_cb, 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)
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old "
- "got non-UTF-8 string for key %d\n", pair->key);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_buddy_denied_our_add_old "
- "got non-UTF-8 string for key %d\n", pair->key);
- yahoo_buddy_denied_our_add(gc, who, msg);
-static void yahoo_process_contact(PurpleConnection *gc, struct yahoo_packet *pkt)
- yahoo_process_status(gc, pkt);
- yahoo_buddy_added_us(gc, pkt);
- yahoo_buddy_denied_our_add_old(gc, pkt);
-#define OUT_CHARSET "utf-8"
-static char *yahoo_decode(const char *text)
- char *converted = NULL;
- n = new = g_malloc(strlen (text) + 1);
- end = text + strlen(text);
- for (p = text; p < end; p++, n++) {
- if (p[1] >= '0' && p[1] <= '7') {
- for (i = 0, k = 0; k < 3; k += 1) {
- if (c < '0' || c > '7') break;
- } 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
- /* 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);
- converted = g_convert(new, n - new, OUT_CHARSET, "iso-8859-1", NULL, NULL, NULL);
-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;
- if (!purple_account_get_check_mail(account))
- struct yahoo_pair *pair = l->data;
- count = strtol(pair->value, NULL, 10);
- } else if (pair->key == 43) {
- if (g_utf8_validate(pair->value, -1, NULL)) {
- 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)) {
- 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)) {
- purple_debug_warning("yahoo", "yahoo_process_mail "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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);
- } 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,
-/* We use this structure once while we authenticate */
-/* 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];
- unsigned char fragment;
- *out++ = base64digits[in[0] >> 2];
- fragment = (in[0] << 4) & 0x30;
- fragment |= in[1] >> 4;
- *out++ = base64digits[fragment];
- *out++ = (inlen < 2) ? '-' : base64digits[(in[1] << 2) & 0x3c];
-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));
- 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",
- 244, YAHOO_CLIENT_VERSION_ID,
- 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",
- 244, YAHOO_CLIENT_VERSION_ID,
- 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);
- 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);
- splits = g_strsplit(purple_http_response_get_data(response, NULL),
- 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'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",
- } 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);
- /* Some error in the login process */
- PurpleConnectionError error;
- char *error_reason = NULL;
- /* Some error in the received stream */
- error_reason = g_strdup(_("Received invalid data"));
- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
- error_reason = g_strdup(_("Unknown error"));
- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
- /* if we have everything we need, why not try to login irrespective of response */
- if ((crumb != NULL) && (yd->cookie_y != NULL) && (yd->cookie_t != NULL)) {
- try_login_on_error = TRUE;
- error_reason = g_strdup(_("Unknown error"));
- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
- purple_debug_error("yahoo", "Authentication error: %s. "
- "Code %d\n", error_reason, response_no);
- purple_connection_error(gc, error, error_reason);
- g_free(auth_data->seed);
- crypt = g_strconcat(crumb, auth_data->seed, NULL);
- yahoo_auth16_stage3(gc, crypt);
- g_free(auth_data->seed);
-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);
- PurpleAccount *account = purple_connection_get_account(gc);
- gchar **split_data = g_strsplit(purple_http_response_get_data(
- response, NULL), "\r\n", -1);
- 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 */
- g_strfreev(split_data);
- /* Some error in the login process */
- PurpleConnectionError error;
- /* Some error in the received stream */
- error_reason = g_strdup(_("Received invalid data"));
- error = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
- /* 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;
- /* 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;
- /* the username does not exist */
- error_reason = g_strdup(_("Username does not exist"));
- error = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
- /* 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;
- /* 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;
- /* username or password missing */
- error_reason = g_strdup(_("Username or password missing"));
- error = PURPLE_CONNECTION_ERROR_AUTHENTICATION_FAILED;
- error_reason = g_strdup_printf(_("Unknown error (%d)"), response_no);
- error = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
- purple_debug_error("yahoo", "Authentication error: %s. Code %d\n",
- error_reason, response_no);
- purple_connection_error(gc, error, error_reason);
- g_free(auth_data->seed);
- 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);
-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->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)
- struct yahoo_pair *pair = l->data;
- /* (pair->key == 1) -> sn */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_auth "
- "got non-UTF-8 string for key %d\n", pair->key);
- } else if (pair->key == 13) {
- /* used to be for really old auth routine, dont support now */
- case 2: /* Yahoo ver 16 authentication */
- yahoo_auth16_stage1(gc, seed);
- 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));
- yahoo_auth16_stage1(gc, seed); /* Can't hurt to try it anyway. */
-static void ignore_buddy(PurpleBuddy *buddy) {
- PurpleAccount *account;
- 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);
-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) {
- gboolean ignore = TRUE;
- for (l = pkt->hash; l; l = l->next) {
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_ignore "
- "got non-UTF-8 string for key %d\n", pair->key);
- /* 1 == ignore, 2 == unignore */
- ignore = (strtol(pair->value, NULL, 10) == 1);
- status = strtol(pair->value, NULL, 10);
- * 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?)
- purple_debug_info("yahoo", "Server reported \"is a buddy\" for %s while %s",
- who, (ignore ? "ignoring" : "unignoring"));
- 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));
- purple_debug_info("yahoo", "Server reported that %s is already in the ignore list.\n",
- purple_debug_info("yahoo", "Server reported that %s is not in the ignore list; could not delete\n",
-#if TRY_WEBMESSENGER_LOGIN
-yahoo_try_webmessenger_login(PurpleConnection *gc)
- YahooData *yd = purple_connection_get_protocol_data(gc);
- PurpleHttpRequest *req;
- purple_input_remove(yd->inpa);
- 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);
-#endif /* TRY_WEBMESSENGER_LOGIN */
-static void yahoo_process_authresp(PurpleConnection *gc, struct yahoo_packet *pkt)
- PurpleAccount *account = purple_connection_get_account(gc);
- PurpleConnectionError reason = PURPLE_CONNECTION_ERROR_OTHER_ERROR;
- struct yahoo_pair *pair = l->data;
- err = strtol(pair->value, NULL, 10);
- } else if (pair->key == 20) {
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_authresp "
- "got non-UTF-8 string for key %d\n", pair->key);
- msg = g_strdup(_("Unknown error"));
- reason = PURPLE_CONNECTION_ERROR_NETWORK_ERROR;
- msg = g_strdup(_("Username does not exist"));
- reason = PURPLE_CONNECTION_ERROR_INVALID_USERNAME;
-#if TRY_WEBMESSENGER_LOGIN
- if (yahoo_try_webmessenger_login(gc))
- 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;
- 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;
- /* 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;
- 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;
- msg = g_strdup_printf(_("Unknown error number %d. Logging into the Yahoo! website may fix this."), err);
- fullmsg = g_strdup_printf("%s\n%s", msg, url);
- fullmsg = g_strdup(msg);
- purple_connection_error(gc, reason, fullmsg);
-static void yahoo_process_addbuddy(PurpleConnection *gc, struct yahoo_packet *pkt)
- YahooData *yd = purple_connection_get_protocol_data(gc);
- struct yahoo_pair *pair = l->data;
- err = strtol(pair->value, NULL, 10);
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_addbuddy "
- "got non-UTF-8 string for key %d\n", pair->key);
- 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);
- 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));
-/* write pkt to the source */
-static void yahoo_p2p_write_pkt(gint source, struct yahoo_packet *pkt)
- /*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");
-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 */
- 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);
-/* 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;
- /* If friend, set him not connected */
- f = yahoo_friend_find(p2p_data->gc, p2p_data->host_username);
- 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);
-/* 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;
- struct yahoo_packet *pkt_to_send;
- PurpleAccount *account;
- int val_13_to_send = 0;
- yd = purple_connection_get_protocol_data(p2p_data->gc);
- /* lets see whats in the packet */
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- 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");
- purple_debug_warning("yahoo", "yahoo_p2p_process_p2pfilexfer "
- "got non-UTF-8 string for key %d\n", pair->key);
- p2p_data->val_13 = strtol(pair->value, NULL, 10); /* Value should be 5-7 */
- /* case 5, 49 look laters, no use right now */
- 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) )
- val_13_to_send = 7; break;
- default: purple_debug_warning("yahoo","p2p:Unknown value for key 13\n");
- /* 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 */
- /* 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(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);
- 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 ?? */
- struct yahoo_packet *pkt;
- struct yahoo_p2p_data *p2p_data;
- 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*/
- 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);
- yahoo_p2p_disconnect_destroy_data(data);
- /* 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)
- 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");
- /* 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);
- yahoo_p2p_disconnect_destroy_data(data);
- purple_debug_warning("yahoo","p2p: Got something other than YMSG packet\n");
- g_memmove(buf, start, len);
- 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",
- /* 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);
- yahoo_p2p_disconnect_destroy_data(data);
- 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 */
- case YAHOO_SERVICE_P2PFILEXFER:
- yahoo_p2p_process_p2pfilexfer(data, source, pkt);
- case YAHOO_SERVICE_MESSAGE:
- yahoo_process_message(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
- case YAHOO_SERVICE_NOTIFY:
- yahoo_process_notify(p2p_data->gc, pkt, YAHOO_PKT_TYPE_P2P);
- 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)
- struct yahoo_p2p_data *p2p_data;
- yd = purple_connection_get_protocol_data(p2p_data->gc);
- acceptfd = accept(source, NULL, 0);
- if(acceptfd == -1 && (errno == EAGAIN || errno == EWOULDBLOCK))
- 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);
- 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;
- 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;
-static void yahoo_p2p_server_listen_cb(int listenfd, gpointer data)
- struct yahoo_p2p_data *p2p_data;
- yd = purple_connection_get_protocol_data(p2p_data->gc);
- yd->listen_data = NULL;
- purple_debug_warning("yahoo","p2p: error starting p2p server\n");
- yahoo_p2p_disconnect_destroy_data(data);
- /* 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);
- 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)
- gchar *base64_ip = NULL;
- 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)
- /* One shouldn't try to connect to self */
- if( strcmp(purple_normalize(account, purple_account_get_username(account)), who) == 0)
- /* 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)) )
- /* Finally, don't try to connect to buddies not online or on sms */
- if( (f->status == YAHOO_STATUS_OFFLINE) || f->sms )
- public_ip = purple_network_get_public_ip();
- if( (sscanf(public_ip, "%u.%u.%u.%u", &temp[0], &temp[1], &temp[2], &temp[3])) !=4 )
- 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",
- 12, base64_ip, /* base64 encode ip */
- 61, 0, /* To-do : figure out what is 61 for?? */
- 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->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;
- /* FIXME: If the port is already used, purple_network_listener returns NULL and old listener won't be canceled
- * in yahoo_close function. */
- purple_debug_warning("yahoo","p2p: Failed to create p2p server - server already exists\n");
- 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");
-/* 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;
- 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);
- /* 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 */
- 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)
- PurpleAccount *account;
- /* 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)
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_p2p "
- "got non-UTF-8 string for key %d\n", pair->key);
- /* who again, the master identity this time? */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- /* 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?*/
- purple_debug_warning("yahoo", "yahoo_process_p2p "
- "got non-UTF-8 string for key %d\n", pair->key);
- val_13 = strtol(pair->value, NULL, 10);
- val_11 = strtol(pair->value, NULL, 10); /* session id of peer */
- if( (f = yahoo_friend_find(gc, who)) )
- f->session_id = val_11;
- yahoo: Key: 61 Value: 0
- yahoo: Key: 13 Value: 0 packet count ??
- yahoo: Key: 49 Value: PEERTOPEER
- yahoo: Key: 140 Value: 1
- struct yahoo_p2p_data *p2p_data;
- decoded = purple_base64_decode(base64, &len);
- purple_debug_info("yahoo","p2p: Unable to decode base64 IP (%s) \n", base64);
- 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);
- ip = strtol((gchar *)decoded, NULL, 10);
- host_ip = g_strdup_printf("%u.%u.%u.%u", ip & 0xff, (ip >> 8) & 0xff, (ip >> 16) & 0xff,
- f = yahoo_friend_find(gc, who);
- yahoo_friend_set_ip(f, host_ip);
- purple_debug_info("yahoo", "IP : %s\n", host_ip);
- account = purple_connection_get_account(gc);
- 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->connection_type = YAHOO_P2P_WE_ARE_CLIENT;
- 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);
-static void yahoo_process_audible(PurpleConnection *gc, struct yahoo_packet *pkt)
- PurpleAccount *account;
- char *who = NULL, *msg = NULL, *id = NULL;
- account = purple_connection_get_account(gc);
- struct yahoo_pair *pair = l->data;
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_audible "
- "got non-UTF-8 string for key %d\n", pair->key);
- /* the audible, in foo.locale.bar.baz format
- eg: base.tw.smiley.smiley43 */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_audible "
- "got non-UTF-8 string for key %d\n", pair->key);
- /* the text of the audible */
- if (g_utf8_validate(pair->value, -1, NULL)) {
- purple_debug_warning("yahoo", "yahoo_process_audible "
- "got non-UTF-8 string for key %d\n", pair->key);
- /* SHA-1 hash of audible SWF file (eg: 4e8691499d9c0fb8374478ff9720f4a9ea4a4915) */
- if (!g_utf8_validate(msg, -1, NULL)) {
- purple_debug_misc("yahoo", "Warning, nonutf8 audible, ignoring!\n");
- 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);
- /* "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));
- 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);
- case YAHOO_SERVICE_NOTIFY:
- yahoo_process_notify(gc, pkt, YAHOO_PKT_TYPE_SERVER);
- case YAHOO_SERVICE_MESSAGE:
- case YAHOO_SERVICE_GAMEMSG:
- case YAHOO_SERVICE_CHATMSG:
- yahoo_process_message(gc, pkt, YAHOO_PKT_TYPE_SERVER);
- case YAHOO_SERVICE_SYSMESSAGE:
- yahoo_process_sysmessage(gc, pkt);
- case YAHOO_SERVICE_NEWMAIL:
- yahoo_process_mail(gc, pkt);
- case YAHOO_SERVICE_NEWCONTACT:
- yahoo_process_contact(gc, pkt);
- case YAHOO_SERVICE_AUTHRESP:
- yahoo_process_authresp(gc, pkt);
- case YAHOO_SERVICE_LIST:
- yahoo_process_list(gc, pkt);
- case YAHOO_SERVICE_LIST_15:
- yahoo_process_list_15(gc, pkt);
- case YAHOO_SERVICE_AUTH:
- yahoo_process_auth(gc, pkt);
- case YAHOO_SERVICE_AUTH_REQ_15:
- yahoo_buddy_auth_req_15(gc, pkt);
- case YAHOO_SERVICE_ADDBUDDY:
- yahoo_process_addbuddy(gc, pkt);
- case YAHOO_SERVICE_IGNORECONTACT:
- yahoo_process_ignore(gc, pkt);
- case YAHOO_SERVICE_CONFINVITE:
- case YAHOO_SERVICE_CONFADDINVITE:
- yahoo_process_conference_invite(gc, pkt);
- case YAHOO_SERVICE_CONFDECLINE:
- yahoo_process_conference_decline(gc, pkt);
- case YAHOO_SERVICE_CONFLOGON:
- yahoo_process_conference_logon(gc, pkt);
- case YAHOO_SERVICE_CONFLOGOFF:
- yahoo_process_conference_logoff(gc, pkt);
- case YAHOO_SERVICE_CONFMSG:
- yahoo_process_conference_message(gc, pkt);
- case YAHOO_SERVICE_CHATONLINE:
- yahoo_process_chat_online(gc, pkt);
- case YAHOO_SERVICE_CHATLOGOUT:
- yahoo_process_chat_logout(gc, pkt);
- case YAHOO_SERVICE_CHATGOTO:
- yahoo_process_chat_goto(gc, pkt);
- case YAHOO_SERVICE_CHATJOIN:
- yahoo_process_chat_join(gc, pkt);
- case YAHOO_SERVICE_CHATLEAVE: /* XXX is this right? */
- case YAHOO_SERVICE_CHATEXIT:
- yahoo_process_chat_exit(gc, pkt);
- case YAHOO_SERVICE_CHATINVITE: /* XXX never seen this one, might not do it right */
- case YAHOO_SERVICE_CHATADDINVITE:
- yahoo_process_chat_addinvite(gc, pkt);
- case YAHOO_SERVICE_COMMENT:
- yahoo_process_chat_message(gc, pkt);
- case YAHOO_SERVICE_PRESENCE_PERM:
- case YAHOO_SERVICE_PRESENCE_SESSION:
- yahoo_process_presence(gc, pkt);
- 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");
- case YAHOO_SERVICE_PEERTOPEER:
- yahoo_process_p2p(gc, pkt);
- case YAHOO_SERVICE_PICTURE:
- yahoo_process_picture(gc, pkt);
- case YAHOO_SERVICE_PICTURE_CHECKSUM:
- yahoo_process_picture_checksum(gc, pkt);
- case YAHOO_SERVICE_PICTURE_UPLOAD:
- yahoo_process_picture_upload(gc, pkt);
- case YAHOO_SERVICE_PICTURE_UPDATE:
- case YAHOO_SERVICE_AVATAR_UPDATE:
- yahoo_process_avatar_update(gc, pkt);
- case YAHOO_SERVICE_AUDIBLE:
- yahoo_process_audible(gc, pkt);
- case YAHOO_SERVICE_CONTACT_DETAILS:
- yahoo_process_contact_details(gc, pkt);
- case YAHOO_SERVICE_FILETRANS_15:
- yahoo_process_filetrans_15(gc, pkt);
- case YAHOO_SERVICE_FILETRANS_INFO_15:
- yahoo_process_filetrans_info_15(gc, pkt);
- case YAHOO_SERVICE_FILETRANS_ACC_15:
- yahoo_process_filetrans_acc_15(gc, pkt);
- case YAHOO_SERVICE_SMS_MSG:
- yahoo_process_sms_message(gc, pkt);
- purple_debug_error("yahoo", "Unhandled service 0x%02x\n", pkt->service);
-static void yahoo_pending(gpointer data, gint source, PurpleInputCondition cond)
- PurpleConnection *gc = data;
- YahooData *yd = purple_connection_get_protocol_data(gc);
- len = read(yd->fd, buf, sizeof(buf));
- tmp = g_strdup_printf(_("Lost connection with server: %s"),
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Server closed the connection"));
- purple_connection_update_last_received(gc);
- yd->rxqueue = g_realloc(yd->rxqueue, len + yd->rxlen);
- memcpy(yd->rxqueue + yd->rxlen, buf, len);
- struct yahoo_packet *pkt;
- if (yd->rxlen < YAHOO_PACKET_HDRLEN)
- 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? */
- purple_debug_warning("yahoo", "Error in YMSG stream, got something not a YMSG packet!\n");
- start = memchr(yd->rxqueue + 1, 'Y', yd->rxlen - 1);
- g_memmove(yd->rxqueue, start, yd->rxlen - (start - yd->rxqueue));
- yd->rxlen -= start - yd->rxqueue;
- 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))
- 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;
- guchar *tmp = g_memdup(yd->rxqueue + YAHOO_PACKET_HDRLEN + pktlen, yd->rxlen);
- 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;
- struct yahoo_packet *pkt;
- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
- yd = purple_connection_get_protocol_data(gc);
- 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;
- struct yahoo_packet *pkt;
- tmp = g_strdup_printf(_("Unable to connect: %s"), error_message);
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR, tmp);
- yd = purple_connection_get_protocol_data(gc);
- 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))),
- yahoo_packet_send_and_free(pkt, yd);
- yd->inpa = purple_input_add(yd->fd, PURPLE_INPUT_READ, yahoo_pending, gc);
-yahoo_login_page_got(PurpleHttpConnection *hc, PurpleHttpResponse *resp,
- 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;
- if (purple_http_response_get_code(resp) != 302) {
- purple_connection_error(gc,
- PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- _("Unable to connect"));
- auth_s = g_string_new(NULL);
- cjar = purple_http_conn_get_cookie_jar(hc);
- cookie = purple_http_cookie_jar_get(cjar, "B");
- g_string_append_printf(auth_s, "B=%s; ", cookie);
- cookie = purple_http_cookie_jar_get(cjar, "T");
- g_string_append_printf(auth_s, "T=%s; ", cookie);
- cookie = purple_http_cookie_jar_get(cjar, "Y");
- g_string_append_printf(auth_s, "Y=%s; ", 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
- 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"));
-static void yahoo_login_page_hash_iter(const char *key, const char *val, GString *url)
- if (!strcmp(key, "passwd") || !strcmp(key, "login"))
- 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);
- 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);
- char name[64], value[64];
- 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=\"")))
- count = sizeof(name)-1;
- for (d = name; (len > ((c - buf) + 1)) && *c!='"'
- && count; c++, d++, count--)
- count = sizeof(value)-1;
- if (!(d = g_strstr_len(c, len - (c - buf), "value=\"")))
- if (strchr(c, '>') < d)
- for (c = d, d = value; (len > ((c - buf) + 1))
- && *c!='"' && count; c++, d++, count--)
- g_hash_table_insert(hash, g_strdup(name), g_strdup(value));
-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);
- char md5[33], *hashp = md5, *chal;
- PurpleHttpRequest *req;
- if (!purple_http_response_is_successful(response))
- purple_connection_error(gc, PURPLE_CONNECTION_ERROR_NETWORK_ERROR,
- purple_http_response_get_error(response));
- 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]);
- 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));
- for (i = 0; i < 16; ++i) {
- g_snprintf(hashp, 3, "%02x", digest[i]);
- * I dunno why this is here and commented out.. but in case it's needed
- purple_cipher_reset(cipher);
- purple_cipher_append(cipher, md5, strlen(md5));
- purple_cipher_digest(cipher, sizeof(digest), digest, NULL);
- for (i = 0; i < 16; ++i) {
- g_snprintf(hashp, 3, "%02x", digest[i]);
- 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);
-static int get_yahoo_status_from_purple_status(PurpleStatus *status)
- PurplePresence *presence;
- 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;
- purple_debug_error("yahoo", "Unexpected PurpleStatus!\n");
- return YAHOO_STATUS_AVAILABLE;
-static void yahoo_got_pager_server(PurpleHttpConnection *http_conn,
- PurpleHttpResponse *response, gpointer _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);
- 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"));
- got_data = purple_http_response_get_data(response, NULL);
- strings = g_strsplit(got_data, "\r\n", -1);
- if((stringslen = g_strv_length(strings)) > 1) {
- 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"));
- 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"));
-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->yahoo_local_p2p_server_fd = -1;
- /* 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->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);
-void yahoo_close(PurpleConnection *gc) {
- YahooData *yd = purple_connection_get_protocol_data(gc);
- purple_input_remove(yd->inpa);
- purple_http_connection_set_destroy(yd->http_reqs);
- for (l = yd->confs; l; l = l->next) {
- PurpleChatConversation *conv = l->data;
- users = purple_chat_conversation_get_users(conv);
- purple_conversation_get_name(PURPLE_CONVERSATION(conv)),
- purple_connection_get_display_name(gc), users);
- g_slist_free(yd->confs);
- g_slist_free_full(yd->cookies, g_free);
- yd->chat_online = FALSE;
- 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);
- purple_input_remove(yd->txhandler);
- g_object_unref(G_OBJECT(yd->txbuf));
- 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);
- 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);
- purple_connection_set_protocol_data(gc, NULL);
-const char *yahoo_list_icon(PurpleAccount *a, PurpleBuddy *b)
-const char *yahoo_list_emblem(PurpleBuddy *b)
- PurpleAccount *account;
- PurplePresence *presence;
- if (!b || !(account = purple_buddy_get_account(b)) ||
- !(gc = purple_account_get_connection(account)) ||
- !purple_connection_get_protocol_data(gc))
- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
- return "not-authorized";
- presence = purple_buddy_get_presence(b);
- if (purple_presence_is_online(presence)) {
- if (yahoo_friend_get_game(f))
-static const char *yahoo_get_status_string(enum yahoo_status a)
- return _("Be Right Back");
- case YAHOO_STATUS_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:
- case YAHOO_STATUS_IDLE:
- case YAHOO_STATUS_OFFLINE:
-static void yahoo_initiate_conference(PurpleBlistNode *node, gpointer data) {
- GHashTable *components;
- 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);
- 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) {
- 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) {
- 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));
- game = yahoo_friend_get_game(f);
- t = game2 = g_strdup(strstr(game, "ante?room="));
- while (*t && *t != '\t')
- g_snprintf(url, sizeof url, "http://games.yahoo.com/games/%s", game2);
- purple_notify_uri(gc, url);
-char *yahoo_status_text(PurpleBuddy *b)
- PurpleAccount *account;
- account = purple_buddy_get_account(b);
- gc = purple_account_get_connection(account);
- if (!gc || !purple_connection_get_protocol_data(gc))
- f = yahoo_friend_find(gc, purple_buddy_get_name(b));
- return g_strdup(_("Not on server list"));
- case YAHOO_STATUS_AVAILABLE:
- case YAHOO_STATUS_IDLE:
- return g_strdup(yahoo_get_status_string(f->status));
- case YAHOO_STATUS_CUSTOM:
- if (!(msg = yahoo_friend_get_status_message(f)))
- msg2 = g_markup_escape_text(msg, strlen(msg));
- purple_util_chrreplace(msg2, '\n', ' ');
- return g_strdup(yahoo_get_status_string(f->status));
-void yahoo_tooltip_text(PurpleBuddy *b, PurpleNotifyUserInfo *user_info, gboolean full)
- 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));
- status = g_strdup_printf("\n%s", _("Not on server list"));
- case YAHOO_STATUS_CUSTOM:
- if (!yahoo_friend_get_status_message(f))
- status = g_strdup(yahoo_friend_get_status_message(f));
- case YAHOO_STATUS_OFFLINE:
- status = g_strdup(yahoo_get_status_string(f->status));
- case YAHOO_PRESENCE_ONLINE:
- presence = _("Appear Online");
- case YAHOO_PRESENCE_PERM_OFFLINE:
- presence = _("Appear Permanently Offline");
- case YAHOO_PRESENCE_DEFAULT:
- purple_debug_error("yahoo", "Unknown presence in yahoo_tooltip_text\n");
- purple_notify_user_info_add_pair_plaintext(user_info, _("Status"), status);
- purple_notify_user_info_add_pair_plaintext(user_info, _("Presence"), presence);
- 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)
- 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)
- 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) {
- 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),
- 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),
- 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),
- m = g_list_append(m, act);
- act = purple_menu_action_new(_("Appear Permanently Offline"),
- PURPLE_CALLBACK(yahoo_presence_settings),
- GINT_TO_POINTER(YAHOO_PRESENCE_PERM_OFFLINE),
- m = g_list_append(m, act);
-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));
-/* XXX: it doesn't seems to work */
-yahoo_userinfo_blist_node(PurpleBlistNode *node, gpointer data)
- PurpleBuddy *b = (PurpleBuddy *)node;
- PurpleAccount *account = purple_buddy_get_account(b);
- PurpleConnection *gc = purple_account_get_connection(account);
- yahoo_set_userinfo_for_buddy(gc, b);
-static GList *yahoo_buddy_menu(PurpleBuddy *buddy)
- PurpleConnection *gc = purple_account_get_connection(purple_buddy_get_account(buddy));
- YahooData *yd = purple_connection_get_protocol_data(gc);
- static char buf2[1024];
- f = yahoo_friend_find(gc, purple_buddy_get_name(buddy));
- act = purple_menu_action_new(_("Add Buddy"),
- PURPLE_CALLBACK(yahoo_addbuddyfrommenu_cb),
- m = g_list_append(m, act);
- if (f && f->status != YAHOO_STATUS_OFFLINE) {
- act = purple_menu_action_new(_("Join in Chat"),
- PURPLE_CALLBACK(yahoo_chat_goto_menu),
- m = g_list_append(m, act);
- act = purple_menu_action_new(_("Initiate Conference"),
- PURPLE_CALLBACK(yahoo_initiate_conference),
- m = g_list_append(m, act);
- if (yahoo_friend_get_game(f)) {
- const char *game = yahoo_friend_get_game(f);
- if ((room = strstr(game, "&follow="))) {/* skip ahead to the url */
- while (*room && *room != '\t') /* skip to the tab */
- t = room++; /* room as now at the name */
- t++; /* replace the \n with a space */
- g_snprintf(buf2, sizeof buf2, "%s", room);
- act = purple_menu_action_new(buf2,
- PURPLE_CALLBACK(yahoo_game),
- m = g_list_append(m, act);
- 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),
- m = g_list_append(m, act);
- /* XXX: it doesn't seems to work */
- act = purple_menu_action_new(_("Set User Info..."),
- PURPLE_CALLBACK(yahoo_userinfo_blist_node),
- m = g_list_append(m, act);
-GList *yahoo_blist_node_menu(PurpleBlistNode *node)
- if(PURPLE_IS_BUDDY(node)) {
- return yahoo_buddy_menu((PurpleBuddy *) node);
-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);
-yahoo_get_inbox_token_cb(PurpleHttpConnection *http_conn,
- PurpleHttpResponse *response, gpointer _unused)
- purple_http_conn_get_purple_connection(http_conn);
- 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);
- /* Should we not be hardcoding the rd url? */
- token = g_strdup(purple_http_response_get_data(response, NULL));
- "http://login.yahoo.com/config/reset_cookies_token?"
- "&.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);
-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);
-/* XXX: it doesn't seems to work */
-yahoo_set_userinfo_fn(PurpleProtocolAction *action)
- yahoo_set_userinfo(action->connection);
-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);
- 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,
- _("OK"), G_CALLBACK(yahoo_act_id),
- 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),
- purple_request_cpar_from_connection(gc),
-GList *yahoo_get_actions(PurpleConnection *gc) {
- PurpleProtocolAction *act;
- /* 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);
- act = purple_protocol_action_new(_("Activate ID..."),
- m = g_list_append(m, act);
- act = purple_protocol_action_new(_("Join User in Chat..."),
- m = g_list_append(m, act);
- m = g_list_append(m, NULL);
- act = purple_protocol_action_new(_("Open Inbox"),
- m = g_list_append(m, act);
-struct yahoo_sms_carrier_cb_data {
-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);
- 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);
- 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));
- 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);
-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))
- 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));
- struct yahoo_p2p_data *p2p_data;
- const gchar *rcpt = purple_message_get_recipient(pmsg);
- msg2 = yahoo_string_encode(gc, msg, TRUE);
- 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);
- /* we have an sms to be sent */
- 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);
- struct yahoo_sms_carrier_cb_data *sms_cb_data;
- sms_cb_data = g_malloc(sizeof(struct yahoo_sms_carrier_cb_data));
- 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);
- else if( strcmp(carrier,"Unknown") == 0 ) {
- purple_conversation_write_system_message(PURPLE_CONVERSATION(im),
- _("Can't send SMS. Unknown mobile carrier."), 0);
- 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),
- yahoo_packet_send_and_free(pkt, yd);
- 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);
- * 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
- * If they have not set an IMVironment, then use the default.
- wb = purple_whiteboard_get_session(purple_connection_get_account(gc), rcpt);
- yahoo_packet_hash_str(pkt, 63, DOODLE_IMV_KEY);
- imv = g_hash_table_lookup(yd->imvironments, rcpt);
- yahoo_packet_hash_str(pkt, 63, imv);
- 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 */
- yahoo_packet_hash_str(pkt, 206, "0"); /* 0 = no picture, 2 = picture, maybe 1 = avatar? */
- 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);
- yahoo_packet_send(pkt, yd);
- yahoo_send_p2p_pkt(gc, rcpt, 0); /* send p2p packet, with val_13=0 */
- yahoo_packet_free(pkt);
-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 )
- 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",
- yahoo_packet_send_and_free(pkt, yd);
-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)
- PurplePresence *presence;
- struct yahoo_packet *pkt;
- const char *msg = NULL;
- if (!purple_status_is_active(status))
- 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);
- if ((msg == NULL) || (*msg == '\0'))
- tmp = yahoo_string_encode(gc, msg, TRUE);
- conv_msg = purple_markup_strip_html(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);
- 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);
- yahoo_packet_hash_str(pkt, 19, "");
- if (purple_presence_is_idle(presence))
- yahoo_packet_hash_str(pkt, 47, "2");
- if (!purple_status_is_available(status))
- yahoo_packet_hash_str(pkt, 47, "1");
- 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);
- yahoo_packet_hash_int(pkt, 10, yd->current_status);
- if (yd->current_status == YAHOO_STATUS_CUSTOM) {
- status = purple_presence_get_active_status(purple_account_get_presence(purple_connection_get_account(gc)));
- tmp = purple_status_get_attr_string(status, "message");
- 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);
- /* 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"));
- yahoo_packet_hash_str(pkt, 19, "");
- 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);
-GList *yahoo_status_types(PurpleAccount *account)
- PurpleStatusType *type;
- 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);
-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) {
- /* The native client will only send PING or CHATPING */
- ycht_chat_send_keepalive(yd->ycht);
- 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);
- 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;
- const char *bname = purple_buddy_get_name(buddy);
- if (!purple_account_privacy_check(purple_connection_get_account(gc), bname))
- 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",
- 1, purple_connection_get_display_name(gc),
- yahoo_packet_send_and_free(pkt, yd);
-void yahoo_remove_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
- YahooData *yd = purple_connection_get_protocol_data(gc);
- struct yahoo_packet *pkt;
- gboolean remove = TRUE;
- const char *bname, *gname;
- bname = purple_buddy_get_name(buddy);
- f = yahoo_friend_find(gc, bname);
- 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))) {
- 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),
- yahoo_packet_send_and_free(pkt, yd);
-void yahoo_add_deny(PurpleConnection *gc, const char *who) {
- YahooData *yd = purple_connection_get_protocol_data(gc);
- struct yahoo_packet *pkt;
- if (!who || who[0] == '\0')
- 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 (!who || who[0] == '\0')
- 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;
- 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);
- 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);
-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;
- 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 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)) {
- 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,
- yahoo_packet_send_and_free(pkt, yd);
-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;
- gpn = yahoo_string_encode(gc, purple_group_get_name(group), FALSE);
- gpo = yahoo_string_encode(gc, old_name, FALSE);
- if (!strcmp(gpn, gpo)) {
- 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),
- yahoo_packet_send_and_free(pkt, yd);
-/********************************* Commands **********************************/
-yahoopurple_cmd_buzz(PurpleConversation *c, const gchar *cmd, gchar **args, gchar **error, void *data) {
- PurpleAccount *account = purple_conversation_get_account(c);
- 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;
-yahoopurple_cmd_chat_join(PurpleConversation *conv, const char *cmd,
- char **args, char **error, void *data)
- 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;
-yahoopurple_cmd_chat_list(PurpleConversation *conv, const char *cmd,
- char **args, char **error, void *data)
- PurpleAccount *account = purple_conversation_get_account(conv);
- return PURPLE_CMD_RET_FAILED;
- purple_roomlist_show_with_account(account);
- return PURPLE_CMD_RET_OK;
-gboolean yahoo_offline_message(const PurpleBuddy *buddy)
-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);
-GList *yahoo_attention_types(PurpleAccount *account)
- static GList *list = NULL;
- /* 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...")));
-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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "circularbuffer.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. */
- YAHOO_PKT_TYPE_SERVER = 0,
- YAHOO_P2P_WE_ARE_CLIENT =0,
- YAHOO_P2P_WE_ARE_SERVER
-} yahoo_p2p_connection_type;
- YAHOO_STATUS_AVAILABLE = 0,
- YAHOO_STATUS_NOTATHOME,
- YAHOO_STATUS_NOTATDESK,
- YAHOO_STATUS_NOTINOFFICE,
- YAHOO_STATUS_ONVACATION,
- YAHOO_STATUS_OUTTOLUNCH,
- YAHOO_STATUS_STEPPEDOUT,
- 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 {
- yahoo_p2p_connection_type connection_type;
-typedef struct _YahooPersonalDetails {
- PurpleCircularBuffer *txbuf;
- 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
- GHashTable *imvironments;
- GString *tmp_serv_blist, *tmp_serv_ilist, *tmp_serv_plist;
- unsigned int conf_id; /* just a counter */
- char *pending_chat_room;
- char *pending_chat_topic;
- char *pending_chat_goto;
- gboolean wm; /* connected w/ web messenger method */
- /* picture aka buddy icon stuff */
- /* 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;
- GHashTable *peers; /* information about p2p data */
- int yahoo_local_p2p_server_fd;
- int yahoo_p2p_server_watcher;
- GHashTable *sms_carrier; /* sms carrier data */
- guint yahoo_p2p_server_timeout_handle;
-#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), \
-#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), \
-#define yahoo_get32(buf) ((((*(buf))<<24)&0xff000000) + \
- (((*((buf)+1))<<16)&0x00ff0000) + \
- (((*((buf)+2))<< 8)&0x0000ff00) + \
- (((*((buf)+3) )&0x000000ff)))
-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
- * 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
- * ESC[1m bold ESC[2m bolditalic ESC[x2mESC[x1mESC[2m italic ESC[x2m
-char *yahoo_html_to_codes(const char *src);
-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);
-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);
--- 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 @@
-#include "ciphers/md5hash.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
- if [ "$tag" == "PERL" ] && [ "${arg%(*}" == "Mkbootstrap" ]; then
- if [ "$tag" == "PERL" ] && [ "${arg%(*}" == "ExtUtils::ParseXS::process_file" ]; then
- object="${arg#*output => \"}"
- object="${object%\", *}"
if [ "${ext_1}" == ".c" ]; then
@@ -51,10 +40,6 @@
-if [ "$tag" == "PERL" ] && [ "$is_final" == 0 ]; then
- object=`echo "$object" | sed -n 's|.*output *=> *"\([^"]*\)".*|\1|p'`
if [ "$object" == "" ] && [ "${file_1}" != "" ]; then
--- 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 @@
@@ -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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "ciphers/hmaccipher.h"
-#include "ciphers/md5hash.h"
-#include "ciphers/sha1hash.h"
-/******************************************************************************
- * See RFC2202 and some other NULL tests I made up
- *****************************************************************************/
-test_hmac(gchar *data, size_t data_len,
- const gchar *key, size_t key_len,
- PurpleHash *hash, const gchar *digest)
- PurpleCipher *cipher = NULL;
- 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_cmpstr(digest, ==, cdigest);
- g_object_unref(G_OBJECT(cipher));
- g_object_unref(G_OBJECT(hash));
-test_hmac_md5_hi(void) {
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
- "9294727a3638bb1c13f48ef8158bfc9d"
-test_hmac_md5_what(void) {
- "what do ya want for nothing?",
- "750c783e6ab0b503eaa86e310a5db738"
-test_hmac_md5_dd(void) {
- "\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",
- "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
- "56be34521d144c88dbb8c733f0e8b3f6"
-test_hmac_md5_cd(void) {
- "\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",
- "\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",
- "697eaf0aca3a3aea3a75164746ffaa79"
-test_hmac_md5_truncation(void) {
- "Test With Truncation",
- "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
- "56461ef2342edc00f9bab995690efd4c"
-test_hmac_md5_large_key(void) {
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "\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",
- "6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd"
-test_hmac_md5_large_key_and_data(void) {
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
- "\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",
- "6f630fad67cda0ee1fb1f562db3aa53e"
-test_hmac_md5_null_key(void) {
- "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b"
- "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b",
- "597bfd644b797a985561eeb03a169e59"
-test_hmac_md5_null_text(void) {
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
- "70be8e1b7b50dfcc335d6cd7992c564f"
-test_hmac_md5_null_key_and_text(void) {
- "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34"
- "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b",
- "b31bcbba35a33a067cbba9131cba4889"
-test_hmac_sha1_hi(void) {
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
- purple_sha1_hash_new(),
- "b617318655057264e28bc0b6fb378c8ef146be00"
-test_hmac_sha1_what(void) {
- "what do ya want for nothing?",
- purple_sha1_hash_new(),
- "effcdf6ae5eb2fa2d27416d5f184df9c259a7c79"
-test_hmac_sha1_dd(void) {
- "\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",
- "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa"
- "\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa\xaa",
- purple_sha1_hash_new(),
- "125d7342b9ac11cd91a39af48aa17b4f63f175d3"
-test_hmac_sha1_cd(void) {
- "\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",
- "\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",
- purple_sha1_hash_new(),
- "4c9007f4026250c6bc8414f9bf50c86c2d7235da"
-test_hmac_sha1_truncation(void) {
- "Test With Truncation",
- "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c"
- "\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c\x0c",
- purple_sha1_hash_new(),
- "4c1a03424b55e07fe7f27be1d58bb9324a9a5a04"
-test_hmac_sha1_large_key(void) {
- "Test Using Larger Than Block-Size Key - Hash Key First",
- "\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",
- purple_sha1_hash_new(),
- "aa4ae5e15272d00e95705637ce8a3b55ed402112"
-test_hmac_sha1_large_key_and_data(void) {
- "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data",
- "\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",
- purple_sha1_hash_new(),
- "e8e99d0f45237d786d6bbaa7965c7808bbff1a91"
-test_hmac_sha1_null_key(void) {
- "\x0a\x0b\x00\x0d\x0e\x0f\x1a\x2f\x0b\x0b"
- "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b",
- purple_sha1_hash_new(),
- "eb62a2e0e33d300be669c52aab3f591bc960aac5"
-test_hmac_sha1_null_text(void) {
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b"
- "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
- purple_sha1_hash_new(),
- "31ca58d849e971e418e3439de2c6f83144b6abb7"
-test_hmac_sha1_null_key_and_text(void) {
- "\x0c\x0d\x00\x0f\x10\x1a\x3a\x3a\xe6\x34"
- "\x0b\x00\x00\x0b\x0b\x49\x5f\x6e\x0b\x0b",
- purple_sha1_hash_new(),
- "e6b8e2fede87aa09dcb13e554df1435e056eae36"
-main(gint argc, gchar **argv) {
- g_test_init(&argc, &argv, NULL);
- g_test_add_func("/hmac/md5/hi",
- g_test_add_func("/hmac/md5/what",
- g_test_add_func("/hmac/md5/dd",
- g_test_add_func("/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",
- g_test_add_func("/hmac/sha1/what",
- g_test_add_func("/hmac/sha1/dd",
- g_test_add_func("/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);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "ciphers/md5hash.h"
-test_md5hash(gchar *data, gchar *digest) {
- PurpleHash *hash = NULL;
- 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_cmpstr(digest, ==, cdigest);
-test_md5hash_empty_string(void) {
- "d41d8cd98f00b204e9800998ecf8427e");
- "0cc175b9c0f1b6a831c399e269772661");
-test_md5hash_abc(void) {
- "900150983cd24fb0d6963f7d28e17f72");
-test_md5hash_message_digest(void) {
- test_md5hash("message digest",
- "f96b697d7cb7938d525a2f31aaf161d0");
-test_md5hash_a_to_z(void) {
- test_md5hash("abcdefghijklmnopqrstuvwxyz",
- "c3fcd3d76192e4007dfb496cca67e13b");
-test_md5hash_A_to_Z_a_to_z_0_to_9(void) {
- test_md5hash("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
- "d174ab98d277d9f5a5611c2c9f419d9f");
-test_md5hash_1_to_0_eight_times(void) {
- test_md5hash("12345678901234567890123456789012345678901234567890123456789012345678901234567890",
- "57edf4a22be3c955ac49da2e2107b67a");
-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",
- g_test_add_func("/hash/md5/abc",
- g_test_add_func("/hash/md5/message digest",
- test_md5hash_message_digest);
- g_test_add_func("/hash/md5/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);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "ciphers/sha1hash.h"
-test_sha1hash(gchar *data, gchar *digest) {
- PurpleHash *hash = NULL;
- hash = purple_sha1_hash_new();
- purple_hash_append(hash, (guchar *)data, strlen(data));
- 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_cmpstr(digest, ==, cdigest);
-test_sha1hash_empty_string(void) {
- "da39a3ee5e6b4b0d3255bfef95601890afd80709");
- "86f7e437faa5a7fce15d1ddcb9eaeaea377667b8");
-test_sha1hash_abc(void) {
- "a9993e364706816aba3e25717850c26c9cd0d89d");
-test_sha1hash_abcd_gibberish(void) {
- test_sha1hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "84983e441c3bd26ebaae4aa1f95129e5e54670f1");
-test_sha1hash_1000_as_1000_times(void) {
- "34aa973cd4c4daa4f61eeb2bdbad27316534016f");
-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",
- g_test_add_func("/hash/sha1/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);
--- 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 is the legal property of its developers, whose names are too numerous
- * to list here. Please refer to the COPYRIGHT file distributed with this
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
-#include "ciphers/sha256hash.h"
-test_sha256hash(gchar *data, gchar *digest) {
- PurpleHash *hash = NULL;
- hash = purple_sha256_hash_new();
- purple_hash_append(hash, (guchar *)data, strlen(data));
- 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_cmpstr(digest, ==, cdigest);
-test_sha256hash_empty_string(void) {
- "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855");
-test_sha256hash_a(void) {
- "ca978112ca1bbdcafac231b39a23dc4da786eff8147c4e72b9807785afee48bb");
-test_sha256hash_abc(void) {
- "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad");
-test_sha256hash_abcd_gibberish(void) {
- test_sha256hash("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq",
- "248d6a61d20638b8e5c026930c3e6039a33ce45964ff2167f6ecedd419db06c1");
-test_sha256hash_1000_as_1000_times(void) {
- "cdc76e5c9914fb9281a1c7e284d73e67f1809a48a497200e046d39ccc7112cd0");
-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",
- g_test_add_func("/hash/sha256/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);
--- 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 @@
/******************************************************************************
- *****************************************************************************/
-test_util_base_64_encode(void) {
- gchar *in = purple_base64_encode((const unsigned char *)"forty-two", 10);
- g_assert_cmpstr("Zm9ydHktdHdvAA==", ==, in);
-test_util_base_64_decode(void) {
- guchar *out = purple_base64_decode("b3d0LXl0cm9mAA==", &sz);
- g_assert_cmpint(sz, ==, 10);
- g_assert_cmpstr("owt-ytrof", ==, (gchar *)out);
-/******************************************************************************
*****************************************************************************/
@@ -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 "tls-certificate-info.h"
-#include "ciphers/sha1hash.h"
@@ -789,7 +788,7 @@
purple_tls_certificate_get_fingerprint_sha1(GTlsCertificate *certificate)
@@ -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); - purple_hash_digest(hash, data, buf_size);
+ g_checksum_get_digest(hash, data, &buf_size); 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 "ciphers/md5hash.h"
#include "conversation.h"
@@ -330,34 +329,12 @@
/**************************************************************************
+ * Quoted Printable Functions (see RFC 2045). **************************************************************************/
static const char xdigits[] =
-purple_base64_encode(const guchar *data, gsize len)
- return g_base64_encode(data, len);
-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.
- return g_base64_decode(str, ret_len != NULL ? ret_len : &unused);
-/**************************************************************************
- * Quoted Printable Functions (see RFC 2045).
- **************************************************************************/
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); @@ -1424,8 +1401,7 @@
purple_markup_unescape_entity(const char *text, int *length)
if (!text || *text != '&')
@@ -4961,9 +4937,8 @@
const gchar *client_nonce)
- gchar hash[33]; /* We only support MD5. */
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"))
if (client_nonce == NULL)
@@ -4996,22 +4972,20 @@
- 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);
+ hash = g_strdup(g_checksum_get_string(hasher)); + g_checksum_free(hasher); gchar *purple_http_digest_calculate_response(
@@ -5025,9 +4999,8 @@
const gchar *client_nonce,
const gchar *session_key)
- static gchar hash2[33]; /* We only support MD5. */
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"))
purple_debug_error("hash", "Required entity missing for auth-int digest calculation.\n");
- 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));
+ entity_hash = g_compute_checksum_for_string(G_CHECKSUM_MD5, + if (entity_hash == NULL) { 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); - digest_ok = purple_hash_digest_to_str(hash, hash2, sizeof(hash2));
- purple_hash_reset(hash);
+ hash2 = g_strdup(g_checksum_get_string(hash)); + g_checksum_reset(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')
purple_debug_error("hash", "Required nonce_count missing for digest calculation.\n");
if (client_nonce == NULL)
purple_debug_error("hash", "Required client_nonce missing for digest calculation.\n");
- 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_return_val_if_fail(digest_ok, NULL);
- return g_strdup(hash2);
+ g_checksum_update(hash, (guchar *)hash2, -1); + hash2 = g_strdup(g_checksum_get_string(hash)); --- 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);
-/**************************************************************************/
-/**************************************************************************/
- * 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 @@
$(CC) $(CFLAGS) $(DEFINES) $(INCLUDE_PATHS) -o $@ -c $<
- $(TAG) "PERL" $(PERL) -MExtUtils::ParseXS -e 'ExtUtils::ParseXS::process_file(filename => "$<", output => "$@", typemap => "$(PURPLE_PERL_TOP)/common/typemap");'
@$(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 @@
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>");
-#warning TODO: Check for perl.
- if (purple_plugins_find_plugin("core-perl") != NULL)
- g_string_append(str, "<dt>Perl:</dt><dd>Enabled</dd>");
- 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>");
- g_string_append(str, "<dt>Tk:</dt><dd>Enabled</dd>");
- g_string_append(str, "<dt>Tk:</dt><dd>Disabled</dd>");
- g_string_append(str, "<dt>Tcl:</dt><dd>Disabled</dd>");
- g_string_append(str, "<dt>Tk:</dt><dd>Disabled</dd>");
g_string_append(str, "<dt>UTF-8 DNS (IDN):</dt><dd>Enabled</dd>");
--- 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 @@
- 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
-GTKPERL_PLUGIN := ./perl
TICKER_PLUGIN := ./ticker
TRANSPARENCY_PLUGIN := ./win32/transparency
WINPREFS_PLUGIN := ./win32/winprefs
@@ -66,14 +65,12 @@
$(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 @@
$(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);
--- 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 @@
- common/GtkMenuTray.xs \
- common/GtkPluginPref.xs \
- common/GtkRoomlist.xs \
- common/GtkSavedStatuses.xs \
- common/GtkStatusBox.xs \
- common/Makefile.PL.in \
- common/Makefile.mingw \
-common/Makefile: common/Makefile.PL
- $(AM_V_GEN)if test "x${top_srcdir}" != "x${top_builddir}"; then \
- for f in ${common_sources}; do \
- case $$srcloc in /*) ;; *) srcloc=../${srcdir} ;; esac; \
- ${LN_S} -f $$srcloc/$$f $$f; \
- $(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 \
- if [ ! -f Makefile ]; then \
- $(perlpath) Makefile.PL; \
- ($(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)) && \
- @for dir in $(perl_dirs); do \
-# ... which doesn't work with DESTDIR installs. FIXME?
- @for dir in $(perl_dirs); do \
- `$(MAKE) uninstall | grep unlink | sed -e 's#/usr#${prefix}#' -e 's#unlink#rm -f#'` && \
- @for dir in $(perl_dirs); do \
- cd common ; rm -rf *.c *.o pm_to_blib Pidgin.bs MYMETA.* blib/*/.exists blib/*/auto/Pidgin blib/*/Pidgin.*pm ; cd ..
- @for dir in $(perl_dirs); do \
- -I$(top_srcdir)/libpurple \
- -I$(top_builddir)/libpurple \
- -I$(top_srcdir)/pidgin \
--- 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 @@
-# 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
-.PHONY: all install clean
- $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE)
-install: all $(PIDGIN_INSTALL_PLUGINS_DIR)
- $(MAKE_at) $(MAKE) -C ./common -f $(MINGW_MAKEFILE) install
- $(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 @@
-MODULE = Pidgin::Account PACKAGE = Pidgin::Account PREFIX = pidgin_account_
-pidgin_accounts_get_handle()
-MODULE = Pidgin::Account PACKAGE = Pidgin::Account::Dialog PREFIX = pidgin_account_dialog_
-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_
-pidgin_accounts_window_show()
-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 @@
-MODULE = Pidgin::BuddyList PACKAGE = Pidgin::BuddyList PREFIX = pidgin_blist_
-pidgin_blist_get_handle()
-pidgin_blist_get_default_gtk_blist()
-pidgin_blist_refresh(list)
-pidgin_blist_update_refresh_timeout()
-pidgin_blist_node_is_contact_expanded(node)
- Purple::BuddyList::Node node
-pidgin_blist_toggle_visibility()
-pidgin_blist_visibility_manager_add()
-pidgin_blist_visibility_manager_remove()
-pidgin_blist_get_sort_methods()
- for (l = pidgin_blist_get_sort_methods(); l != NULL; l = l->next) {
- XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::BuddyList::SortMethod")));
-pidgin_blist_sort_method_reg(id, name, func)
- Pidgin::BuddyList::SortFunction func
-pidgin_blist_sort_method_unreg(id)
-pidgin_blist_sort_method_set(id)
-pidgin_blist_setup_sort_methods()
-pidgin_blist_update_accounts_menu()
-pidgin_blist_update_plugin_actions()
-pidgin_blist_update_sort_methods()
-pidgin_blist_joinchat_is_showable()
-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 @@
-MODULE = Pidgin::Connection PACKAGE = Pidgin::Connection PREFIX = pidgin_connection_
-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 @@
-MODULE = Pidgin::Conversation PACKAGE = Pidgin::Conversation PREFIX = pidgin_conv_
-pidgin_conv_update_buddy_icon(im)
- Purple::IMConversation im
-pidgin_conv_switch_active_conversation(conv)
- Purple::Conversation conv
-pidgin_conv_update_buttons_by_protocol(conv)
- Purple::Conversation conv
-pidgin_conv_present_conversation(conv)
- Purple::Conversation conv
-Pidgin::Conversation::Window
-pidgin_conv_get_window(conv)
- Pidgin::Conversation conv
-pidgin_conv_new(class, conv)
- Purple::Conversation conv
-pidgin_conv_is_hidden(gtkconv)
- Pidgin::Conversation gtkconv
-pidgin_conv_get_gtkconv(conv)
- Purple::Conversation conv
- 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_
-pidgin_conversations_get_unseen_all(min_state, hidden_only, max_count)
- Pidgin::UnseenState min_state
-pidgin_conversations_get_unseen_ims(min_state, hidden_only, max_count)
- Pidgin::UnseenState min_state
-pidgin_conversations_get_unseen_chats(min_state, hidden_only, max_count)
- Pidgin::UnseenState min_state
-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 @@
-MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Window PREFIX = pidgin_conv_window_
-Pidgin::Conversation::Window
-pidgin_conv_window_new(class)
-pidgin_conv_window_destroy(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_show(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_hide(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_raise(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_switch_gtkconv(win, gtkconv)
- Pidgin::Conversation::Window win
- Pidgin::Conversation gtkconv
-pidgin_conv_window_add_gtkconv(win, gtkconv)
- Pidgin::Conversation::Window win
- Pidgin::Conversation gtkconv
-pidgin_conv_window_remove_gtkconv(win, gtkconv)
- Pidgin::Conversation::Window win
- Pidgin::Conversation gtkconv
-pidgin_conv_window_get_gtkconv_at_index(win, index)
- Pidgin::Conversation::Window win
-pidgin_conv_window_get_active_gtkconv(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_get_active_conversation(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_is_active_conversation(conv)
- Purple::Conversation conv
-pidgin_conv_window_has_focus(win)
- Pidgin::Conversation::Window win
-pidgin_conv_window_get_gtkconvs(win)
- Pidgin::Conversation::Window win
- for (l = pidgin_conv_window_get_gtkconvs(win); l != NULL; l = l->next) {
- XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::Conversation")));
-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_
-pidgin_conv_placement_get_options()
- for (l = pidgin_conv_placement_get_options(); l != NULL; l = l->next) {
- XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Pidgin::Conversation::Window")));
-pidgin_conv_placement_add_fnc(id, name, fnc)
- Pidgin::Conversation::PlacementFunc fnc
-pidgin_conv_placement_remove_fnc(id)
-pidgin_conv_placement_get_name(id)
-Pidgin::Conversation::PlacementFunc
-pidgin_conv_placement_get_fnc(id)
-pidgin_conv_placement_set_current_func(func)
- Pidgin::Conversation::PlacementFunc func
-Pidgin::Conversation::PlacementFunc
-pidgin_conv_placement_get_current_func()
-pidgin_conv_placement_place(gtkconv)
- Pidgin::Conversation gtkconv
-MODULE = Pidgin::Conversation::Window PACKAGE = Pidgin::Conversation::Windows PREFIX = pidgin_conv_windows_
-pidgin_conv_windows_get_list()
- 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 @@
-MODULE = Pidgin::Debug PACKAGE = Pidgin::Debug PREFIX = pidgin_debug_
-pidgin_debug_get_handle()
-MODULE = Pidgin::Debug PACKAGE = Pidgin::Debug::Window PREFIX = pidgin_debug_window_
-pidgin_debug_window_show()
-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 @@
-MODULE = Pidgin::Dialogs PACKAGE = Pidgin::Dialogs PREFIX = pidgin_dialogs_
-pidgin_dialogs_destroy_all()
-pidgin_dialogs_im_with_user(account, username)
- Purple::Account account
-pidgin_dialogs_alias_buddy(buddy)
- Purple::BuddyList::Buddy buddy
-pidgin_dialogs_alias_chat(chat)
- Purple::BuddyList::Chat chat
-pidgin_dialogs_remove_buddy(buddy)
- Purple::BuddyList::Buddy buddy
-pidgin_dialogs_remove_group(group)
- Purple::BuddyList::Group group
-pidgin_dialogs_remove_chat(chat)
- Purple::BuddyList::Chat chat
-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 @@
-MODULE = Pidgin::Xfer PACKAGE = Pidgin::Xfer PREFIX = pidgin_
-pidgin_set_xfer_dialog(dialog)
- Pidgin::Xfer::Dialog dialog
-pidgin_get_xfer_dialog()
-MODULE = Pidgin::Xfer PACKAGE = Pidgin::Xfer::Dialog PREFIX = pidgin_xfer_dialog_
-pidgin_xfer_dialog_new(class)
-pidgin_xfer_dialog_destroy(dialog)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_show(dialog = NULL)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_hide(dialog)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_add_xfer(dialog, xfer)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_remove_xfer(dialog, xfer)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_cancel_xfer(dialog, xfer)
- Pidgin::Xfer::Dialog dialog
-pidgin_xfer_dialog_update_xfer(dialog, xfer)
- Pidgin::Xfer::Dialog dialog
--- 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 @@
-MODULE = Pidgin::Log PACKAGE = Pidgin::Log PREFIX = pidgin_log_
-pidgin_log_show(type, buddyname, account)
- Purple::Account account
-pidgin_log_show_contact(contact)
- Purple::BuddyList::Contact contact
-MODULE = Pidgin::Log PACKAGE = Pidgin::SysLog PREFIX = pidgin_syslog_
--- 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 @@
-/* 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
-pidgin_menu_tray_get_box(menu_tray)
- Pidgin::MenuTray menu_tray
-pidgin_menu_tray_append(menu_tray, widget, tooltip)
- Pidgin::MenuTray menu_tray
-pidgin_menu_tray_prepend(menu_tray, widget, tooltip)
- Pidgin::MenuTray menu_tray
-pidgin_menu_tray_set_tooltip(menu_tray, widget, tooltip)
- Pidgin::MenuTray menu_tray
-MODULE = Pidgin::MenuTray PACKAGE = Pidgin::MenuTray PREFIX = pidgin_menu_tray
--- 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 @@
-MODULE = Pidgin::Plugin PACKAGE = Pidgin::Plugins PREFIX = pidgin_plugins_
-MODULE = Pidgin::Plugin PACKAGE = Pidgin::Plugin::Dialog PREFIX = pidgin_plugin_dialog_
-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 @@
-MODULE = Pidgin::PluginPref PACKAGE = Pidgin::PluginPref PREFIX = pidgin_plugin_pref_
--- 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 @@
-MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounce PREFIX = pidgin_pounce_
-pidgin_pounce_editor_show(account, name, cur_pounce)
- Purple::Account account
- Purple::Pounce cur_pounce
-MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces PREFIX = pidgin_pounces_
-pidgin_pounces_get_handle()
-MODULE = Pidgin::Pounce PACKAGE = Pidgin::Pounces::Manager PREFIX = pidgin_pounces_manager_
-pidgin_pounces_manager_show()
-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 @@
-MODULE = Pidgin::Prefs PACKAGE = Pidgin::Prefs PREFIX = pidgin_prefs_
--- 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 @@
-MODULE = Pidgin::Privacy PACKAGE = Pidgin::Privacy PREFIX = pidgin_
-pidgin_request_add_permit(account, name)
- Purple::Account account
-pidgin_request_add_block(account, name)
- Purple::Account account
-MODULE = Pidgin::Privacy PACKAGE = Pidgin::Privacy::Dialog PREFIX = pidgin_privacy_dialog_
-pidgin_privacy_dialog_show()
-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 @@
-MODULE = Pidgin::Roomlist PACKAGE = Pidgin::Roomlist PREFIX = pidgin_roomlist_
-pidgin_roomlist_is_showable()
-MODULE = Pidgin::Roomlist PACKAGE = Pidgin::Roomlist::Dialog PREFIX = pidgin_roomlist_dialog_
-pidgin_roomlist_dialog_show()
-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 @@
-MODULE = Pidgin::Status PACKAGE = Pidgin::Status PREFIX = pidgin_status_
-pidgin_status_get_handle()
-MODULE = Pidgin::Status PACKAGE = Pidgin::Status::Editor PREFIX = pidgin_status_editor_
-pidgin_status_editor_show(edit, status)
- Purple::SavedStatus status
-MODULE = Pidgin::Status PACKAGE = Pidgin::Status::Window PREFIX = pidgin_status_window_
-pidgin_status_window_show()
-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 @@
-MODULE = Pidgin::Session PACKAGE = Pidgin::Session PREFIX = pidgin_session_
-pidgin_session_init(argv0, previous_id, config_dir)
--- 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 @@
-MODULE = Pidgin::Sound PACKAGE = Pidgin::Sound PREFIX = pidgin_sound_
-pidgin_sound_get_event_option(event)
- Purple::SoundEventID event
-pidgin_sound_get_event_label(event)
- Purple::SoundEventID event
-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 @@
-/* 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
-pidgin_status_box_new_with_account(account)
- Purple::Account account
-pidgin_status_box_add(status_box, type, pixbuf, text, sec_text, data)
- Pidgin::StatusBox status_box
- Pidgin::StatusBox::ItemType type
-MODULE = Pidgin::StatusBox PACKAGE = Pidgin::StatusBox PREFIX = pidgin_status_box_
-pidgin_status_box_add_separator(status_box)
- Pidgin::StatusBox status_box
-pidgin_status_box_set_connecting(status_box, connecting)
- Pidgin::StatusBox status_box
-pidgin_status_box_pulse_connecting(status_box)
- Pidgin::StatusBox status_box
-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 @@
-MODULE = Pidgin::Utils PACKAGE = Pidgin::Utils PREFIX = pidgin_
-pidgin_save_accels(data)
-pidgin_convert_buddy_icon(plugin, path, 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 @@
--- 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 ExtUtils::MakeMaker;
-# See lib/ExtUtils/MakeMaker.pm for details of how to influence the contents
-# of the Makefile that is written.
- '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',
- '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 @@
-# 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))
- -I$(PURPLE_TOP)/win32 \
- -I$(PIDGIN_TOP)/win32 \
- -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
- -L$(PERL_LIB_TOP)/lib \
-C_FILES = $(XS_FILES:%.xs=%.c)
-OBJECTS = $(C_FILES:%.c=%.o)
-include $(PIDGIN_COMMON_RULES)
-.PHONY: all install clean
-$(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
- 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 @@
-XSLoader::load('Pidgin', $VERSION);
-Pidgin - Perl extension for the Pidgin instant messenger.
- This module provides the interface for using perl scripts as plugins in
- Pidgin, with access to the Pidgin Gtk interface functions.
-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.
-Pidgin C API documentation - https://developer.pidgin.im/doxygen/
-Pidgin website - https://pidgin.im/
-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)
-/* 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);
-PIDGIN_PERL_BOOT_PROTO(Session);
-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_
- 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(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);
- PIDGIN_PERL_BOOT(Session);
- 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
-#define SILENT_NO_TAINT_SUPPORT 0
-#define NO_TAINT_SUPPORT 0
-#include <plugins/perl/common/module.h>
-#include "gtkmenutray.h"
-#include "gtkpluginpref.h"
-#include "gtkroomlist.h"
-#include "gtksavedstatuses.h"
-#include "gtkstatusbox.h"
-typedef PidginAccountDialogType Pidgin__Account__Dialog__Type;
-typedef PidginBuddyList * Pidgin__BuddyList;
-typedef pidgin_blist_sort_function Pidgin__BuddyList__SortFunction;
-typedef PidginConversation * Pidgin__Conversation;
-typedef PidginUnseenState Pidgin__UnseenState;
-typedef PidginConvWindow * Pidgin__Conversation__Window;
-typedef PidginConvPlacementFunc Pidgin__Conversation__PlacementFunc;
-typedef PidginXferDialog * Pidgin__Xfer__Dialog;
-typedef PidginMenuTray * Pidgin__MenuTray;
-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 @@
-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."),
"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"
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