changeset 22345:eb03ec8ea666

merge of 'a4c768e127679f724617481cff7d907dab10463f' and 'aea32e6ae9d3ad9d53703140a0895ce8965769e7'
author Ka-Hing Cheung <khc@hxbc.us>
date Wed, 27 Feb 2008 04:36:23 +0000
parents c8192603b150 (diff) 7287cf8dbbca (current diff)
children 382bc33e8824
files
diffstat 28 files changed, 262 insertions(+), 69 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Feb 27 01:27:40 2008 +0000
+++ b/COPYRIGHT	Wed Feb 27 04:36:23 2008 +0000
@@ -154,6 +154,7 @@
 Konrad Gräfe
 Miah Gregory
 David Grohmann
+Gideon N. Guillen
 Christian Hammond
 Erick Hamness
 Fred Hampton
--- a/ChangeLog	Wed Feb 27 01:27:40 2008 +0000
+++ b/ChangeLog	Wed Feb 27 04:36:23 2008 +0000
@@ -1,6 +1,6 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-version 2.4.0 (??/??/????):
+version 2.4.0 (??/??/2008):
 	libpurple:
 	* Fixed various problems with loss of status messages when going
 	  or returning from idle on MySpaceIM.
@@ -10,12 +10,20 @@
 	* Partial support for viewing ICQ status notes (Collin from
 	  ComBOTS GmbH).
 	* Support for /notice on IRC.
-	* Support for Yahoo Messenger 7.0+ file transfer method (Thanumalayan S.)
+	* Support for Yahoo! Messenger 7.0+ file transfer method (Thanumalayan S.)
 	* Support for retrieving full names and addresses from the address book
 	  on Yahoo! Japan (Yusuke Odate)
 	* The AIM/ICQ server-side preference for "allow others to see me
 	  as idle" is no longer unconditionally set to "yes" even when
 	  your libpurple preference is "no."
+	* Fix SSL certificate checks for renewed certificates
+	* Fix the ability to set vCard buddy icons on Google Talk/XMPP
+	* D-Bus fixes on 64bit
+	* Fixed retrieval of buddy icons and setting of server-side aliases on
+	  Yahoo! and Yahoo! Japan when using an HTTP proxy server (Gideon N.
+	  Guillen)
+	* Fixed an MSN bug that would leave you appearing offline when transferred
+	  to different server
 
 	Pidgin:
 	* Added the ability to theme conversation name colors (red and blue)
@@ -25,6 +33,7 @@
 	  de Andrade)
 	* Save the conversation "Enable Logging" option per-contact (Moos
 	  Heintzen)
+	* Typing notifications are now shown in the conversation area
 
 	Finch:
 	* Color is used in the buddylist to indicate status, and the conversation
@@ -44,6 +53,7 @@
 	* Added a log viewer
 	* Added the ability to block/unblock buddies - see the buddy context menu
 	  and the menu for the buddy list.
+	* Fixed a bug preventing finch working on x86_64
 
 version 2.3.1 (12/7/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.3.1
--- a/ChangeLog.API	Wed Feb 27 01:27:40 2008 +0000
+++ b/ChangeLog.API	Wed Feb 27 04:36:23 2008 +0000
@@ -9,6 +9,7 @@
 		  purple_micro_version variables are exported by version.h,
 		  giving the version of libpurple in use at runtime.
 		* purple_util_set_current_song, purple_util_format_song_info
+		* purple_ip_address_is_valid
 		* Some accessor functions to the Roomlist API:
 			* purple_roomlist_get_fields
 			* purple_roomlist_room_get_type
@@ -43,6 +44,8 @@
 			* purple_connection_get_prpl
 			* purple_xfer_get_start_time
 			* purple_xfer_get_end_time
+		* purple_serv_got_private_alias for prpls to call after receiving a
+		  private alias from the server.
 
 	Pidgin:
 		Added:
--- a/libpurple/account.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/account.c	Wed Feb 27 04:36:23 2008 +0000
@@ -2368,8 +2368,13 @@
 set_current_error(PurpleAccount *account,
                   PurpleConnectionErrorInfo *new_err)
 {
-	PurpleAccountPrivate *priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
-	PurpleConnectionErrorInfo *old_err = priv->current_error;
+	PurpleAccountPrivate *priv;
+	PurpleConnectionErrorInfo *old_err;
+
+	g_return_if_fail(account != NULL);
+
+	priv = PURPLE_ACCOUNT_GET_PRIVATE(account);
+	old_err = priv->current_error;
 
 	if(new_err == old_err)
 		return;
@@ -2393,8 +2398,14 @@
                     const gchar *description,
                     gpointer unused)
 {
-	PurpleAccount *account = purple_connection_get_account(gc);
-	PurpleConnectionErrorInfo *err = g_new0(PurpleConnectionErrorInfo, 1);
+	PurpleAccount *account;
+	PurpleConnectionErrorInfo *err;
+
+	account = purple_connection_get_account(gc);
+
+	g_return_if_fail(account != NULL);
+
+	err = g_new0(PurpleConnectionErrorInfo, 1);
 
 	err->type = type;
 	err->description = g_strdup(description);
--- a/libpurple/blist.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/blist.c	Wed Feb 27 04:36:23 2008 +0000
@@ -1588,7 +1588,7 @@
 					hb->group = gnode;
 					g_hash_table_replace(purplebuddylist->buddies, hb, b);
 
-					if (b->account->gc)
+					if (purple_account_get_connection(b->account))
 						serv_move_buddy(b, (PurpleGroup *)cnode->parent, g);
 				} else {
 					gboolean empty_contact = FALSE;
@@ -1597,7 +1597,7 @@
 					 * gonna delete it instead */
 					g_free(hb->name);
 					g_free(hb);
-					if (b->account->gc)
+					if (purple_account_get_connection(b->account))
 						purple_account_remove_buddy(b->account, b, (PurpleGroup *)cnode->parent);
 
 					if (!cnode->child->next)
@@ -2087,7 +2087,7 @@
 	prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
 	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-	parts = prpl_info->chat_info(chat->account->gc);
+	parts = prpl_info->chat_info(purple_account_get_connection(chat->account));
 	pce = parts->data;
 	ret = g_hash_table_lookup(chat->components, pce->identifier);
 	g_list_foreach(parts, (GFunc)g_free, NULL);
--- a/libpurple/conversation.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/conversation.c	Wed Feb 27 04:36:23 2008 +0000
@@ -209,11 +209,14 @@
 		const char *message, PurpleMessageFlags flags, time_t when)
 {
 	PurpleConvMessage *msg;
+	PurpleConnection *gc;
+
+	gc = purple_account_get_connection(conv->account);
 
 	if (flags & PURPLE_MESSAGE_SEND) {
 		const char *me = NULL;
-		if (conv->account->gc)
-			me = conv->account->gc->display_name;
+		if (gc)
+			me = purple_connection_get_display_name(gc);
 		if (!me)
 			me = conv->account->username;
 		who = me;
--- a/libpurple/protocols/irc/msgs.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/irc/msgs.c	Wed Feb 27 04:36:23 2008 +0000
@@ -495,6 +495,8 @@
 					cur++;
 				} else if(irc->mode_chars
 					  && strchr(irc->mode_chars, *cur)) {
+					if (*cur == '~')
+						f = PURPLE_CBFLAGS_FOUNDER;
 					cur++;
 				}
 				tmp = g_strndup(cur, end - cur);
@@ -854,6 +856,9 @@
 					newflag = PURPLE_CBFLAGS_HALFOP;
 				else if (*mcur == 'v')
 					newflag = PURPLE_CBFLAGS_VOICE;
+				else if(irc->mode_chars
+					  && strchr(irc->mode_chars, '~') && (*mcur == 'q'))
+					newflag = PURPLE_CBFLAGS_FOUNDER;
 				if (newflag) {
 					if (add)
 						flags |= newflag;
--- a/libpurple/protocols/jabber/jabber.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Wed Feb 27 04:36:23 2008 +0000
@@ -564,9 +564,16 @@
 			jabber_login_callback_ssl, jabber_ssl_connect_failure, js->certificate_CN, js->gc);
 }
 
-static void jabber_login_connect(JabberStream *js, const char *fqdn, const char *host, int port)
+static void jabber_login_connect(JabberStream *js, const char *domain, const char *host, int port)
 {
-	js->serverFQDN = g_strdup(fqdn);
+	/* host should be used in preference to domain to
+	 * allow SASL authentication to work with FQDN of the server,
+	 * but we use domain as fallback for when users enter IP address
+	 * in connect server */
+	if (purple_ip_address_is_valid(host))
+		js->serverFQDN = g_strdup(domain);
+	else
+		js->serverFQDN = g_strdup(host);
 
 	if (purple_proxy_connect(js->gc, js->gc->account, host,
 			port, jabber_login_callback, js->gc) == NULL)
--- a/libpurple/protocols/myspace/message.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/myspace/message.c	Wed Feb 27 04:36:23 2008 +0000
@@ -429,6 +429,7 @@
  * @param user_data Not used; required to match g_list_foreach() callback prototype.
  *
  * Frees both the element data and the element itself.
+ * Also frees the name if dynamic_name is TRUE.
  */
 static void 
 msim_msg_free_element(gpointer data, gpointer user_data)
@@ -439,6 +440,12 @@
 
 	msim_msg_free_element_data(elem);
 
+	if (elem->dynamic_name)
+		/* Need to cast to remove const-ness, because
+		 * elem->name is almost always a constant, static
+		 * string, but not in this case. */
+		g_free((gchar *)elem->name);
+
 	g_free(elem);
 }
 
@@ -512,15 +519,18 @@
 /** Create a new MsimMessageElement * - must be g_free()'d. 
  *
  * For internal use; users probably want msim_msg_append() or msim_msg_insert_before(). 
+ *
+ * @param dynamic_name Whether 'name' should be freed when the message is destroyed.
  */
 static MsimMessageElement *
-msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data)
+msim_msg_element_new(const gchar *name, MsimMessageType type, gpointer data, gboolean dynamic_name)
 {
 	MsimMessageElement *elem;
 
 	elem = g_new0(MsimMessageElement, 1);
 
 	elem->name = name;
+	elem->dynamic_name = dynamic_name;
 	elem->type = type;
 	elem->data = data;
 
@@ -559,7 +569,18 @@
 msim_msg_append(MsimMessage *msg, const gchar *name, 
 		MsimMessageType type, gpointer data)
 {
-	return g_list_append(msg, msim_msg_element_new(name, type, data));
+	return g_list_append(msg, msim_msg_element_new(name, type, data, FALSE));
+}
+
+/** Append a new element, but with a dynamically-allocated name.
+ * Exactly the same as msim_msg_append(), except 'name' will be freed when
+ * the message is destroyed. Normally, it isn't, because a static string is given.
+ */
+static MsimMessage *
+msim_msg_append_dynamic_name(MsimMessage *msg, gchar *name,
+		MsimMessageType type, gpointer data)
+{
+	return g_list_append(msg, msim_msg_element_new(name, type, data, TRUE));
 }
 
 /** Insert a new element into a message, before the given element name.
@@ -576,7 +597,7 @@
 	MsimMessageElement *new_elem;
 	GList *node_before;
 
-	new_elem = msim_msg_element_new(name, type, data);
+	new_elem = msim_msg_element_new(name, type, data, FALSE);
 
 	node_before = msim_msg_get_node(msg, name_before);
 
@@ -1196,8 +1217,9 @@
 		purple_debug_info("msim_msg_parse_dictionary","-- %s: %s\n", key ? key : "(NULL)", 
 				value ? value : "(NULL)");
 #endif
-		/* TODO: free key; right now it is treated as static */
-		dict = msim_msg_append(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
+		/* Append with _dynamic_name since g_strdup(key) is dynamic, and
+		 * needs to be freed when the message is destroyed. It isn't static as usual. */
+		dict = msim_msg_append_dynamic_name(dict, g_strdup(key), MSIM_TYPE_RAW, g_strdup(value));
 
 		g_strfreev(elements);
 	}
--- a/libpurple/protocols/myspace/message.h	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/myspace/message.h	Wed Feb 27 04:36:23 2008 +0000
@@ -29,6 +29,7 @@
 typedef struct _MsimMessageElement
 {
 	const gchar *name;              /**< Textual name of element. */
+	gboolean dynamic_name;          /**< TRUE if 'name' is a dynamic string to be freed, not static. */
 	guint type;                     /**< MSIM_TYPE_* code. */
 	gpointer data;                  /**< Pointer to data, or GUINT_TO_POINTER for int/bool. */
 } MsimMessageElement;
--- a/libpurple/protocols/silc/util.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/silc/util.c	Wed Feb 27 04:36:23 2008 +0000
@@ -442,6 +442,7 @@
 		strcat(buf, "[rejects watching] ");
 	if (mode & SILC_UMODE_BLOCK_INVITE)
 		strcat(buf, "[blocks invites] ");
+	g_strchomp(buf);
 }
 
 void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
@@ -470,6 +471,7 @@
 		strcat(buf, "[users silenced] ");
 	if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
 		strcat(buf, "[operators silenced] ");
+	g_strchomp(buf);
 }
 
 void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
@@ -488,6 +490,7 @@
 		strcat(buf, "[blocks robot messages] ");
 	if (mode & SILC_CHANNEL_UMODE_QUIET)
 		strcat(buf, "[quieted] ");
+	g_strchomp(buf);
 }
 
 void
@@ -544,6 +547,7 @@
 	if (strlen(s->str)) {
 		*moodstr = s->str;
 		g_string_free(s, FALSE);
+		g_strchomp(*moodstr);
 	} else
 		g_string_free(s, TRUE);
 
@@ -573,6 +577,7 @@
 	if (strlen(s->str)) {
 		*contactstr = s->str;
 		g_string_free(s, FALSE);
+		g_strchomp(*contactstr);
 	} else
 		g_string_free(s, TRUE);
 
--- a/libpurple/protocols/silc10/util.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/silc10/util.c	Wed Feb 27 04:36:23 2008 +0000
@@ -432,6 +432,7 @@
 		strcat(buf, "[rejects watching] ");
 	if (mode & SILC_UMODE_BLOCK_INVITE)
 		strcat(buf, "[blocks invites] ");
+	g_strchomp(buf);
 }
 
 void silcpurple_get_chmode_string(SilcUInt32 mode, char *buf,
@@ -460,6 +461,7 @@
 		strcat(buf, "[users silenced] ");
 	if (mode & SILC_CHANNEL_MODE_SILENCE_OPERS)
 		strcat(buf, "[operators silenced] ");
+	g_strchomp(buf);
 }
 
 void silcpurple_get_chumode_string(SilcUInt32 mode, char *buf,
@@ -478,6 +480,7 @@
 		strcat(buf, "[blocks robot messages] ");
 	if (mode & SILC_CHANNEL_UMODE_QUIET)
 		strcat(buf, "[quieted] ");
+	g_strchomp(buf);
 }
 
 void
@@ -534,6 +537,7 @@
 	if (strlen(s->str)) {
 		*moodstr = s->str;
 		g_string_free(s, FALSE);
+		g_strchomp(*moodstr);
 	} else
 		g_string_free(s, TRUE);
 
@@ -563,6 +567,7 @@
 	if (strlen(s->str)) {
 		*contactstr = s->str;
 		g_string_free(s, FALSE);
+		g_strchomp(*contactstr);
 	} else
 		g_string_free(s, TRUE);
 
--- a/libpurple/protocols/yahoo/yahoo.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Wed Feb 27 04:36:23 2008 +0000
@@ -3509,8 +3509,13 @@
 		"Host: login.yahoo.com\r\n"
 		"Content-Length: 0\r\n\r\n",
 		yd->cookie_t, yd->cookie_y);
-
-	url_data = purple_util_fetch_url_request(base_url, FALSE,
+	gboolean use_whole_url = FALSE;
+
+	/* use whole URL if using HTTP Proxy */
+	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+	    use_whole_url = TRUE;
+
+	url_data = purple_util_fetch_url_request(base_url, use_whole_url,
 			"Mozilla/4.0 (compatible; MSIE 5.5)", TRUE, request, FALSE,
 			yahoo_get_inbox_token_cb, gc);
 
--- a/libpurple/protocols/yahoo/yahoo_aliases.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_aliases.c	Wed Feb 27 04:36:23 2008 +0000
@@ -148,6 +148,12 @@
 	char *request, *webpage, *webaddress;
 	PurpleUtilFetchUrlData *url_data;
 
+	gboolean use_whole_url = FALSE;
+
+	/* use whole URL if using HTTP Proxy */
+	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+	    use_whole_url = TRUE;
+
 	/* Using callback_data so I have access to gc in the callback function */
 	cb = g_new0(struct callback_data, 1);
 	cb->gc = gc;
@@ -155,15 +161,15 @@
 	/*  Build all the info to make the web request */
 	url = yd->jp ? YAHOOJP_ALIAS_FETCH_URL : YAHOO_ALIAS_FETCH_URL;
 	purple_url_parse(url, &webaddress, NULL, &webpage, NULL, NULL);
-	request = g_strdup_printf("GET /%s HTTP/1.1\r\n"
+	request = g_strdup_printf("GET %s%s/%s HTTP/1.1\r\n"
 				 "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n"
 				 "Cookie: T=%s; Y=%s\r\n"
 				 "Host: %s\r\n"
 				 "Cache-Control: no-cache\r\n\r\n",
-				 webpage, yd->cookie_t,yd->cookie_y, webaddress);
+				  use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage, yd->cookie_t,yd->cookie_y, webaddress);
 
 	/* We have a URL and some header information, let's connect and get some aliases  */
-	url_data = purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_fetch_aliases_cb, cb);
+	url_data = purple_util_fetch_url_request(url, use_whole_url, NULL, TRUE, request, FALSE, yahoo_fetch_aliases_cb, cb);
 	if (url_data != NULL) {
 		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 	}
@@ -232,6 +238,11 @@
 	struct callback_data *cb;
 	PurpleBuddy *buddy;
 	PurpleUtilFetchUrlData *url_data;
+	gboolean use_whole_url = FALSE;
+
+	/* use whole URL if using HTTP Proxy */
+	if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+	    use_whole_url = TRUE;
 
 	g_return_if_fail(alias != NULL);
 	g_return_if_fail(who != NULL);
@@ -274,18 +285,18 @@
 		g_free(escaped_alias);
 	}
 
-	request = g_strdup_printf("POST /%s HTTP/1.1\r\n"
+	request = g_strdup_printf("POST %s%s/%s HTTP/1.1\r\n"
 				  "User-Agent: Mozilla/4.0 (compatible; MSIE 5.5)\r\n"
 				  "Cookie: T=%s; Y=%s\r\n"
 				  "Host: %s\r\n"
 				  "Content-Length: %" G_GSIZE_FORMAT "\r\n"
 				  "Cache-Control: no-cache\r\n\r\n"
 				  "%s",
-				  webpage, yd->cookie_t,yd->cookie_y, webaddress,
+				  use_whole_url ? "http://" : "", use_whole_url ? webaddress : "", webpage, yd->cookie_t,yd->cookie_y, webaddress,
 			 	  strlen(content), content);
 
 	/* We have a URL and some header information, let's connect and update the alias  */
-	url_data = purple_util_fetch_url_request(url, FALSE, NULL, TRUE, request, FALSE, yahoo_update_alias_cb, cb);
+	url_data = purple_util_fetch_url_request(url, use_whole_url, NULL, TRUE, request, FALSE, yahoo_update_alias_cb, cb);
 	if (url_data != NULL) {
 		yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
 	}
--- a/libpurple/protocols/yahoo/yahoo_picture.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_picture.c	Wed Feb 27 04:36:23 2008 +0000
@@ -116,6 +116,11 @@
 		struct yahoo_fetch_picture_data *data;
 		PurpleBuddy *b = purple_find_buddy(gc->account, who);
 		const char *locksum = NULL;
+		gboolean use_whole_url = FALSE;
+
+		/* use whole URL if using HTTP Proxy */
+		if ((gc->account->proxy_info) && (gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+		    use_whole_url = TRUE;
 
 		/* FIXME: Cleanup this strtol() stuff if possible. */
 		if (b && (locksum = purple_buddy_icons_get_checksum_for_user(b)) != NULL && 
@@ -126,7 +131,7 @@
 		data->gc = gc;
 		data->who = g_strdup(who);
 		data->checksum = checksum;
-		url_data = purple_util_fetch_url(url, FALSE,
+		url_data = purple_util_fetch_url(url, use_whole_url,
 				"Mozilla/4.0 (compatible; MSIE 5.0)", FALSE,
 				yahoo_fetch_picture_cb, data);
 		if (url_data != NULL) {
--- a/libpurple/protocols/yahoo/yahoo_profile.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/protocols/yahoo/yahoo_profile.c	Wed Feb 27 04:36:23 2008 +0000
@@ -932,11 +932,17 @@
 	/* Try to put the photo in there too, if there's one */
 	if (photo_url_text) {
 		PurpleUtilFetchUrlData *url_data;
+		gboolean use_whole_url = FALSE;
+
+		/* use whole URL if using HTTP Proxy */
+		if ((info_data->gc->account->proxy_info) && (info_data->gc->account->proxy_info->type == PURPLE_PROXY_HTTP))
+		    use_whole_url = TRUE;
+
 		/* User-uploaded photos use a different server that requires the Host
 		 * header, but Yahoo Japan will use the "chunked" content encoding if
 		 * we specify HTTP 1.1. So we have to specify 1.0 & fix purple_util_fetch_url
 		 */
-		url_data = purple_util_fetch_url(photo_url_text, FALSE, NULL,
+		url_data = purple_util_fetch_url(photo_url_text, use_whole_url, NULL,
 				FALSE, yahoo_got_photo, info2_data);
 		if (url_data != NULL)
 			yd->url_datas = g_slist_prepend(yd->url_datas, url_data);
--- a/libpurple/proxy.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/proxy.c	Wed Feb 27 04:36:23 2008 +0000
@@ -737,6 +737,7 @@
 				proxy_do_write(connect_data, connect_data->fd, cond);
 				return;
 			} else if((ntlm = g_strrstr((const char *)connect_data->read_buffer, "Proxy-Authenticate: NTLM"))) { /* Empty message */
+				gchar *ntlm_type1;
 				gchar request[2048];
 				gchar *domain = (gchar*) purple_proxy_info_get_username(connect_data->gpi);
 				gchar *username = NULL;
@@ -759,11 +760,13 @@
 						connect_data->host, connect_data->port);
 
 				g_return_if_fail(request_len < sizeof(request));
+				ntlm_type1 = purple_ntlm_gen_type1(hostname, domain);
 				request_len += g_snprintf(request + request_len,
 					sizeof(request) - request_len,
 					"Proxy-Authorization: NTLM %s\r\n"
 					"Proxy-Connection: Keep-Alive\r\n\r\n",
-					purple_ntlm_gen_type1(hostname, domain));
+					ntlm_type1);
+				g_free(ntlm_type1);
 				*username = '\\';
 
 				purple_input_remove(connect_data->inpa);
@@ -847,7 +850,7 @@
 
 	if (purple_proxy_info_get_username(connect_data->gpi) != NULL)
 	{
-		char *t1, *t2;
+		char *t1, *t2, *ntlm_type1;
 		char hostname[256];
 
 		ret = gethostname(hostname, sizeof(hostname));
@@ -864,11 +867,14 @@
 		t2 = purple_base64_encode((const guchar *)t1, strlen(t1));
 		g_free(t1);
 
+		ntlm_type1 = purple_ntlm_gen_type1(hostname, "");
+
 		g_string_append_printf(request,
 			"Proxy-Authorization: Basic %s\r\n"
 			"Proxy-Authorization: NTLM %s\r\n"
 			"Proxy-Connection: Keep-Alive\r\n",
-			t2, purple_ntlm_gen_type1(hostname, ""));
+			t2, ntlm_type1);
+		g_free(ntlm_type1);
 		g_free(t2);
 	}
 
--- a/libpurple/server.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/server.c	Wed Feb 27 04:36:23 2008 +0000
@@ -274,6 +274,29 @@
 	}
 }
 
+void
+purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const char *alias)
+{
+	PurpleAccount *account = NULL;
+	GSList *buddies = NULL;
+	PurpleBuddy *b = NULL;
+
+	account = purple_connection_get_account(gc);
+	buddies = purple_find_buddies(account, who);
+
+	while(buddies != NULL) {
+		b = buddies->data;
+
+		buddies = g_slist_delete_link(buddies, buddies);
+
+		if((!b->alias && !alias) || (b->alias && alias && !strcmp(b->alias, alias)))
+			continue;
+
+		purple_blist_alias_buddy(b, alias);
+	}
+}
+
+
 PurpleAttentionType *purple_get_attention_type_from_code(PurpleAccount *account, guint type_code)
 {
 	PurplePlugin *prpl;
--- a/libpurple/server.h	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/server.h	Wed Feb 27 04:36:23 2008 +0000
@@ -98,6 +98,17 @@
 void serv_alias_buddy(PurpleBuddy *);
 void serv_got_alias(PurpleConnection *gc, const char *who, const char *alias);
 
+/**
+ * A protocol plugin should call this when it retrieves a private alias from
+ * the server.  Private aliases are the aliases the user sets, while public
+ * aliases are the aliases or display names that buddies set for themselves.
+ *
+ * @param gc The connection on which the alias was received.
+ * @param who The screen name of the buddy whose alias was received.
+ * @param alias The alias that was received.
+ */
+void purple_serv_got_private_alias(PurpleConnection *gc, const char *who, const char *alias);
+
 
 /**
  * Receive a typing message from a remote user.  Either PURPLE_TYPING
--- a/libpurple/util.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/util.c	Wed Feb 27 04:36:23 2008 +0000
@@ -4129,6 +4129,17 @@
 	return ((c - domain) > 3 ? TRUE : FALSE);
 }
 
+gboolean
+purple_ip_address_is_valid(const char *ip)
+{
+	int c, o1, o2, o3, o4;
+	char end;
+	c = sscanf(ip, "%d.%d.%d.%d%c", &o1, &o2, &o3, &o4, &end);
+	if (c > 4 || o1 < 0 || o1 > 255 || o2 < 0 || o2 > 255 || o3 < 0 || o3 > 255 || o4 < 0 || o4 > 255)
+		return FALSE;
+	return TRUE;
+}
+
 /* Stolen from gnome_uri_list_extract_uris */
 GList *
 purple_uri_list_extract_uris(const gchar *uri_list)
--- a/libpurple/util.h	Wed Feb 27 01:27:40 2008 +0000
+++ b/libpurple/util.h	Wed Feb 27 04:36:23 2008 +0000
@@ -1081,6 +1081,15 @@
 gboolean purple_email_is_valid(const char *address);
 
 /**
+ * Checks if the given IP address is a syntactically valid IPv4 address.
+ *
+ * @param address The IP address to validate.
+ *
+ * @return True if the IP address is syntactically correct.
+ */
+gboolean purple_ip_address_is_valid(const char *ip);
+
+/**
  * This function extracts a list of URIs from the a "text/uri-list"
  * string.  It was "borrowed" from gnome_uri_list_extract_uris
  *
--- a/pidgin/gtkaccount.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/gtkaccount.c	Wed Feb 27 04:36:23 2008 +0000
@@ -2092,8 +2092,10 @@
 	/* Figure out which node was clicked */
 	if (!gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(dialog->treeview), event->x, event->y, &path, &column, NULL, NULL))
 		return FALSE;
-	if (column == gtk_tree_view_get_column(treeview, 0))
+	if (column == gtk_tree_view_get_column(treeview, 0)) {
+		gtk_tree_path_free(path);
 		return FALSE;
+	}
 
 	gtk_tree_model_get_iter(GTK_TREE_MODEL(dialog->model), &iter, path);
 	gtk_tree_path_free(path);
--- a/pidgin/gtkblist.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/gtkblist.c	Wed Feb 27 04:36:23 2008 +0000
@@ -2953,6 +2953,9 @@
 	gtk_tree_view_get_path_at_pos(GTK_TREE_VIEW(tv), x, y, &path, NULL, NULL, NULL);
 	gtk_tree_view_get_cell_area(GTK_TREE_VIEW(tv), path, NULL, &rect);
 
+	if (path)
+		gtk_tree_path_free(path);
+
 	/* Only autoexpand when in the middle of the cell to avoid annoying un-intended expands */
 	if (y < rect.y + (rect.height / 3) ||
 	    y > rect.y + (2 * (rect.height /3)))
@@ -2963,8 +2966,6 @@
 
 	gtkblist->tip_rect = rect;
 
-	if (path)
-		gtk_tree_path_free(path);
 	gtkblist->drag_timeout = g_timeout_add(delay, (GSourceFunc)pidgin_blist_expand_timeout, tv);
 
 	if (gtkblist->mouseover_contact) {
--- a/pidgin/gtkconv.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/gtkconv.c	Wed Feb 27 04:36:23 2008 +0000
@@ -2806,16 +2806,11 @@
 void
 pidgin_conv_present_conversation(PurpleConversation *conv)
 {
-	PidginConversation *gtkconv = PIDGIN_CONVERSATION(conv);
+	PidginConversation *gtkconv;
 	GdkModifierType state;
 
-	if (gtkconv == NULL) {
-		pidgin_conv_attach_to_conversation(conv);
-		gtkconv = PIDGIN_CONVERSATION(conv);
-	} else if (gtkconv->win == hidden_convwin) {
-		pidgin_conv_window_remove_gtkconv(hidden_convwin, gtkconv);
-		pidgin_conv_placement_place(gtkconv);
-	}
+	pidgin_conv_attach_to_conversation(conv);
+	gtkconv = PIDGIN_CONVERSATION(conv);
 
 	pidgin_conv_switch_active_conversation(conv);
 	/* Switch the tab only if the user initiated the event by pressing
--- a/pidgin/gtkdialogs.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/gtkdialogs.c	Wed Feb 27 04:36:23 2008 +0000
@@ -97,6 +97,7 @@
 
 /* Order: Alphabetical by Last Name */
 static const struct developer patch_writers[] = {
+	{"Felipe 'shx' Contreras",		NULL,	NULL},
 	{"Dennis 'EvilDennisR' Ristuccia",	N_("Senior Contributor/QA"),	NULL},
 	{"Peter 'Fmoo' Ruibal",		NULL,	NULL},
 	{"Elliott 'QuLogic' Sales de Andrade",	NULL,	NULL},
@@ -121,7 +122,6 @@
 
 /* Order: Alphabetical by Last Name */
 static const struct developer retired_patch_writers[] = {
-	{"Felipe 'shx' Contreras",		NULL,	NULL},
 	{"Decklin Foster",				NULL,	NULL},
 	{"Peter 'Bleeter' Lawler",      NULL,   NULL},
 	{"Robert 'Robot101' McQueen",	NULL,	NULL},
--- a/pidgin/gtklog.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/gtklog.c	Wed Feb 27 04:36:23 2008 +0000
@@ -263,11 +263,10 @@
 				gtk_tree_store_remove(treestore, iter);
 			}
 		}
-		gtk_tree_path_free(path);
 #else
 		gtk_tree_store_remove(treestore, iter);
+#endif
 		gtk_tree_path_free(path);
-#endif
 	}
 
 	delete_log_cleanup_cb(data);
@@ -363,6 +362,7 @@
 		gtk_tree_model_get_iter(GTK_TREE_MODEL(lv->treestore), iter, path);
 		val.g_type = 0;
 		gtk_tree_model_get_value(GTK_TREE_MODEL(lv->treestore), iter, 1, &val);
+		gtk_tree_path_free(path);
 
 		log = g_value_get_pointer(&val);
 
--- a/pidgin/minidialog.c	Wed Feb 27 01:27:40 2008 +0000
+++ b/pidgin/minidialog.c	Wed Feb 27 04:36:23 2008 +0000
@@ -164,7 +164,8 @@
 	priv->idle_destroy_cb_id =
 		g_idle_add((GSourceFunc) idle_destroy_cb, data->mini_dialog);
 
-	data->callback(data->mini_dialog, button, data->user_data);
+	if (data->callback != NULL)
+		data->callback(data->mini_dialog, button, data->user_data);
 
 }
 
--- a/po/de.po	Wed Feb 27 01:27:40 2008 +0000
+++ b/po/de.po	Wed Feb 27 04:36:23 2008 +0000
@@ -11,8 +11,8 @@
 msgstr ""
 "Project-Id-Version: de\n"
 "Report-Msgid-Bugs-To: \n"
-"POT-Creation-Date: 2008-02-08 16:08+0100\n"
-"PO-Revision-Date: 2008-02-08 16:08+0100\n"
+"POT-Creation-Date: 2008-02-24 19:28+0100\n"
+"PO-Revision-Date: 2008-02-24 19:28+0100\n"
 "Last-Translator: Jochen Kemnade <jochenkemnade@web.de>\n"
 "Language-Team: Deutsch <de@li.org>\n"
 "MIME-Version: 1.0\n"
@@ -196,11 +196,11 @@
 msgid "Screen Name"
 msgstr "Benutzername"
 
-msgid "Alias"
-msgstr "Alias"
-
-msgid "Group"
-msgstr "Gruppe"
+msgid "Alias (optional)"
+msgstr "Alias (optional)"
+
+msgid "Add in group"
+msgstr "Zu Gruppe hinzufügen"
 
 msgid "Account"
 msgstr "Konto"
@@ -218,6 +218,12 @@
 msgid "Name"
 msgstr "Name"
 
+msgid "Alias"
+msgstr "Alias"
+
+msgid "Group"
+msgstr "Gruppe"
+
 msgid "Auto-join"
 msgstr "Automatisch beitreten"
 
@@ -758,13 +764,13 @@
 msgid "Transferring"
 msgstr "Übertragung"
 
-#, fuzzy, c-format
+#, c-format
 msgid "Conversation in %s on %s"
-msgstr "Unterhaltung in %s"
-
-#, fuzzy, c-format
+msgstr "Unterhaltung in %s am %s"
+
+#, c-format
 msgid "Conversation with %s on %s"
-msgstr "Unterhaltung mit %s"
+msgstr "Unterhaltung mit %s am %s"
 
 msgid "%B %Y"
 msgstr "%B %Y"
@@ -5346,23 +5352,22 @@
 msgid "MySpace"
 msgstr "MySpace"
 
+msgid "MySpaceIM - No Username Set"
+msgstr "MySpaceIM - Kein Benutzername gesetzt"
+
+msgid "You appear to have no MySpace username."
+msgstr "Sie scheinen keinen MySpace-Benutzernamen zu haben."
+
+msgid "Would you like to set one now? (Note: THIS CANNOT BE CHANGED!)"
+msgstr ""
+"Möchten Sie jetzt einen setzen? (Bemerkung: DIES KANN NICHT GEÄNDERT WERDEN!)"
+
 #. The session is now set up, ready to be connected. This emits the
 #. * signedOn signal, so clients can now do anything with msimprpl, and
 #. * we're ready for it (session key, userid, username all setup).
 msgid "Connected"
 msgstr "Verbunden"
 
-msgid "No username set"
-msgstr "Kein Benutzername gesetzt"
-
-msgid ""
-"Please go to http://editprofile.myspace.com/index.cfm?fuseaction=profile."
-"username and choose a username and try to login again."
-msgstr ""
-"Bitte besuchen Sie http://editprofile.myspace.com/index.cfm?"
-"fuseaction=profile.username und wählen sie einen Benutzernamen und versuchen "
-"Sie sich erneut anzumelden."
-
 #, c-format
 msgid "Protocol error, code %d: %s"
 msgstr "Protokollfehler, Code %d: %s"
@@ -5492,6 +5497,32 @@
 msgid "Client Version"
 msgstr "Client-Version"
 
+#. Protocol won't log in now without a username set.. Disconnect
+msgid "No username set"
+msgstr "Kein Benutzername gesetzt"
+
+msgid "MySpaceIM - Please Set a Username"
+msgstr "MySpaceIM - Bitte setzen Sie einen Benutzernamen"
+
+msgid "Please enter a username to check its availability:"
+msgstr ""
+"Bitte geben Sie einen Benutzernamen ein um seine Verfügbarkeit zu überprüfen:"
+
+msgid "MySpaceIM - Username Available"
+msgstr "MySpaceIM - Benutzername verfügbar"
+
+msgid "This username is available. Would you like to set it?"
+msgstr "Dieser Benutzername ist verfügbar. Möchten Sie ihn setzen?"
+
+msgid "ONCE SET, THIS CANNOT BE CHANGED!"
+msgstr "EINMAL GESETZT, KANN DIES NICHT GEÄNDERT WERDEN!"
+
+msgid "This username is unavailable."
+msgstr "Dieser Benutzername ist nicht verfügbar."
+
+msgid "Please try another username:"
+msgstr "Bitte versuchen Sie einen anderen Benutzernamen:"
+
 #. TODO: icons for each zap
 #. Lots of comments for translators:
 #. Zap means "to strike suddenly and forcefully as if with a
@@ -11838,6 +11869,9 @@
 msgid "Show _formatting on incoming messages"
 msgstr "Zeige _Formatierung bei ankommenden Nachrichten"
 
+msgid "Close IMs immediately when the tab is closed"
+msgstr "IMs automatisch schließen, wenn der Reiter geschlossen wird"
+
 msgid "Show _detailed information"
 msgstr "_Detaillierte Informationen anzeigen"