changeset 27865:86e7e2b5e59a

propagate from branch 'im.pidgin.pidgin' (head 1036d6fc1c09bf3b42c737dab42d188245f16b17) to branch 'im.pidgin.pidgin.yaz' (head 6e8c4f9c7db93e0a327a2d0f3220d7797d37dff0)
author Yoshiki Yazawa <yaz@honeyplanet.jp>
date Thu, 31 Jul 2008 06:23:55 +0000
parents 85189641a970 (diff) e81f0d1966db (current diff)
children b522393714d6
files libpurple/protocols/msn/msn.c
diffstat 27 files changed, 441 insertions(+), 288 deletions(-) [+]
line wrap: on
line diff
--- a/AUTHORS	Mon Jul 28 06:18:51 2008 +0000
+++ b/AUTHORS	Thu Jul 31 06:23:55 2008 +0000
@@ -24,6 +24,7 @@
 Bartosz Oler - Developer
 Etan 'deryni' Reisner - Developer
 Tim 'marv' Ringenbach - Developer
+Elliott 'QuLogic' Sales de Andrade - Developer
 Luke 'LSchiere' Schierer - Support
 Megan 'Cae' Schneider - support/QA
 Evan Schoenberg - Developer
@@ -37,7 +38,6 @@
 Felipe 'shx' Contreras
 Dennis 'EvilDennisR' Ristuccia
 Peter 'Fmoo' Ruibal
-Elliott 'QuLogic' Sales de Andrade
 Gabriel 'Nix' Schulhof
 Jorge 'Masca' Villaseñor
 
--- a/ChangeLog.win32	Mon Jul 28 06:18:51 2008 +0000
+++ b/ChangeLog.win32	Thu Jul 31 06:23:55 2008 +0000
@@ -2,6 +2,7 @@
 	* Don't install the GSSAPI SASL plugin on NT4 to avoid an error popup.
 	* Upgrade to Perl 5.10 (System Perl runtime must be upgraded for Perl
 	  plugins to continue to work).
+	* Upgrade SILC to use the 1.1.7 toolkit
 
 version 2.4.3 (07/01/2008):
 	* No changes
--- a/doc/pidgin.1.in	Mon Jul 28 06:18:51 2008 +0000
+++ b/doc/pidgin.1.in	Thu Jul 31 06:23:55 2008 +0000
@@ -582,6 +582,8 @@
 .br
   Tim 'marv' Ringenbach (developer) <\fImarv_sf@users.sf.net\fR>
 .br
+  Elliott 'QuLogic' Sales de Andrade (developer)
+.br
   Luke 'LSchiere' Schierer (support)
 .br
   Megan 'Cae' Schneider (support/QA)
@@ -606,8 +608,6 @@
 .br
   Peter 'fmoo' Ruibal
 .br
-  Elliott 'QuLogic' Sales de Andrade
-.br
   Gabriel 'Nix' Schulhof
 .br
   Jorge 'Masca' Villaseñor
--- a/libpurple/plugins/perl/common/Prefs.xs	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/plugins/perl/common/Prefs.xs	Thu Jul 31 06:23:55 2008 +0000
@@ -1,4 +1,5 @@
 #include "module.h"
+#include "../perl-handlers.h"
 
 MODULE = Purple::Prefs  PACKAGE = Purple::Prefs  PREFIX = purple_prefs_
 PROTOTYPES: ENABLE
@@ -62,13 +63,28 @@
 void
 purple_prefs_destroy()
 
+guint
+purple_prefs_connect_callback(plugin, name, callback, data = 0);
+	Purple::Plugin plugin
+	const char *name
+	SV *callback
+	SV *data
+CODE:
+	RETVAL = purple_perl_prefs_connect_callback(plugin, name, callback, data);
+OUTPUT:
+	RETVAL
+
 void
-purple_prefs_disconnect_by_handle(handle)
-	void * handle
+purple_prefs_disconnect_by_handle(plugin)
+	Purple::Plugin plugin
+CODE:
+	purple_perl_pref_cb_clear_for_plugin(plugin);
 
 void
 purple_prefs_disconnect_callback(callback_id)
 	guint callback_id
+CODE:
+	purple_perl_prefs_disconnect_callback(callback_id);
 
 gboolean
 purple_prefs_exists(name)
--- a/libpurple/plugins/perl/perl-handlers.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/plugins/perl/perl-handlers.c	Thu Jul 31 06:23:55 2008 +0000
@@ -5,9 +5,10 @@
 #include "signals.h"
 
 extern PerlInterpreter *my_perl;
-static GList *cmd_handlers = NULL;
-static GList *signal_handlers = NULL;
-static GList *timeout_handlers = NULL;
+static GSList *cmd_handlers = NULL;
+static GSList *signal_handlers = NULL;
+static GSList *timeout_handlers = NULL;
+static GSList *pref_handlers = NULL;
 
 /* perl < 5.8.0 doesn't define PERL_MAGIC_ext */
 #ifndef PERL_MAGIC_ext
@@ -70,7 +71,7 @@
 	STRLEN na;
 	dSP;
 
-	gps = (PurplePerlScript *)plugin->info->extra_info;
+	gps = plugin->info->extra_info;
 
 	ENTER;
 	SAVETMPS;
@@ -131,7 +132,7 @@
 	STRLEN na;
 	dSP;
 
-	gps = (PurplePerlScript *)plugin->info->extra_info;
+	gps = plugin->info->extra_info;
 
 	ENTER;
 	SAVETMPS;
@@ -212,7 +213,7 @@
 {
 	gboolean ret = FALSE;
 
-	timeout_handlers = g_list_remove(timeout_handlers, handler);
+	timeout_handlers = g_slist_remove(timeout_handlers, handler);
 
 	if (handler->iotag > 0)
 		ret = purple_timeout_remove(handler->iotag);
@@ -231,7 +232,7 @@
 static void
 destroy_signal_handler(PurplePerlSignalHandler *handler)
 {
-	signal_handlers = g_list_remove(signal_handlers, handler);
+	signal_handlers = g_slist_remove(signal_handlers, handler);
 
 	if (handler->callback != NULL)
 		SvREFCNT_dec(handler->callback);
@@ -246,7 +247,7 @@
 static gboolean
 perl_timeout_cb(gpointer data)
 {
-	PurplePerlTimeoutHandler *handler = (PurplePerlTimeoutHandler *)data;
+	PurplePerlTimeoutHandler *handler = data;
 	gboolean ret = FALSE;
 	STRLEN na;
 
@@ -282,7 +283,7 @@
 static void *
 perl_signal_cb(va_list args, void *data)
 {
-	PurplePerlSignalHandler *handler = (PurplePerlSignalHandler *)data;
+	PurplePerlSignalHandler *handler = data;
 	void *ret_val = NULL;
 	int i;
 	int count;
@@ -414,10 +415,10 @@
 find_signal_handler(PurplePlugin *plugin, void *instance, const char *signal)
 {
 	PurplePerlSignalHandler *handler;
-	GList *l;
+	GSList *l;
 
 	for (l = signal_handlers; l != NULL; l = l->next) {
-		handler = (PurplePerlSignalHandler *)l->data;
+		handler = l->data;
 
 		if (handler->plugin == plugin &&
 			handler->instance == instance &&
@@ -447,9 +448,9 @@
 	handler->data     = (data != NULL && data != &PL_sv_undef
 	                     ? newSVsv(data) : NULL);
 
-	timeout_handlers = g_list_append(timeout_handlers, handler);
+	timeout_handlers = g_slist_append(timeout_handlers, handler);
 
-	handler->iotag = purple_timeout_add(seconds * 1000, perl_timeout_cb, handler);
+	handler->iotag = purple_timeout_add_seconds(seconds, perl_timeout_cb, handler);
 
 	return handler->iotag;
 }
@@ -457,15 +458,13 @@
 gboolean
 purple_perl_timeout_remove(guint handle)
 {
-	GList *l, *l_next;
+	PurplePerlTimeoutHandler *handler;
+	GSList *l, *l_next;
 
 	for (l = timeout_handlers; l != NULL; l = l_next) {
-		PurplePerlTimeoutHandler *handler;
-
+		handler =  l->data;
 		l_next = l->next;
 
-		handler = (PurplePerlTimeoutHandler *)l->data;
-
 		if (handler->iotag == handle)
 			return destroy_timeout_handler(handler);
 	}
@@ -478,15 +477,13 @@
 void
 purple_perl_timeout_clear_for_plugin(PurplePlugin *plugin)
 {
-	GList *l, *l_next;
+	PurplePerlTimeoutHandler *handler;
+	GSList *l, *l_next;
 
 	for (l = timeout_handlers; l != NULL; l = l_next) {
-		PurplePerlTimeoutHandler *handler;
-
+		handler = l->data;
 		l_next = l->next;
 
-		handler = (PurplePerlTimeoutHandler *)l->data;
-
 		if (handler->plugin == plugin)
 			destroy_timeout_handler(handler);
 	}
@@ -516,7 +513,7 @@
 	handler->data     = (data != NULL &&
 	                     data != &PL_sv_undef ? newSVsv(data) : NULL);
 
-	signal_handlers = g_list_append(signal_handlers, handler);
+	signal_handlers = g_slist_append(signal_handlers, handler);
 
 	purple_signal_connect_priority_vargs(instance, signal, plugin,
 	                                   PURPLE_CALLBACK(perl_signal_cb),
@@ -544,12 +541,11 @@
 purple_perl_signal_clear_for_plugin(PurplePlugin *plugin)
 {
 	PurplePerlSignalHandler *handler;
-	GList *l, *l_next;
+	GSList *l, *l_next;
 
 	for (l = signal_handlers; l != NULL; l = l_next) {
 		l_next = l->next;
-
-		handler = (PurplePerlSignalHandler *)l->data;
+		handler = l->data;
 
 		if (handler->plugin == plugin)
 			destroy_signal_handler(handler);
@@ -570,7 +566,7 @@
 	int i = 0, count, ret_value = PURPLE_CMD_RET_OK;
 	STRLEN na;
 	SV *cmdSV, *tmpSV, *convSV;
-	PurplePerlCmdHandler *handler = (PurplePerlCmdHandler *)data;
+	PurplePerlCmdHandler *handler = data;
 
 	dSP;
 	ENTER;
@@ -645,7 +641,7 @@
 	else
 		handler->data = NULL;
 
-	cmd_handlers = g_list_append(cmd_handlers, handler);
+	cmd_handlers = g_slist_append(cmd_handlers, handler);
 
 	handler->id = purple_cmd_register(command, args, priority, flag, prpl_id,
 	                                PURPLE_CMD_FUNC(perl_cmd_cb), helpstr,
@@ -657,7 +653,7 @@
 static void
 destroy_cmd_handler(PurplePerlCmdHandler *handler)
 {
-	cmd_handlers = g_list_remove(cmd_handlers, handler);
+	cmd_handlers = g_slist_remove(cmd_handlers, handler);
 
 	if (handler->callback != NULL)
 		SvREFCNT_dec(handler->callback);
@@ -673,11 +669,11 @@
 void
 purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin)
 {
-	GList *l, *l_next;
+	PurplePerlCmdHandler *handler;
+	GSList *l, *l_next;
 
 	for (l = cmd_handlers; l != NULL; l = l_next) {
-		PurplePerlCmdHandler *handler = (PurplePerlCmdHandler *)l->data;
-
+		handler = l->data;
 		l_next = l->next;
 
 		if (handler->plugin == plugin)
@@ -688,10 +684,11 @@
 static PurplePerlCmdHandler *
 find_cmd_handler(PurpleCmdId id)
 {
-	GList *l;
+	PurplePerlCmdHandler *handler;
+	GSList *l;
 
 	for (l = cmd_handlers; l != NULL; l = l->next) {
-		PurplePerlCmdHandler *handler = (PurplePerlCmdHandler *)l->data;
+		handler = (PurplePerlCmdHandler *)l->data;
 
 		if (handler->id == id)
 			return handler;
@@ -715,3 +712,141 @@
 	purple_cmd_unregister(id);
 	destroy_cmd_handler(handler);
 }
+
+static void
+perl_pref_cb(const char *name, PurplePrefType type, gconstpointer value,
+			 gpointer data)
+{
+	PurplePerlPrefsHandler *handler = data;
+	STRLEN na;
+
+	dSP;
+	ENTER;
+	SAVETMPS;
+	PUSHMARK(sp);
+	XPUSHs(sv_2mortal(newSVpv(name, 0)));
+
+	XPUSHs(sv_2mortal(newSViv(type)));
+
+	switch(type) {
+		case PURPLE_PREF_INT:
+			XPUSHs(sv_2mortal(newSViv(GPOINTER_TO_INT(value))));
+			break;
+		case PURPLE_PREF_BOOLEAN:
+			XPUSHs((GPOINTER_TO_INT(value) == FALSE) ? &PL_sv_no : &PL_sv_yes);
+			break;
+		case PURPLE_PREF_STRING:
+		case PURPLE_PREF_PATH:
+			XPUSHs(sv_2mortal(newSVGChar(value)));
+			break;
+		case PURPLE_PREF_STRING_LIST:
+		case PURPLE_PREF_PATH_LIST:
+			{
+				AV* av = newAV();
+				const GList *l = value;
+
+				/* Append stuff backward to preserve order */
+				while (l && l->next) l = l->next;
+				while (l) {
+					av_push(av, sv_2mortal(newSVGChar(l->data)));
+					l = l->prev;
+				}
+				XPUSHs(sv_2mortal(newRV_noinc((SV *) av)));
+			} break;
+		default:
+		case PURPLE_PREF_NONE:
+			XPUSHs(&PL_sv_undef);
+			break;
+	}
+
+	XPUSHs((SV *)handler->data);
+	PUTBACK;
+	call_sv(handler->callback, G_EVAL | G_VOID | G_DISCARD);
+	SPAGAIN;
+
+	if (SvTRUE(ERRSV)) {
+		purple_debug_error("perl",
+		                 "Perl prefs callback function exited abnormally: %s\n",
+		                 SvPV(ERRSV, na));
+	}
+
+	PUTBACK;
+	FREETMPS;
+	LEAVE;
+}
+
+guint
+purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name,
+								   SV *callback, SV *data)
+{
+	PurplePerlPrefsHandler *handler;
+
+	if (plugin == NULL) {
+		croak("Invalid handle in adding perl prefs handler.\n");
+		return 0;
+	}
+
+	handler = g_new0(PurplePerlPrefsHandler, 1);
+
+	handler->plugin   = plugin;
+	handler->callback = (callback != NULL && callback != &PL_sv_undef
+	                     ? newSVsv(callback) : NULL);
+	handler->data     = (data != NULL && data != &PL_sv_undef
+	                     ? newSVsv(data) : NULL);
+
+	pref_handlers = g_slist_prepend(pref_handlers, handler);
+
+	handler->iotag = purple_prefs_connect_callback(plugin, name, perl_pref_cb, handler);
+
+	return handler->iotag;
+}
+
+static void
+destroy_prefs_handler(PurplePerlPrefsHandler *handler)
+{
+	pref_handlers = g_slist_remove(pref_handlers, handler);
+
+	if (handler->iotag > 0)
+		purple_prefs_disconnect_callback(handler->iotag);
+
+	if (handler->callback != NULL)
+		SvREFCNT_dec(handler->callback);
+
+	if (handler->data != NULL)
+		SvREFCNT_dec(handler->data);
+
+	g_free(handler);
+}
+
+void purple_perl_prefs_disconnect_callback(guint callback_id)
+{
+	GSList *l, *l_next;
+	PurplePerlPrefsHandler *handler;
+
+	for (l = pref_handlers; l != NULL; l = l_next) {
+		l_next = l->next;
+		handler = l->data;
+
+		if (handler->iotag == callback_id) {
+			destroy_prefs_handler(handler);
+			return;
+		}
+	}
+
+	purple_debug_info("perl", "No prefs handler found with handle %u.\n",
+	                  callback_id);
+}
+
+void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin)
+{
+	GSList *l, *l_next;
+	PurplePerlPrefsHandler *handler;
+
+	for (l = pref_handlers; l != NULL; l = l_next) {
+		l_next = l->next;
+		handler = l->data;
+
+		if (handler->plugin == plugin)
+			destroy_prefs_handler(handler);
+	}
+}
--- a/libpurple/plugins/perl/perl-handlers.h	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/plugins/perl/perl-handlers.h	Thu Jul 31 06:23:55 2008 +0000
@@ -15,8 +15,8 @@
 	PurpleCmdId id;
 	SV *callback;
 	SV *data;
-	char *prpl_id;
-	char *cmd;
+	gchar *prpl_id;
+	gchar *cmd;
 	PurplePlugin *plugin;
 } PurplePerlCmdHandler;
 
@@ -31,7 +31,7 @@
 
 typedef struct
 {
-	char *signal;
+	gchar *signal;
 	SV *callback;
 	SV *data;
 	void *instance;
@@ -39,8 +39,17 @@
 
 } PurplePerlSignalHandler;
 
+typedef struct
+{
+	SV *callback;
+	SV *data;
+	PurplePlugin *plugin;
+	int iotag;
+
+} PurplePerlPrefsHandler;
+
 void purple_perl_plugin_action_cb(PurplePluginAction * gpa);
-GList *purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context); 
+GList *purple_perl_plugin_actions(PurplePlugin *plugin, gpointer context);
 
 PurplePluginPrefFrame *purple_perl_get_plugin_frame(PurplePlugin *plugin);
 
@@ -69,4 +78,8 @@
 void purple_perl_cmd_unregister(PurpleCmdId id);
 void purple_perl_cmd_clear_for_plugin(PurplePlugin *plugin);
 
+guint purple_perl_prefs_connect_callback(PurplePlugin *plugin, const char *name, SV *callback, SV *data);
+void purple_perl_prefs_disconnect_callback(guint callback_id);
+void purple_perl_pref_cb_clear_for_plugin(PurplePlugin *plugin);
+
 #endif /* _PURPLE_PERL_HANDLERS_H_ */
--- a/libpurple/plugins/perl/perl.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/plugins/perl/perl.c	Thu Jul 31 06:23:55 2008 +0000
@@ -251,7 +251,7 @@
 
 	char *args[] = {"", plugin->path };
 	char **argv = args;
-	int argc = 2;
+	int argc = 2, ret;
 	PerlInterpreter *prober;
 	gboolean status = TRUE;
 	HV *plugin_info;
@@ -285,9 +285,29 @@
 }
 #endif
 
-	perl_parse(prober, xs_init, argc, argv, NULL);
+	ret = perl_parse(prober, xs_init, argc, argv, NULL);
+
+	if (ret != 0) {
+		STRLEN len;
+		const char * errmsg = "Unknown error";
+		if (SvTRUE(ERRSV))
+			errmsg = SvPV(ERRSV, len);
+		purple_debug_error("perl", "Unable to parse plugin %s (%d:%s)\n",
+						   plugin->path, ret, errmsg);
+		goto cleanup;
+	}
 
-	perl_run(prober);
+	ret = perl_run(prober);
+
+	if (ret != 0) {
+		STRLEN len;
+		const char * errmsg = "Unknown error";
+		if (SvTRUE(ERRSV))
+			errmsg = SvPV(ERRSV, len);
+		purple_debug_error("perl", "Unable to run perl interpreter on plugin %s (%d:%s)\n",
+						   plugin->path, ret, errmsg);
+		goto cleanup;
+	}
 
 	plugin_info = perl_get_hv("PLUGIN_INFO", FALSE);
 
@@ -435,6 +455,7 @@
 		}
 	}
 
+	cleanup:
 	PL_perl_destruct_level = 1;
 	PERL_SET_CONTEXT(prober);
 	perl_destruct(prober);
@@ -557,6 +578,7 @@
 	purple_perl_cmd_clear_for_plugin(plugin);
 	purple_perl_signal_clear_for_plugin(plugin);
 	purple_perl_timeout_clear_for_plugin(plugin);
+	purple_perl_pref_cb_clear_for_plugin(plugin);
 
 	destroy_package(gps->package);
 
--- a/libpurple/plugins/perl/scripts/plugin_pref.pl	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/plugins/perl/scripts/plugin_pref.pl	Thu Jul 31 06:23:55 2008 +0000
@@ -44,8 +44,8 @@
 	$ppref = Purple::PluginPref->new_with_name_and_label(
 	    "/plugins/core/perl_test/choice", "Choice Preference");
 	$ppref->set_type(1);
-	$ppref->add_choice("ch0", $frame);
-	$ppref->add_choice("ch1", $frame);
+	$ppref->add_choice("ch0", "ch0-val");
+	$ppref->add_choice("ch1", "ch1-val");
 	$frame->add($ppref);
 	
 	$ppref = Purple::PluginPref->new_with_name_and_label(
@@ -56,12 +56,17 @@
 	return $frame;
 }
 
+sub pref_cb {
+	my ($pref, $type, $value, $data) = @_;
+	
+	print "pref changed: [$pref]($type)=$value data=$data\n";
+}
+
 sub plugin_init { 
 	
 	return %PLUGIN_INFO; 
 } 
 
-
 # This is the sub defined in %PLUGIN_INFO to be called when the plugin is loaded
 #	Note: The plugin has a reference to itself on top of the argument stack.
 sub plugin_load { 
@@ -75,7 +80,11 @@
 	Purple::Prefs::add_bool("/plugins/core/perl_test/bool", 1);	
 	Purple::Prefs::add_string("/plugins/core/perl_test/choice", "ch1");	
 	Purple::Prefs::add_string("/plugins/core/perl_test/text", "Foobar");	
-	
+
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test", \&pref_cb, "none");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/bool", \&pref_cb, "bool");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/choice", \&pref_cb, "choice");
+	Purple::Prefs::connect_callback($plugin, "/plugins/core/perl_test/text", \&pref_cb, "text");
 
 	print "\n\n" . "#" x 80 . "\n\n";
 } 
--- a/libpurple/protocols/jabber/Makefile.mingw	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/jabber/Makefile.mingw	Thu Jul 31 06:23:55 2008 +0000
@@ -88,10 +88,6 @@
 LIB_PATHS += -L$(CYRUS_SASL_TOP)/bin
 LIBS += -llibsasl
 CYRUS_SASL_DLLS = \
-			$(CYRUS_SASL_TOP)/bin/comerr32.dll \
-			$(CYRUS_SASL_TOP)/bin/gssapi32.dll \
-			$(CYRUS_SASL_TOP)/bin/k5sprt32.dll \
-			$(CYRUS_SASL_TOP)/bin/krb5_32.dll \
 			$(CYRUS_SASL_TOP)/bin/libsasl.dll
 
 CYRUS_SASL_PLUGINS = \
--- a/libpurple/protocols/jabber/libxmpp.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/jabber/libxmpp.c	Thu Jul 31 06:23:55 2008 +0000
@@ -194,6 +194,7 @@
 {
 #ifdef HAVE_CYRUS_SASL
 #ifdef _WIN32
+	UINT old_error_mode;
 	gchar *sasldir;
 #endif
 	int ret;
@@ -250,10 +251,16 @@
 	sasldir = g_build_filename(wpurple_install_dir(), "sasl2", NULL);
 	sasl_set_path(SASL_PATH_TYPE_PLUGIN, sasldir);
 	g_free(sasldir);
+	/* Suppress error popups for failing to load sasl plugins */
+	old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
 #endif
 	if ((ret = sasl_client_init(NULL)) != SASL_OK) {
 		purple_debug_error("xmpp", "Error (%d) initializing SASL.\n", ret);
 	}
+#ifdef _WIN32
+	/* Restore the original error mode */
+	SetErrorMode(old_error_mode);
+#endif
 #endif
 	jabber_register_commands();
 	
--- a/libpurple/protocols/msn/contact.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/contact.c	Thu Jul 31 06:23:55 2008 +0000
@@ -228,8 +228,8 @@
 	msn_soap_message_send(session,
 		msn_soap_message_new(MSN_ADD_ADDRESSBOOK_SOAP_ACTION,
 			xmlnode_from_str(body, -1)),
-		MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, msn_create_address_cb,
-		session);
+		MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE,
+		msn_create_address_cb, session);
 
 	g_free(body);
 }
@@ -415,7 +415,7 @@
 	msn_soap_message_send(session,
 		msn_soap_message_new(MSN_GET_CONTACT_SOAP_ACTION,
 			xmlnode_from_str(body, -1)),
-		MSN_CONTACT_SERVER, MSN_GET_CONTACT_POST_URL,
+		MSN_CONTACT_SERVER, MSN_GET_CONTACT_POST_URL, FALSE,
 		msn_get_contact_list_cb, g_memdup(&cb_data, sizeof(cb_data)));
 
 	g_free(update_str);
@@ -815,8 +815,8 @@
 	msn_soap_message_send(session,
 		msn_soap_message_new(MSN_GET_ADDRESS_SOAP_ACTION,
 			xmlnode_from_str(body, -1)),
-		MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, msn_get_address_cb,
-		session);
+		MSN_CONTACT_SERVER, MSN_ADDRESS_BOOK_POST_URL, FALSE,
+		msn_get_address_cb, session);
 
 	g_free(update_str);
 	g_free(body);
@@ -917,7 +917,8 @@
 		msn_nexus_get_token_str(state->session->nexus, MSN_AUTH_CONTACTS), -1);
 	msn_soap_message_send(state->session,
 		msn_soap_message_new(state->post_action, xmlnode_copy(state->body)),
-		MSN_CONTACT_SERVER, state->post_url, msn_contact_request_cb, state);
+		MSN_CONTACT_SERVER, state->post_url, FALSE,
+		msn_contact_request_cb, state);
 	return FALSE;
 }
 
--- a/libpurple/protocols/msn/msn.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/msn.c	Thu Jul 31 06:23:55 2008 +0000
@@ -452,25 +452,27 @@
 	gc = (PurpleConnection *) action->context;
 	session = gc->proto_data;
 
+	if (!session->passport_info.email_enabled) {
+		purple_notify_error(gc, NULL,
+						  _("This account does not have email enabled."), NULL);
+		return;
+	}
+
 	/** apparently the correct value is 777, use 750 as a failsafe */ 
-	if (time (NULL) - session->passport_info.mail_timestamp >= 750) {
+	if ((session->passport_info.mail_url == NULL)
+		|| (time (NULL) - session->passport_info.mail_timestamp >= 750)) {
 		MsnTransaction *trans;
 		MsnCmdProc *cmdproc;
 
 		cmdproc = session->notification->cmdproc;
 
 		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
-		msn_transaction_set_data(trans, GUINT_TO_POINTER (TRUE));
+		msn_transaction_set_data(trans, GUINT_TO_POINTER(TRUE));
 
 		msn_cmdproc_send_trans(cmdproc, trans);
 
-	} else if (session->passport_info.file != NULL) {
-		purple_notify_uri(gc, session->passport_info.file);
-
-	} else {
-		purple_notify_error(gc, NULL,
-						  _("This Hotmail account may not be active."), NULL);
-	}
+	} else
+		purple_notify_uri(gc, session->passport_info.mail_url);
 }
 
 static void
@@ -605,17 +607,23 @@
 msn_can_receive_file(PurpleConnection *gc, const char *who)
 {
 	PurpleAccount *account;
-	char *normal;
+	gchar *normal;
 	gboolean ret;
 
 	account = purple_connection_get_account(gc);
 
 	normal = g_strdup(msn_normalize(account, purple_account_get_username(account)));
-
 	ret = strcmp(normal, msn_normalize(account, who));
-
 	g_free(normal);
 
+	if (ret) {
+		MsnSession *session = gc->proto_data;
+		MsnUser *user = msn_userlist_find_user(session->userlist, who);
+		if (user)
+			ret = (user->clientid & MSN_CLIENT_CAP_WEBMSGR) == 0;
+		/* Include these too: MSN_CLIENT_CAP_MSNMOBILE|MSN_CLIENT_CAP_MSNDIRECT ? */
+	}
+
 	return ret;
 }
 
@@ -638,14 +646,14 @@
 		if (user->clientid & MSN_CLIENT_CAP_BOT)
 			return "bot";
 		if (user->clientid & MSN_CLIENT_CAP_WIN_MOBILE)
-			return "hiptop"; /* XXX: Rename to Mobile / Use different icon? */
+			return "mobile";
 #if 0
 		/* XXX: Since we don't support this, there's no point in showing it just yet */
 		if (user->clientid & MSN_CLIENT_CAP_SCHANNEL)
 			return "secure";
 #endif
 		if (user->clientid & MSN_CLIENT_CAP_WEBMSGR)
-			return "web";
+			return "external";
 		if (user->networkid == MSN_NETWORK_YAHOO)
 			return "yahoo";
 	}
@@ -1367,6 +1375,7 @@
 
 	if (group_id >= 0)
 	{
+		/* This is wrong... user->group_ids contains g_strdup()'d data now */
 		user->group_ids = g_list_append(user->group_ids,
 										GINT_TO_POINTER(group_id));
 	}
--- a/libpurple/protocols/msn/nexus.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/nexus.c	Thu Jul 31 06:23:55 2008 +0000
@@ -411,7 +411,7 @@
 
 	soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
 	g_free(request);
-	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL,
+	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
 	                      nexus_got_response_cb, nexus);
 }
 
@@ -597,7 +597,7 @@
 
 	soap = msn_soap_message_new(NULL, xmlnode_from_str(request, -1));
 	g_free(request);
-	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL,
+	msn_soap_message_send(session, soap, MSN_SSO_SERVER, SSO_POST_URL, TRUE,
 	                      nexus_got_update_cb, ud);
 }
 
--- a/libpurple/protocols/msn/notification.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/notification.c	Thu Jul 31 06:23:55 2008 +0000
@@ -1289,7 +1289,6 @@
 	const char *url;
 	PurpleCipherContext *cipher;
 	gchar digest[33];
-	FILE *fd;
 	char *buf;
 
 	gulong tmp_timestamp;
@@ -1316,111 +1315,19 @@
 
 	g_free(buf);
 
-	if (session->passport_info.file != NULL)
-	{
-		g_unlink(session->passport_info.file);
-		g_free(session->passport_info.file);
-	}
-
-	if ((fd = purple_mkstemp(&session->passport_info.file, FALSE)) == NULL)
-	{
-		purple_debug_error("msn",
-						 "Error opening temp passport file: %s\n",
-						 g_strerror(errno));
-		/* The user wanted to check his or her email */
-		if (cmd->trans && cmd->trans->data)
-			/* TODO: This error might be a bit technical... */
-			purple_notify_error(gc, NULL,
-							  _("Error opening temporary passport file."), NULL);
-	}
-	else
-	{
-#ifdef _WIN32
-		fputs("<!-- saved from url=(0013)about:internet -->\n", fd);
-#endif
-		fputs("<html>\n"
-			  "<head>\n"
-			  "<noscript>\n"
-			  "<meta http-equiv=\"Refresh\" content=\"0; "
-			  "url=http://www.hotmail.com\">\n"
-			  "</noscript>\n"
-			  "</head>\n\n",
-			  fd);
+	g_free(session->passport_info.mail_url);
+	session->passport_info.mail_url = g_strdup_printf("%s&auth=%s&creds=%s&sl=%ld&username=%s&mode=ttl&sid=%s&id=2&rru=%ssvc_mail&js=yes",
+                                                        url,
+                                                        session->passport_info.mspauth ? session->passport_info.mspauth : "BOGUS",
+                                                        buf,
+                                                        tmp_timestamp,
+                                                        msn_user_get_passport(session->user),
+                                                        session->passport_info.sid,
+                                                        rru);
 
-		fprintf(fd, "<body onload=\"document.pform.submit(); \">\n");
-		fprintf(fd, "<form name=\"pform\" action=\"%s\" method=\"POST\">\n\n",
-				url);
-		fprintf(fd, "<input type=\"hidden\" name=\"mode\" value=\"ttl\">\n");
-		fprintf(fd, "<input type=\"hidden\" name=\"login\" value=\"%s\">\n",
-				purple_account_get_username(account));
-		fprintf(fd, "<input type=\"hidden\" name=\"username\" value=\"%s\">\n",
-				purple_account_get_username(account));
-		if (session->passport_info.sid != NULL)
-			fprintf(fd, "<input type=\"hidden\" name=\"sid\" value=\"%s\">\n",
-					session->passport_info.sid);
-		if (session->passport_info.kv != NULL)
-			fprintf(fd, "<input type=\"hidden\" name=\"kv\" value=\"%s\">\n",
-					session->passport_info.kv);
-		fprintf(fd, "<input type=\"hidden\" name=\"id\" value=\"2\">\n");
-		fprintf(fd, "<input type=\"hidden\" name=\"sl\" value=\"%ld\">\n",
-				tmp_timestamp);
-		fprintf(fd, "<input type=\"hidden\" name=\"rru\" value=\"%s\">\n",
-				rru);
-		if (session->passport_info.mspauth != NULL)
-			fprintf(fd, "<input type=\"hidden\" name=\"auth\" value=\"%s\">\n",
-					session->passport_info.mspauth);
-		fprintf(fd, "<input type=\"hidden\" name=\"creds\" value=\"%s\">\n",
-				digest); /* TODO Digest me (huh? -- ChipX86) */
-		fprintf(fd, "<input type=\"hidden\" name=\"svc\" value=\"mail\">\n");
-		fprintf(fd, "<input type=\"hidden\" name=\"js\" value=\"yes\">\n");
-		fprintf(fd, "</form></body>\n");
-		fprintf(fd, "</html>\n");
-
-		if (fclose(fd))
-		{
-			purple_debug_error("msn",
-							 "Error closing temp passport file: %s\n",
-							 g_strerror(errno));
-
-			/* The user wanted to check his or her email */
-			if (cmd->trans && cmd->trans->data)
-				/* TODO: This error might be a bit technical... */
-				purple_notify_error(gc, NULL,
-								  _("Error closing temporary passport file."), NULL);
-
-			g_unlink(session->passport_info.file);
-			g_free(session->passport_info.file);
-			session->passport_info.file = NULL;
-		}
-#ifdef _WIN32
-		else
-		{
-			/*
-			 * Renaming file with .html extension, so that the
-			 * win32 open_url will work.
-			 */
-			char *tmp;
-
-			if ((tmp =
-				g_strdup_printf("%s.html",
-					session->passport_info.file)) != NULL)
-			{
-				if (g_rename(session->passport_info.file,
-							tmp) == 0)
-				{
-					g_free(session->passport_info.file);
-					session->passport_info.file = tmp;
-				}
-				else
-					g_free(tmp);
-			}
-		}
-#endif
-
-		/* The user wants to check his or her email */
-		if (cmd->trans && cmd->trans->data)
-			purple_notify_uri(purple_account_get_connection(account), session->passport_info.file);
-	}
+	/* The user wants to check his or her email */
+	if (cmd->trans && cmd->trans->data)
+		purple_notify_uri(purple_account_get_connection(account), session->passport_info.mail_url);
 }
 /**************************************************************************
  * Switchboards
@@ -1666,6 +1573,9 @@
 	if ((value = msn_message_get_attr(msg, "LoginTime")) != NULL)
 		session->passport_info.sl = atol(value);
 
+	if ((value = msn_message_get_attr(msg, "EmailEnabled")) != NULL)
+		session->passport_info.email_enabled = (gboolean)atol(value);
+
 	/*starting retrieve the contact list*/
 	clLastChange = purple_account_get_string(session->account, "CLLastChange", NULL);
 #ifdef MSN_PARTIAL_LISTS
@@ -1696,7 +1606,7 @@
 		/* This isn't an official message. */
 		return;
 
-	if (session->passport_info.file == NULL)
+	if (session->passport_info.mail_url == NULL)
 	{
 		MsnTransaction *trans;
 		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
@@ -1724,7 +1634,7 @@
 			const char *url;
 
 			passport = msn_user_get_passport(session->user);
-			url = session->passport_info.file;
+			url = session->passport_info.mail_url;
 
 			purple_notify_emails(gc, count, FALSE, NULL, NULL,
 							   &passport, &url, NULL, NULL);
@@ -1763,7 +1673,7 @@
 		return;
 	}
 
-	if (session->passport_info.file == NULL)
+	if (session->passport_info.mail_url == NULL)
 	{
 		MsnTransaction *trans;
 		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
@@ -1793,7 +1703,7 @@
 			const char *url;
 
 			passport = msn_user_get_passport(session->user);
-			url = session->passport_info.file;
+			url = session->passport_info.mail_url;
 
 			purple_notify_emails(gc, count, FALSE, NULL, NULL,
 							   &passport, &url, NULL, NULL);
@@ -1825,7 +1735,7 @@
 		/* This isn't an official message. */
 		return;
 
-	if (session->passport_info.file == NULL)
+	if (session->passport_info.mail_url == NULL)
 	{
 		MsnTransaction *trans;
 		trans = msn_transaction_new(cmdproc, "URL", "%s", "INBOX");
@@ -1855,7 +1765,7 @@
 					  (subject != NULL ? subject : ""),
 					  (from != NULL ?  from : ""),
 					  msn_user_get_passport(session->user),
-					  session->passport_info.file, NULL, NULL);
+					  session->passport_info.mail_url, NULL, NULL);
 
 	g_free(from);
 	g_free(subject);
--- a/libpurple/protocols/msn/oim.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/oim.c	Thu Jul 31 06:23:55 2008 +0000
@@ -219,7 +219,8 @@
 
 	msn_soap_message_send(session,
 		msn_soap_message_new(data->action, xmlnode_copy(data->body)),
-		data->host, data->url, msn_oim_request_cb, data);
+		data->host, data->url, FALSE,
+		msn_oim_request_cb, data);
 }
 
 
@@ -692,7 +693,7 @@
 	{
 		char *unread = xmlnode_get_data(iu_node);
 		const char *passport = msn_user_get_passport(session->user);
-		const char *url = session->passport_info.file;
+		const char *url = session->passport_info.mail_url;
 		int count = atoi(unread);
 
 		/* XXX/khc: pretty sure this is wrong */
--- a/libpurple/protocols/msn/session.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/session.c	Thu Jul 31 06:23:55 2008 +0000
@@ -80,11 +80,7 @@
 	g_free(session->passport_info.mspauth);
 	g_free(session->passport_info.client_ip);
 
-	if (session->passport_info.file != NULL)
-	{
-		g_unlink(session->passport_info.file);
-		g_free(session->passport_info.file);
-	}
+	g_free(session->passport_info.mail_url);
 
 	if (session->sync != NULL)
 		msn_sync_destroy(session->sync);
--- a/libpurple/protocols/msn/session.h	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/session.h	Thu Jul 31 06:23:55 2008 +0000
@@ -115,10 +115,11 @@
 		char *sid;
 		char *mspauth;
 		unsigned long sl;
-		char *file;
 		char *client_ip;
 		int client_port;
+		char *mail_url;
 		gulong mail_timestamp;
+		gboolean email_enabled;
 	} passport_info;
 
 	GHashTable *soap_table;
--- a/libpurple/protocols/msn/soap.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/soap.c	Thu Jul 31 06:23:55 2008 +0000
@@ -42,6 +42,7 @@
 typedef struct _MsnSoapRequest {
 	char *path;
 	MsnSoapMessage *message;
+	gboolean secure;
 	MsnSoapCallback cb;
 	gpointer cb_data;
 } MsnSoapRequest;
@@ -76,8 +77,8 @@
 static void msn_soap_connection_handle_next(MsnSoapConnection *conn);
 static void msn_soap_connection_destroy(MsnSoapConnection *conn);
 
-static void msn_soap_message_send_internal(MsnSession *session,
-	MsnSoapMessage *message, const char *host, const char *path,
+static void msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
+	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data, gboolean first);
 
 static void msn_soap_request_destroy(MsnSoapRequest *req, gboolean keep_message);
@@ -187,8 +188,8 @@
 	char *path;
 
 	if (purple_url_parse(url, &host, NULL, &path, NULL, NULL)) {
-		msn_soap_message_send_internal(conn->session,
-			conn->current_request->message,	host, path,
+		msn_soap_message_send_internal(conn->session, conn->current_request->message,
+			host, path, conn->current_request->secure,
 			conn->current_request->cb, conn->current_request->cb_data, TRUE);
 
 		msn_soap_request_destroy(conn->current_request, TRUE);
@@ -309,6 +310,11 @@
 	char *cursor;
 	char *linebreak;
 
+#ifndef MSN_UNSAFE_DEBUG
+	if (conn->current_request->secure)
+		purple_debug_info("soap", "Received secure request.\n");
+	else
+#endif
 	purple_debug_info("soap", "current %s\n", conn->buf->str);
 
 	cursor = conn->buf->str + conn->handled_len;
@@ -506,6 +512,11 @@
 			g_string_append(conn->buf, "\r\n");
 			g_string_append(conn->buf, body);
 
+#ifndef MSN_UNSAFE_DEBUG
+			if (req->secure)
+				purple_debug_info("soap", "Sending secure request.\n");
+			else
+#endif
 			purple_debug_info("soap", "%s\n", conn->buf->str);
 
 			conn->handled_len = 0;
@@ -534,16 +545,16 @@
 
 void
 msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
-	const char *host, const char *path,
+	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data)
 {
-	msn_soap_message_send_internal(session, message, host, path, cb, cb_data,
-		FALSE);
+	msn_soap_message_send_internal(session, message, host, path, secure,
+		cb, cb_data, FALSE);
 }
 
 static void
-msn_soap_message_send_internal(MsnSession *session,
-	MsnSoapMessage *message, const char *host, const char *path,
+msn_soap_message_send_internal(MsnSession *session, MsnSoapMessage *message,
+	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data, gboolean first)
 {
 	MsnSoapConnection *conn = msn_soap_get_connection(session, host);
@@ -551,6 +562,7 @@
 
 	req->path = g_strdup(path);
 	req->message = message;
+	req->secure = secure;
 	req->cb = cb;
 	req->cb_data = cb_data;
 
--- a/libpurple/protocols/msn/soap.h	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/soap.h	Thu Jul 31 06:23:55 2008 +0000
@@ -47,8 +47,8 @@
 void msn_soap_message_add_header(MsnSoapMessage *req,
 	const char *name, const char *value);
 
-void msn_soap_message_send(MsnSession *session,
-	MsnSoapMessage *message, const char *host, const char *path,
+void msn_soap_message_send(MsnSession *session, MsnSoapMessage *message,
+	const char *host, const char *path, gboolean secure,
 	MsnSoapCallback cb, gpointer cb_data);
 
 void msn_soap_message_destroy(MsnSoapMessage *message);
--- a/libpurple/protocols/msn/user.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/protocols/msn/user.c	Thu Jul 31 06:23:55 2008 +0000
@@ -235,21 +235,19 @@
 
 /*add group id to User object*/
 void
-msn_user_add_group_id(MsnUser *user, const char* id)
+msn_user_add_group_id(MsnUser *user, const char* group_id)
 {
 	MsnUserList *userlist;
 	PurpleAccount *account;
 	PurpleBuddy *b;
 	PurpleGroup *g;
 	const char *passport;
-	char *group_id;
 	const char *group_name;
 
 	g_return_if_fail(user != NULL);
-	g_return_if_fail(id != NULL);
+	g_return_if_fail(group_id != NULL);
 
-	group_id = g_strdup(id);
-	user->group_ids = g_list_append(user->group_ids, group_id);
+	user->group_ids = g_list_append(user->group_ids, g_strdup(group_id));
 
 	userlist = user->userlist;
 	account = userlist->session->account;
@@ -261,7 +259,7 @@
 
 	g = purple_find_group(group_name);
 
-	if ((id == NULL) && (g == NULL))
+	if ((group_id == NULL) && (g == NULL))
 	{
 		g = purple_group_new(group_name);
 		purple_blist_add_group(g, NULL);
--- a/libpurple/win32/global.mak	Mon Jul 28 06:18:51 2008 +0000
+++ b/libpurple/win32/global.mak	Thu Jul 31 06:23:55 2008 +0000
@@ -20,7 +20,7 @@
 NSPR_TOP ?= $(WIN32_DEV_TOP)/nspr-4.6.4
 NSS_TOP ?= $(WIN32_DEV_TOP)/nss-3.11.4
 PERL_LIB_TOP ?= $(WIN32_DEV_TOP)/perl-5.10.0
-SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.5
+SILC_TOOLKIT ?= $(WIN32_DEV_TOP)/silc-toolkit-1.1.7
 TCL_LIB_TOP ?= $(WIN32_DEV_TOP)/tcl-8.4.5
 GSTREAMER_TOP ?= $(WIN32_DEV_TOP)/gstreamer-0.10.13
 
--- a/pidgin/gtkdialogs.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/pidgin/gtkdialogs.c	Thu Jul 31 06:23:55 2008 +0000
@@ -73,7 +73,8 @@
 	{"John 'rekkanoryo' Bailey",	N_("developer"), NULL},
 	{"Ethan 'Paco-Paco' Blanton",	N_("developer"), NULL},
 	{"Thomas Butter",				N_("developer"), NULL},
-	{"Ka-Hing Cheung",				N_("developer"), NULL},
+	/* feel free to not translate this */
+	{N_("Ka-Hing Cheung"),			N_("developer"), NULL},
 	{"Sadrul Habib Chowdhury",		N_("developer"), NULL},
 	{"Mark 'KingAnt' Doliner",		N_("developer"), "mark@kingant.net"},
 	{"Sean Egan",					N_("developer"), "sean.egan@gmail.com"},
@@ -85,6 +86,7 @@
 	{"Bartosz Oler",		N_("developer"), NULL},
 	{"Etan 'deryni' Reisner",       N_("developer"), NULL},
 	{"Tim 'marv' Ringenbach",		N_("developer"), NULL},
+	{"Elliott 'QuLogic' Sales de Andrade",	N_("developer"),	NULL},
 	{"Luke 'LSchiere' Schierer",	N_("support"), "lschiere@users.sf.net"},
 	{"Megan 'Cae' Schneider",       N_("support/QA"), NULL},
 	{"Evan Schoenberg",		N_("developer"), NULL},
@@ -100,7 +102,6 @@
 	{"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},
 	{"Gabriel 'Nix' Schulhof", 	NULL, 	NULL},
 	{"Jorge 'Masca' Villaseñor", 	NULL, 	NULL},
 	{NULL, NULL, NULL}
@@ -424,11 +425,11 @@
 	for (i = 0; developers[i].name != NULL; i++) {
 		if (developers[i].email != NULL) {
 			g_string_append_printf(str, "  %s (%s) &lt;<a href=\"mailto:%s\">%s</a>&gt;<br/>",
-					developers[i].name, _(developers[i].role),
+					_(developers[i].name), _(developers[i].role),
 					developers[i].email, developers[i].email);
 		} else {
 			g_string_append_printf(str, "  %s (%s)<br/>",
-					developers[i].name, _(developers[i].role));
+					_(developers[i].name), _(developers[i].role));
 		}
 	}
 	g_string_append(str, "<BR/>");
--- a/pidgin/gtkroomlist.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/pidgin/gtkroomlist.c	Thu Jul 31 06:23:55 2008 +0000
@@ -53,7 +53,6 @@
 	PurpleRoomlist *roomlist;
 
 	gboolean pg_needs_pulse;
-	gboolean pg_to_active;
 	guint pg_update_to;
 } PidginRoomlistDialog;
 
@@ -84,32 +83,34 @@
 
 static gint delete_win_cb(GtkWidget *w, GdkEventAny *e, gpointer d)
 {
-	PidginRoomlistDialog *dialog;
-
-	dialog = (PidginRoomlistDialog *) d;
+	PidginRoomlistDialog *dialog = d;
 
 	if (dialog->roomlist && purple_roomlist_get_in_progress(dialog->roomlist))
 		purple_roomlist_cancel_get_list(dialog->roomlist);
 
+	if (dialog->pg_update_to > 0)
+		purple_timeout_remove(dialog->pg_update_to);
+
 	if (dialog->roomlist) {
-		if (dialog->pg_to_active) {
-			purple_timeout_remove(dialog->pg_update_to);
-			dialog->pg_to_active = FALSE;
+		PidginRoomlist *rl = dialog->roomlist->ui_data;
+
+		if (dialog->pg_update_to > 0)
 			/* yes, that's right, unref it twice. */
 			purple_roomlist_unref(dialog->roomlist);
-		}
+
+		if (rl)
+			rl->dialog = NULL;
+		purple_roomlist_unref(dialog->roomlist);
 	}
 
-	/* free stuff here */
-	if (dialog->roomlist)
-		purple_roomlist_unref(dialog->roomlist);
+	dialog->progress = NULL;
 	g_free(dialog);
 
 	return FALSE;
 }
 
 static void dialog_select_account_cb(GObject *w, PurpleAccount *account,
-                                     PidginRoomlistDialog *dialog)
+				     PidginRoomlistDialog *dialog)
 {
 	dialog->account = account;
 }
@@ -186,9 +187,7 @@
 	GValue val;
 	PurpleRoomlistRoom *room;
 	static struct _menu_cb_info *info;
-	PidginRoomlistDialog *dialog;
-
-	dialog = grl->dialog;
+	PidginRoomlistDialog *dialog = grl->dialog;
 
 	if (gtk_tree_selection_get_selected(selection, NULL, &iter)) {
 		val.g_type = 0;
@@ -239,9 +238,7 @@
 {
 	PurpleRoomlist *rl = dialog->roomlist;
 	PidginRoomlist *grl = rl->ui_data;
-	struct _menu_cb_info *info;
-
-	info = (struct _menu_cb_info*)g_object_get_data(G_OBJECT(button), "room-info");
+	struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info");
 
 	if(info != NULL)
 		do_add_room_cb(grl->tree, info);
@@ -256,9 +253,7 @@
 {
 	PurpleRoomlist *rl = dialog->roomlist;
 	PidginRoomlist *grl = rl->ui_data;
-	struct _menu_cb_info *info;
-
-	info = (struct _menu_cb_info*)g_object_get_data(G_OBJECT(button), "room-info");
+	struct _menu_cb_info *info = g_object_get_data(G_OBJECT(button), "room-info");
 
 	if(info != NULL)
 		do_join_cb(grl->tree, info);
@@ -490,12 +485,13 @@
 
 static gboolean account_filter_func(PurpleAccount *account)
 {
-	PurpleConnection *gc = purple_account_get_connection(account);
+	PurpleConnection *conn = purple_account_get_connection(account);
 	PurplePluginProtocolInfo *prpl_info = NULL;
 
-	prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(gc->prpl);
+	if (conn)
+		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(conn->prpl);
 
-	return (prpl_info->roomlist_get_list != NULL);
+	return (prpl_info && prpl_info->roomlist_get_list != NULL);
 }
 
 gboolean
@@ -518,10 +514,7 @@
 pidgin_roomlist_dialog_new_with_account(PurpleAccount *account)
 {
 	PidginRoomlistDialog *dialog;
-	GtkWidget *window;
-	GtkWidget *vbox;
-	GtkWidget *vbox2;
-	GtkWidget *bbox;
+	GtkWidget *window, *vbox, *vbox2, *bbox;
 
 	dialog = g_new0(PidginRoomlistDialog, 1);
 	dialog->account = account;
@@ -611,9 +604,8 @@
 
 void pidgin_roomlist_dialog_show_with_account(PurpleAccount *account)
 {
-	PidginRoomlistDialog *dialog;
+	PidginRoomlistDialog *dialog = pidgin_roomlist_dialog_new_with_account(account);
 
-	dialog = pidgin_roomlist_dialog_new_with_account(account);
 	if (!dialog)
 		return;
 
@@ -627,9 +619,7 @@
 
 static void pidgin_roomlist_new(PurpleRoomlist *list)
 {
-	PidginRoomlist *rl;
-
-	rl = g_new0(PidginRoomlist, 1);
+	PidginRoomlist *rl = g_new0(PidginRoomlist, 1);
 
 	list->ui_data = rl;
 
@@ -802,7 +792,7 @@
 
 	if (!rl || !rl->dialog || !rl->dialog->pg_needs_pulse) {
 		if (rl && rl->dialog)
-			rl->dialog->pg_to_active = FALSE;
+			rl->dialog->pg_update_to = 0;
 		purple_roomlist_unref(list);
 		return FALSE;
 	}
@@ -827,15 +817,14 @@
 		rl->num_rooms++;
 
 	if (rl->dialog) {
-		if (!rl->dialog->pg_to_active) {
-			rl->dialog->pg_to_active = TRUE;
+		if (rl->dialog->pg_update_to == 0) {
 			purple_roomlist_ref(list);
 			rl->dialog->pg_update_to = g_timeout_add(100, pidgin_progress_bar_pulse, list);
 			gtk_progress_bar_pulse(GTK_PROGRESS_BAR(rl->dialog->progress));
-		} else {
+		} else
 			rl->dialog->pg_needs_pulse = TRUE;
-		}
 	}
+
 	if (room->parent) {
 		parentrr = g_hash_table_lookup(rl->cats, room->parent);
 		path = gtk_tree_row_reference_get_path(parentrr);
@@ -881,14 +870,14 @@
 	}
 }
 
-static void pidgin_roomlist_in_progress(PurpleRoomlist *list, gboolean flag)
+static void pidgin_roomlist_in_progress(PurpleRoomlist *list, gboolean in_progress)
 {
 	PidginRoomlist *rl = list->ui_data;
 
 	if (!rl || !rl->dialog)
 		return;
 
-	if (flag) {
+	if (in_progress) {
 		if (rl->dialog->account_widget)
 			gtk_widget_set_sensitive(rl->dialog->account_widget, FALSE);
 		gtk_widget_set_sensitive(rl->dialog->stop_button, TRUE);
@@ -905,12 +894,10 @@
 
 static void pidgin_roomlist_destroy(PurpleRoomlist *list)
 {
-	PidginRoomlist *rl;
+	PidginRoomlist *rl = list->ui_data;
 
 	roomlists = g_list_remove(roomlists, list);
 
-	rl = list->ui_data;
-
 	g_return_if_fail(rl != NULL);
 
 	g_hash_table_destroy(rl->cats);
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Mon Jul 28 06:18:51 2008 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Thu Jul 31 06:23:55 2008 +0000
@@ -376,7 +376,7 @@
     StrCmp $R0 "2" +2 ; Upgrade isn't optional
     MessageBox MB_YESNO $(GTK_UPGRADE_PROMPT) /SD IDYES IDNO done
     ClearErrors
-    ExecWait '"$TEMP\gtk-runtime.exe" /L=$LANGUAGE /S /D=$GTK_FOLDER'
+    ExecWait '"$TEMP\gtk-runtime.exe" /L=$LANGUAGE $ISSILENT /D=$GTK_FOLDER'
     IfErrors gtk_install_error done
 
     gtk_install_error:
@@ -515,10 +515,6 @@
       Delete "$INSTDIR\libsilc-1-1-2.dll"
       ;GSSAPI
       Delete "$INSTDIR\sasl2\saslGSSAPI.dll"
-      Delete "$INSTDIR\gssapi32.dll"
-      Delete "$INSTDIR\k5sprt32.dll"
-      Delete "$INSTDIR\krb5_32.dll"
-      Delete "$INSTDIR\comerr32.dll"
     ${EndIf}
 
     SetOutPath "$INSTDIR"
@@ -1315,12 +1311,12 @@
   ;Reset ShellVarContext because we may have changed it
   SetShellVarContext "current"
 
-  StrCpy $ISSILENT "/NOUI"
+  StrCpy $ISSILENT "/S"
 
   ; GTK installer has two silent states.. one with Message boxes, one without
   ; If pidgin installer was run silently, we want to supress gtk installer msg boxes.
   IfSilent 0 set_gtk_normal
-      StrCpy $ISSILENT "/S"
+      StrCpy $ISSILENT "/NOUI"
   set_gtk_normal:
 
   ${GetParameters} $R0
--- a/pidgin/win32/winpidgin.c	Mon Jul 28 06:18:51 2008 +0000
+++ b/pidgin/win32/winpidgin.c	Thu Jul 31 06:23:55 2008 +0000
@@ -441,45 +441,77 @@
 	_putenv(envstr);
 }
 
-static void winpidgin_add_perl_to_path() {
+
+static void winpidgin_add_stuff_to_path() {
 	char perl_path[MAX_PATH + 1];
-	DWORD plen = sizeof(perl_path);
+	char *ppath = NULL;
+	char mit_kerberos_path[MAX_PATH + 1];
+	char *mpath = NULL;
+	DWORD plen;
 
 	printf("%s", "Looking for Perl... ");
 
+	plen = sizeof(perl_path);
 	if (read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\Perl", "",
 			    (LPBYTE) &perl_path, &plen)) {
-		const char *path = getenv("PATH");
-		/* Enough to add "PATH=" + ";"  + perl_path + "\\bin" + \0 */
-
 		/* We *could* check for perl510.dll, but it seems unnecessary. */
-
 		printf("found in '%s'.\n", perl_path);
 
-		if (perl_path[strlen(perl_path) - 1] != '\\') {
+		if (perl_path[strlen(perl_path) - 1] != '\\')
 			strcat(perl_path, "\\");
-		}
 		strcat(perl_path, "bin");
 
-		if (!strstr(path, perl_path)) {
-			int newlen = (path ? strlen(path) : 0) + strlen(perl_path) + 10;
-			char *newpath = malloc(newlen);
+		ppath = perl_path;
+	} else
+		printf("%s", "not found.\n");
+
+	printf("%s", "Looking for MIT Kerberos... ");
+
+	plen = sizeof(mit_kerberos_path);
+	if (read_reg_string(HKEY_LOCAL_MACHINE, "SOFTWARE\\MIT\\Kerberos", "InstallDir",
+			    (LPBYTE) &mit_kerberos_path, &plen)) {
+		/* We *could* check for gssapi32.dll */
+		printf("found in '%s'.\n", mit_kerberos_path);
+
+		if (mit_kerberos_path[strlen(mit_kerberos_path) - 1] != '\\')
+			strcat(mit_kerberos_path, "\\");
+		strcat(mit_kerberos_path, "bin");
+
+		mpath = mit_kerberos_path;
+	} else
+		printf("%s", "not found.\n");
+
+	if (ppath != NULL || mpath != NULL) {
+		const char *path = getenv("PATH");
+		BOOL add_ppath = ppath != NULL && (path == NULL || !strstr(path, ppath));
+		BOOL add_mpath = mpath != NULL && (path == NULL || !strstr(path, mpath));
+		char *newpath;
+		int newlen;
+
+		if (add_ppath || add_mpath) {
+			/* Enough to add "PATH=" + path + ";"  + ppath + ";" + mpath + \0 */
+			newlen = 6 + (path ? strlen(path) + 1 : 0);
+			if (add_ppath)
+				newlen += strlen(ppath) + 1;
+			if (add_mpath)
+				newlen += strlen(mpath) + 1;
+			newpath = malloc(newlen);
 			*newpath = '\0';
 
-			_snprintf(newpath, newlen, "PATH=%s%s%s",
+			_snprintf(newpath, newlen, "PATH=%s%s%s%s%s%s",
 				  path ? path : "",
 				  path ? ";" : "",
-				  perl_path);
+				  add_ppath ? ppath : "",
+				  add_ppath ? ";" : "",
+				  add_mpath ? mpath : "",
+				  add_mpath ? ";" : "");
 
-			printf("Adding Perl to PATH: %s\n", newpath);
+			printf("New PATH: %s\n", newpath);
 
 			_putenv(newpath);
 			free(newpath);
-		} else
-			printf("%s\n", "Perl already in PATH.");
-	} else
-		printf("%s", "not found.\n");
-
+		}
+	}
 }
 
 #define PIDGIN_WM_FOCUS_REQUEST (WM_APP + 13)
@@ -672,7 +704,7 @@
 
 	winpidgin_set_locale();
 
-	winpidgin_add_perl_to_path();
+	winpidgin_add_stuff_to_path();
 
 	/* If help, version or multiple flag used, do not check Mutex */
 	if (!strstr(lpszCmdLine, "-h") && !strstr(lpszCmdLine, "-v"))
--- a/po/zh_CN.po	Mon Jul 28 06:18:51 2008 +0000
+++ b/po/zh_CN.po	Thu Jul 31 06:23:55 2008 +0000
@@ -17454,3 +17454,8 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr "此插件用于调试 XMPP 服务器或客户端。"
 
+#. feel free to not translate this
+#: ../pidgin/gtkdialogs.c:77
+msgid "Ka-Hing Cheung"
+msgstr "张家兴"
+
--- a/po/zh_TW.po	Mon Jul 28 06:18:51 2008 +0000
+++ b/po/zh_TW.po	Thu Jul 31 06:23:55 2008 +0000
@@ -13684,6 +13684,11 @@
 msgid "This plugin is useful for debbuging XMPP servers or clients."
 msgstr "幫助為 XMPP 伺服器或客戶端進行除錯。"
 
+#. feel free to not translate this
+#: ../pidgin/gtkdialogs.c:77
+msgid "Ka-Hing Cheung"
+msgstr "張家興"
+
 #~ msgid "_Resume"
 #~ msgstr "恢復(_R)"