changeset 30054:70b0f46f2966

merged with im.pidgin.pidgin
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Tue, 30 Mar 2010 15:27:03 +0900
parents fdeb9a9543ce (current diff) 0646207f360f (diff)
children 1e59677a2035
files configure.ac libpurple/certificate.c libpurple/protocols/oscar/oscar.h libpurple/util.c libpurple/util.h pidgin/gtkblist.c pidgin/gtkutils.c
diffstat 25 files changed, 398 insertions(+), 257 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Thu Mar 25 18:03:55 2010 +0900
+++ b/COPYRIGHT	Tue Mar 30 15:27:03 2010 +0900
@@ -383,6 +383,7 @@
 Mart Raudsepp
 Etan Reisner
 Luoh Ren-Shan
+Daniele Ricci
 Kristian Rietveld
 Pekka Riikonen
 Tim Ringenbach
--- a/ChangeLog	Thu Mar 25 18:03:55 2010 +0900
+++ b/ChangeLog	Tue Mar 30 15:27:03 2010 +0900
@@ -29,7 +29,9 @@
 	  conversation windows. This can be changed in .gtkrc-2.0. For example,
 	  Ctrl+v can be bound to 'Paste as Plain Text' by default.
 	* Plugins can now handle markup in buddy names by attaching to the signal
-	  "drawing-buddy".
+	  "drawing-buddy". (Daniele Ricci, Andrea Piccinelli)
+	* Be more accommodating when scaling down large images for use as
+	  buddy icons.
 
 	Bonjour:
 	* Added support for IPv6. (Thanks to T_X for testing)
--- a/ChangeLog.API	Thu Mar 25 18:03:55 2010 +0900
+++ b/ChangeLog.API	Tue Mar 30 15:27:03 2010 +0900
@@ -24,6 +24,9 @@
 		* sent-attention conversation signal
 		* got-attention conversation signal
 		* PurpleMood struct in status.h
+		* purple_certificates_import for importing multiple certificates from
+		  a single file (and corresponding import_certificates member of
+		  PurpleCertificateScheme struct)
 
 	Pidgin:
 		Added:
--- a/configure.ac	Thu Mar 25 18:03:55 2010 +0900
+++ b/configure.ac	Tue Mar 30 15:27:03 2010 +0900
@@ -1684,6 +1684,9 @@
 
 SSL_CERTIFICATES_DIR=""
 if ! test -z "$ssl_certificates_dir" ; then
+	if test "x$ssl_certificates_dir" = "xyes" ; then
+		AC_MSG_ERROR([--with-system-ssl-certs requires that a location is specified, eg. --with-system-ssl-certs=/etc/pki/tls/certs])
+	fi
 	if ! test -d "$ssl_certificates_dir" ; then
 		AC_MSG_ERROR([$ssl_certificates_dir does not exist, if this is the correct location please make sure that it exists.])
 	fi
--- a/libpurple/certificate.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/certificate.c	Tue Mar 30 15:27:03 2010 +0900
@@ -377,6 +377,16 @@
 	return (scheme->import_certificate)(filename);
 }
 
+GSList *
+purple_certificates_import(PurpleCertificateScheme *scheme, const gchar *filename)
+{
+	g_return_val_if_fail(scheme, NULL);
+	g_return_val_if_fail(scheme->import_certificates, NULL);
+	g_return_val_if_fail(filename, NULL);
+
+	return (scheme->import_certificates)(filename);
+}
+
 gboolean
 purple_certificate_export(const gchar *filename, PurpleCertificate *crt)
 {
@@ -800,8 +810,9 @@
 	PurpleCertificateScheme *x509;
 	GDir *certdir;
 	const gchar *entry;
-	GPatternSpec *pempat;
+	GPatternSpec *pempat, *crtpat;
 	GList *iter = NULL;
+	GSList *crts = NULL;
 
 	if (x509_ca_initialized) return TRUE;
 
@@ -817,6 +828,7 @@
 
 	/* Use a glob to only read .pem files */
 	pempat = g_pattern_spec_new("*.pem");
+	crtpat = g_pattern_spec_new("*.crt");
 
 	/* Populate the certificates pool from the search path(s) */
 	for (iter = x509_ca_paths; iter; iter = iter->next) {
@@ -830,32 +842,39 @@
 			gchar *fullpath;
 			PurpleCertificate *crt;
 
-			if ( !g_pattern_match_string(pempat, entry) ) {
+			if (!g_pattern_match_string(pempat, entry) && !g_pattern_match_string(crtpat, entry)) {
 				continue;
 			}
 
 			fullpath = g_build_filename(iter->data, entry, NULL);
 
 			/* TODO: Respond to a failure in the following? */
-			crt = purple_certificate_import(x509, fullpath);
+			crts = purple_certificates_import(x509, fullpath);
 
-			if (x509_ca_quiet_put_cert(crt)) {
-				purple_debug_info("certificate/x509/ca",
-						  "Loaded %s\n",
-						  fullpath);
-			} else {
-				purple_debug_error("certificate/x509/ca",
-						  "Failed to load %s\n",
-						  fullpath);
+			while (crts && crts->data) {
+				crt = crts->data;
+				if (x509_ca_quiet_put_cert(crt)) {
+					gchar *name;
+					name = purple_certificate_get_subject_name(crt);
+					purple_debug_info("certificate/x509/ca",
+							  "Loaded %s from %s\n",
+							  name ? name : "(unknown)", fullpath);
+				} else {
+					purple_debug_error("certificate/x509/ca",
+							  "Failed to load certificate from %s\n",
+							  fullpath);
+				}
+				purple_certificate_destroy(crt);
+				crts = g_slist_delete_link(crts, crts);
 			}
 
-			purple_certificate_destroy(crt);
 			g_free(fullpath);
 		}
 		g_dir_close(certdir);
 	}
 
 	g_pattern_spec_free(pempat);
+	g_pattern_spec_free(crtpat);
 
 	purple_debug_info("certificate/x509/ca",
 			  "Lazy init completed.\n");
--- a/libpurple/certificate.h	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/certificate.h	Tue Mar 30 15:27:03 2010 +0900
@@ -250,10 +250,17 @@
 	/** Retrieve the certificate activation/expiration times */
 	gboolean (* get_times)(PurpleCertificate *crt, time_t *activation, time_t *expiration);
 
+	/** Imports certificates from a file
+	 *
+	 *  @param filename   File to import the certificates from
+	 *  @return           GSList of pointers to the newly allocated Certificate structs
+	 *                    or NULL on failure.
+	 */
+	GSList * (* import_certificates)(const gchar * filename);
+
 	void (*_purple_reserved1)(void);
 	void (*_purple_reserved2)(void);
 	void (*_purple_reserved3)(void);
-	void (*_purple_reserved4)(void);
 };
 
 /** A set of operations used to provide logic for verifying a Certificate's
@@ -492,6 +499,16 @@
 purple_certificate_import(PurpleCertificateScheme *scheme, const gchar *filename);
 
 /**
+ * Imports a list of PurpleCertificates from a file
+ *
+ * @param scheme      Scheme to import under
+ * @param filename    File path to import from
+ * @return Pointer to a GSList of new PurpleCertificates, or NULL on failure
+ */
+GSList *
+purple_certificates_import(PurpleCertificateScheme *scheme, const gchar *filename);
+
+/**
  * Exports a PurpleCertificate to a file
  *
  * @param filename    File to export the certificate to
--- a/libpurple/plugins/perl/scripts/account.pl	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/perl/scripts/account.pl	Tue Mar 30 15:27:03 2010 +0900
@@ -27,7 +27,7 @@
 
 	# We will create these on load then destroy them on unload
 	my $TEST_NAME	 	= "perlTestName";
-	my $PROTOCOL_ID 	= "prpl-oscar";
+	my $PROTOCOL_ID 	= "prpl-aim";
 
 
 sub plugin_init {
--- a/libpurple/plugins/perl/scripts/buddy_list.pl	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/perl/scripts/buddy_list.pl	Tue Mar 30 15:27:03 2010 +0900
@@ -24,7 +24,7 @@
 	my $TEST_GROUP		= "UConn Buddies";
 	my $TEST_NAME	 	= "johnhkelm";
 	my $TEST_ALIAS	 	= "John Kelm";
-	my $PROTOCOL_ID 	= "prpl-oscar";
+	my $PROTOCOL_ID 	= "prpl-aim";
 
 
 sub plugin_init {
--- a/libpurple/plugins/perl/scripts/conversation.pl	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/perl/scripts/conversation.pl	Tue Mar 30 15:27:03 2010 +0900
@@ -30,7 +30,7 @@
 	my $TEST_GROUP		= "UConn Buddies";
 	my $TEST_NAME	 	= "johnhkelm";
 	my $TEST_ALIAS	 	= "John Kelm";
-	my $PROTOCOL_ID 	= "prpl-oscar";
+	my $PROTOCOL_ID 	= "prpl-aim";
 
 
 sub plugin_init { 
--- a/libpurple/plugins/perl/scripts/plugin_pref.pl	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/perl/scripts/plugin_pref.pl	Tue Mar 30 15:27:03 2010 +0900
@@ -28,7 +28,7 @@
 	my $TEST_GROUP		= "perlTestGroup";
 	my $TEST_NAME	 	= "perlTestName";
 	my $TEST_ALIAS	 	= "perlTestAlias";
-	my $PROTOCOL_ID 	= "prpl-oscar";
+	my $PROTOCOL_ID 	= "prpl-aim";
 
 sub foo {
 	$frame = Purple::PluginPref::Frame->new();
--- a/libpurple/plugins/ssl/ssl-gnutls.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/ssl/ssl-gnutls.c	Tue Mar 30 15:27:03 2010 +0900
@@ -548,6 +548,55 @@
 	return crt;
 }
 
+/** Imports a number of PEM-formatted X.509 certificates from the specified file.
+ * @param filename Filename to import from. Format is PEM
+ *
+ * @return A newly allocated GSList of Certificate structures of the x509_gnutls scheme
+ */
+static GSList *
+x509_importcerts_from_file(const gchar * filename)
+{
+	PurpleCertificate *crt;  /* Certificate being constructed */
+	gchar *buf;        /* Used to load the raw file data */
+	gchar *begin, *end;
+	GSList *crts = NULL;
+	gsize buf_sz;      /* Size of the above */
+	gnutls_datum dt; /* Struct to pass down to GnuTLS */
+
+	purple_debug_info("gnutls",
+			  "Attempting to load X.509 certificates from %s\n",
+			  filename);
+
+	/* Next, we'll simply yank the entire contents of the file
+	   into memory */
+	/* TODO: Should I worry about very large files here? */
+	g_return_val_if_fail(
+		g_file_get_contents(filename,
+			    &buf,
+			    &buf_sz,
+			    NULL      /* No error checking for now */
+		),
+		NULL);
+
+	begin = buf;
+	while((end = strstr(begin, "-----END CERTIFICATE-----")) != NULL) {
+		end += sizeof("-----END CERTIFICATE-----")-1;
+		/* Load the datum struct */
+		dt.data = (unsigned char *) begin;
+		dt.size = (end-begin);
+
+		/* Perform the conversion; files should be in PEM format */
+		crt = x509_import_from_datum(dt, GNUTLS_X509_FMT_PEM);
+		crts = g_slist_prepend(crts, crt);
+		begin = end;
+	}
+
+	/* Cleanup */
+	g_free(buf);
+
+	return crts;
+}
+
 /**
  * Exports a PEM-formatted X.509 certificate to the specified file.
  * @param filename Filename to export to. Format will be PEM
@@ -964,10 +1013,10 @@
 	x509_common_name,                /* Subject name */
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
+	x509_importcerts_from_file,      /* Multiple certificates import function */
 
 	NULL,
 	NULL,
-	NULL,
 	NULL
 
 };
--- a/libpurple/plugins/ssl/ssl-nss.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/plugins/ssl/ssl-nss.c	Tue Mar 30 15:27:03 2010 +0900
@@ -530,7 +530,7 @@
 /** Imports a PEM-formatted X.509 certificate from the specified file.
  * @param filename Filename to import from. Format is PEM
  *
- * @return A newly allocated Certificate structure of the x509_gnutls scheme
+ * @return A newly allocated Certificate structure of the x509_nss scheme
  */
 static PurpleCertificate *
 x509_import_from_file(const gchar *filename)
@@ -575,6 +575,60 @@
 	return crt;
 }
 
+/** Imports a number of PEM-formatted X.509 certificates from the specified file.
+ * @param filename Filename to import from. Format is PEM
+ *
+ * @return A GSList of newly allocated Certificate structures of the x509_nss scheme
+ */
+static GSList *
+x509_importcerts_from_file(const gchar *filename)
+{
+	gchar *rawcert, *begin, *end;
+	gsize len = 0;
+	GSList *crts = NULL;
+	CERTCertificate *crt_dat;
+	PurpleCertificate *crt;
+
+	g_return_val_if_fail(filename != NULL, NULL);
+
+	purple_debug_info("nss/x509",
+			  "Loading certificate from %s\n",
+			  filename);
+
+	/* Load the raw data up */
+	if (!g_file_get_contents(filename,
+				 &rawcert, &len,
+				 NULL)) {
+		purple_debug_error("nss/x509", "Unable to read certificate file.\n");
+		return NULL;
+	}
+
+	if (len == 0) {
+		purple_debug_error("nss/x509",
+				"Certificate file has no contents!\n");
+		if (rawcert)
+			g_free(rawcert);
+		return NULL;
+	}
+
+	begin = rawcert;
+	while((end = strstr(begin, "-----END CERTIFICATE-----")) != NULL) {
+		end += sizeof("-----END CERTIFICATE-----")-1;
+		/* Decode the certificate */
+		crt_dat = CERT_DecodeCertFromPackage(begin, (end-begin));
+
+		g_return_val_if_fail(crt_dat != NULL, NULL);
+
+		crt = g_new0(PurpleCertificate, 1);
+		crt->scheme = &x509_nss;
+		crt->data = crt_dat;
+		crts = g_slist_prepend(crts, crt);
+		begin = end;
+	}
+	g_free(rawcert);
+
+	return crts;
+}
 /**
  * Exports a PEM-formatted X.509 certificate to the specified file.
  * @param filename Filename to export to. Format will be PEM
@@ -874,10 +928,10 @@
 	x509_common_name,                /* Subject name */
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
+	x509_importcerts_from_file,      /* Multiple certificate import function */
 
 	NULL,
 	NULL,
-	NULL,
 	NULL
 };
 
--- a/libpurple/protocols/bonjour/jabber.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/protocols/bonjour/jabber.c	Tue Mar 30 15:27:03 2010 +0900
@@ -1185,6 +1185,9 @@
 		for (l = buddies; l; l = l->next) {
 			BonjourBuddy *bb = purple_buddy_get_protocol_data((PurpleBuddy*) l->data);
 			if (bb != NULL) {
+				/* Any ongoing connection attempt is cancelled
+				 * by _purple_connection_destroy */
+				bb->conversation->connect_data = NULL;
 				bonjour_jabber_close_conversation(bb->conversation);
 				bb->conversation = NULL;
 			}
--- a/libpurple/protocols/oscar/oscar.h	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/protocols/oscar/oscar.h	Tue Mar 30 15:27:03 2010 +0900
@@ -344,39 +344,39 @@
 	OSCAR_DISCONNECT_RETRYING /* peer connections only */
 } OscarDisconnectReason;
 
-#define OSCAR_CAPABILITY_BUDDYICON             0x0000000000000001
-#define OSCAR_CAPABILITY_TALK                  0x0000000000000002
-#define OSCAR_CAPABILITY_DIRECTIM              0x0000000000000004
-#define OSCAR_CAPABILITY_CHAT                  0x0000000000000008
-#define OSCAR_CAPABILITY_GETFILE               0x0000000000000010
-#define OSCAR_CAPABILITY_SENDFILE              0x0000000000000020
-#define OSCAR_CAPABILITY_GAMES                 0x0000000000000040
-#define OSCAR_CAPABILITY_ADDINS                0x0000000000000080
-#define OSCAR_CAPABILITY_SENDBUDDYLIST         0x0000000000000100
-#define OSCAR_CAPABILITY_GAMES2                0x0000000000000200
-#define OSCAR_CAPABILITY_ICQ_DIRECT            0x0000000000000400
-#define OSCAR_CAPABILITY_APINFO                0x0000000000000800
-#define OSCAR_CAPABILITY_ICQRTF                0x0000000000001000
-#define OSCAR_CAPABILITY_EMPTY                 0x0000000000002000
-#define OSCAR_CAPABILITY_ICQSERVERRELAY        0x0000000000004000
-#define OSCAR_CAPABILITY_UNICODEOLD            0x0000000000008000
-#define OSCAR_CAPABILITY_TRILLIANCRYPT         0x0000000000010000
-#define OSCAR_CAPABILITY_UNICODE               0x0000000000020000
-#define OSCAR_CAPABILITY_INTEROPERATE          0x0000000000040000
-#define OSCAR_CAPABILITY_SHORTCAPS             0x0000000000080000
-#define OSCAR_CAPABILITY_HIPTOP                0x0000000000100000
-#define OSCAR_CAPABILITY_SECUREIM              0x0000000000200000
-#define OSCAR_CAPABILITY_SMS                   0x0000000000400000
-#define OSCAR_CAPABILITY_VIDEO                 0x0000000000800000
-#define OSCAR_CAPABILITY_ICHATAV               0x0000000001000000
-#define OSCAR_CAPABILITY_LIVEVIDEO             0x0000000002000000
-#define OSCAR_CAPABILITY_CAMERA                0x0000000004000000
-#define OSCAR_CAPABILITY_ICHAT_SCREENSHARE     0x0000000008000000
-#define OSCAR_CAPABILITY_TYPING                0x0000000010000000
-#define OSCAR_CAPABILITY_NEWCAPS               0x0000000020000000
-#define OSCAR_CAPABILITY_XTRAZ                 0x0000000040000000
-#define OSCAR_CAPABILITY_GENERICUNKNOWN        0x0000000080000000
-#define OSCAR_CAPABILITY_LAST                  0x0000000100000000
+#define OSCAR_CAPABILITY_BUDDYICON             0x0000000000000001LL
+#define OSCAR_CAPABILITY_TALK                  0x0000000000000002LL
+#define OSCAR_CAPABILITY_DIRECTIM              0x0000000000000004LL
+#define OSCAR_CAPABILITY_CHAT                  0x0000000000000008LL
+#define OSCAR_CAPABILITY_GETFILE               0x0000000000000010LL
+#define OSCAR_CAPABILITY_SENDFILE              0x0000000000000020LL
+#define OSCAR_CAPABILITY_GAMES                 0x0000000000000040LL
+#define OSCAR_CAPABILITY_ADDINS                0x0000000000000080LL
+#define OSCAR_CAPABILITY_SENDBUDDYLIST         0x0000000000000100LL
+#define OSCAR_CAPABILITY_GAMES2                0x0000000000000200LL
+#define OSCAR_CAPABILITY_ICQ_DIRECT            0x0000000000000400LL
+#define OSCAR_CAPABILITY_APINFO                0x0000000000000800LL
+#define OSCAR_CAPABILITY_ICQRTF                0x0000000000001000LL
+#define OSCAR_CAPABILITY_EMPTY                 0x0000000000002000LL
+#define OSCAR_CAPABILITY_ICQSERVERRELAY        0x0000000000004000LL
+#define OSCAR_CAPABILITY_UNICODEOLD            0x0000000000008000LL
+#define OSCAR_CAPABILITY_TRILLIANCRYPT         0x0000000000010000LL
+#define OSCAR_CAPABILITY_UNICODE               0x0000000000020000LL
+#define OSCAR_CAPABILITY_INTEROPERATE          0x0000000000040000LL
+#define OSCAR_CAPABILITY_SHORTCAPS             0x0000000000080000LL
+#define OSCAR_CAPABILITY_HIPTOP                0x0000000000100000LL
+#define OSCAR_CAPABILITY_SECUREIM              0x0000000000200000LL
+#define OSCAR_CAPABILITY_SMS                   0x0000000000400000LL
+#define OSCAR_CAPABILITY_VIDEO                 0x0000000000800000LL
+#define OSCAR_CAPABILITY_ICHATAV               0x0000000001000000LL
+#define OSCAR_CAPABILITY_LIVEVIDEO             0x0000000002000000LL
+#define OSCAR_CAPABILITY_CAMERA                0x0000000004000000LL
+#define OSCAR_CAPABILITY_ICHAT_SCREENSHARE     0x0000000008000000LL
+#define OSCAR_CAPABILITY_TYPING                0x0000000010000000LL
+#define OSCAR_CAPABILITY_NEWCAPS               0x0000000020000000LL
+#define OSCAR_CAPABILITY_XTRAZ                 0x0000000040000000LL
+#define OSCAR_CAPABILITY_GENERICUNKNOWN        0x0000000080000000LL
+#define OSCAR_CAPABILITY_LAST                  0x0000000100000000LL
 
 /*
  * Byte Stream type. Sort of.
--- a/libpurple/protocols/qq/qq.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/protocols/qq/qq.c	Tue Mar 30 15:27:03 2010 +0900
@@ -221,6 +221,9 @@
 		qd->connect_watcher = 0;
 	}
 
+	/* This is cancelled by _purple_connection_destroy */
+	qd->conn_data = NULL;
+
 	qq_disconnect(gc);
 
 	if (qd->redirect) g_free(qd->redirect);
--- a/libpurple/savedstatuses.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/savedstatuses.c	Tue Mar 30 15:27:03 2010 +0900
@@ -436,12 +436,12 @@
  *   And I can always make them smile
  *   From White Castle to the Nile</message>
  *       <substatus>
- *           <account protocol='prpl-oscar'>markdoliner</account>
+ *           <account protocol='prpl-aim'>markdoliner</account>
  *           <state>available</state>
  *           <message>The ladies man is here to answer your queries.</message>
  *       </substatus>
  *       <substatus>
- *           <account protocol='prpl-oscar'>giantgraypanda</account>
+ *           <account protocol='prpl-aim'>giantgraypanda</account>
  *           <state>away</state>
  *           <message>A.C. ain't in charge no more.</message>
  *       </substatus>
--- a/libpurple/util.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/util.c	Tue Mar 30 15:27:03 2010 +0900
@@ -1959,13 +1959,14 @@
 					}
 				}
 
-				/* Check for tags which should be mapped to newline */
-				else if (g_ascii_strncasecmp(str2 + i, "<p>", 3) == 0
-				 || g_ascii_strncasecmp(str2 + i, "<tr", 3) == 0
+				/* Check for tags which should be mapped to newline (but ignore some of
+				 * the tags at the beginning of the text) */
+				else if ((j && (g_ascii_strncasecmp(str2 + i, "<p>", 3) == 0
+				              || g_ascii_strncasecmp(str2 + i, "<tr", 3) == 0
+				              || g_ascii_strncasecmp(str2 + i, "<hr", 3) == 0
+				              || g_ascii_strncasecmp(str2 + i, "<li", 3) == 0
+				              || g_ascii_strncasecmp(str2 + i, "<div", 4) == 0))
 				 || g_ascii_strncasecmp(str2 + i, "<br", 3) == 0
-				 || g_ascii_strncasecmp(str2 + i, "<hr", 3) == 0
-				 || g_ascii_strncasecmp(str2 + i, "<li", 3) == 0
-				 || g_ascii_strncasecmp(str2 + i, "<div", 4) == 0
 				 || g_ascii_strncasecmp(str2 + i, "</table>", 8) == 0)
 				{
 					str2[j++] = '\n';
--- a/libpurple/util.h	Thu Mar 25 18:03:55 2010 +0900
+++ b/libpurple/util.h	Tue Mar 30 15:27:03 2010 +0900
@@ -1429,6 +1429,10 @@
 /**
  * This is added temporarily to assist the split of oscar into aim and icq.
  * This should not be used by plugins.
+ *
+ * @deprecated This function should not be used in new code and should be
+ *             removed in 3.0.0.  The aim/icq prpl split happened a long
+ *             time ago, and we don't need to keep migrating old data.
  */
 const char *_purple_oscar_convert(const char *act, const char *protocol);
 
--- a/pidgin/gtkblist.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/gtkblist.c	Tue Mar 30 15:27:03 2010 +0900
@@ -123,7 +123,6 @@
 	PidginMiniDialog *signed_on_elsewhere;
 
 	PidginBlistTheme *current_theme;
-
 } PidginBuddyListPrivate;
 
 #define PIDGIN_BUDDY_LIST_GET_PRIVATE(list) \
@@ -2235,8 +2234,8 @@
 		return FALSE;
 	}
 
-	add_buddies_from_vcard("prpl-oscar",  group, aims,    alias);
-	add_buddies_from_vcard("prpl-oscar",  group, icqs,    alias);
+	add_buddies_from_vcard("prpl-aim",    group, aims,    alias);
+	add_buddies_from_vcard("prpl-icq",    group, icqs,    alias);
 	add_buddies_from_vcard("prpl-yahoo",  group, yahoos,  alias);
 	add_buddies_from_vcard("prpl-msn",    group, msns,    alias);
 	add_buddies_from_vcard("prpl-jabber", group, jabbers, alias);
@@ -3410,7 +3409,7 @@
 update_status_with_mood(PurpleAccount *account, const gchar *mood,
     const gchar *text)
 {
-	if (mood != NULL && !purple_strequal(mood, "")) {
+	if (mood && *mood) {
 		if (text) {
 			purple_account_set_status(account, "mood", TRUE,
 			                          PURPLE_MOOD_NAME, mood,
@@ -3429,20 +3428,27 @@
 static void
 edit_mood_cb(PurpleConnection *gc, PurpleRequestFields *fields)
 {
-	PurpleRequestField *mood_field, *text_field;
+	PurpleRequestField *mood_field;
 	GList *l;
 
 	mood_field = purple_request_fields_get_field(fields, "mood");
-	text_field = purple_request_fields_get_field(fields, "text");
 	l = purple_request_field_list_get_selected(mood_field);
 
 	if (l) {
 		const char *mood = purple_request_field_list_get_data(mood_field, l->data);
-		const char *text = purple_request_field_string_get_value(text_field);
 
 		if (gc) {
+			const char *text;
 			PurpleAccount *account = purple_connection_get_account(gc);
 
+			if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOOD_MESSAGES) {
+				PurpleRequestField *text_field;
+				text_field = purple_request_fields_get_field(fields, "text");
+				text = purple_request_field_string_get_value(text_field);
+			} else {
+				text = NULL;
+			}
+
 			update_status_with_mood(account, mood, text);
 		} else {
 			GList *accounts = purple_accounts_get_all_active();
@@ -3451,8 +3457,8 @@
 				PurpleAccount *account = (PurpleAccount *) accounts->data;
 				PurpleConnection *gc = purple_account_get_connection(account);
 
-				if (gc->flags && PURPLE_CONNECTION_SUPPORT_MOODS) {
-					update_status_with_mood(account, mood, text);
+				if (gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) {
+					update_status_with_mood(account, mood, NULL);
 				}
 			}
 		}
@@ -3472,9 +3478,9 @@
 get_global_moods(void)
 {
 	GHashTable *global_moods =
-		g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+		g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
 	GHashTable *mood_counts =
-		g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
+		g_hash_table_new_full(g_str_hash, g_str_equal, NULL, NULL);
 	GList *accounts = purple_accounts_get_all_active();
 	PurpleMood *result = NULL;
 	GList *out_moods = NULL;
@@ -3489,16 +3495,19 @@
 			PurplePluginProtocolInfo *prpl_info =
 				PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
 			PurpleMood *mood = NULL;
-			
+
+			/* PURPLE_CONNECTION_SUPPORT_MOODS would not be set if the prpl doesn't
+			 * have get_moods, so using PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary
+			 * here */
 			for (mood = prpl_info->get_moods(account) ;
 			    mood->mood != NULL ; mood++) {
 				int mood_count =
 						GPOINTER_TO_INT(g_hash_table_lookup(mood_counts, mood->mood));
 
 				if (!g_hash_table_lookup(global_moods, mood->mood)) {
-					g_hash_table_insert(global_moods, g_strdup(mood->mood), mood);
+					g_hash_table_insert(global_moods, (gpointer)mood->mood, mood);
 				}
-				g_hash_table_insert(mood_counts, g_strdup(mood->mood),
+				g_hash_table_insert(mood_counts, (gpointer)mood->mood,
 				    GINT_TO_POINTER(mood_count + 1));
 			}
 
@@ -3591,6 +3600,9 @@
 		purple_request_field_list_add_selected(f, _("None"));
 
 	/* TODO: rlaager wants this sorted. */
+	/* The connection is checked for PURPLE_CONNECTION_SUPPORT_MOODS flag before
+	 * this function is called for a non-null account. So using
+	 * PURPLE_PROTOCOL_PLUGIN_HAS_FUNC isn't necessary here */
 	for (mood = account ? prpl_info->get_moods(account) : global_moods;
 	     mood->mood != NULL ; mood++) {
 		char *path;
@@ -8158,22 +8170,12 @@
 			 PURPLE_PLUGIN_HAS_ACTIONS(plugin))) {
 			if (PURPLE_PROTOCOL_PLUGIN_HAS_FUNC(prpl_info, get_moods) &&
 			    gc->flags & PURPLE_CONNECTION_SUPPORT_MOODS) {
-				GList *types;
-
-				for (types = purple_account_get_status_types(account);
-			     	types != NULL ; types = types->next) {
-					PurpleStatusType *type = types->data;
-
-					if (strcmp(purple_status_type_get_id(type), "mood") != 0)
-						continue;
-
+
+				if (purple_account_get_status(account, "mood")) {
 					menuitem = gtk_menu_item_new_with_mnemonic(_("Set _Mood..."));
 					g_signal_connect(G_OBJECT(menuitem), "activate",
 					         	G_CALLBACK(set_mood_cb), account);
 					gtk_menu_shell_append(GTK_MENU_SHELL(submenu), menuitem);
-
-					/* Be safe.  It shouldn't match more than once anyway */
-					break;
 				}
 			}
 			if (PURPLE_PLUGIN_HAS_ACTIONS(plugin)) {
--- a/pidgin/gtkutils.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/gtkutils.c	Tue Mar 30 15:27:03 2010 +0900
@@ -2332,7 +2332,9 @@
 	return dialog->icon_filesel;
 }
 
-
+/**
+ * @return True if any string from array a exists in array b.
+ */
 static gboolean
 str_array_match(char **a, char **b)
 {
@@ -2351,165 +2353,171 @@
 pidgin_convert_buddy_icon(PurplePlugin *plugin, const char *path, size_t *len)
 {
 	PurplePluginProtocolInfo *prpl_info;
+	PurpleBuddyIconSpec *spec;
+	int orig_width, orig_height, new_width, new_height;
+	GdkPixbufFormat *format;
+	char **pixbuf_formats;
 	char **prpl_formats;
-	int width, height;
-	char **pixbuf_formats = NULL;
-	GdkPixbufFormat *format;
-	GdkPixbuf *pixbuf;
+	GError *error = NULL;
 	gchar *contents;
 	gsize length;
+	GdkPixbuf *pixbuf, *original;
+	float scale_factor;
+	int i;
+	gchar *tmp;
 
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin);
-
-	g_return_val_if_fail(prpl_info->icon_spec.format != NULL, NULL);
-
-
-	format = gdk_pixbuf_get_file_info(path, &width, &height);
-
-	if (format == NULL)
+	spec = &prpl_info->icon_spec;
+	g_return_val_if_fail(spec->format != NULL, NULL);
+
+	format = gdk_pixbuf_get_file_info(path, &orig_width, &orig_height);
+	if (format == NULL) {
+		purple_debug_warning("buddyicon", "Could not get file info of %s\n", path);
 		return NULL;
+	}
 
 	pixbuf_formats = gdk_pixbuf_format_get_extensions(format);
-	prpl_formats = g_strsplit(prpl_info->icon_spec.format,",",0);
-	if (str_array_match(pixbuf_formats, prpl_formats) &&                  /* This is an acceptable format AND */
-		 (!(prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) ||   /* The prpl doesn't scale before it sends OR */
-		  (prpl_info->icon_spec.min_width <= width &&
-		   prpl_info->icon_spec.max_width >= width &&
-		   prpl_info->icon_spec.min_height <= height &&
-		   prpl_info->icon_spec.max_height >= height)))                   /* The icon is the correct size */
+	prpl_formats = g_strsplit(spec->format, ",", 0);
+
+	if (str_array_match(pixbuf_formats, prpl_formats) && /* This is an acceptable format AND */
+		 (!(spec->scale_rules & PURPLE_ICON_SCALE_SEND) || /* The prpl doesn't scale before it sends OR */
+		  (spec->min_width <= orig_width && spec->max_width >= orig_width &&
+		   spec->min_height <= orig_height && spec->max_height >= orig_height))) /* The icon is the correct size */
 	{
-		g_strfreev(prpl_formats);
 		g_strfreev(pixbuf_formats);
 
-		/* We don't need to scale the image. */
-		contents = NULL;
-		if (!g_file_get_contents(path, &contents, &length, NULL))
-		{
-			g_free(contents);
-			return NULL;
-		}
-	}
-	else
-	{
-		int i;
-		GError *error = NULL;
-		GdkPixbuf *scale;
-		gboolean success = FALSE;
-		char *filename = NULL;
-
-		g_strfreev(pixbuf_formats);
-
-		pixbuf = gdk_pixbuf_new_from_file(path, &error);
-		if (error) {
-			purple_debug_error("buddyicon", "Could not open icon for conversion: %s\n", error->message);
-			g_error_free(error);
+		if (!g_file_get_contents(path, &contents, &length, &error)) {
+			purple_debug_warning("buddyicon", "Could not get file contents "
+					"of %s: %s\n", path, error->message);
 			g_strfreev(prpl_formats);
 			return NULL;
 		}
 
-		if ((prpl_info->icon_spec.scale_rules & PURPLE_ICON_SCALE_SEND) &&
-			(width < prpl_info->icon_spec.min_width ||
-			 width > prpl_info->icon_spec.max_width ||
-			 height < prpl_info->icon_spec.min_height ||
-			 height > prpl_info->icon_spec.max_height))
-		{
-			int new_width = width;
-			int new_height = height;
-
-			purple_buddy_icon_get_scale_size(&prpl_info->icon_spec, &new_width, &new_height);
-
-			scale = gdk_pixbuf_scale_simple(pixbuf, new_width, new_height,
-					GDK_INTERP_HYPER);
-			g_object_unref(G_OBJECT(pixbuf));
-			pixbuf = scale;
+		if (spec->max_filesize == 0 || length < spec->max_filesize) {
+			/* The supplied image fits the file size, dimensions and type
+			   constraints.  Great!  Return it without making any changes. */
+			if (len)
+				*len = length;
+			g_strfreev(prpl_formats);
+			return contents;
 		}
 
+		/* The image was too big.  Fall-through and try scaling it down. */
+		g_free(contents);
+	} else {
+		g_strfreev(pixbuf_formats);
+	}
+
+	/* The original image wasn't compatible.  Scale it or convert file type. */
+	pixbuf = gdk_pixbuf_new_from_file(path, &error);
+	if (error) {
+		purple_debug_warning("buddyicon", "Could not open icon '%s' for "
+				"conversion: %s\n", path, error->message);
+		g_error_free(error);
+		g_strfreev(prpl_formats);
+		return NULL;
+	}
+	original = g_object_ref(G_OBJECT(pixbuf));
+
+	new_width = orig_width;
+	new_height = orig_height;
+
+	/* Make sure the image is the correct dimensions */
+	if (spec->scale_rules & PURPLE_ICON_SCALE_SEND &&
+		(orig_width < spec->min_width || orig_width > spec->max_width ||
+		 orig_height < spec->min_height || orig_height > spec->max_height))
+	{
+		purple_buddy_icon_get_scale_size(spec, &new_width, &new_height);
+
+		g_object_unref(G_OBJECT(pixbuf));
+		pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER);
+	}
+
+	scale_factor = 1;
+	do {
 		for (i = 0; prpl_formats[i]; i++) {
-			FILE *fp;
-
-			g_free(filename);
-			fp = purple_mkstemp(&filename, TRUE);
-			if (!fp)
-			{
-				g_free(filename);
-				return NULL;
-			}
-			fclose(fp);
-
-			purple_debug_info("buddyicon", "Converting buddy icon to %s as %s\n", prpl_formats[i], filename);
-			/* The "compression" param wasn't supported until gdk-pixbuf 2.8.
-			 * Using it in previous versions causes the save to fail (and an assert message).  */
-			if ((gdk_pixbuf_major_version > 2 || (gdk_pixbuf_major_version == 2
-						&& gdk_pixbuf_minor_version >= 8))
-					&& strcmp(prpl_formats[i], "png") == 0) {
-				if (gdk_pixbuf_save(pixbuf, filename, prpl_formats[i],
-						&error, "compression", "9", NULL)) {
-					success = TRUE;
+			int quality = 100;
+			do {
+				const char *key = NULL;
+				const char *value = NULL;
+				gchar tmp_buf[4];
+
+				purple_debug_info("buddyicon", "Converting buddy icon to %s\n", prpl_formats[i]);
+
+				if (g_str_equal(prpl_formats[i], "png")) {
+					key = "compression";
+					value = "9";
+				} else if (g_str_equal(prpl_formats[i], "jpeg")) {
+					sprintf(tmp_buf, "%u", quality);
+					key = "quality";
+					value = tmp_buf;
+				}
+
+				if (!gdk_pixbuf_save_to_buffer(pixbuf, &contents, &length,
+						prpl_formats[i], &error, key, value, NULL))
+				{
+					/* The NULL checking of error is necessary due to this bug:
+					 * http://bugzilla.gnome.org/show_bug.cgi?id=405539 */
+					purple_debug_warning("buddyicon",
+							"Could not convert to %s: %s\n", prpl_formats[i],
+							(error && error->message) ? error->message : "Unknown error");
+					g_error_free(error);
+					error = NULL;
+
+					/* We couldn't convert to this image type.  Try the next
+					   image type. */
 					break;
 				}
-			} else if (gdk_pixbuf_save(pixbuf, filename, prpl_formats[i],
-					&error, NULL)) {
-				success = TRUE;
-				break;
-			}
-
-			/* The NULL checking is necessary due to this bug:
-			 * http://bugzilla.gnome.org/show_bug.cgi?id=405539 */
-			purple_debug_warning("buddyicon", "Could not convert to %s: %s\n", prpl_formats[i],
-				(error && error->message) ? error->message : "Unknown error");
-			g_error_free(error);
-			error = NULL;
-		}
-		g_strfreev(prpl_formats);
-		g_object_unref(G_OBJECT(pixbuf));
-		if (!success) {
-			purple_debug_error("buddyicon", "Could not convert icon to usable format.\n");
-			g_free(filename);
-			return NULL;
-		}
-
-		contents = NULL;
-		if (!g_file_get_contents(filename, &contents, &length, NULL))
-		{
-			purple_debug_error("buddyicon",
-					"Could not read '%s', which we just wrote to disk.\n",
-					filename);
-
-			g_free(contents);
-			g_free(filename);
-			return NULL;
+
+				if (spec->max_filesize == 0 || length < spec->max_filesize) {
+					/* We were able to save the image as this image type and
+					   have it be within the size constraints.  Great!  Return
+					   the image. */
+					purple_debug_info("buddyicon", "Converted image from "
+							"%dx%d to %dx%d, format=%s, quality=%u, "
+							"filesize=%zu\n", orig_width, orig_height,
+							new_width, new_height, prpl_formats[i], quality,
+							length);
+					if (len)
+						*len = length;
+					g_strfreev(prpl_formats);
+					g_object_unref(G_OBJECT(pixbuf));
+					g_object_unref(G_OBJECT(original));
+					return contents;
+				}
+
+				g_free(contents);
+
+				if (!g_str_equal(prpl_formats[i], "jpeg")) {
+					/* File size was too big and we can't lower the quality,
+					   so skip to the next image type. */
+					break;
+				}
+
+				/* File size was too big, but we're dealing with jpeg so try
+				   lowering the quality. */
+				quality -= 5;
+			} while (quality >= 70);
 		}
 
-		g_unlink(filename);
-		g_free(filename);
-	}
-
-	/* Check the image size */
-	/*
-	 * TODO: If the file is too big, it would be cool if we checked if
-	 *       the prpl supported jpeg, and then we could convert to that
-	 *       and use a lower quality setting.
-	 */
-	if ((prpl_info->icon_spec.max_filesize != 0) &&
-	    (length > prpl_info->icon_spec.max_filesize))
-	{
-		gchar *tmp;
-		tmp = g_strdup_printf(_("The file '%s' is too large for %s.  Please try a smaller image.\n"),
-				path, plugin->info->name);
-		purple_notify_error(NULL, _("Icon Error"),
-				_("Could not set icon"), tmp);
-		purple_debug_info("buddyicon",
-				"'%s' was converted to an image which is %" G_GSIZE_FORMAT
-				" bytes, but the maximum icon size for %s is %" G_GSIZE_FORMAT
-				" bytes\n", path, length, plugin->info->name,
-				prpl_info->icon_spec.max_filesize);
-		g_free(tmp);
-		return NULL;
-	}
-
-	if (len)
-		*len = length;
-	return contents;
+		/* We couldn't save the image in any format that was below the max
+		   file size.  Maybe we can reduce the image dimensions? */
+		scale_factor *= 0.8;
+		new_width = orig_width * scale_factor;
+		new_height = orig_height * scale_factor;
+		g_object_unref(G_OBJECT(pixbuf));
+		pixbuf = gdk_pixbuf_scale_simple(original, new_width, new_height, GDK_INTERP_HYPER);
+	} while (new_width > 10 || new_height > 10);
+	g_strfreev(prpl_formats);
+	g_object_unref(G_OBJECT(pixbuf));
+	g_object_unref(G_OBJECT(original));
+
+	tmp = g_strdup_printf(_("The file '%s' is too large for %s.  Please try a smaller image.\n"),
+			path, plugin->info->name);
+	purple_notify_error(NULL, _("Icon Error"), _("Could not set icon"), tmp);
+	g_free(tmp);
+
+	return NULL;
 }
 
 void pidgin_set_custom_buddy_icon(PurpleAccount *account, const char *who, const char *filename)
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c	Tue Mar 30 15:27:03 2010 +0900
@@ -314,13 +314,11 @@
 		}
 		else
 		{
-			add_ims(dialog, contact, name, aims,    "prpl-oscar");
 			add_ims(dialog, contact, name, aims,    "prpl-aim");
 			add_ims(dialog, contact, name, jabbers, "prpl-jabber");
 			add_ims(dialog, contact, name, yahoos,  "prpl-yahoo");
 			add_ims(dialog, contact, name, msns,    "prpl-msn");
 			add_ims(dialog, contact, name, icqs,    "prpl-icq");
-			add_ims(dialog, contact, name, icqs,    "prpl-oscar");
 			add_ims(dialog, contact, name, novells, "prpl-novell");
 		}
 	}
@@ -399,12 +397,10 @@
 		else
 		{
 			add_ims(dialog, contact, name, aims,    "prpl-aim");
-			add_ims(dialog, contact, name, aims,    "prpl-oscar");
 			add_ims(dialog, contact, name, jabbers, "prpl-jabber");
 			add_ims(dialog, contact, name, yahoos,  "prpl-yahoo");
 			add_ims(dialog, contact, name, msns,    "prpl-msn");
 			add_ims(dialog, contact, name, icqs,    "prpl-icq");
-			add_ims(dialog, contact, name, icqs,    "prpl-oscar");
 			add_ims(dialog, contact, name, novells, "prpl-novell");
 		}
 	}
--- a/pidgin/plugins/gevolution/gevo-util.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/plugins/gevolution/gevo-util.c	Tue Mar 30 15:27:03 2010 +0900
@@ -99,23 +99,7 @@
 
 	protocol_id = purple_account_get_protocol_id(account);
 
-	if (!strcmp(protocol_id, "prpl-oscar"))
-	{
-		PurpleConnection *gc;
-		PurplePluginProtocolInfo *prpl_info;
-
-		gc = purple_account_get_connection(account);
-
-		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
-
-		if (!strcmp("aim", prpl_info->list_icon(account, buddy)))
-		{
-			protocol_field = E_CONTACT_IM_AIM;
-		}
-		else
-			protocol_field = E_CONTACT_IM_ICQ;
-	}
-	else if (!strcmp(protocol_id, "prpl-aim"))
+	if (!strcmp(protocol_id, "prpl-aim"))
 		protocol_field = E_CONTACT_IM_AIM;
 	else if (!strcmp(protocol_id, "prpl-icq"))
 		protocol_field = E_CONTACT_IM_ICQ;
--- a/pidgin/plugins/gevolution/gevolution.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/plugins/gevolution/gevolution.c	Tue Mar 30 15:27:03 2010 +0900
@@ -111,12 +111,10 @@
 	name = e_contact_get_const(contact, E_CONTACT_FULL_NAME);
 
 	update_ims_from_contact(contact, name, "prpl-aim",    E_CONTACT_IM_AIM);
-	update_ims_from_contact(contact, name, "prpl-oscar",  E_CONTACT_IM_AIM);
 	update_ims_from_contact(contact, name, "prpl-jabber", E_CONTACT_IM_JABBER);
 	update_ims_from_contact(contact, name, "prpl-yahoo",  E_CONTACT_IM_YAHOO);
 	update_ims_from_contact(contact, name, "prpl-msn",    E_CONTACT_IM_MSN);
 	update_ims_from_contact(contact, name, "prpl-icq",    E_CONTACT_IM_ICQ);
-	update_ims_from_contact(contact, name, "prpl-oscar",  E_CONTACT_IM_ICQ);
 	update_ims_from_contact(contact, name, "prpl-novell", E_CONTACT_IM_GROUPWISE);
 }
 
--- a/pidgin/plugins/gevolution/new_person_dialog.c	Thu Mar 25 18:03:55 2010 +0900
+++ b/pidgin/plugins/gevolution/new_person_dialog.c	Tue Mar 30 15:27:03 2010 +0900
@@ -141,14 +141,7 @@
 		if (*email)
 			e_contact_set(contact, E_CONTACT_EMAIL_1, (gpointer)email);
 
-		if (!strcmp(im_service, "prpl-oscar"))
-		{
-			if (isdigit(*username))
-				field = E_CONTACT_IM_ICQ;
-			else
-				field = E_CONTACT_IM_AIM;
-		}
-		else if (!strcmp(im_service, "prpl-aim"))
+		if (!strcmp(im_service, "prpl-aim"))
 			field = E_CONTACT_IM_AIM;
 		else if (!strcmp(im_service, "prpl-icq"))
 			field = E_CONTACT_IM_ICQ;
--- a/po/POTFILES.in	Thu Mar 25 18:03:55 2010 +0900
+++ b/po/POTFILES.in	Tue Mar 30 15:27:03 2010 +0900
@@ -95,6 +95,7 @@
 libpurple/protocols/jabber/buddy.c
 libpurple/protocols/jabber/chat.c
 libpurple/protocols/jabber/jabber.c
+libpurple/protocols/jabber/jutil.c
 libpurple/protocols/jabber/libxmpp.c
 libpurple/protocols/jabber/message.c
 libpurple/protocols/jabber/parser.c