changeset 20001:94718bbf29d2

propagate from branch 'im.pidgin.cpw.rekkanoryo.examples' (head 55aed29a474f580bfb8b319bdcab36dc80024bd4) to branch 'im.pidgin.pidgin' (head c21ddc415f78c6438fefa0859dee72f99f578c3b)
author John Bailey <rekkanoryo@rekkanoryo.org>
date Fri, 14 Sep 2007 00:28:55 +0000
parents 4a38af2279c7 (current diff) ab38146f8f78 (diff)
children 6583988a57ae
files
diffstat 28 files changed, 393 insertions(+), 123 deletions(-) [+]
line wrap: on
line diff
--- a/COPYRIGHT	Wed Sep 12 17:22:33 2007 +0000
+++ b/COPYRIGHT	Fri Sep 14 00:28:55 2007 +0000
@@ -270,6 +270,7 @@
 Nathan Owens (pianocomp81)
 John Oyler
 Matt Pandina
+Laszlo Pandy
 Ricardo Fernandez Pascual
 Riley Patterson
 Havoc Pennington
--- a/ChangeLog	Wed Sep 12 17:22:33 2007 +0000
+++ b/ChangeLog	Fri Sep 14 00:28:55 2007 +0000
@@ -10,7 +10,8 @@
 	* Option to show protocol icons in the buddy list, from the
 	  Buddies > Show menu (Justin Heiner)
 	* Ability to build with native, non-X11 GTK+ on OSX (Anders
-   	  Hasselqvist)
+	  Hasselqvist)
+	* Remember the 'Enable Sounds' setting for a conversation
 
 	Finch:
 	* Per-conversation mute and logging options (accessible from the menu)
--- a/autogen.sh	Wed Sep 12 17:22:33 2007 +0000
+++ b/autogen.sh	Fri Sep 14 00:28:55 2007 +0000
@@ -58,7 +58,7 @@
 done
 
 libtoolize -c -f --automake
-glib-gettextize --force --copy
+glib-gettextize --force --copy --previous
 intltoolize --force --copy
 aclocal $ACLOCAL_FLAGS || exit;
 autoheader || exit;
--- a/finch/gntconv.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/finch/gntconv.c	Fri Sep 14 00:28:55 2007 +0000
@@ -63,6 +63,25 @@
 		const char *message, PurpleMessageFlags flags, time_t mtime);
 static void generate_send_to_menu(FinchConv *ggc);
 
+static PurpleBlistNode *
+get_conversation_blist_node(PurpleConversation *conv)
+{
+	PurpleBlistNode *node = NULL;
+
+	switch (purple_conversation_get_type(conv)) {
+		case PURPLE_CONV_TYPE_IM:
+			node = (PurpleBlistNode*)purple_find_buddy(conv->account, conv->name);
+			node = node ? node->parent : NULL;
+			break;
+		case PURPLE_CONV_TYPE_CHAT:
+			node = (PurpleBlistNode*)purple_blist_find_chat(conv->account, conv->name);
+			break;
+		default:
+			break;
+	}
+	return node;
+}
+
 static void
 send_typing_notification(GntWidget *w, FinchConv *ggconv)
 {
@@ -391,7 +410,10 @@
 toggle_sound_cb(GntMenuItem *item, gpointer ggconv)
 {
 	FinchConv *fc = ggconv;
+	PurpleBlistNode *node = get_conversation_blist_node(fc->active_conv);
 	fc->flags ^= FINCH_CONV_NO_SOUND;
+	if (node)
+		purple_blist_node_set_bool(node, "gnt-mute-sound", !!(fc->flags & FINCH_CONV_NO_SOUND));
 }
 
 static void
@@ -547,6 +569,7 @@
 	PurpleConversationType type;
 	PurpleConversation *cc;
 	PurpleAccount *account;
+	PurpleBlistNode *convnode = NULL;
 
 	if (ggc)
 		return;
@@ -653,7 +676,9 @@
 		g_signal_connect(G_OBJECT(ggc->entry), "text_changed", G_CALLBACK(send_typing_notification), ggc);
 	}
 
-	if (!finch_sound_is_enabled())
+	convnode = get_conversation_blist_node(conv);
+	if ((convnode && purple_blist_node_get_bool(convnode, "gnt-mute-sound")) ||
+			!finch_sound_is_enabled())
 		ggc->flags |= FINCH_CONV_NO_SOUND;
 
 	gg_create_menu(ggc);
--- a/libpurple/ntlm.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/ntlm.c	Fri Sep 14 00:28:55 2007 +0000
@@ -131,7 +131,7 @@
 	tmsg->protocol[6] = 'P';
 	tmsg->protocol[7] = '\0';
 	tmsg->type      = 0x00000001;
-	tmsg->flags     = 0x0000b202;
+	tmsg->flags     = 0x0000b203;
 	tmsg->dom_len1  = tmsg->dom_len2 = domainlen;
 	tmsg->dom_off   = sizeof(struct type1_message) + hostnamelen;
 	tmsg->host_len1 = tmsg->host_len2 = hostnamelen;
@@ -286,7 +286,7 @@
 		tmsg->sess_len1 = tmsg->sess_len2 = 0x0010;
 	}
 
-	tmsg->flags = 0x00008200;
+	tmsg->flags = 0x00008201;
 
 	tmp = (char *)tmsg + sizeof(struct type3_message);
 
--- a/libpurple/plugins/ssl/ssl-nss.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/plugins/ssl/ssl-nss.c	Fri Sep 14 00:28:55 2007 +0000
@@ -24,6 +24,7 @@
 #include "certificate.h"
 #include "plugin.h"
 #include "sslconn.h"
+#include "util.h"
 #include "version.h"
 
 #define SSL_NSS_PLUGIN_ID "ssl-nss"
@@ -34,6 +35,7 @@
 
 #include <nspr.h>
 #include <nss.h>
+#include <nssb64.h>
 #include <pk11func.h>
 #include <prio.h>
 #include <secerr.h>
@@ -454,11 +456,48 @@
  *
  * @return TRUE if success, otherwise FALSE
  */
+/* This function should not be so complicated, but NSS doesn't seem to have a
+   "convert yon certificate to PEM format" function. */
 static gboolean
 x509_export_certificate(const gchar *filename, PurpleCertificate *crt)
 {
-	/* TODO: WRITEME */
-	return FALSE;
+	CERTCertificate *crt_dat;
+	SECItem *dercrt;
+	gchar *b64crt;
+	gchar *pemcrt;
+	gboolean ret = FALSE;
+
+	g_return_val_if_fail(filename, FALSE);
+	g_return_val_if_fail(crt, FALSE);
+	g_return_val_if_fail(crt->scheme == &x509_nss, FALSE);
+
+	crt_dat = X509_NSS_DATA(crt);
+	g_return_val_if_fail(crt_dat, FALSE);
+
+	purple_debug_info("nss/x509",
+			  "Exporting certificate to %s\n", filename);
+	
+	/* First, use NSS voodoo to create a DER-formatted certificate */
+	dercrt = SEC_ASN1EncodeItem(NULL, NULL, crt_dat,
+				    SEC_ASN1_GET(SEC_SignedCertificateTemplate));
+	g_return_val_if_fail(dercrt != NULL, FALSE);
+
+	/* Now encode it to b64 */
+	b64crt = NSSBase64_EncodeItem(NULL, NULL, 0, dercrt);
+	SECITEM_FreeItem(dercrt, PR_TRUE);
+	g_return_val_if_fail(b64crt, FALSE);
+
+	/* Wrap it in nice PEM header things */
+	pemcrt = g_strdup_printf("-----BEGIN CERTIFICATE-----\n%s\n-----END CERTIFICATE-----\n", b64crt);
+	PORT_Free(b64crt); /* Notice that b64crt was allocated by an NSS
+			      function; hence, we'll let NSPR free it. */
+
+	/* Finally, dump the silly thing to a file. */
+	ret =  purple_util_write_data_to_file_absolute(filename, pemcrt, -1);
+
+	g_free(pemcrt);
+	
+	return ret;
 }
 
 static PurpleCertificate *
@@ -509,7 +548,6 @@
 	g_free(crt);
 }
 
-#if 0
 /** Determines whether one certificate has been issued and signed by another
  *
  * @param crt       Certificate to check the signature of
@@ -519,12 +557,11 @@
  * @TODO  Modify this function to return a reason for invalidity?
  */
 static gboolean
-x509_certificate_signed_by(PurpleCertificate * crt,
-			   PurpleCertificate * issuer)
+x509_signed_by(PurpleCertificate * crt,
+	       PurpleCertificate * issuer)
 {
-	return FALSE;
+	return TRUE;
 }
-#endif
 
 static GByteArray *
 x509_sha1sum(PurpleCertificate *crt)
@@ -564,6 +601,34 @@
 }
 
 static gchar *
+x509_dn (PurpleCertificate *crt)
+{
+	CERTCertificate *crt_dat;
+	
+	g_return_val_if_fail(crt, NULL);
+	g_return_val_if_fail(crt->scheme == &x509_nss, NULL);
+
+	crt_dat = X509_NSS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	return g_strdup(crt_dat->subjectName);
+}
+
+static gchar *
+x509_issuer_dn (PurpleCertificate *crt)
+{
+	CERTCertificate *crt_dat;
+	
+	g_return_val_if_fail(crt, NULL);
+	g_return_val_if_fail(crt->scheme == &x509_nss, NULL);
+
+	crt_dat = X509_NSS_DATA(crt);
+	g_return_val_if_fail(crt_dat, NULL);
+
+	return g_strdup(crt_dat->subjectName);
+}
+
+static gchar *
 x509_common_name (PurpleCertificate *crt)
 {
 	CERTCertificate *crt_dat;
@@ -642,11 +707,14 @@
 						&nss_activ, &nss_expir),
 		FALSE);
 
+	/* NSS's native PRTime type *almost* corresponds to time_t; however,
+	   it measures *microseconds* since the epoch, not seconds. Hence
+	   the funny conversion. */
 	if (activation) {
-		*activation = nss_activ;
+		*activation = nss_activ / 1000000;
 	}
 	if (expiration) {
-		*expiration = nss_expir;
+		*expiration = nss_expir / 1000000;
 	}
 	
 	return TRUE;
@@ -659,10 +727,10 @@
 	x509_export_certificate,         /* Certificate export function */
 	x509_copy_certificate,           /* Copy */
 	x509_destroy_certificate,        /* Destroy cert */
-	NULL,                            /* Signed-by */
+	x509_signed_by,                  /* Signed-by */
 	x509_sha1sum,                    /* SHA1 fingerprint */
-	NULL,                            /* Unique ID */
-	NULL,                            /* Issuer Unique ID */
+	x509_dn,                         /* Unique ID */
+	x509_issuer_dn,                  /* Issuer Unique ID */
 	x509_common_name,                /* Subject name */
 	x509_check_name,                 /* Check subject name */
 	x509_times,                      /* Activation/Expiration time */
--- a/libpurple/protocols/jabber/adhoccommands.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/adhoccommands.c	Fri Sep 14 00:28:55 2007 +0000
@@ -22,7 +22,6 @@
 #include "internal.h"
 
 #include "adhoccommands.h"
-#include <assert.h>
 #include <string.h>
 #include "internal.h"
 #include "xdata.h"
--- a/libpurple/protocols/jabber/auth.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/auth.c	Fri Sep 14 00:28:55 2007 +0000
@@ -538,6 +538,9 @@
 					(err_code = xmlnode_get_attrib(error, "code")) &&
 					!strcmp(err_code, "401")) {
 			js->gc->wants_to_die = TRUE;
+			/* Clear the pasword if it isn't being saved */
+			if (!purple_account_get_remember_password(js->gc->account))
+				purple_account_set_password(js->gc->account, NULL);
 		}
 
 		purple_connection_error(js->gc, msg);
--- a/libpurple/protocols/jabber/jabber.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Fri Sep 14 00:28:55 2007 +0000
@@ -57,8 +57,6 @@
 #include "pep.h"
 #include "adhoccommands.h"
 
-#include <assert.h>
-
 #define JABBER_CONNECT_STEPS (js->gsc ? 9 : 5)
 
 static PurplePlugin *my_protocol = NULL;
@@ -458,7 +456,7 @@
 	if(!PURPLE_CONNECTION_IS_VALID(gc)) {
 		purple_ssl_close(gsc);
 		return;
-	}	
+	}
 
 	js = gc->proto_data;
 
@@ -1134,17 +1132,17 @@
 static void jabber_unregister_account_cb(JabberStream *js) {
 	JabberIq *iq;
 	xmlnode *query;
-	assert(js->unregistration);
-	
-	iq = jabber_iq_new_query(js,JABBER_IQ_SET,"jabber:iq:register");
-	assert(iq);
-	query = xmlnode_get_child_with_namespace(iq->node,"query","jabber:iq:register");
-	assert(query);
-	xmlnode_new_child(query,"remove");
-	
-	xmlnode_set_attrib(iq->node,"to",js->user->domain);
-	jabber_iq_set_callback(iq,jabber_unregister_account_iq_cb,NULL);
-	
+
+	g_return_if_fail(js->unregistration);
+
+	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:register");
+
+	query = xmlnode_get_child_with_namespace(iq->node, "query", "jabber:iq:register");
+
+	xmlnode_new_child(query, "remove");
+	xmlnode_set_attrib(iq->node, "to", js->user->domain);
+
+	jabber_iq_set_callback(iq, jabber_unregister_account_iq_cb, NULL);
 	jabber_iq_send(iq);
 }
 
@@ -1163,11 +1161,16 @@
 	}
 	
 	js = gc->proto_data;
-	assert(!js->unregistration); /* don't allow multiple calls */
+
+	if (js->unregistration) {
+		purple_debug_error("jabber", "Unregistration in process; ignoring duplicate request.\n");
+		return;
+	}
+
 	js->unregistration = TRUE;
 	js->unregistration_cb = cb;
 	js->unregistration_user_data = user_data;
-	
+
 	jabber_unregister_account_cb(js);
 }
 
@@ -1325,10 +1328,10 @@
 
 void jabber_add_feature(const char *shortname, const char *namespace, JabberFeatureEnabled cb) {
 	JabberFeature *feat;
-	
-	assert(shortname != NULL);
-	assert(namespace != NULL);
-	
+
+	g_return_if_fail(shortname != NULL);
+	g_return_if_fail(namespace != NULL);
+
 	feat = g_new0(JabberFeature,1);
 	feat->shortname = g_strdup(shortname);
 	feat->namespace = g_strdup(namespace);
@@ -1731,7 +1734,7 @@
 			_("Change XMPP Password"), _("Please enter your new password"),
 			fields, _("OK"), G_CALLBACK(jabber_password_change_cb),
 			_("Cancel"), NULL,
-			purple_connection_get_account(gc), NULL, NULL,			  
+			purple_connection_get_account(gc), NULL, NULL,
 			js);
 }
 
@@ -1899,6 +1902,9 @@
 			text = _("Authorization mechanism too weak");
 		} else if(xmlnode_get_child(packet, "not-authorized")) {
 			js->gc->wants_to_die = TRUE;
+			/* Clear the pasword if it isn't being saved */
+			if (!purple_account_get_remember_password(js->gc->account))
+				purple_account_set_password(js->gc->account, NULL);
 			text = _("Not Authorized");
 		} else if(xmlnode_get_child(packet, "temporary-auth-failure")) {
 			text = _("Temporary Authentication Failure");
--- a/libpurple/protocols/jabber/libxmpp.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Fri Sep 14 00:28:55 2007 +0000
@@ -28,6 +28,7 @@
 #include "internal.h"
 
 #include "accountopt.h"
+#include "debug.h"
 #include "version.h"
 
 #include "iq.h"
@@ -45,14 +46,11 @@
 
 static PurplePluginProtocolInfo prpl_info =
 {
+	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
 #ifdef HAVE_CYRUS_SASL
-	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME |
-	OPT_PROTO_MAIL_CHECK | OPT_PROTO_PASSWORD_OPTIONAL |
+	OPT_PROTO_PASSWORD_OPTIONAL |
+#endif
 	OPT_PROTO_SLASH_COMMANDS_NATIVE,
-#else
-	OPT_PROTO_CHAT_TOPIC | OPT_PROTO_UNIQUE_CHATNAME | OPT_PROTO_MAIL_CHECK |
-	OPT_PROTO_SLASH_COMMANDS_NATIVE,
-#endif
 	NULL,							/* user_splits */
 	NULL,							/* protocol_options */
 	{"png", 32, 32, 96, 96, 8191, PURPLE_ICON_SCALE_SEND | PURPLE_ICON_SCALE_DISPLAY}, /* icon_spec */
@@ -194,6 +192,9 @@
 static void
 init_plugin(PurplePlugin *plugin)
 {
+#ifdef HAVE_CYRUS_SASL
+	int ret;
+#endif
 	PurpleAccountUserSplit *split;
 	PurpleAccountOption *option;
 	
@@ -236,7 +237,9 @@
 	
 	/* XXX - If any other plugin wants SASL this won't be good ... */
 #ifdef HAVE_CYRUS_SASL
-	sasl_client_init(NULL);
+	if ((ret = sasl_client_init(NULL)) != SASL_OK) {
+		purple_debug_error("xmpp", "Error (%d) initializing SASL.\n", ret);
+	}
 #endif
 	jabber_register_commands();
 	
--- a/libpurple/protocols/jabber/usermood.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/usermood.c	Fri Sep 14 00:28:55 2007 +0000
@@ -23,7 +23,6 @@
 
 #include "usermood.h"
 #include "pep.h"
-#include <assert.h>
 #include <string.h>
 #include "internal.h"
 #include "request.h"
@@ -195,9 +194,9 @@
 
 void jabber_mood_set(JabberStream *js, const char *mood, const char *text) {
 	xmlnode *publish, *moodnode;
-	
-	assert(mood != NULL);
-	
+
+	g_return_if_fail(mood != NULL);
+
 	publish = xmlnode_new("publish");
 	xmlnode_set_attrib(publish,"node","http://jabber.org/protocol/mood");
 	moodnode = xmlnode_new_child(xmlnode_new_child(publish, "item"), "mood");
--- a/libpurple/protocols/jabber/usernick.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/usernick.c	Fri Sep 14 00:28:55 2007 +0000
@@ -23,7 +23,6 @@
 
 #include "usernick.h"
 #include "pep.h"
-#include <assert.h>
 #include <string.h>
 #include "internal.h"
 #include "request.h"
--- a/libpurple/protocols/jabber/usertune.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/jabber/usertune.c	Fri Sep 14 00:28:55 2007 +0000
@@ -23,7 +23,6 @@
 
 #include "usertune.h"
 #include "pep.h"
-#include <assert.h>
 #include <string.h>
 #include "internal.h"
 #include "request.h"
--- a/libpurple/protocols/msn/httpconn.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/msn/httpconn.c	Fri Sep 14 00:28:55 2007 +0000
@@ -725,7 +725,7 @@
 		msn_httpconn_disconnect(httpconn);
 
 	httpconn->connect_data = purple_proxy_connect(NULL, httpconn->session->account,
-		"gateway.messenger.hotmail.com", 80, connect_cb, httpconn);
+		host, 80, connect_cb, httpconn);
 
 	if (httpconn->connect_data != NULL)
 	{
--- a/libpurple/protocols/msn/msn.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Fri Sep 14 00:28:55 2007 +0000
@@ -351,7 +351,7 @@
 						_("Do you want to allow or disallow people on "
 						  "your buddy list to send you MSN Mobile pages "
 						  "to your cell phone or other mobile device?"),
-						-1, 
+						-1,
 						purple_connection_get_account(gc), NULL, NULL,
 						gc, 3,
 						_("Allow"), G_CALLBACK(enable_msn_pages_cb),
@@ -537,13 +537,13 @@
 
 	user = buddy->proto_data;
 
-	
+
 	if (purple_presence_is_online(presence))
 	{
 		purple_notify_user_info_add_pair(user_info, _("Status"),
 									   (purple_presence_is_idle(presence) ? _("Idle") : purple_status_get_name(status)));
 	}
-	
+
 	if (full && user)
 	{
 		purple_notify_user_info_add_pair(user_info, _("Has you"),
@@ -598,11 +598,11 @@
 	status = purple_status_type_new_full(PURPLE_STATUS_OFFLINE,
 			NULL, NULL, FALSE, TRUE, FALSE);
 	types = g_list_append(types, status);
-	
+
 	status = purple_status_type_new_full(PURPLE_STATUS_MOBILE,
 			"mobile", NULL, FALSE, FALSE, TRUE);
 	types = g_list_append(types, status);
-	
+
 	return types;
 }
 
@@ -730,7 +730,10 @@
 
 	http_method = purple_account_get_bool(account, "http_method", FALSE);
 
-	host = purple_account_get_string(account, "server", MSN_SERVER);
+	if (http_method)
+		host = purple_account_get_string(account, "http_method_server", MSN_SERVER);
+	else
+		host = purple_account_get_string(account, "server", MSN_SERVER);
 	port = purple_account_get_int(account, "port", MSN_PORT);
 
 	session = msn_session_new(account);
@@ -1570,16 +1573,16 @@
 	/* No we're not. */
 	s = g_string_sized_new(strlen(url_buffer));
 	s2 = g_string_sized_new(strlen(url_buffer));
-	
+
 	/* General section header */
 	if (has_tooltip_text)
 		purple_notify_user_info_add_section_break(user_info);
-	
+
 	purple_notify_user_info_add_section_header(user_info, _("General"));
-	
+
 	/* Extract their Name and put it in */
 	MSN_GOT_INFO_GET_FIELD("Name", _("Name"));
-	
+
 	/* General */
 	MSN_GOT_INFO_GET_FIELD("Nickname", _("Nickname"));
 	MSN_GOT_INFO_GET_FIELD_NO_SEARCH("Age", _("Age"));
@@ -1597,24 +1600,24 @@
 		sect_info = TRUE;
 
 	MSN_GOT_INFO_GET_FIELD("More about me", _("A Little About Me"));
-	
+
 	if (sect_info)
 	{
 		has_info = TRUE;
 		sect_info = FALSE;
 	}
-    else 
+    else
     {
 		/* Remove the section header */
 		purple_notify_user_info_remove_last_item(user_info);
 		if (has_tooltip_text)
 			purple_notify_user_info_remove_last_item(user_info);
 	}
-											   
+
 	/* Social */
 	purple_notify_user_info_add_section_break(user_info);
 	purple_notify_user_info_add_section_header(user_info, _("Social"));
-										   
+
 	MSN_GOT_INFO_GET_FIELD("Marital status", _("Marital Status"));
 	MSN_GOT_INFO_GET_FIELD("Interested in", _("Interests"));
 	MSN_GOT_INFO_GET_FIELD("Pets", _("Pets"));
@@ -1630,7 +1633,7 @@
 		has_info = TRUE;
 		sect_info = FALSE;
 	}
-    else 
+    else
     {
 		/* Remove the section header */
 		purple_notify_user_info_remove_last_item(user_info);
@@ -1662,7 +1665,7 @@
 		sect_info = FALSE;
 		has_contact_info = TRUE;
 	}
-    else 
+    else
     {
 		/* Remove the section header */
 		purple_notify_user_info_remove_last_item(user_info);
@@ -1692,7 +1695,7 @@
 		sect_info = FALSE;
 		has_contact_info = TRUE;
 	}
-    else 
+    else
     {
 		/* Remove the section header */
 		purple_notify_user_info_remove_last_item(user_info);
@@ -1867,7 +1870,7 @@
 	tmp = g_strdup_printf("<a href=\"%s%s\">%s%s</a>",
 					PROFILE_URL, info_data->name, PROFILE_URL, info_data->name);
 	purple_notify_user_info_add_pair(user_info, _("Profile URL"), tmp);
-	g_free(tmp);									   
+	g_free(tmp);
 
 #if PHOTO_SUPPORT
 	/* Find the URL to the photo; must be before the marshalling [Bug 994207] */
@@ -2193,6 +2196,12 @@
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
 											   option);
 
+	/* TODO: Mark translatable as soon as 2.2.0 is released and we're not string frozen */
+	option = purple_account_option_string_new("HTTP Method Server",
+										  "http_method_server", MSN_HTTPCONN_SERVER);
+	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
+											   option);
+
 	option = purple_account_option_bool_new(_("Show custom smileys"),
 										  "custom_smileys", TRUE);
 	prpl_info.protocol_options = g_list_append(prpl_info.protocol_options,
--- a/libpurple/protocols/msn/msn.h	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/msn/msn.h	Fri Sep 14 00:28:55 2007 +0000
@@ -59,6 +59,7 @@
 
 #define USEROPT_MSNSERVER 3
 #define MSN_SERVER "messenger.hotmail.com"
+#define MSN_HTTPCONN_SERVER "gateway.messenger.hotmail.com"
 #define USEROPT_MSNPORT 4
 #define MSN_PORT 1863
 
--- a/libpurple/protocols/msn/servconn.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/msn/servconn.c	Fri Sep 14 00:28:55 2007 +0000
@@ -223,7 +223,7 @@
 
 		if (!servconn->httpconn->connected)
 			if (!msn_httpconn_connect(servconn->httpconn, host, port))
-				return FALSE;;
+				return FALSE;
 
 		servconn->connected = TRUE;
 		servconn->httpconn->virgin = TRUE;
--- a/libpurple/protocols/simple/simple.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/simple/simple.c	Fri Sep 14 00:28:55 2007 +0000
@@ -693,19 +693,24 @@
 }
 
 static void do_register_exp(struct simple_account_data *sip, int expire) {
-	char *uri = g_strdup_printf("sip:%s", sip->servername);
-	char *to = g_strdup_printf("sip:%s@%s", sip->username, sip->servername);
-	char *contact = get_contact(sip);
-	char *hdr = g_strdup_printf("Contact: %s\r\nExpires: %d\r\n", contact, expire);
+	char *uri, *to, *contact, *hdr;
+
+	/* Set our default expiration to 900, 
+	 * as done in the initialization of the simple_account_data
+	 * structure.
+	 */
+	if (!expire)
+		expire = 900;
+
+	sip->reregister = time(NULL) + expire - 50;
+
+	uri = g_strdup_printf("sip:%s", sip->servername);
+	to = g_strdup_printf("sip:%s@%s", sip->username, sip->servername);
+	contact = get_contact(sip);
+	hdr = g_strdup_printf("Contact: %s\r\nExpires: %d\r\n", contact, expire);
 	g_free(contact);
 
-	sip->registerstatus = 1;
-
-	if(expire) {
-		sip->reregister = time(NULL) + expire - 50;
-	} else {
-		sip->reregister = time(NULL) + 600;
-	}
+	sip->registerstatus = SIMPLE_REGISTER_SENT;
 
 	send_sip_request(sip->gc, "REGISTER", uri, to, hdr, "", NULL,
 		process_register_response);
@@ -1013,12 +1018,12 @@
 	purple_debug(PURPLE_DEBUG_MISC, "simple", "in process register response response: %d\n", msg->response);
 	switch (msg->response) {
 		case 200:
-			if(sip->registerstatus < 3) { /* registered */
+			if(sip->registerstatus < SIMPLE_REGISTER_COMPLETE) { /* registered */
 				if(purple_account_get_bool(sip->account, "dopublish", TRUE)) {
 					send_publish(sip);
 				}
 			}
-			sip->registerstatus = 3;
+			sip->registerstatus = SIMPLE_REGISTER_COMPLETE;
 			purple_connection_set_state(sip->gc, PURPLE_CONNECTED);
 
 			/* get buddies from blist */
@@ -1032,16 +1037,29 @@
 
 			break;
 		case 401:
-			if(sip->registerstatus != 2) {
+			if(sip->registerstatus != SIMPLE_REGISTER_RETRY) {
 				purple_debug_info("simple", "REGISTER retries %d\n", sip->registrar.retries);
-				if(sip->registrar.retries > 3) {
+				if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) {
+					purple_debug_info("simple", "Setting wants_to_die to true.\n");
 					sip->gc->wants_to_die = TRUE;
 					purple_connection_error(sip->gc, _("Incorrect password."));
 					return TRUE;
 				}
 				tmp = sipmsg_find_header(msg, "WWW-Authenticate");
 				fill_auth(sip, tmp, &sip->registrar);
-				sip->registerstatus = 2;
+				sip->registerstatus = SIMPLE_REGISTER_RETRY;
+				do_register(sip);
+			}
+			break;
+		default:
+			if (sip->registerstatus != SIMPLE_REGISTER_RETRY) {
+				purple_debug_info("simple", "Unrecognized return code for REGISTER.\n");
+				if (sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) {
+					sip->gc->wants_to_die = TRUE;
+					purple_connection_error(sip->gc, _("Unknown server response."));
+					return TRUE;
+				}
+				sip->registerstatus = SIMPLE_REGISTER_RETRY;
 				do_register(sip);
 			}
 			break;
@@ -1327,13 +1345,29 @@
 				} else {
 					sip->proxy.retries = 0;
 					if(!strcmp(trans->msg->method, "REGISTER")) {
-						if(msg->response == 401) sip->registrar.retries++;
-						else sip->registrar.retries = 0;
+
+						/* This is encountered when a REGISTER request was ...
+						 */
+						if(msg->response == 401) {
+							/* denied until further authentication was provided. */
+							sip->registrar.retries++;
+						}
+						else if (msg->response != 200) {
+							/* denied for some other reason! */
+							sip->registrar.retries++;
+						}
+						else {
+							/* accepted! */
+							sip->registrar.retries = 0;
+						}
 					} else {
 						if(msg->response == 401) {
+							/* This is encountered when a generic (MESSAGE, NOTIFY, etc)
+							 * was denied until further authorization is provided.
+							 */
 							gchar *resend, *auth, *ptmp;
 
-							if(sip->registrar.retries > 4) return;
+							if(sip->registrar.retries > SIMPLE_REGISTER_RETRY_MAX) return;
 							sip->registrar.retries++;
 
 							ptmp = sipmsg_find_header(msg, "WWW-Authenticate");
@@ -1347,6 +1381,11 @@
 							/* resend request */
 							sendout_pkt(sip->gc, resend);
 							g_free(resend);
+						} else {
+							/* Reset any count of retries that may have
+							 * accumulated in the above branch.
+							 */
+							sip->registrar.retries = 0;
 						}
 					}
 					if(trans->callback) {
@@ -1696,7 +1735,8 @@
 
 	if(sip) {
 		/* unregister */
-		do_register_exp(sip, 0);
+		if (sip->registerstatus == SIMPLE_REGISTER_COMPLETE)
+			do_register_exp(sip, 0);
 		connection_free_all(sip);
 
 		if (sip->query_data != NULL)
--- a/libpurple/protocols/simple/simple.h	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/protocols/simple/simple.h	Fri Sep 14 00:28:55 2007 +0000
@@ -37,6 +37,11 @@
 #include "sipmsg.h"
 
 #define SIMPLE_BUF_INC 1024
+#define SIMPLE_REGISTER_RETRY_MAX 2
+
+#define SIMPLE_REGISTER_SENT 1
+#define SIMPLE_REGISTER_RETRY 2
+#define SIMPLE_REGISTER_COMPLETE 3
 
 struct sip_dialog {
 	gchar *ourtag;
--- a/libpurple/proxy.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/libpurple/proxy.c	Fri Sep 14 00:28:55 2007 +0000
@@ -668,6 +668,16 @@
 		if (status == 407 /* Proxy Auth */)
 		{
 			gchar *ntlm;
+			char hostname[256];
+			int ret;
+
+			ret = gethostname(hostname, sizeof(hostname));
+			hostname[sizeof(hostname) - 1] = '\0';
+			if (ret < 0 || hostname[0] == '\0') {
+				purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
+				strcpy(hostname, "localhost");
+			}
+
 			ntlm = g_strrstr((const gchar *)connect_data->read_buffer,
 					"Proxy-Authenticate: NTLM ");
 			if (ntlm != NULL)
@@ -679,6 +689,7 @@
 				gchar *username;
 				gchar *request;
 				gchar *response;
+
 				username = strchr(domain, '\\');
 				if (username == NULL)
 				{
@@ -694,7 +705,7 @@
 				nonce = purple_ntlm_parse_type2(ntlm, NULL);
 				response = purple_ntlm_gen_type3(username,
 					(gchar*) purple_proxy_info_get_password(connect_data->gpi),
-					(gchar*) purple_proxy_info_get_host(connect_data->gpi),
+					hostname,
 					domain, nonce, NULL);
 				username--;
 				*username = '\\';
@@ -745,9 +756,7 @@
 					sizeof(request) - request_len,
 					"Proxy-Authorization: NTLM %s\r\n"
 					"Proxy-Connection: Keep-Alive\r\n\r\n",
-					purple_ntlm_gen_type1(
-						(gchar*) purple_proxy_info_get_host(connect_data->gpi),
-						domain));
+					purple_ntlm_gen_type1(hostname, domain));
 				*username = '\\';
 
 				purple_input_remove(connect_data->inpa);
@@ -832,6 +841,14 @@
 	if (purple_proxy_info_get_username(connect_data->gpi) != NULL)
 	{
 		char *t1, *t2;
+		char hostname[256];
+
+		ret = gethostname(hostname, sizeof(hostname));
+		hostname[sizeof(hostname) - 1] = '\0';
+		if (ret < 0 || hostname[0] == '\0') {
+			purple_debug_warning("proxy", "gethostname() failed -- is your hostname set?");
+			strcpy(hostname, "localhost");
+		}
 
 		t1 = g_strdup_printf("%s:%s",
 			purple_proxy_info_get_username(connect_data->gpi),
@@ -844,8 +861,7 @@
 			"Proxy-Authorization: Basic %s\r\n"
 			"Proxy-Authorization: NTLM %s\r\n"
 			"Proxy-Connection: Keep-Alive\r\n",
-			t2, purple_ntlm_gen_type1(
-					purple_proxy_info_get_host(connect_data->gpi), ""));
+			t2, purple_ntlm_gen_type1(hostname, ""));
 		g_free(t2);
 	}
 
--- a/pidgin/Makefile.am	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/Makefile.am	Fri Sep 14 00:28:55 2007 +0000
@@ -29,6 +29,7 @@
 		win32/nsis/langmacros.nsh \
 		win32/nsis/translations/afrikaans.nsh \
 		win32/nsis/translations/albanian.nsh \
+		win32/nsis/translations/basque.nsh \
 		win32/nsis/translations/bulgarian.nsh \
 		win32/nsis/translations/catalan.nsh \
 		win32/nsis/translations/czech.nsh \
--- a/pidgin/gtkcertmgr.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/gtkcertmgr.c	Fri Sep 14 00:28:55 2007 +0000
@@ -312,10 +312,6 @@
 	GtkTreeModel *model;
 	gchar *id;
 	PurpleCertificate *crt;
-	gchar *subject;
-	GByteArray *fpr_sha1;
-	gchar *fpr_sha1_asc;
-	gchar *primary, *secondary;
 
 	/* See if things are selected */
 	if (!gtk_tree_selection_get_selected(select, &model, &iter)) {
@@ -331,25 +327,9 @@
 	crt = purple_certificate_pool_retrieve(tpm_dat->tls_peers, id);
 	g_return_if_fail(crt);
 	
-	/* Build a notification thing */
-	/* TODO: This needs a better GUI, but a notification will do for now */
-	primary = g_strdup_printf(_("Certificate for %s"), id);
-
-	fpr_sha1 = purple_certificate_get_fingerprint_sha1(crt);
-	fpr_sha1_asc = purple_base16_encode_chunked(fpr_sha1->data,
-						    fpr_sha1->len);
-	subject = purple_certificate_get_subject_name(crt);
-
-	secondary = g_strdup_printf(_("Common name: %s\n\nSHA1 fingerprint:\n%s"), subject, fpr_sha1_asc);
+	/* Fire the notification */
+	purple_certificate_display_x509(crt);
 	
-	purple_notify_info(tpm_dat,
-			   _("SSL Host Certificate"),  primary, secondary );
-
-	g_free(primary);
-	g_free(secondary);
-	g_byte_array_free(fpr_sha1, TRUE);
-	g_free(fpr_sha1_asc);
-	g_free(subject);
 	g_free(id);
 	purple_certificate_destroy(crt);
 }
--- a/pidgin/gtkconv.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/gtkconv.c	Fri Sep 14 00:28:55 2007 +0000
@@ -183,6 +183,25 @@
 	return &col;
 }
 
+static PurpleBlistNode *
+get_conversation_blist_node(PurpleConversation *conv)
+{
+	PurpleBlistNode *node = NULL;
+
+	switch (purple_conversation_get_type(conv)) {
+		case PURPLE_CONV_TYPE_IM:
+			node = (PurpleBlistNode*)purple_find_buddy(conv->account, conv->name);
+			node = node ? node->parent : NULL;
+			break;
+		case PURPLE_CONV_TYPE_CHAT:
+			node = (PurpleBlistNode*)purple_blist_find_chat(conv->account, conv->name);
+			break;
+		default:
+			break;
+	}
+	return node;
+}
+
 /**************************************************************************
  * Callbacks
  **************************************************************************/
@@ -1379,6 +1398,7 @@
 	PidginWindow *win = data;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
+	PurpleBlistNode *node;
 
 	conv = pidgin_conv_window_get_active_conversation(win);
 
@@ -1389,6 +1409,9 @@
 
 	gtkconv->make_sound =
 		gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget));
+	node = get_conversation_blist_node(conv);
+	if (node)
+		purple_blist_node_set_bool(node, "gtk-mute-sound", !gtkconv->make_sound);
 }
 
 static void
@@ -2948,7 +2971,7 @@
 
 		if (gtkconv != NULL)
 			gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(win->menu.sounds),
-			                               TRUE);
+			                               gtkconv->make_sound);
 		gtk_widget_set_sensitive(win->menu.sounds, TRUE);
 
 	}
@@ -4927,6 +4950,7 @@
 	PurpleConversationType conv_type = purple_conversation_get_type(conv);
 	GtkWidget *pane = NULL;
 	GtkWidget *tab_cont;
+	PurpleBlistNode *convnode;
 
 	if (conv_type == PURPLE_CONV_TYPE_IM && (gtkconv = pidgin_conv_find_gtkconv(conv))) {
 		conv->ui_data = gtkconv;
@@ -5004,7 +5028,9 @@
 	gtk_container_add(GTK_CONTAINER(tab_cont), pane);
 	gtk_widget_show(pane);
 
-	gtkconv->make_sound = TRUE;
+	convnode = get_conversation_blist_node(conv);
+	if (convnode == NULL || !purple_blist_node_get_bool(convnode, "gtk-mute-sound"))
+		gtkconv->make_sound = TRUE;
 
 	if (purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/conversations/show_formatting_toolbar"))
 		gtk_widget_show(gtkconv->toolbar);
--- a/pidgin/gtkimhtmltoolbar.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Fri Sep 14 00:28:55 2007 +0000
@@ -1298,6 +1298,10 @@
 			imhtmltoolbar_view_pref_changed, toolbar);
 	purple_prefs_trigger_callback(PIDGIN_PREFS_ROOT "/conversations/toolbar/wide");
 
+#if GTK_CHECK_VERSION(2,4,0)
+	gtk_event_box_set_visible_window(GTK_EVENT_BOX(event), FALSE);
+#endif
+
 	gtk_widget_add_events(event, GDK_BUTTON_PRESS_MASK);
 	gtk_box_pack_start(GTK_BOX(hbox), event, TRUE, TRUE, 0);
 	g_signal_connect(G_OBJECT(event), "button-press-event", G_CALLBACK(gtk_imhtmltoolbar_popup_menu), toolbar);
--- a/pidgin/plugins/musicmessaging/musicmessaging.c	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/plugins/musicmessaging/musicmessaging.c	Fri Sep 14 00:28:55 2007 +0000
@@ -311,7 +311,9 @@
 static gboolean
 intercept_sent(PurpleAccount *account, const char *who, char **message, void* pData)
 {
-	
+	if (message == NULL || *message == NULL || **message == '\0')
+		return FALSE;
+
 	if (0 == strncmp(*message, MUSICMESSAGING_PREFIX, strlen(MUSICMESSAGING_PREFIX)))
 	{
 		purple_debug_misc("purple-musicmessaging", "Sent MM Message: %s\n", *message);
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Wed Sep 12 17:22:33 2007 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Fri Sep 14 00:28:55 2007 +0000
@@ -167,6 +167,7 @@
 
   !insertmacro MUI_LANGUAGE "Afrikaans"
   !insertmacro MUI_LANGUAGE "Albanian"
+  !insertmacro MUI_LANGUAGE "Basque"
   !insertmacro MUI_LANGUAGE "Bulgarian"
   !insertmacro MUI_LANGUAGE "Catalan"
   !insertmacro MUI_LANGUAGE "Czech"
@@ -206,6 +207,7 @@
 
   !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "AFRIKAANS"	"${PIDGIN_NSIS_INCLUDE_PATH}\translations\afrikaans.nsh"
   !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "ALBANIAN"		"${PIDGIN_NSIS_INCLUDE_PATH}\translations\albanian.nsh"
+  !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "BASQUE"		"${PIDGIN_NSIS_INCLUDE_PATH}\translations\basque.nsh"
   !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "BULGARIAN"	"${PIDGIN_NSIS_INCLUDE_PATH}\translations\bulgarian.nsh"
   !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "CATALAN"		"${PIDGIN_NSIS_INCLUDE_PATH}\translations\catalan.nsh"
   !insertmacro PIDGIN_MACRO_INCLUDE_LANGFILE "CZECH"		"${PIDGIN_NSIS_INCLUDE_PATH}\translations\czech.nsh"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pidgin/win32/nsis/translations/basque.nsh	Fri Sep 14 00:28:55 2007 +0000
@@ -0,0 +1,80 @@
+;;
+;;  basque.nsh
+;;Abio-menua - Istanteko Mezularitza
+;;  Basque language strings for the Windows Pidgin NSIS installer.
+;;  Windows Code page: 1252
+;;
+;;  Author: Mikel Pascual Aldabaldetreku <mikel.paskual@gmail.com>, 2007.
+
+; Startup Checks
+!define INSTALLER_IS_RUNNING			"Instalatzailea martxan dago."
+!define PIDGIN_IS_RUNNING			"Pidgin istantzia bat dago martxan. Pidgin itxi eta berriro saiatu."
+!define GTK_INSTALLER_NEEDED			"GTK+ exekuzio-ingurunea falta da, edo eguneratu egin beharko litzateke.$\rGTK+ exekuzio-ingurunearen ${GTK_MIN_VERSION} bertsioa edo berriagoa instalatu"
+
+; License Page
+!define PIDGIN_LICENSE_BUTTON			"Jarraitu >"
+!define PIDGIN_LICENSE_BOTTOM_TEXT		"GNU Lizentzia Orokor Publikopean (GPL) argitaratzen da $(^Name). Informatzeko helburu soilarekin aurkezten da hemen lizentzia. $_CLICK"
+
+; Components Page
+!define PIDGIN_SECTION_TITLE			"Pidgin Istanteko Mezularitza Bezeroa (beharrezkoa)"
+!define GTK_SECTION_TITLE			"GTK+ exekuzio ingurunea (beharrezkoa)"
+!define PIDGIN_SHORTCUTS_SECTION_TITLE		"Lasterbideak"
+!define PIDGIN_DESKTOP_SHORTCUT_SECTION_TITLE	"Mahaigaina"
+!define PIDGIN_STARTMENU_SHORTCUT_SECTION_TITLE	"Abio-menua"
+!define PIDGIN_SECTION_DESCRIPTION		"Funtsezko Pidgin fitxategi eta dll-ak"
+!define GTK_SECTION_DESCRIPTION		"Plataforma anitzeko GUI tresna-sorta, Pidgin-ek erabilia"
+
+!define PIDGIN_SHORTCUTS_SECTION_DESCRIPTION	"Pidgin abiarazteko lasterbideak"
+!define PIDGIN_DESKTOP_SHORTCUT_DESC		"Pidgin-entzako lasterbidea Mahaigainean"
+!define PIDGIN_STARTMENU_SHORTCUT_DESC		"Pidgin-entzako lasterbidea Abio-Menuan"
+
+; GTK+ Directory Page
+!define GTK_UPGRADE_PROMPT			"GTK+ exekuzio-ingurunearen bertsio zahar bat aurkitu da. Eguneratu egin nahi al duzu?$\rOharra: Bestela, posible da $(^Name) ez ibiltzea."
+!define GTK_WINDOWS_INCOMPATIBLE		"GTK+ 2.8.0 eta berriagoekin bateraezinak dira Windows 95/98/Me.  Ez da GTK+ ${GTK_INSTALL_VERSION} instalatuko.$\rJadanik ez badaukazu GTK+ ${GTK_MIN_VERSION} edo berriagorik instalatuta, bertan behera utziko da instalazioa."
+
+; Installer Finish Page
+!define PIDGIN_FINISH_VISIT_WEB_SITE		"Pidgin Webgunera etorri"
+
+; Pidgin Section Prompts and Texts
+!define PIDGIN_PROMPT_CONTINUE_WITHOUT_UNINSTALL	"Ezin izan da jadanik instalatuta zegoen Pidgin bertsioa kendu. Aurreko bertsioa kendu gabe instalatuko da bertsio berria."
+
+; GTK+ Section Prompts
+!define GTK_INSTALL_ERROR			"Errorea GTK+ exekuzio-ingurunea instalatzean."
+!define GTK_BAD_INSTALL_PATH			"The path you entered can not be accessed or created."
+
+; URL Handler section
+!define URI_HANDLERS_SECTION_TITLE		"URI Kudeatzaileak"
+
+; Uninstall Section Prompts
+!define un.PIDGIN_UNINSTALL_ERROR_1		"Ezin izan dira Pidgin-en erregistro-sarrerak aurkitu.$\rZiurrenik, beste erabiltzaile batek instalatu zuen aplikazio hau."
+!define un.PIDGIN_UNINSTALL_ERROR_2		"Ez daukazu aplikazio hau kentzeko baimenik."
+
+; Spellcheck Section Prompts
+!define PIDGIN_SPELLCHECK_SECTION_TITLE	"Zuzentzaile Ortografikoa"
+!define PIDGIN_SPELLCHECK_ERROR		"Errorea Zuzentzaile Ortografikoa instalatzean"
+!define PIDGIN_SPELLCHECK_DICT_ERROR		"Errorea Zuzentzaile Ortografikoarentzako hiztegia instalatzean"
+!define PIDGIN_SPELLCHECK_SECTION_DESCRIPTION	"Zuzentzaile Ortografikoa.  (Internet konexioa behar du instalatzeko)"
+!define ASPELL_INSTALL_FAILED			"Ezin izan da instalatu"
+!define PIDGIN_SPELLCHECK_BRETON		"Britaniera"
+!define PIDGIN_SPELLCHECK_CATALAN		"Katalana"
+!define PIDGIN_SPELLCHECK_CZECH		"Txekiera"
+!define PIDGIN_SPELLCHECK_WELSH		"Gaelikoa"
+!define PIDGIN_SPELLCHECK_DANISH		"Daniera"
+!define PIDGIN_SPELLCHECK_GERMAN		"Alemana"
+!define PIDGIN_SPELLCHECK_GREEK		"Grekoa"
+!define PIDGIN_SPELLCHECK_ENGLISH		"Ingelesa"
+!define PIDGIN_SPELLCHECK_ESPERANTO		"Esperantoa"
+!define PIDGIN_SPELLCHECK_SPANISH		"Gaztelania"
+!define PIDGIN_SPELLCHECK_FAROESE		"Faroera"
+!define PIDGIN_SPELLCHECK_FRENCH		"Frantsesa"
+!define PIDGIN_SPELLCHECK_ITALIAN		"Italiera"
+!define PIDGIN_SPELLCHECK_DUTCH		"Nederlandera"
+!define PIDGIN_SPELLCHECK_NORWEGIAN		"Norvegiera"
+!define PIDGIN_SPELLCHECK_POLISH		"Poloniera"
+!define PIDGIN_SPELLCHECK_PORTUGUESE		"Portugesa"
+!define PIDGIN_SPELLCHECK_ROMANIAN		"Errumaniera"
+!define PIDGIN_SPELLCHECK_RUSSIAN		"Errusiera"
+!define PIDGIN_SPELLCHECK_SLOVAK		"Eslovakiera"
+!define PIDGIN_SPELLCHECK_SWEDISH		"Suediera"
+!define PIDGIN_SPELLCHECK_UKRAINIAN		"Ukraniera"
+
--- a/po/ChangeLog	Wed Sep 12 17:22:33 2007 +0000
+++ b/po/ChangeLog	Fri Sep 14 00:28:55 2007 +0000
@@ -1,6 +1,7 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
 version 2.2.0
+	* Basque win32 translation added (Mikel Pascual Aldabaldetreku)
 	* Belarusian Latin translation added (Ihar Hrachyshka)
 	* Czech translation updated (Miloslav Trmac)
 	* English (British) translation updated (Luke Ross)