changeset 27419:6b11903c87c8

merge of '2010b6cf9dfaf940d22f5593c63b22db86ee8844' and '7142fad92bc4df6efc61c59c9115cb247b95810b'
author Paul Aurich <paul@darkrain42.org>
date Wed, 08 Jul 2009 04:06:38 +0000
parents d9ee3adfee58 (diff) a50d0b8e3b7d (current diff)
children a712df376f19
files
diffstat 17 files changed, 265 insertions(+), 73 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Wed Jul 08 04:06:19 2009 +0000
+++ b/ChangeLog	Wed Jul 08 04:06:38 2009 +0000
@@ -27,6 +27,16 @@
 	  it off.  This will optionally be used to only show less useful debug
 	  information on an as-needed basis.
 	* Add support for receiving handwritten (ink) messages on MSN.
+	* Don't do IPv6 address lookups if the computer does not have an IPv6
+	  address configured.
+
+	AIM and ICQ:
+	* Preliminary support for a new authentication scheme called
+	  "clientLogin."
+	* Fixed a bug where your away message sometimes would not get set when
+	  you first sign on.
+	* Make sure links in your away messages show up as links to other people.
+	* For ICQ, Never change the privacy setting specified by the user.
 
 	Gadu-Gadu:
 	* Accounts can specify a server to which to connect.
@@ -124,6 +134,8 @@
 	* Draw the user's buddy icon at the bottom of the Buddy List with rounded
 	  corners for visual consistency with the actual icons in the Buddy List.
 	  (Kosta Arvanitis)
+	* When file transfers are complete, the received file name written to the
+	  conversation window is now linked to the file.
 
 	Finch:
 	* The hardware cursor is updated correctly. This will be useful
--- a/Makefile.mingw	Wed Jul 08 04:06:19 2009 +0000
+++ b/Makefile.mingw	Wed Jul 08 04:06:38 2009 +0000
@@ -129,7 +129,7 @@
 	rm -rf doc/html Doxyfile.mingw
 
 uninstall:
-	rm -rf $(PURPLE_INSTALL_PERLMOD_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(STRIPPED_RELEASE_DIR)
+	rm -rf $(PURPLE_INSTALL_PERL_DIR) $(PIDGIN_INSTALL_PLUGINS_DIR) $(PURPLE_INSTALL_PO_DIR) $(PIDGIN_INSTALL_DIR) $(STRIPPED_RELEASE_DIR)
 	rm -f ./VERSION
 
 include $(PIDGIN_COMMON_TARGETS)
--- a/libpurple/ft.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/ft.c	Wed Jul 08 04:06:38 2009 +0000
@@ -696,14 +696,34 @@
 
 	if (completed == TRUE) {
 		char *msg = NULL;
+		PurpleConversation *conv;
+
 		purple_xfer_set_status(xfer, PURPLE_XFER_STATUS_DONE);
 
 		if (purple_xfer_get_filename(xfer) != NULL)
-			msg = g_strdup_printf(_("Transfer of file %s complete"),
-								purple_xfer_get_filename(xfer));
+		{
+			char *filename = g_markup_escape_text(purple_xfer_get_filename(xfer), -1);
+			if (purple_xfer_get_local_filename(xfer)
+			 && purple_xfer_get_type(xfer) == PURPLE_XFER_RECEIVE)
+			{
+				char *local = g_markup_escape_text(purple_xfer_get_local_filename(xfer), -1);
+				msg = g_strdup_printf(_("Transfer of file <A HREF=\"file://%s\">%s</A> complete"),
+				                      local, filename);
+				g_free(local);
+			}
+			else
+				msg = g_strdup_printf(_("Transfer of file %s complete"),
+				                      filename);
+			g_free(filename);
+		}
 		else
 			msg = g_strdup(_("File transfer complete"));
-		purple_xfer_conversation_write(xfer, msg, FALSE);
+
+		conv = purple_find_conversation_with_account(PURPLE_CONV_TYPE_IM, xfer->who,
+		                                             purple_xfer_get_account(xfer));
+
+		if (conv != NULL)
+			purple_conversation_write(conv, NULL, msg, PURPLE_MESSAGE_SYSTEM, time(NULL));
 		g_free(msg);
 	}
 
--- a/libpurple/plugins/perl/common/Makefile.mingw	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/plugins/perl/common/Makefile.mingw	Wed Jul 08 04:06:38 2009 +0000
@@ -97,9 +97,10 @@
 all: $(TARGET).dll $(AUTOSPLIT)
 
 install: all
-	rm -rf $(PURPLE_INSTALL_PERLMOD_DIR)
-	cp -R lib $(PURPLE_INSTALL_PERLMOD_DIR)
-	cp $(TARGET).dll $(PURPLE_INSTALL_PERLMOD_DIR)
+	rm -rf $(PURPLE_INSTALL_PERL_DIR)
+	mkdir -p $(PURPLE_INSTALL_PERL_DIR)
+	cp -R lib/* $(PURPLE_INSTALL_PERL_DIR)
+	cp $(TARGET).dll $(PURPLE_INSTALL_PERL_DIR)/auto/Purple
 
 $(C_FILES): $(PURPLE_CONFIG_H)
 
--- a/libpurple/plugins/perl/perl.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/plugins/perl/perl.c	Wed Jul 08 04:06:38 2009 +0000
@@ -146,8 +146,8 @@
 		const gchar *search_path = search_paths->data;
 		search_paths = g_list_next(search_paths);
 
-		uselib = g_strdup_printf("unshift @INC, \"%s%cperl\";",
-		                         search_path, G_DIR_SEPARATOR);
+		uselib = g_strdup_printf("unshift @INC, q(%s%sperl);",
+		                         search_path, G_DIR_SEPARATOR_S);
 		eval_pv(uselib, TRUE);
 		g_free(uselib);
 	}
--- a/libpurple/protocols/msn/msn.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/protocols/msn/msn.c	Wed Jul 08 04:06:38 2009 +0000
@@ -1389,40 +1389,70 @@
                   MsnNetwork network,
                   MsnUser *user)
 {
-	MsnUserList *userlist = session->userlist;
-	MsnUser *user2;
 	char *group;
 
 	g_return_if_fail(user != NULL);
 
 	group = msn_user_remove_pending_group(user);
 
-	user2 = msn_userlist_find_user(userlist, who);
-	if (user2 != NULL) {
-		/* User already in userlist, so just update it. */
+	if (network != MSN_NETWORK_UNKNOWN) {
+		MsnUserList *userlist = session->userlist;
+		MsnUser *user2 = msn_userlist_find_user(userlist, who);
+		if (user2 != NULL) {
+			/* User already in userlist, so just update it. */
+			msn_user_destroy(user);
+			user = user2;
+		} else {
+			msn_userlist_add_user(userlist, user);
+		}
+
+		msn_user_set_network(user, network);
+		msn_userlist_add_buddy(userlist, who, group);
+	}
+	else
+	{
+		PurpleBuddy * buddy = purple_find_buddy(session->account, who);
+		gchar *buf;
+		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be a valid email address."), who);
+		if (!purple_conv_present_error(who, session->account, buf))
+			purple_notify_error(purple_account_get_connection(session->account), NULL, _("Unable to Add"), buf);
+		g_free(buf);
+
+		/* Remove from local list */
+		purple_blist_remove_buddy(buddy);
 		msn_user_destroy(user);
-		user = user2;
-	} else {
-		msn_userlist_add_user(userlist, user);
 	}
-
-	msn_user_set_network(user, network);
-	msn_userlist_add_buddy(userlist, who, group);
 	g_free(group);
 }
 
 static void
 msn_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group)
 {
+	PurpleAccount *account;
 	MsnSession *session;
 	MsnUserList *userlist;
-	const char *who, *gname;
+	const char *bname, *who, *gname;
 	MsnUser *user;
 
+	account = purple_connection_get_account(gc);
 	session = gc->proto_data;
 	userlist = session->userlist;
-	who = msn_normalize(purple_connection_get_account(gc), purple_buddy_get_name(buddy));
-
+	bname = purple_buddy_get_name(buddy);
+
+	if (!purple_email_is_valid(bname)) {
+		gchar *buf;
+		buf = g_strdup_printf(_("Unable to add the buddy %s because the username is invalid.  Usernames must be a valid email address."), bname);
+		if (!purple_conv_present_error(bname, account, buf))
+			purple_notify_error(gc, NULL, _("Unable to Add"), buf);
+		g_free(buf);
+
+		/* Remove from local list */
+		purple_blist_remove_buddy(buddy);
+
+		return;
+	}
+
+	who = msn_normalize(account, bname);
 	gname = group ? purple_group_get_name(group) : NULL;
 	purple_debug_info("msn", "Add user:%s to group:%s\n", who, gname ? gname : "(null)");
 	if (!session->logged_in)
--- a/libpurple/util.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/util.c	Wed Jul 08 04:06:38 2009 +0000
@@ -2967,10 +2967,10 @@
 }
 
 /*
- * TODO: Consider using something faster than SHA-1, such as MD5, MD4
- *       or CRC32.  Are there security implications to that?  Would
- *       probably be a good idea to benchmark some algorithms with
- *       3KB-10KB chunks of data (typical buddy icon sizes).
+ * We thought about using non-cryptographic hashes like CRC32 here.
+ * They would be faster, but we think using something more secure is
+ * important, so that it is more difficult for someone to maliciously
+ * replace one buddy's icon with something else.
  */
 char *
 purple_util_get_image_checksum(gconstpointer image_data, size_t image_len)
--- a/libpurple/win32/global.mak	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/win32/global.mak	Wed Jul 08 04:06:38 2009 +0000
@@ -27,10 +27,10 @@
 # Where we installing this stuff to?
 PIDGIN_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
 PURPLE_INSTALL_DIR := $(PIDGIN_TREE_TOP)/win32-install-dir
-PIDGIN_INSTALL_PERLMOD_DIR := $(PIDGIN_INSTALL_DIR)/perlmod
 PIDGIN_INSTALL_PLUGINS_DIR := $(PIDGIN_INSTALL_DIR)/plugins
-PURPLE_INSTALL_PERLMOD_DIR := $(PURPLE_INSTALL_DIR)/perlmod
+PIDGIN_INSTALL_PERL_DIR := $(PIDGIN_INSTALL_PLUGINS_DIR)/perl
 PURPLE_INSTALL_PLUGINS_DIR := $(PURPLE_INSTALL_DIR)/plugins
+PURPLE_INSTALL_PERL_DIR := $(PURPLE_INSTALL_PLUGINS_DIR)/perl
 PURPLE_INSTALL_PO_DIR := $(PURPLE_INSTALL_DIR)/locale
 
 # Important (enough) locations in our source code
--- a/libpurple/win32/targets.mak	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/win32/targets.mak	Wed Jul 08 04:06:38 2009 +0000
@@ -37,7 +37,7 @@
 	mkdir -p $(PIDGIN_INSTALL_DIR)
 
 $(PIDGIN_INSTALL_PERLMOD_DIR):
-	mkdir -p $(PURPLE_INSTALL_PERLMOD_DIR)
+	mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
 
 $(PIDGIN_INSTALL_PLUGINS_DIR):
 	mkdir -p $(PIDGIN_INSTALL_PLUGINS_DIR)
@@ -45,3 +45,8 @@
 $(PURPLE_INSTALL_PO_DIR):
 	mkdir -p $(PURPLE_INSTALL_PO_DIR)
 
+#$(PURPLE_INSTALL_PLUGINS_DIR):
+#	mkdir -p $(PURPLE_INSTALL_PLUGINS_DIR)
+
+#$(PURPLE_INSTALL_PERL_DIR):
+#	mkdir -p $(PURPLE_INSTALL_PERL_DIR)
--- a/libpurple/win32/win32dep.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/libpurple/win32/win32dep.c	Wed Jul 08 04:06:38 2009 +0000
@@ -419,8 +419,6 @@
 void wpurple_init(void) {
 	WORD wVersionRequested;
 	WSADATA wsaData;
-	const char *perlenv;
-	char *newenv;
 
 	if (!g_thread_supported())
 		g_thread_init(NULL);
@@ -444,17 +442,6 @@
 		WSACleanup();
 	}
 
-	/* Set Environmental Variables */
-	/* Tell perl where to find Purple's perl modules */
-	perlenv = g_getenv("PERL5LIB");
-	newenv = g_strdup_printf("%s%s%s" G_DIR_SEPARATOR_S "perlmod;",
-		perlenv ? perlenv : "",
-		perlenv ? ";" : "",
-		wpurple_install_dir());
-	if (!g_setenv("PERL5LIB", newenv, TRUE))
-		purple_debug_warning("wpurple", "putenv failed for PERL5LIB\n");
-	g_free(newenv);
-
 	purple_debug_info("wpurple", "wpurple_init end\n");
 }
 
--- a/pidgin/gtkaccount.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/gtkaccount.c	Wed Jul 08 04:06:38 2009 +0000
@@ -784,7 +784,7 @@
 	dialog->protocol_frame = vbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BOX_SPACE);
 	gtk_container_set_border_width(GTK_CONTAINER(vbox), PIDGIN_HIG_BORDER);
 	gtk_notebook_insert_page(GTK_NOTEBOOK(dialog->notebook), vbox,
-			gtk_label_new_with_mnemonic(_("_Advanced")), 1);
+			gtk_label_new_with_mnemonic(_("Ad_vanced")), 1);
 	gtk_widget_show(vbox);
 
 	for (l = dialog->prpl_info->protocol_options; l != NULL; l = l->next)
@@ -1533,7 +1533,7 @@
 	dbox = gtk_vbox_new(FALSE, PIDGIN_HIG_BORDER);
 	gtk_container_set_border_width(GTK_CONTAINER(dbox), PIDGIN_HIG_BORDER);
 	gtk_notebook_append_page(GTK_NOTEBOOK(notebook), dbox,
-			gtk_label_new_with_mnemonic(_("_Proxy")));
+			gtk_label_new_with_mnemonic(_("P_roxy")));
 	gtk_widget_show(dbox);
 	add_proxy_options(dialog, dbox);
 
--- a/pidgin/gtkblist.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/gtkblist.c	Wed Jul 08 04:06:38 2009 +0000
@@ -1505,7 +1505,6 @@
 	PurpleContact *contact;
 	PurpleBlistNode *node;
 	gboolean contact_expanded = FALSE;
-	gboolean show_offline = FALSE;
 
 	g_return_if_fail(menu);
 	g_return_if_fail(buddy);
@@ -1573,8 +1572,8 @@
 				G_CALLBACK(gtk_blist_menu_showlog_cb), buddy, 0, 0, NULL);
 	}
 
-	if (!(purple_blist_node_get_flags(node) & PURPLE_BLIST_NODE_FLAG_NO_SAVE)) {
-		show_offline = purple_blist_node_get_bool(node, "show_offline");
+	if (!PURPLE_BLIST_NODE_HAS_FLAG(node, PURPLE_BLIST_NODE_FLAG_NO_SAVE)) {
+		gboolean show_offline = purple_blist_node_get_bool(node, "show_offline");
 		pidgin_new_item_from_stock(menu, show_offline ? _("Hide When Offline") : _("Show When Offline"),
 				NULL, G_CALLBACK(gtk_blist_menu_showoffline_cb), node, 0, 0, NULL);
 	}
@@ -6322,15 +6321,15 @@
 		mark = g_strdup_printf("<span foreground='%s' font_desc='%s'><b>%s</b>%s%s%s</span>",
 		                       text_color, text_font,
 		                       esc ? esc : "",
-		                       !expanded ? " <span font_weight='light'>(</span>" : "",
+		                       !expanded ? " <span weight='light'>(</span>" : "",
 		                       group_count,
-		                       !expanded ? "<span font_weight='light'>)</span>" : "");
+		                       !expanded ? "<span weight='light'>)</span>" : "");
 	} else {
 		mark = g_strdup_printf("<span font_desc='%s'><b>%s</b>%s%s%s</span>",
 		                       text_font, esc ? esc : "",
-		                       !expanded ? " <span font_weight='light'>(</span>" : "",
+		                       !expanded ? " <span weight='light'>(</span>" : "",
 		                       group_count,
-		                       !expanded ? "<span font_weight='light'>)</span>" : "");
+		                       !expanded ? "<span weight='light'>)</span>" : "");
 	}
 
 	g_free(esc);
--- a/pidgin/gtkrequest.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/gtkrequest.c	Wed Jul 08 04:06:38 2009 +0000
@@ -717,12 +717,16 @@
 			GtkWidget *optmenu = NULL;
 			PurpleRequestFieldGroup *group = purple_request_field_get_group(field);
 			GList *fields = group->fields;
+
+			/* Ensure the account option menu is created (if the widget hasn't
+			 * been initialized already) for username auto-completion. */
 			while (fields)
 			{
 				PurpleRequestField *fld = fields->data;
 				fields = fields->next;
 
-				if (purple_request_field_get_type(fld) == PURPLE_REQUEST_FIELD_ACCOUNT)
+				if (purple_request_field_get_type(fld) == PURPLE_REQUEST_FIELD_ACCOUNT &&
+						purple_request_field_is_visible(fld))
 				{
 					const char *type_hint = purple_request_field_get_type_hint(fld);
 					if (type_hint != NULL && strcmp(type_hint, "account") == 0)
@@ -730,7 +734,7 @@
 						optmenu = GTK_WIDGET(purple_request_field_get_ui_data(fld));
 						if (optmenu == NULL) {
 							optmenu = GTK_WIDGET(create_account_field(fld));
-							purple_request_field_set_ui_data(field, optmenu);
+							purple_request_field_set_ui_data(fld, optmenu);
 						}
 						break;
 					}
--- a/pidgin/gtkutils.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/gtkutils.c	Wed Jul 08 04:06:38 2009 +0000
@@ -3578,6 +3578,135 @@
 	return TRUE;
 }
 
+static void
+file_open_uri(GtkIMHtml *imhtml, const char *uri)
+{
+	/* Copied from gtkft.c:open_button_cb */
+#ifdef _WIN32
+	/* If using Win32... */
+	int code;
+	if (G_WIN32_HAVE_WIDECHAR_API()) {
+		wchar_t *wc_filename = g_utf8_to_utf16(
+				uri, -1, NULL, NULL, NULL);
+
+		code = (int)ShellExecuteW(NULL, NULL, wc_filename, NULL, NULL,
+				SW_SHOW);
+
+		g_free(wc_filename);
+	} else {
+		char *l_filename = g_locale_from_utf8(
+				uri, -1, NULL, NULL, NULL);
+
+		code = (int)ShellExecuteA(NULL, NULL, l_filename, NULL, NULL,
+				SW_SHOW);
+
+		g_free(l_filename);
+	}
+
+	if (code == SE_ERR_ASSOCINCOMPLETE || code == SE_ERR_NOASSOC)
+	{
+		purple_notify_error(imhtml, NULL,
+				_("There is no application configured to open this type of file."), NULL);
+	}
+	else if (code < 32)
+	{
+		purple_notify_error(imhtml, NULL,
+				_("An error occurred while opening the file."), NULL);
+		purple_debug_warning("gtkutils", "filename: %s; code: %d\n", uri, code);
+	}
+#else
+	char *command = NULL;
+	char *tmp = NULL;
+	GError *error = NULL;
+
+	if (purple_running_gnome())
+	{
+		char *escaped = g_shell_quote(uri);
+		command = g_strdup_printf("gnome-open %s", escaped);
+		g_free(escaped);
+	}
+	else if (purple_running_kde())
+	{
+		char *escaped = g_shell_quote(uri);
+
+		if (purple_str_has_suffix(uri, ".desktop"))
+			command = g_strdup_printf("kfmclient openURL %s 'text/plain'", escaped);
+		else
+			command = g_strdup_printf("kfmclient openURL %s", escaped);
+		g_free(escaped);
+	}
+	else
+	{
+		purple_notify_uri(NULL, uri);
+		return;
+	}
+
+	if (purple_program_is_valid(command))
+	{
+		gint exit_status;
+		if (!g_spawn_command_line_sync(command, NULL, NULL, &exit_status, &error))
+		{
+			tmp = g_strdup_printf(_("Error launching %s: %s"),
+							uri, error->message);
+			purple_notify_error(imhtml, NULL, _("Unable to open file."), tmp);
+			g_free(tmp);
+			g_error_free(error);
+		}
+		if (exit_status != 0)
+		{
+			char *primary = g_strdup_printf(_("Error running %s"), command);
+			char *secondary = g_strdup_printf(_("Process returned error code %d"),
+									exit_status);
+			purple_notify_error(imhtml, NULL, primary, secondary);
+			g_free(tmp);
+		}
+	}
+#endif
+}
+
+#define FILELINKSIZE  (sizeof("file://") - 1)
+static gboolean
+file_clicked_cb(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
+{
+	const char *uri = gtk_imhtml_link_get_url(link) + FILELINKSIZE;
+	file_open_uri(imhtml, uri);
+	return TRUE;
+}
+
+static gboolean
+open_containing_cb(GtkIMHtml *imhtml, const char *url)
+{
+	char *dir = g_path_get_dirname(url + FILELINKSIZE);
+	file_open_uri(imhtml, dir);
+	g_free(dir);
+	return TRUE;
+}
+
+static gboolean
+file_context_menu(GtkIMHtml *imhtml, GtkIMHtmlLink *link, GtkWidget *menu)
+{
+	GtkWidget *img, *item;
+	const char *url;
+
+	url = gtk_imhtml_link_get_url(link);
+
+	/* Open File */
+	img = gtk_image_new_from_stock(GTK_STOCK_JUMP_TO, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("_Open File"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect_swapped(G_OBJECT(item), "activate", G_CALLBACK(gtk_imhtml_link_activate), link);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	/* Open Containing Directory */
+	img = gtk_image_new_from_stock(GTK_STOCK_COPY, GTK_ICON_SIZE_MENU);
+	item = gtk_image_menu_item_new_with_mnemonic(_("Open _Containing Directory"));
+	gtk_image_menu_item_set_image(GTK_IMAGE_MENU_ITEM(item), img);
+	g_signal_connect(G_OBJECT(item), "activate", G_CALLBACK(open_containing_cb), (gpointer)url);
+	gtk_menu_shell_append(GTK_MENU_SHELL(menu), item);
+
+	return TRUE;
+}
+
 /* XXX: The following two functions are for demonstration purposes only! */
 static gboolean
 open_dialog(GtkIMHtml *imhtml, GtkIMHtmlLink *link)
@@ -3684,6 +3813,8 @@
 	gtk_imhtml_class_register_protocol("gopher://", url_clicked_cb, link_context_menu);
 	gtk_imhtml_class_register_protocol("mailto:", url_clicked_cb, copy_email_address);
 
+	gtk_imhtml_class_register_protocol("file://", file_clicked_cb, file_context_menu);
+
 	/* Example custom URL handler. */
 	gtk_imhtml_class_register_protocol("open://", open_dialog, dummy);
 
--- a/pidgin/plugins/disco/xmppdisco.c	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/plugins/disco/xmppdisco.c	Wed Jul 08 04:06:38 2009 +0000
@@ -59,13 +59,6 @@
                                const char *id, const char *from, xmlnode *iq,
                                gpointer data);
 
-struct xmpp_iq_cb_data
-{
-	gpointer context;
-	PurpleConnection *pc;
-	XmppIqCallback cb;
-};
-
 struct item_data {
 	PidginDiscoList *list;
 	XmppDiscoService *parent;
@@ -73,6 +66,20 @@
 	char *node; /* disco#info replies don't always include the node */
 };
 
+struct xmpp_iq_cb_data
+{
+	/*
+	 * Every IQ callback in this plugin uses the same structure for the
+	 * callback data. It's a hack (it wouldn't scale), but it's used so that
+	 * it's easy to clean up all the callbacks when the account disconnects
+	 * (see remove_iq_callbacks_by_pc below).
+	 */
+	struct item_data *context;
+	PurpleConnection *pc;
+	XmppIqCallback cb;
+};
+
+
 static char*
 generate_next_id()
 {
@@ -93,11 +100,6 @@
 	struct xmpp_iq_cb_data *cb_data = value;
 
 	if (cb_data && cb_data->pc == user_data) {
-		/*
-		 * This is a hack. All the IQ callback datas in this code are
-		 * the same structure so that we can free them here. Ideally they'd
-		 * be objects and this would be polymorphic. That's overkill, here.
-		 */
 		struct item_data *item_data = cb_data->context;
 
 		if (item_data) {
--- a/pidgin/plugins/perl/common/Makefile.mingw	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/plugins/perl/common/Makefile.mingw	Wed Jul 08 04:06:38 2009 +0000
@@ -86,14 +86,15 @@
 
 all: $(TARGET).dll
 
-$(PURPLE_INSTALL_PERLMOD_DIR)/Purple.pm:
+$(PURPLE_INSTALL_PERL_DIR)/Purple.pm:
 	$(MAKE) -C $(PURPLE_PERL_TOP)/common -f $(MINGW_MAKEFILE) install
 
-install: all $(PURPLE_INSTALL_PERLMOD_DIR)/Purple.pm
-	rm -f $(PIDGIN_INSTALL_PERLMOD_DIR)/$(TARGET).dll $(PIDGIN_INSTALL_PERLMOD_DIR)/Pidgin/$(TARGET).pm
-	mkdir -p $(PIDGIN_INSTALL_PERLMOD_DIR)
-	cp $(TARGET).pm $(PIDGIN_INSTALL_PERLMOD_DIR)
-	cp $(TARGET).dll $(PIDGIN_INSTALL_PERLMOD_DIR)
+install: all $(PURPLE_INSTALL_PERL_DIR)/Purple.pm
+	rm -f $(PIDGIN_INSTALL_PERL_DIR)/$(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin/$(TARGET).pm
+	mkdir -p $(PIDGIN_INSTALL_PERL_DIR)
+	cp $(TARGET).pm $(PIDGIN_INSTALL_PERL_DIR)
+	mkdir -p $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
+	cp $(TARGET).dll $(PIDGIN_INSTALL_PERL_DIR)/auto/Pidgin
 
 $(C_FILES): $(PIDGIN_CONFIG_H)
 
--- a/pidgin/win32/nsis/pidgin-installer.nsi	Wed Jul 08 04:06:19 2009 +0000
+++ b/pidgin/win32/nsis/pidgin-installer.nsi	Wed Jul 08 04:06:38 2009 +0000
@@ -726,7 +726,6 @@
     RMDir "$INSTDIR\ca-certs"
     RMDir /r "$INSTDIR\locale"
     RMDir /r "$INSTDIR\pixmaps"
-    RMDir /r "$INSTDIR\perlmod"
     Delete "$INSTDIR\plugins\autoaccept.dll"
     Delete "$INSTDIR\plugins\buddynote.dll"
     Delete "$INSTDIR\plugins\convcolors.dll"
@@ -775,6 +774,7 @@
     Delete "$INSTDIR\plugins\winprefs.dll"
     Delete "$INSTDIR\plugins\xmppconsole.dll"
     Delete "$INSTDIR\plugins\xmppdisco.dll"
+    RMDir /r "$INSTDIR\plugins\perl"
     RMDir "$INSTDIR\plugins"
     RMDir /r "$INSTDIR\sasl2"
     Delete "$INSTDIR\sounds\purple\alert.wav"