changeset 18193:09eb621782bc

explicit merge of 'f2eb358baf2c72cb37b6b9bcb4c036e44e0bcc2b' and '2344c84a6e70c374b19936a127462d2f19c0139c'
author Ka-Hing Cheung <khc@hxbc.us>
date Tue, 19 Jun 2007 17:17:57 +0000
parents afeb35205669 (diff) 02f39842d28b (current diff)
children 9c17cdcfc799
files libpurple/savedstatuses.c libpurple/savedstatuses.h pidgin/gtksavedstatuses.c pidgin/gtkstatusbox.c
diffstat 111 files changed, 877 insertions(+), 585 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog.API	Sun Jun 17 18:03:03 2007 +0000
+++ b/ChangeLog.API	Tue Jun 19 17:17:57 2007 +0000
@@ -13,21 +13,13 @@
 		    UIs can now use better scheduling for whole-second timers.  For
 		    example, clients based on the glib event loop can now use
 		    g_timeout_add_seconds.
-		* gtk_imhtml_setup_entry
-		* pidgin_create_window
 		* purple_blist_node_get_type
 		* purple_conversation_do_command
 		* purple_conversation_get_extended_menu
 		* purple_core_ensure_single_instance
 		    This is for UIs to use to ensure only one copy is running.
 		* purple_dbus_is_owner
-		* purple_dbusify_const_GList
-		* purple_dbusify_const_GSList
-		* purple_const_GList_to_array
-		* purple_const_GSList_to_array
 		* purple_image_data_calculate_filename
-		* pidgin_retrieve_user_info, shows immediate feedback when getting
-		  information about a user.
 		* purple_timeout_add_seconds
 		    Callers should prefer this to purple_timeout_add for timers
 		    longer than 1 second away.  Be aware of the rounding, though.
@@ -35,11 +27,12 @@
 		    Callers should prefer this to purple_timeout_add for timers
 		    longer than 1 second away.  Be aware of the rounding, though.
 		* purple_xfer_get_remote_user
-		* gtk_imhtml_animation_new
-		    Can be used for inserting an animated image into an IMHTML.
+		* purple_pounces_get_all_for_ui
 
 		Changed:
-		* Mark some return types const:
+		* The documentation of the following functions now properly
+		  declares that the returned value must not be modified or
+		  freed, which was always the case:
 			* purple_accounts_get_all
 			* purple_connections_get_all
 			* purple_connections_get_connecting
@@ -49,18 +42,36 @@
 			* purple_get_conversations
 			* purple_get_ims
 			* purple_notify_user_info_get_entries
-
-		Deprecated:
-		* purple_dbusify_GList:  Use purple_dbusify_const_GList (and
-		  g_list_free if needed) if depending on 2.1.0 is okay.
-		* purple_dbusify_GSList:  Use purple_dbusify_const_GSList (and
-		  g_slist_free if needed) if depending on 2.1.0 is okay..
-		* purple_GList_to_array:  Use purple_const_GList_to_array (and
-		  g_list_free if needed) if depending on 2.1.0 is okay..
-		* purple_GSList_to_array:  Use purple_const_GSList_to_array (and
-		  g_slist_free if needed) if depending on 2.1.0 is okay..
+		* The following functions now return a GList* instead of a
+		  const GList*, as const is not very useful with GLists.  The
+		  returned value still must not be modified or freed:
+			* purple_account_get_status_types
+			* purple_mime_document_get_fields
+			* purple_mime_document_get_parts
+			* purple_mime_part_get_fields
+			* purple_request_fields_get_required
+			* purple_request_field_list_get_selected
+			* purple_request_field_list_get_items
+			* purple_status_type_get_attrs
+			* purple_presence_get_statuses
+		* purple_request_field_list_set_selected now takes a GList*
+		  instead of a const GList* for items, as const is not very
+		  useful with GLists.  The passed list is still not modified
+		  or freed.
+		* purple_presence_add_list now takes a GList* instead of a
+		  const GList* for source_list, as const is not very useful with
+		  GLists.  The passed list is still not modified or freed.
 
 	Pidgin:
+		Added:
+		* gtk_imhtml_setup_entry
+		* pidgin_create_window
+		* pidgin_retrieve_user_info, shows immediate feedback when getting
+		  information about a user.
+		* gtk_imhtml_animation_new
+		    Can be used for inserting an animated image into an IMHTML.
+		* pidgin_menu_position_func_helper
+
 		Changed:
 		* pidgin_append_menu_action returns the menuitem added to the menu.
 		* pidgin_separator returns the separator added to the menu.
@@ -69,6 +80,11 @@
 		Added:
 		* finch_retrieve_user_info
 
+		Changed:
+		* gnt_tree_get_rows() now returns a GList* instead of a const
+		  GList*, as const is not very useful with GLists.  The
+		  returned value still must not be modified or freed.
+
 version 2.0.2 (6/14/2007):
 	Pidgin:
 		Deprecated:
--- a/configure.ac	Sun Jun 17 18:03:03 2007 +0000
+++ b/configure.ac	Tue Jun 19 17:17:57 2007 +0000
@@ -47,7 +47,7 @@
 m4_define([purple_major_version], [2])
 m4_define([purple_minor_version], [1])
 m4_define([purple_micro_version], [0])
-m4_define([purple_version_suffix], [])
+m4_define([purple_version_suffix], [devel])
 m4_define([purple_version],
           [purple_major_version.purple_minor_version.purple_micro_version])
 m4_define([purple_display_version], purple_version[]m4_ifdef([purple_version_suffix],[purple_version_suffix]))
@@ -56,7 +56,7 @@
 m4_define([gnt_major_version], [2])
 m4_define([gnt_minor_version], [0])
 m4_define([gnt_micro_version], [0])
-m4_define([gnt_version_suffix], [])
+m4_define([gnt_version_suffix], [devel])
 m4_define([gnt_version],
           [gnt_major_version.gnt_minor_version.gnt_micro_version])
 m4_define([gnt_display_version], gnt_version[]m4_ifdef([gnt_version_suffix],[gnt_version_suffix]))
--- a/finch/gntaccount.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntaccount.c	Tue Jun 19 17:17:57 2007 +0000
@@ -641,7 +641,7 @@
 
 void finch_accounts_show_all()
 {
-	const GList *iter;
+	GList *iter;
 	GntWidget *box, *button;
 
 	if (accounts.window)
@@ -734,7 +734,7 @@
 
 void finch_accounts_init()
 {
-	const GList *iter;
+	GList *iter;
 
 	purple_signal_connect(purple_accounts_get_handle(), "account-added",
 			finch_accounts_get_handle(), PURPLE_CALLBACK(account_added_callback),
@@ -831,7 +831,7 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(data->account);
 
-	if (g_list_find((GList *)purple_connections_get_all(), gc))
+	if (g_list_find(purple_connections_get_all(), gc))
 	{
 		purple_blist_request_add_buddy(data->account, data->username,
 									 NULL, data->alias);
--- a/finch/gntft.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntft.c	Tue Jun 19 17:17:57 2007 +0000
@@ -86,7 +86,7 @@
 static void
 update_title_progress()
 {
-	const GList *list;
+	GList *list;
 	int num_active_xfers = 0;
 	guint64 total_bytes_xferred = 0;
 	guint64 total_file_size = 0;
@@ -172,7 +172,7 @@
 void
 finch_xfer_dialog_new(void)
 {
-	const GList *iter;
+	GList *iter;
 	GntWidget *window;
 	GntWidget *bbox;
 	GntWidget *button;
@@ -411,7 +411,7 @@
 
 	size_str      = purple_str_size_to_units(purple_xfer_get_size(xfer));
 	remaining_str = purple_str_size_to_units(purple_xfer_get_bytes_remaining(xfer));
-	kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+	kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);
 
 	gnt_tree_change_text(GNT_TREE(xfer_dialog->tree), xfer, COLUMN_PROGRESS,
 			g_ascii_dtostr(prog_str, sizeof(prog_str), purple_xfer_get_progress(xfer) * 100.));
--- a/finch/gntpounce.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntpounce.c	Tue Jun 19 17:17:57 2007 +0000
@@ -137,12 +137,12 @@
 static void
 populate_pounces_list(PouncesManager *dialog)
 {
-	const GList *pounces;
+	GList *pounces;
 
 	gnt_tree_remove_all(GNT_TREE(dialog->tree));
 
-	for (pounces = purple_pounces_get_all(); pounces != NULL;
-			pounces = g_list_next(pounces))
+	for (pounces = purple_pounces_get_all_for_ui(FINCH_UI); pounces != NULL;
+			pounces = g_list_delete_link(pounces, pounces))
 	{
 		add_pounce_to_treeview(GNT_TREE(dialog->tree), pounces->data);
 	}
@@ -288,7 +288,7 @@
 	GntWidget *hbox, *vbox;
 	GntWidget *button;
 	GntWidget *combo;
-	const GList *list;
+	GList *list;
 
 	g_return_if_fail((cur_pounce != NULL) ||
 	                 (account != NULL) ||
@@ -303,7 +303,7 @@
 		dialog->pounce  = NULL;
 		dialog->account = account;
 	} else {
-		const GList *connections = purple_connections_get_all();
+		GList *connections = purple_connections_get_all();
 		PurpleConnection *gc;
 
 		if (connections != NULL) {
--- a/finch/gntprefs.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntprefs.c	Tue Jun 19 17:17:57 2007 +0000
@@ -89,7 +89,7 @@
 get_status_titles()
 {
 	GList *list = NULL;
-	const GList *iter;
+	GList *iter;
 	for (iter = purple_savedstatuses_get_all(); iter; iter = iter->next) {
 		char *str;
 		if (purple_savedstatus_is_transient(iter->data))
--- a/finch/gntrequest.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntrequest.c	Tue Jun 19 17:17:57 2007 +0000
@@ -297,7 +297,7 @@
 				GList *list = NULL;
 				if (purple_request_field_list_get_multi_select(field))
 				{
-					const GList *iter;
+					GList *iter;
 					GntWidget *tree = field->ui_data;
 
 					iter = purple_request_field_list_get_items(field);
@@ -433,7 +433,7 @@
 			else if (type == PURPLE_REQUEST_FIELD_CHOICE)
 			{
 				int id;
-				const GList *list;
+				GList *list;
 				GntWidget *combo = gnt_combo_box_new();
 				gnt_box_add_widget(GNT_BOX(hbox), combo);
 				field->ui_data = combo;
@@ -449,7 +449,7 @@
 			}
 			else if (type == PURPLE_REQUEST_FIELD_LIST)
 			{
-				const GList *list;
+				GList *list;
 				gboolean multi = purple_request_field_list_get_multi_select(field);
 				if (multi)
 				{
@@ -490,7 +490,7 @@
 			{
 				gboolean all;
 				PurpleAccount *def;
-				const GList *list;
+				GList *list;
 				GntWidget *combo = gnt_combo_box_new();
 				gnt_box_set_alignment(GNT_BOX(hbox), GNT_ALIGN_MID);
 				gnt_box_add_widget(GNT_BOX(hbox), combo);
--- a/finch/gntstatus.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/gntstatus.c	Tue Jun 19 17:17:57 2007 +0000
@@ -83,7 +83,7 @@
 static void
 populate_statuses(GntTree *tree)
 {
-	const GList *list;
+	GList *list;
 
 	for (list = purple_savedstatuses_get_all(); list; list = list->next)
 	{
@@ -244,7 +244,7 @@
 static void
 set_substatuses(EditStatus *edit)
 {
-	const GList *iter;
+	GList *iter;
 	for (iter = gnt_tree_get_rows(GNT_TREE(edit->tree)); iter; iter = iter->next) {
 		RowInfo *key = iter->data;
 		if (gnt_tree_get_choice(GNT_TREE(edit->tree), key)) {
@@ -410,7 +410,7 @@
 		EditSubStatus *sub;
 		GntWidget *window, *combo, *entry, *box, *button, *l;
 		PurpleSavedStatusSub *substatus = NULL;
-		const GList *iter;
+		GList *iter;
 		char *name;
 		RowInfo *selected = gnt_tree_get_selection_data(tree);
 		PurpleAccount *account = selected->account;
@@ -497,7 +497,7 @@
 	GntWidget *window, *box, *button, *entry, *combo, *label, *tree;
 	PurpleStatusPrimitive prims[] = {PURPLE_STATUS_AVAILABLE, PURPLE_STATUS_AWAY,
 		PURPLE_STATUS_INVISIBLE, PURPLE_STATUS_OFFLINE, PURPLE_STATUS_UNSET}, current;
-	const GList *iter;
+	GList *iter;
 	int i;
 
 	if (saved)
--- a/finch/libgnt/gnttree.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/libgnt/gnttree.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1017,7 +1017,7 @@
 	return ret;
 }
 
-const GList *gnt_tree_get_rows(GntTree *tree)
+GList *gnt_tree_get_rows(GntTree *tree)
 {
 	return tree->list;
 }
--- a/finch/libgnt/gnttree.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/libgnt/gnttree.h	Tue Jun 19 17:17:57 2007 +0000
@@ -190,7 +190,13 @@
  */
 GList * gnt_tree_get_selection_text_list(GntTree *tree);
 
-const GList *gnt_tree_get_rows(GntTree *tree);
+/**
+ *
+ * @param tree
+ *
+ * @constreturn
+ */
+GList *gnt_tree_get_rows(GntTree *tree);
 
 /**
  * 
--- a/finch/libgnt/gntwm.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/libgnt/gntwm.h	Tue Jun 19 17:17:57 2007 +0000
@@ -163,7 +163,7 @@
 	/* List of windows. Although the WM can keep a list of its own for the windows,
 	 * it'd be better if there was a way to share between the 'core' and the WM.
 	 */
-	/*const GList *(*window_list)();*/
+	/*GList *(*window_list)();*/
 
 	void (*res1)(void);
 	void (*res2)(void);
--- a/finch/libgnt/wms/irssi.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/libgnt/wms/irssi.c	Tue Jun 19 17:17:57 2007 +0000
@@ -177,7 +177,8 @@
 {
 	char title[256];
 	snprintf(title, sizeof(title), "%d: %s",
-			(int)g_object_get_data(G_OBJECT(node->me), "irssi-index") + 1, GNT_BOX(node->me)->title);
+			GPOINTER_TO_INT(g_object_get_data(G_OBJECT(node->me), "irssi-index")) + 1,
+			GNT_BOX(node->me)->title);
 	wbkgdset(node->window, '\0' | COLOR_PAIR(gnt_widget_has_focus(node->me) ? GNT_COLOR_TITLE : GNT_COLOR_TITLE_D));
 	mvwaddstr(node->window, 0, 0, title);
 	update_panels();
@@ -226,7 +227,7 @@
 
 	find_window_position(irssi, win, &hor, &vert);
 
-	switch ((int)list->data) {
+	switch (GPOINTER_TO_INT(list->data)) {
 		case 'k':
 			vert = MAX(0, vert - 1);
 			break;
--- a/finch/libgnt/wms/s.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/libgnt/wms/s.c	Tue Jun 19 17:17:57 2007 +0000
@@ -121,7 +121,7 @@
 static GntWidget *
 find_widget(GntWM *wm, const char *wname)
 {
-	const GList *iter = wm->cws->list;
+	GList *iter = wm->cws->list;
 	for (; iter; iter = iter->next) {
 		GntWidget *widget = iter->data;
 		const char *name = gnt_widget_get_name(widget);
--- a/finch/plugins/Makefile.am	Sun Jun 17 18:03:03 2007 +0000
+++ b/finch/plugins/Makefile.am	Tue Jun 19 17:17:57 2007 +0000
@@ -28,7 +28,7 @@
 
 endif # PLUGINS
 
-EXTRA_DIST = 
+EXTRA_DIST = pietray.py
 
 AM_CPPFLAGS = \
 	-DDATADIR=\"$(datadir)\" \
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/finch/plugins/pietray.py	Tue Jun 19 17:17:57 2007 +0000
@@ -0,0 +1,183 @@
+#!/usr/bin/env python
+
+# This is a dbus script to show a docklet for Finch. This should work
+# for any 'compatible' purple client.
+#
+# By 'compatible', I mean any client that sets and updates the
+# "unseen-count" data on the conversations.
+#
+# It allows doing the following things:
+#    - It allows changing status.
+#    - It shows the current status and info about unread messages in
+#      the tooltip.
+#    - It can blink on unread IM/Chat messages, and it allows canging
+#      the preference for that.
+# 
+# It requires GTK+ 2.10 or above, since it uses GtkStatusIcon.
+# 
+# Sadrul <sadrul@pidgin.im>
+
+import pygtk
+pygtk.require("2.0")
+import gtk
+import dbus, gobject, dbus.glib
+import os # to get the pkg-config output
+
+bus = dbus.SessionBus()
+obj = bus.get_object(
+    "im.pidgin.purple.PurpleService", "/im/pidgin/purple/PurpleObject")
+purple = dbus.Interface(obj, "im.pidgin.purple.PurpleInterface")
+
+def pack_image_label(menu, image, label):
+	item = gtk.ImageMenuItem(label)
+	if image:
+		img = gtk.Image()
+		img.set_from_stock(image, 1)
+		item.set_image(img)
+	menu.append(item)
+	return item
+
+def activate_primitive_status(item, status):
+	saved = purple.PurpleSavedstatusFindTransientByTypeAndMessage(status, "")
+	if not saved:
+		saved = purple.PurpleSavedstatusNew("", status)
+	purple.PurpleSavedstatusActivate(saved)
+
+def activate_popular_status(item, time):
+	saved = purple.PurpleSavedstatusFindByCreationTime(time)
+	if saved:
+		purple.PurpleSavedstatusActivate(saved)
+
+def generate_status_menu(menu):
+	item = gtk.MenuItem("Available")
+	item.connect("activate", activate_primitive_status, 2)
+	menu.append(item)
+
+	item = gtk.MenuItem("Away")
+	item.connect("activate", activate_primitive_status, 5)
+	menu.append(item)
+
+	item = gtk.MenuItem("Invisible")
+	item.connect("activate", activate_primitive_status, 4)
+	menu.append(item)
+
+	item = gtk.MenuItem("Offline")
+	item.connect("activate", activate_primitive_status, 1)
+	menu.append(item)
+
+	menu.append(gtk.MenuItem())
+
+	popular = purple.PurpleSavedstatusesGetPopular(10)
+	for pop in popular:
+		title = purple.PurpleSavedstatusGetTitle(pop).replace('_', '__')
+		item = gtk.MenuItem(title)
+		item.set_data("timestamp", purple.PurpleSavedstatusGetCreationTime(pop))
+		item.connect("activate", activate_popular_status, purple.PurpleSavedstatusGetCreationTime(pop))
+		menu.append(item)
+
+def toggle_pref(item, pref):
+	purple.PurplePrefsSetBool(pref, item.get_active())
+
+def popup_menu(icon, button, tm, none):
+	menu = gtk.Menu()
+
+	item = gtk.CheckMenuItem("Blink for unread IM")
+	item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im"))
+	item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/im")
+	menu.append(item)
+
+	item = gtk.CheckMenuItem("Blink for unread Chats")
+	item.set_active(purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat"))
+	item.connect("activate", toggle_pref, "/plugins/dbus/docklet/blink/chat")
+	menu.append(item)
+
+	menu.append(gtk.MenuItem())
+
+	#item = pack_image_label(menu, None, "Change Status...")
+	item = gtk.MenuItem("Change Status...")
+	menu.append(item)
+	submenu = gtk.Menu()
+	item.set_submenu(submenu)
+	generate_status_menu(submenu)
+
+	menu.show_all()
+	menu.popup(None, None, None, button, tm)
+
+def get_status_message():
+	status = purple.PurpleSavedstatusGetCurrent()
+	msg = purple.PurpleSavedstatusGetMessage(status)
+	if msg and len(msg) > 0:
+		text = msg + " "
+	else:
+		text = ""
+	text = text + "(" + {
+		2: "Available",
+		5: "Away",
+		4: "Invisible",
+		1: "Offline"
+	}[purple.PurpleSavedstatusGetType(status)] + ")"
+	return text
+
+def detect_unread_conversations():
+	im = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/im")
+	chat = purple.PurplePrefsGetBool("/plugins/dbus/docklet/blink/chat")
+	tooltip = ""
+	blink = False
+	if im and chat:
+		convs = purple.PurpleGetConversations()
+	elif im:
+		convs = purple.PurpleGetIms()
+	elif chat:
+		convs = purple.PurpleGetChats()
+	else:
+		convs = None
+	for conv in convs:
+		count = purple.PurpleConversationGetData(conv, "unseen-count")
+		if count and count > 0:
+			blink = True
+			tooltip = tooltip + "\n" + purple.PurpleConversationGetName(conv) + " (" + str(count) + ")"
+	t.set_from_file(path + "/share/pixmaps/pidgin.png")
+	if blink:
+		# I hate this icon
+		# t.set_from_file(path + "/share/pixmaps/pidgin/tray/22/tray-message.png")
+		tooltip = "\nUnread Messages:" + tooltip
+	# There's going to be some way to expose the client's display name in 2.1.0.
+	# Use that instead of hardcoding Finch here.
+	t.set_tooltip("Finch: " + get_status_message() + tooltip)
+	t.set_blinking(blink)
+
+def conversation_updated(conv, type):
+	detect_unread_conversations()
+
+def savedstatus_changed(new, old):
+	# Change the icon for status perhaps?
+	detect_unread_conversations()
+
+def init_prefs():
+	if not purple.PurplePrefsExists("/plugins/dbus/docklet/blink"):
+		purple.PurplePrefsAddNone("/plugins")
+		purple.PurplePrefsAddNone("/plugins/dbus")
+		purple.PurplePrefsAddNone("/plugins/dbus/docklet")
+		purple.PurplePrefsAddNone("/plugins/dbus/docklet/blink")
+		purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/im", True)
+		purple.PurplePrefsAddBool("/plugins/dbus/docklet/blink/chat", True)
+
+pkg = os.popen("pkg-config --variable=prefix pidgin")
+path = pkg.readline().rstrip()
+
+bus.add_signal_receiver(conversation_updated,
+  dbus_interface="im.pidgin.purple.PurpleInterface",
+  signal_name="ConversationUpdated")
+
+bus.add_signal_receiver(savedstatus_changed,
+  dbus_interface="im.pidgin.purple.PurpleInterface",
+  signal_name="SavedstatusChanged")
+
+t = gtk.StatusIcon()
+t.connect("popup-menu", popup_menu, None)
+
+init_prefs()
+detect_unread_conversations()
+
+gtk.main ()
+
--- a/libpurple/account.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/account.c	Tue Jun 19 17:17:57 2007 +0000
@@ -205,7 +205,7 @@
 {
 	PurpleStatusType *type = purple_status_get_type(status);
 	xmlnode *node, *child;
-	const GList *attrs, *attr;
+	GList *attrs, *attr;
 
 	node = xmlnode_new("attributes");
 
@@ -241,7 +241,7 @@
 statuses_to_xmlnode(const PurplePresence *presence)
 {
 	xmlnode *node, *child;
-	const GList *statuses, *status;
+	GList *statuses, *status;
 
 	node = xmlnode_new("statuses");
 
@@ -371,7 +371,7 @@
 accounts_to_xmlnode(void)
 {
 	xmlnode *node, *child;
-	const GList *cur;
+	GList *cur;
 
 	node = xmlnode_new("account");
 	xmlnode_set_attrib(node, "version", "1.0");
@@ -877,7 +877,7 @@
 void
 purple_account_destroy(PurpleAccount *account)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(account != NULL);
 
@@ -1805,7 +1805,7 @@
 PurpleStatusType *
 purple_account_get_status_type(const PurpleAccount *account, const char *id)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(account != NULL, NULL);
 	g_return_val_if_fail(id      != NULL, NULL);
@@ -1824,7 +1824,7 @@
 PurpleStatusType *
 purple_account_get_status_type_with_primitive(const PurpleAccount *account, PurpleStatusPrimitive primitive)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(account != NULL, NULL);
 
@@ -1857,7 +1857,7 @@
 	return purple_presence_is_status_active(account->presence, status_id);
 }
 
-const GList *
+GList *
 purple_account_get_status_types(const PurpleAccount *account)
 {
 	g_return_val_if_fail(account != NULL, NULL);
@@ -2272,7 +2272,7 @@
 	schedule_accounts_save();
 }
 
-const GList *
+GList *
 purple_accounts_get_all(void)
 {
 	return accounts;
@@ -2282,7 +2282,7 @@
 purple_accounts_get_all_active(void)
 {
 	GList *list = NULL;
-	const GList *all = purple_accounts_get_all();
+	GList *all = purple_accounts_get_all();
 
 	while (all != NULL) {
 		PurpleAccount *account = all->data;
@@ -2300,7 +2300,7 @@
 purple_accounts_find(const char *name, const char *protocol_id)
 {
 	PurpleAccount *account = NULL;
-	const GList *l;
+	GList *l;
 	char *who;
 
 	g_return_val_if_fail(name != NULL, NULL);
@@ -2327,7 +2327,7 @@
 void
 purple_accounts_restore_current_statuses()
 {
-	const GList *l;
+	GList *l;
 	PurpleAccount *account;
 
 	/* If we're not connected to the Internet right now, we bail on this */
--- a/libpurple/account.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/account.h	Tue Jun 19 17:17:57 2007 +0000
@@ -672,9 +672,9 @@
  *
  * @param account The account.
  *
- * @return The account's status types.
+ * @constreturn The account's status types.
  */
-const GList *purple_account_get_status_types(const PurpleAccount *account);
+GList *purple_account_get_status_types(const PurpleAccount *account);
 
 /**
  * Returns a protocol-specific integer setting for an account.
@@ -884,9 +884,9 @@
 /**
  * Returns a list of all accounts.
  *
- * @return A list of all accounts.
+ * @constreturn A list of all accounts.
  */
-const GList *purple_accounts_get_all(void);
+GList *purple_accounts_get_all(void);
 
 /**
  * Returns a list of all enabled accounts
--- a/libpurple/accountopt.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/accountopt.c	Tue Jun 19 17:17:57 2007 +0000
@@ -282,7 +282,7 @@
 	return option->masked;
 }
 
-const GList *
+GList *
 purple_account_option_get_list(const PurpleAccountOption *option)
 {
 	g_return_val_if_fail(option != NULL, NULL);
--- a/libpurple/accountopt.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/accountopt.h	Tue Jun 19 17:17:57 2007 +0000
@@ -296,9 +296,9 @@
  *
  * @param option The account option.
  *
- * @return The list values.
+ * @constreturn The list values.
  */
-const GList *purple_account_option_get_list(const PurpleAccountOption *option);
+GList *purple_account_option_get_list(const PurpleAccountOption *option);
 
 /*@}*/
 
--- a/libpurple/blist.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/blist.c	Tue Jun 19 17:17:57 2007 +0000
@@ -35,8 +35,6 @@
 #include "value.h"
 #include "xmlnode.h"
 
-#define PATHSIZE 1024
-
 static PurpleBlistUiOps *blist_ui_ops = NULL;
 
 static PurpleBuddyList *purplebuddylist = NULL;
@@ -304,7 +302,7 @@
 {
 	xmlnode *node, *child, *grandchild;
 	PurpleBlistNode *gnode;
-	const GList *cur;
+	GList *cur;
 
 	node = xmlnode_new("purple");
 	xmlnode_set_attrib(node, "version", "1.0");
@@ -1895,7 +1893,7 @@
 {
 	PurpleBlistUiOps *ops = purple_blist_get_ui_ops();
 	PurpleBlistNode *node;
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(group != NULL);
 
--- a/libpurple/buddyicon.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/buddyicon.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1021,7 +1021,7 @@
 _purple_buddy_icons_account_loaded_cb()
 {
 	const char *dirname = purple_buddy_icons_get_cache_dir();
-	const GList *cur;
+	GList *cur;
 
 	for (cur = purple_accounts_get_all(); cur != NULL; cur = cur->next)
 	{
--- a/libpurple/connection.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/connection.c	Tue Jun 19 17:17:57 2007 +0000
@@ -456,7 +456,7 @@
 void
 purple_connections_disconnect_all(void)
 {
-	const GList *l;
+	GList *l;
 	PurpleConnection *gc;
 
 	while ((l = purple_connections_get_all()) != NULL) {
@@ -466,13 +466,13 @@
 	}
 }
 
-const GList *
+GList *
 purple_connections_get_all(void)
 {
 	return connections;
 }
 
-const GList *
+GList *
 purple_connections_get_connecting(void)
 {
 	return connections_connecting;
--- a/libpurple/connection.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/connection.h	Tue Jun 19 17:17:57 2007 +0000
@@ -259,16 +259,16 @@
  * Returns a list of all active connections.  This does not
  * include connections that are in the process of connecting.
  *
- * @return A list of all active connections.
+ * @constreturn A list of all active connections.
  */
-const GList *purple_connections_get_all(void);
+GList *purple_connections_get_all(void);
 
 /**
  * Returns a list of all connections in the process of connecting.
  *
- * @return A list of connecting connections.
+ * @constreturn A list of connecting connections.
  */
-const GList *purple_connections_get_connecting(void);
+GList *purple_connections_get_connecting(void);
 
 /**
  * Checks if gc is still a valid pointer to a gc.
@@ -279,7 +279,7 @@
  * TODO: Eventually this bad boy will be removed, because it is
  *       a gross fix for a crashy problem.
  */
-#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find((GList *)purple_connections_get_all(), (gc)) != NULL)
+#define PURPLE_CONNECTION_IS_VALID(gc) (g_list_find(purple_connections_get_all(), (gc)) != NULL)
 
 /*@}*/
 
--- a/libpurple/conversation.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/conversation.c	Tue Jun 19 17:17:57 2007 +0000
@@ -631,7 +631,7 @@
 purple_conversation_foreach(void (*func)(PurpleConversation *conv))
 {
 	PurpleConversation *conv;
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(func != NULL);
 
@@ -732,19 +732,19 @@
 	return g_hash_table_lookup(conv->data, key);
 }
 
-const GList *
+GList *
 purple_get_conversations(void)
 {
 	return conversations;
 }
 
-const GList *
+GList *
 purple_get_ims(void)
 {
 	return ims;
 }
 
-const GList *
+GList *
 purple_get_chats(void)
 {
 	return chats;
@@ -759,7 +759,7 @@
 	PurpleConversation *c = NULL;
 	gchar *name1;
 	const gchar *name2;
-	const GList *cnv;
+	GList *cnv;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
@@ -819,7 +819,7 @@
 		return;
 
 	if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_IM &&
-		!g_list_find((GList *)purple_get_conversations(), conv))
+		!g_list_find(purple_get_conversations(), conv))
 		return;
 
 	displayed = g_strdup(message);
@@ -1250,7 +1250,7 @@
 	return users;
 }
 
-const GList *
+GList *
 purple_conv_chat_get_users(const PurpleConvChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
@@ -1284,7 +1284,7 @@
 	if (!purple_conv_chat_is_user_ignored(chat, name))
 		return;
 
-	item = g_list_find((GList *)purple_conv_chat_get_ignored(chat),
+	item = g_list_find(purple_conv_chat_get_ignored(chat),
 					   purple_conv_chat_get_ignored_user(chat, name));
 
 	purple_conv_chat_set_ignored(chat,
@@ -1304,7 +1304,7 @@
 	return ignored;
 }
 
-const GList *
+GList *
 purple_conv_chat_get_ignored(const PurpleConvChat *chat)
 {
 	g_return_val_if_fail(chat != NULL, NULL);
@@ -1315,7 +1315,7 @@
 const char *
 purple_conv_chat_get_ignored_user(const PurpleConvChat *chat, const char *user)
 {
-	const GList *ignored;
+	GList *ignored;
 
 	g_return_val_if_fail(chat != NULL, NULL);
 	g_return_val_if_fail(user != NULL, NULL);
@@ -1810,7 +1810,7 @@
 	PurpleConversation *conv;
 	PurpleConversationUiOps *ops;
 	GList *users;
-	const GList *l;
+	GList *l;
 	GList *names = NULL;
 
 	g_return_if_fail(chat != NULL);
@@ -1919,7 +1919,7 @@
 PurpleConversation *
 purple_find_chat(const PurpleConnection *gc, int id)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 
 	for (l = purple_get_chats(); l != NULL; l = l->next) {
@@ -1968,7 +1968,7 @@
 PurpleConvChatBuddy *
 purple_conv_chat_cb_find(PurpleConvChat *chat, const char *name)
 {
-	const GList *l;
+	GList *l;
 	PurpleConvChatBuddy *cb = NULL;
 
 	g_return_val_if_fail(chat != NULL, NULL);
--- a/libpurple/conversation.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/conversation.h	Tue Jun 19 17:17:57 2007 +0000
@@ -502,23 +502,23 @@
  *
  * This list includes both IMs and chats.
  *
- * @return A GList of all conversations.
+ * @constreturn A GList of all conversations.
  */
-const GList *purple_get_conversations(void);
+GList *purple_get_conversations(void);
 
 /**
  * Returns a list of all IMs.
  *
- * @return A GList of all IMs.
+ * @constreturn A GList of all IMs.
  */
-const GList *purple_get_ims(void);
+GList *purple_get_ims(void);
 
 /**
  * Returns a list of all chats.
  *
- * @return A GList of all chats.
+ * @constreturn A GList of all chats.
  */
-const GList *purple_get_chats(void);
+GList *purple_get_chats(void);
 
 /**
  * Finds a conversation with the specified type, name, and Purple account.
@@ -875,9 +875,9 @@
  *
  * @param chat The chat.
  *
- * @return The list of users.
+ * @constreturn The list of users.
  */
-const GList *purple_conv_chat_get_users(const PurpleConvChat *chat);
+GList *purple_conv_chat_get_users(const PurpleConvChat *chat);
 
 /**
  * Ignores a user in a chat room.
@@ -912,7 +912,7 @@
  *
  * @return The list of ignored users.
  */
-const GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat);
+GList *purple_conv_chat_get_ignored(const PurpleConvChat *chat);
 
 /**
  * Returns the actual name of the specified ignored user, if it exists in
--- a/libpurple/core.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/core.c	Tue Jun 19 17:17:57 2007 +0000
@@ -489,13 +489,33 @@
 			/* We're only going to duplicate a logs symlink. */
 			if (!strcmp(entry, "logs"))
 			{
+				char *link;
+#if GLIB_CHECK_VERSION(2,4,0)
+				GError *err = NULL;
+
+				if ((link = g_file_read_link(name, &err)) == NULL)
+				{
+					char *name_utf8 = g_filename_to_utf8(name, -1, NULL, NULL, NULL);
+					purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n",
+					                   name_utf8 ? name_utf8 : name, err->message);
+					g_free(name_utf8);
+					g_error_free(err);
+					g_free(name);
+					g_dir_close(dir);
+					g_free(status_file);
+					g_free(old_user_dir);
+					return FALSE;
+				}
+#else
 				char buf[MAXPATHLEN];
 				size_t linklen;
 
 				if ((linklen = readlink(name, buf, sizeof(buf) - 1) == -1))
 				{
+					char *name_utf8 = g_filename_to_utf8(name);
 					purple_debug_error("core", "Error reading symlink %s: %s. Please report this at http://developer.pidgin.im\n",
-					                   name, strerror(errno));
+					                   name_utf8, strerror(errno));
+					g_free(name_utf8);
 					g_free(name);
 					g_dir_close(dir);
 					g_free(status_file);
@@ -504,13 +524,18 @@
 				}
 				buf[linklen] = '\0';
 
-				logs_dir = g_strconcat(user_dir, G_DIR_SEPARATOR_S "logs", NULL);
+				/* This way we don't have to GLIB_VERSION_CHECK every g_free(link) below. */
+				link = g_strdup(buf);
+#endif
 
-				if (!strcmp(buf, "../.purple/logs") || !strcmp(buf, logs_dir))
+				logs_dir = g_build_filename(user_dir, "logs", NULL);
+
+				if (!strcmp(link, "../.purple/logs") || !strcmp(link, logs_dir))
 				{
 					/* If the symlink points to the new directory, we're
 					 * likely just trying again after a failed migration,
 					 * so there's no need to fail here. */
+					g_free(link);
 					g_free(logs_dir);
 					continue;
 				}
@@ -522,12 +547,13 @@
 				g_unlink(logs_dir);
 
 				/* Relative links will most likely still be
-				 * valid from ~/.purple, though not it's not
+				 * valid from ~/.purple, though it's not
 				 * guaranteed.  Oh well. */
-				if (symlink(buf, logs_dir))
+				if (symlink(link, logs_dir))
 				{
 					purple_debug_error("core", "Error symlinking %s to %s: %s. Please report this at http://developer.pidgin.im\n",
-					                   logs_dir, buf, strerror(errno));
+					                   logs_dir, link, strerror(errno));
+					g_free(link);
 					g_free(name);
 					g_free(logs_dir);
 					g_dir_close(dir);
@@ -536,6 +562,7 @@
 					return FALSE;
 				}
 
+				g_free(link);
 				g_free(logs_dir);
 				continue;
 			}
--- a/libpurple/dbus-analyze-functions.py	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/dbus-analyze-functions.py	Tue Jun 19 17:17:57 2007 +0000
@@ -3,7 +3,7 @@
 import sys
 
 # types translated into "int"
-simpletypes = ["int", "gint", "guint", "gboolean"]
+simpletypes = ["int", "gint", "guint", "gboolean", "gpointer", "size_t", "gssize", "time_t"]
 
 # List "excluded" contains functions that shouldn't be exported via
 # DBus.  If you remove a function from this list, please make sure
@@ -32,8 +32,8 @@
     "purple_log_read",
     ]
 
-# This is a list of functions that return a GList* whose elements are
-# string, not pointers to objects.
+# This is a list of functions that return a GList* or GSList * whose elements
+# are strings, not pointers to objects.
 stringlists = [
     "purple_prefs_get_path_list",
     "purple_prefs_get_string_list",
@@ -41,6 +41,32 @@
     "purple_uri_list_extract_uris",
 ]
 
+# This is a list of functions that return a GList* or GSList* that should
+# not be freed.  Ideally, this information should be obtained from the Doxygen
+# documentation at some point.
+constlists = [
+    "purple_account_get_status_types",
+    "purple_accounts_get_all",
+    "purple_account_option_get_list",
+    "purple_connections_get_all",
+    "purple_connections_get_connecting",
+    "purple_get_conversations",
+    "purple_get_ims",
+    "purple_get_chats",
+    "purple_conv_chat_get_users",
+    "purple_conv_chat_get_ignored",
+    "purple_mime_document_get_fields",
+    "purple_mime_document_get_parts",
+    "purple_mime_part_get_fields",
+    "purple_notify_user_info_get_entries",
+    "purple_request_fields_get_required",
+    "purple_request_field_list_get_selected",
+    "purple_request_field_list_get_items",
+    "purple_savedstatuses_get_all",
+    "purple_status_type_get_attrs",
+    "purple_presence_get_statuses",
+]
+
 pointer = "#pointer#"
 myexception = "My Exception"
 
@@ -93,21 +119,26 @@
 
     def processinput(self, type, name):
         const = False
+        unsigned = False
         if type[0] == "const":
             type = type[1:]
             const = True
 
+        if type[0] == "unsigned":
+            type = type[1:]
+            unsigned = True
+
         if len(type) == 1:
             # simple types (int, gboolean, etc.) and enums
             if (type[0] in simpletypes) or ((type[0].startswith("Purple") and not type[0].endswith("Callback"))):
-                return self.inputsimple(type, name)
+                return self.inputsimple(type, name, unsigned)
 
         # pointers ... 
         if (len(type) == 2) and (type[1] == pointer):
             # strings
             if type[0] in ["char", "gchar"]:
                 if const:
-                    return self.inputstring(type, name)
+                    return self.inputstring(type, name, unsigned)
                 else:
                     raise myexception
 
@@ -152,7 +183,7 @@
                 return self.outputpurplestructure(type, name)
 
             if type[0] in ["GList", "GSList"]:
-                return self.outputlist(type, name, const)
+                return self.outputlist(type, name)
 
         raise myexception
     
@@ -206,12 +237,18 @@
             print "typedef struct _%s %s;" % (type[0], type[0])
             self.knowntypes.append(type[0])
 
-    def inputsimple(self, type, name):
+    def inputsimple(self, type, name, us):
         self.paramshdr.append("%s %s" % (type[0], name))
-        self.inputparams.append(("G_TYPE_INT", name))
+        if us:
+            self.inputparams.append(("G_TYPE_UINT", name))
+        else:
+            self.inputparams.append(("G_TYPE_INT", name))
 
-    def inputstring(self, type, name):
-        self.paramshdr.append("const char *%s" % name)
+    def inputstring(self, type, name, us):
+        if us:
+            self.paramshdr.append("const unsigned char *%s" % name)
+        else:
+            self.paramshdr.append("const char *%s" % name)
         self.inputparams.append(("G_TYPE_STRING", name))
         
     def inputpurplestructure(self, type, name):
@@ -254,7 +291,7 @@
         self.returncode.append("return (%s*) GINT_TO_POINTER(%s);" % (type[0], name));
         self.definepurplestructure(type)
 
-    def outputlist(self, type, name, const):
+    def outputlist(self, type, name):
         self.functiontype = "%s*" % type[0]
         self.decls.append("GArray *%s;" % name)
         self.outputparams.append(('dbus_g_type_get_collection("GArray", G_TYPE_INT)', name))
@@ -298,7 +335,7 @@
         print "\tdbus_message_append_args(reply_DBUS,",
         for param in self.cparamsout:
             if type(param) is str:
-                print "%s," % param
+                print "%s," % param,
             else:
                 print "DBUS_TYPE_%s, &%s," % param,
         print "DBUS_TYPE_INVALID);"
@@ -322,15 +359,23 @@
 
     # input parameters
 
-    def inputsimple(self, type, name):
-        self.cdecls.append("\tdbus_int32_t %s;" % name)
-        self.cparams.append(("INT32", name))
-        self.addintype("i", name)
+    def inputsimple(self, type, name, us):
+        if us:
+            self.cdecls.append("\tdbus_int32_t %s;" % name)
+            self.cparams.append(("INT32", name))
+            self.addintype("i", name)
+        else:
+            self.cdecls.append("\tdbus_uint32_t %s;" % name)
+            self.cparams.append(("UINT32", name))
+            self.addintype("u", name)
 
-    def inputstring(self, type, name):
-        self.cdecls.append("\tconst char *%s;" % name)
+    def inputstring(self, type, name, us):
+        if us:
+            self.cdecls.append("\tconst unsigned char *%s;" % name)
+        else:
+            self.cdecls.append("\tconst char *%s;" % name)
         self.cparams.append(("STRING", name))
-        self.ccode  .append("\tNULLIFY(%s);" % name)
+        self.ccode.append("\t%s = (%s && %s[0]) ? %s : NULL;" % (name,name,name,name))
         self.addintype("s", name)
 
     def inputhash(self, type, name):
@@ -390,28 +435,20 @@
 
     # GList*, GSList*, assume that list is a list of objects
     # unless the function is in stringlists
-    def outputlist(self, type, name, const):
+    def outputlist(self, type, name):
         self.cdecls.append("\tdbus_int32_t %s_LEN;" % name)
         self.ccodeout.append("\tg_free(%s);" % name)
 
-        if const:
-            const_prefix = "const_"
-        else:
-            const_prefix = ""
-
-        if (const):
-            self.cdecls.append("\tconst %s *list;" % type[0]);
-        else:
-            self.cdecls.append("\t%s *list;" % type[0]);
+        self.cdecls.append("\t%s *list;" % type[0]);
 
         if self.function.name in stringlists:
             self.cdecls.append("\tchar **%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = (char **)purple_const_%s_to_array(list, &%s_LEN);" % \
+            self.ccode.append("\t%s = (char **)purple_%s_to_array(list, FALSE, &%s_LEN);" % \
                          (name, type[0], name))
-            self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \
+            self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_STRING, &%s, %s_LEN" \
                           % (name, name))
-            if (not const):
+            if (not (self.function.name in constlists)):
                 type_name = type[0].lower()[1:]
                 self.ccodeout.append("\tg_%s_foreach(list, (GFunc)g_free, NULL);" % type_name)
                 self.ccodeout.append("\tg_%s_free(list);" % type_name)
@@ -419,11 +456,11 @@
         else:
             self.cdecls.append("\tdbus_int32_t *%s;" % name)
             self.ccode.append("\tlist = %s;" % self.call)
-            self.ccode.append("\t%s = purple_dbusify_const_%s(list, &%s_LEN);" % \
+            self.ccode.append("\t%s = purple_dbusify_%s(list, FALSE, &%s_LEN);" % \
                          (name, type[0], name))
-            if (not const):
+            if (not (self.function.name in constlists)):
                 self.ccode.append("\tg_%s_free(list);" % type[0].lower()[1:])
-            self.cparamsout.append("\tDBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
+            self.cparamsout.append("DBUS_TYPE_ARRAY, DBUS_TYPE_INT32, &%s, %s_LEN" \
                               % (name, name))
             self.addouttype("ai", name)
 
--- a/libpurple/dbus-bindings.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/dbus-bindings.h	Tue Jun 19 17:17:57 2007 +0000
@@ -83,52 +83,14 @@
 					int              first_arg_type,
 					va_list          var_args);
 
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_dbusify_const_GList().
- */
 dbus_int32_t* purple_dbusify_GList(GList *list, gboolean free_memory, 
 				 dbus_int32_t *len);
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_dbusify_const_GSList().
- */
 dbus_int32_t* purple_dbusify_GSList(GSList *list, gboolean free_memory,
 				  dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-dbus_int32_t* purple_dbusify_const_GList(const GList *list, dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-dbus_int32_t* purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len);
-
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_const_GList_to_array().
- */
 gpointer* purple_GList_to_array(GList *list, gboolean free_memory,
 			      dbus_int32_t *len);
-/**
- * @deprecated In 3.0.0, this method will have a signature and behavior
- *             like that of purple_const_GSList_to_array().
- */
 gpointer* purple_GSList_to_array(GSList *list, gboolean free_memory,
 			      dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-gpointer* purple_const_GList_to_array(const GList *list, dbus_int32_t *len);
-
-/**
- * @since 2.1.0
- */
-gpointer* purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len);
-
 GHashTable *purple_dbus_iter_hash_table(DBusMessageIter *iter, DBusError *error);
 
 const char* empty_to_null(const char *str);
--- a/libpurple/dbus-server.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/dbus-server.c	Tue Jun 19 17:17:57 2007 +0000
@@ -120,7 +120,7 @@
 	if ((id == 0) && (node != NULL))
 	{
 		purple_debug_warning("dbus",
-				"Need to register an object with the dbus subsystem.\n");
+				"Need to register an object with the dbus subsystem. (If you are not a developer, please ignore this message.)\n");
 		return 0;
 	}
 	return id;
@@ -290,45 +290,19 @@
 }
 
 dbus_int32_t *
-purple_dbusify_const_GList(const GList *list, dbus_int32_t *len)
+purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
 {
 	dbus_int32_t *array;
 	int i;
-	const GList *elem;
+	GList *elem;
 
-	/* g_list_length() should really take a const GList */
-	*len = g_list_length((GList *)list);
+	*len = g_list_length(list);
 	array = g_new0(dbus_int32_t, *len);
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	return array;
-}
-
-dbus_int32_t *
-purple_dbusify_GList(GList *list, gboolean free_memory, dbus_int32_t *len)
-{
-	dbus_int32_t *array = purple_dbusify_const_GList(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_list_free(list);
-	return array;
-}
-
-dbus_int32_t *
-purple_dbusify_const_GSList(const GSList *list, dbus_int32_t *len)
-{
-	dbus_int32_t *array;
-	int i;
-	const GSList *elem;
-
-	/* g_slist_length should really take a const GSList */
-	*len = g_slist_length((GSList *)list);
-	array = g_new0(dbus_int32_t, *len);
-	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
-		array[i] = purple_dbus_pointer_to_id(elem->data);
+	if (free_memory)
+		g_list_free(list);
 
 	return array;
 }
@@ -336,26 +310,17 @@
 dbus_int32_t *
 purple_dbusify_GSList(GSList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	dbus_int32_t *array = purple_dbusify_const_GSList(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_slist_free(list);
-	return array;
-}
+	dbus_int32_t *array;
+	int i;
+	GSList *elem;
 
-gpointer *
-purple_const_GList_to_array(const GList *list, dbus_int32_t *len)
-{
-	gpointer *array;
-	int i;
-	const GList *elem;
+	*len = g_slist_length(list);
+	array = g_new0(dbus_int32_t, *len);
+	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
+		array[i] = purple_dbus_pointer_to_id(elem->data);
 
-	*len = g_list_length((GList *)list);
-	array = g_new0(gpointer, *len);
-	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
-		array[i] = elem->data;
+	if (free_memory)
+		g_slist_free(list);
 
 	return array;
 }
@@ -363,39 +328,36 @@
 gpointer *
 purple_GList_to_array(GList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	gpointer *array = purple_const_GList_to_array(list, len);
-
-	if (!free_memory)
-		return array;
-
-	g_list_free(list);
-	return array;
-}
-
-gpointer *
-purple_const_GSList_to_array(const GSList *list, dbus_int32_t *len)
-{
 	gpointer *array;
 	int i;
-	const GSList *elem;
+	GList *elem;
 
-	*len = g_slist_length((GSList *)list);
+	*len = g_list_length(list);
 	array = g_new0(gpointer, *len);
 	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
 		array[i] = elem->data;
 
+	if (free_memory)
+		g_list_free(list);
+
 	return array;
 }
 
 gpointer *
 purple_GSList_to_array(GSList *list, gboolean free_memory, dbus_int32_t *len)
 {
-	gpointer *array = purple_const_GSList_to_array(list, len);
+	gpointer *array;
+	int i;
+	GSList *elem;
 
-	if (!free_memory)
-		return array;
+	*len = g_slist_length(list);
+	array = g_new0(gpointer, *len);
+	for (i = 0, elem = list; elem != NULL; elem = elem->next, i++)
+		array[i] = elem->data;
 
-	g_slist_free(list);
+	if (free_memory)
+		g_slist_free(list);
+
 	return array;
 }
 
@@ -798,7 +760,7 @@
 	dbus_message_iter_init_append(signal, &iter);
 
 	if (purple_dbus_message_append_purple_values(&iter, num_values, values, vargs))
-		purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error.\n", name);
+		purple_debug_warning("dbus", "The signal \"%s\" caused some dbus error. (If you are not a developer, please ignore this message.)\n", name);
 
 	dbus_connection_send(purple_dbus_connection, signal, NULL);
 
@@ -835,8 +797,18 @@
 void
 purple_dbus_uninit(void)
 {
-	/* Surely we must do SOME kind of uninitialization? */
+	DBusError error;
+	if (!purple_dbus_connection)
+		return;
 
+	dbus_error_init(&error);
+	dbus_connection_unregister_object_path(purple_dbus_connection, DBUS_PATH_PURPLE);
+	dbus_bus_release_name(purple_dbus_connection, DBUS_SERVICE_PURPLE, &error);
+	dbus_error_free(&error);
+	dbus_connection_unref(purple_dbus_connection);
+	purple_dbus_connection = NULL;
+	purple_signals_disconnect_by_handle(purple_dbus_get_handle());
 	g_free(init_error);
 	init_error = NULL;
 }
+
--- a/libpurple/dbus-useful.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/dbus-useful.c	Tue Jun 19 17:17:57 2007 +0000
@@ -11,7 +11,7 @@
 		       gboolean (*account_test)(const PurpleAccount *account))
 {
 	PurpleAccount *result = NULL;
-	const GList *l;
+	GList *l;
 	char *who;
 
 	if (name)
--- a/libpurple/idle.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/idle.c	Tue Jun 19 17:17:57 2007 +0000
@@ -199,7 +199,7 @@
 	/* Idle reporting stuff */
 	if (report_idle && (time_idle >= IDLEMARK))
 	{
-		const GList *l;
+		GList *l;
 		for (l = purple_connections_get_all(); l != NULL; l = l->next)
 		{
 			PurpleConnection *gc = l->data;
--- a/libpurple/internal.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/internal.h	Tue Jun 19 17:17:57 2007 +0000
@@ -111,16 +111,10 @@
 # include <unistd.h>
 #endif
 
-#ifndef MAXPATHLEN
-# define MAXPATHLEN 1024
-#endif
-
 #ifndef HOST_NAME_MAX
 # define HOST_NAME_MAX 255
 #endif
 
-#define PATHSIZE 1024
-
 #include <glib.h>
 #if !GLIB_CHECK_VERSION(2,4,0)
 #	define G_MAXUINT32 ((guint32) 0xffffffff)
--- a/libpurple/log.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/log.c	Tue Jun 19 17:17:57 2007 +0000
@@ -985,7 +985,7 @@
 		GDir *protocol_dir;
 		const gchar *username;
 		gchar *protocol_unescaped;
-		const GList *account_iter;
+		GList *account_iter;
 		GList *accounts = NULL;
 
 		if ((protocol_dir = g_dir_open(protocol_path, 0, NULL)) == NULL) {
--- a/libpurple/mime.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/mime.c	Tue Jun 19 17:17:57 2007 +0000
@@ -277,7 +277,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_part_get_fields(PurpleMimePart *part)
 {
 	g_return_val_if_fail(part != NULL, NULL);
@@ -513,7 +513,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_document_get_fields(PurpleMimeDocument *doc)
 {
 	g_return_val_if_fail(doc != NULL, NULL);
@@ -537,7 +537,7 @@
 }
 
 
-const GList *
+GList *
 purple_mime_document_get_parts(PurpleMimeDocument *doc)
 {
 	g_return_val_if_fail(doc != NULL, NULL);
--- a/libpurple/mime.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/mime.h	Tue Jun 19 17:17:57 2007 +0000
@@ -90,10 +90,10 @@
  *
  * @param doc The MIME document.
  *
- * @returns   A list of strings indicating the fields (but not the values of
- *            the fields) in the header of doc.
+ * @constreturn A list of strings indicating the fields (but not the values
+ *              of the fields) in the header of doc.
  */
-const GList *purple_mime_document_get_fields(PurpleMimeDocument *doc);
+GList *purple_mime_document_get_fields(PurpleMimeDocument *doc);
 
 /**
  * Get the value of a specific field in the header of a document.
@@ -125,9 +125,9 @@
  *
  * @param doc The MIME document.
  *
- * @returns   List of PurpleMimePart contained within doc.
+ * @constreturn   List of PurpleMimePart contained within doc.
  */
-const GList *purple_mime_document_get_parts(PurpleMimeDocument *doc);
+GList *purple_mime_document_get_parts(PurpleMimeDocument *doc);
 
 /**
  * Create and insert a new part into a MIME document.
@@ -142,10 +142,10 @@
  *
  * @param part The MIME document part.
  *
- * @returns    List of strings indicating the fields (but not the values
- *             of the fields) in the header of part.
+ * @constreturn List of strings indicating the fields (but not the values
+ *              of the fields) in the header of part.
  */
-const GList *purple_mime_part_get_fields(PurpleMimePart *part);
+GList *purple_mime_part_get_fields(PurpleMimePart *part);
 
 
 /**
--- a/libpurple/notify.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/notify.c	Tue Jun 19 17:17:57 2007 +0000
@@ -530,7 +530,7 @@
 	g_free(user_info);
 }
 
-const GList *
+GList *
 purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info)
 {
 	g_return_val_if_fail(user_info != NULL, NULL);
--- a/libpurple/notify.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/notify.h	Tue Jun 19 17:17:57 2007 +0000
@@ -456,9 +456,9 @@
  *
  * @param user_info          The PurpleNotifyUserInfo
  *
- * @result                   A GList of PurpleNotifyUserInfoEntry objects
+ * @constreturn              A GList of PurpleNotifyUserInfoEntry objects
  */
-const GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
+GList *purple_notify_user_info_get_entries(PurpleNotifyUserInfo *user_info);
 
 /**
  * Create a textual representation of a PurpleNotifyUserInfo, separating entries with newline
--- a/libpurple/plugins/joinpart.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/joinpart.c	Tue Jun 19 17:17:57 2007 +0000
@@ -86,7 +86,7 @@
 	/* If the room is small, don't bother. */
 	chat = PURPLE_CONV_CHAT(conv);
 	threshold = purple_prefs_get_int(THRESHOLD_PREF);
-	if (g_list_length((GList *)purple_conv_chat_get_users(chat)) < threshold)
+	if (g_list_length(purple_conv_chat_get_users(chat)) < threshold)
 		return FALSE;
 
 	/* We always care about our buddies! */
--- a/libpurple/plugins/perl/common/Account.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Account.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -184,7 +184,7 @@
 purple_account_get_status_types(account)
     Purple::Account account
 PREINIT:
-    const GList *l;
+    GList *l;
 PPCODE:
     for (l = purple_account_get_status_types(account); l != NULL; l = l->next) {
         XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusType")));
@@ -290,7 +290,7 @@
 void
 purple_accounts_get_all()
 PREINIT:
-    const GList *l;
+    GList *l;
 PPCODE:
     for (l = purple_accounts_get_all(); l != NULL; l = l->next) {
         XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Account")));
--- a/libpurple/plugins/perl/common/AccountOpts.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/AccountOpts.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -88,7 +88,7 @@
 purple_account_option_get_list(option)
 	Purple::Account::Option option
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_account_option_get_list(option); l != NULL; l = l->next) {
 		/* XXX These are actually PurpleKeyValuePairs but we don't have a
--- a/libpurple/plugins/perl/common/Connection.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Connection.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -72,7 +72,7 @@
 void
 purple_connections_get_all()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_connections_get_all(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
@@ -81,7 +81,7 @@
 void
 purple_connections_get_connecting()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_connections_get_connecting(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Connection")));
--- a/libpurple/plugins/perl/common/Conversation.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Conversation.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -93,7 +93,7 @@
 void
 purple_get_ims()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_ims(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -102,7 +102,7 @@
 void
 purple_get_conversations()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -111,7 +111,7 @@
 void
 purple_get_chats()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_get_chats(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Conversation")));
@@ -354,7 +354,7 @@
 purple_conv_chat_get_users(chat)
 	Purple::Conversation::Chat chat
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_conv_chat_get_users(chat); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
@@ -394,7 +394,7 @@
 purple_conv_chat_get_ignored(chat)
 	Purple::Conversation::Chat chat
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_conv_chat_get_ignored(chat); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::ListEntry")));
--- a/libpurple/plugins/perl/common/Notify.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Notify.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -140,7 +140,7 @@
 purple_notify_user_info_get_entries(user_info)
 	Purple::NotifyUserInfo user_info
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	l = purple_notify_user_info_get_entries(user_info);
 	for (; l != NULL; l = l->next) {
--- a/libpurple/plugins/perl/common/Request.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Request.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -396,7 +396,7 @@
 purple_request_field_list_get_items(field)
 	Purple::Request::Field field
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_field_list_get_items(field); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
@@ -410,7 +410,7 @@
 purple_request_field_list_get_selected(field)
 	Purple::Request::Field field
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_field_list_get_selected(field); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(newSVpv(l->data, 0)));
@@ -625,7 +625,7 @@
 purple_request_fields_get_required(fields)
 	Purple::Request::Fields fields
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_request_fields_get_required(fields); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Request::Field")));
--- a/libpurple/plugins/perl/common/SavedStatuses.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/SavedStatuses.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -130,7 +130,7 @@
 void
 purple_savedstatuses_get_all()
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_savedstatuses_get_all(); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
@@ -140,7 +140,7 @@
 purple_savedstatuses_get_popular(how_many)
 	unsigned int how_many
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_savedstatuses_get_popular(how_many); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::SavedStatus")));
--- a/libpurple/plugins/perl/common/Status.xs	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/perl/common/Status.xs	Tue Jun 19 17:17:57 2007 +0000
@@ -142,7 +142,7 @@
 purple_presence_get_statuses(presence)
 	Purple::Presence presence
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_presence_get_statuses(presence); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::Status")));
@@ -392,7 +392,7 @@
 purple_status_type_get_attrs(status_type)
 	Purple::StatusType status_type
 PREINIT:
-	const GList *l;
+	GList *l;
 PPCODE:
 	for (l = purple_status_type_get_attrs(status_type); l != NULL; l = l->next) {
 		XPUSHs(sv_2mortal(purple_perl_bless_object(l->data, "Purple::StatusAttr")));
--- a/libpurple/plugins/startup.py	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/startup.py	Tue Jun 19 17:17:57 2007 +0000
@@ -25,6 +25,13 @@
 import dbus
 import os
 
+if len(sys.argv) == 1:
+	print "Usage:", sys.argv[0], """<purple-client> [arguments]
+
+Example:
+	""", sys.argv[0], "pidgin -d -c /my/home"
+	sys.exit(1)
+
 home = os.path.expanduser('~/.purple/')
 for arg in range(1, len(sys.argv[1:])):
 	if sys.argv[arg] == "-c":
--- a/libpurple/plugins/tcl/tcl_cmds.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/plugins/tcl/tcl_cmds.c	Tue Jun 19 17:17:57 2007 +0000
@@ -43,7 +43,7 @@
 static PurpleAccount *tcl_validate_account(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleAccount *account;
-	const GList *cur;
+	GList *cur;
 
 	account = purple_tcl_ref_get(interp, obj, PurpleTclRefAccount);
 
@@ -62,7 +62,7 @@
 static PurpleConversation *tcl_validate_conversation(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleConversation *convo;
-	const GList *cur;
+	GList *cur;
 
 	convo = purple_tcl_ref_get(interp, obj, PurpleTclRefConversation);
 
@@ -81,7 +81,7 @@
 static PurpleConnection *tcl_validate_gc(Tcl_Obj *obj, Tcl_Interp *interp)
 {
 	PurpleConnection *gc;
-	const GList *cur;
+	GList *cur;
 
 	gc = purple_tcl_ref_get(interp, obj, PurpleTclRefConnection);
 
@@ -113,7 +113,7 @@
 	const char *listopts[] = { "-all", "-online", NULL };
 	enum { CMD_ACCOUNTLIST_ALL, CMD_ACCOUNTLIST_ONLINE } listopt;
 	const char *alias;
-	const GList *cur;
+	GList *cur;
 	PurpleAccount *account;
 	PurpleStatus *status;
 	PurpleStatusType *status_type;
@@ -612,7 +612,7 @@
 	const char *cmds[] = { "account", "displayname", "handle", "list", NULL };
 	enum { CMD_CONN_ACCOUNT, CMD_CONN_DISPLAYNAME, CMD_CONN_HANDLE, CMD_CONN_LIST } cmd;
 	int error;
-	const GList *cur;
+	GList *cur;
 	PurpleConnection *gc;
 
 	if (objc < 2) {
@@ -680,7 +680,7 @@
 	PurpleConversation *convo;
 	PurpleAccount *account;
 	PurpleConversationType type;
-	const GList *cur;
+	GList *cur;
 	char *opt, *from, *what;
 	int error, argsused, flags = 0;
 
@@ -1082,7 +1082,7 @@
 	Tcl_Obj *result = Tcl_GetObjResult(interp);
 	Tcl_Obj *list, *elem;
 	PurplePresence *presence;
-	const GList *cur;
+	GList *cur;
 	int error, idle, idle_time, login_time;
 
 	if (objc < 2) {
@@ -1524,7 +1524,7 @@
 	Tcl_Obj *result = Tcl_GetObjResult(interp);
 	PurpleStatusType *status_type;
 	Tcl_Obj *list, *elem;
-	const GList *cur;
+	GList *cur;
 	int error;
 
 	if (objc < 2) {
--- a/libpurple/pounce.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/pounce.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1014,6 +1014,20 @@
 	return pounces;
 }
 
+GList *purple_pounces_get_all_for_ui(const char *ui)
+{
+	GList *list = NULL, *iter;
+	g_return_val_if_fail(ui != NULL, NULL);
+
+	for (iter = pounces; iter; iter = iter->next) {
+		PurplePounce *pounce = iter->data;
+		if (pounce->ui_type && strcmp(pounce->ui_type, ui) == 0)
+			list = g_list_prepend(list, pounce);
+	}
+	list = g_list_reverse(list);
+	return list;
+}
+
 static void
 free_pounce_handler(gpointer user_data)
 {
--- a/libpurple/pounce.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/pounce.h	Tue Jun 19 17:17:57 2007 +0000
@@ -343,6 +343,17 @@
 GList *purple_pounces_get_all(void);
 
 /**
+ * Returns a list of registered buddy pounces for the ui-type.
+ *
+ * @param ui  The ID of the UI using the core.
+ *
+ * @return The list of buddy pounces. The list should be freed by
+ *         the caller when it's no longer used.
+ * @since  2.1.0
+ */
+GList *purple_pounces_get_all_for_ui(const char *ui);
+
+/**
  * Returns the buddy pounce subsystem handle.
  *
  * @return The subsystem handle.
--- a/libpurple/prefs.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/prefs.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1355,7 +1355,6 @@
 	purple_prefs_remove("/plugins/core/autorecon/hide_reconnecting_dialog");
 	purple_prefs_remove("/plugins/core/autorecon/restore_state");
 	purple_prefs_remove("/plugins/core/autorecon");
-	purple_prefs_remove("/purple/debug/timestamps");
 
 	/* Convert old sounds while_away pref to new 3-way pref. */
 	if (purple_prefs_exists("/purple/sound/while_away") &&
--- a/libpurple/protocols/gg/gg.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/gg/gg.c	Tue Jun 19 17:17:57 2007 +0000
@@ -823,7 +823,7 @@
 {
 	GGPInfo *info = gc->proto_data;
 	PurpleRequestField *field;
-	const GList *sel;
+	GList *sel;
 
 	field = purple_request_fields_get_field(fields, "name");
 	sel = purple_request_field_list_get_selected(field);
--- a/libpurple/protocols/irc/irc.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/irc/irc.c	Tue Jun 19 17:17:57 2007 +0000
@@ -592,7 +592,7 @@
 	struct irc_conn *irc = gc->proto_data;
 	int len;
 
-	if(!g_list_find((GList *)purple_connections_get_all(), gc)) {
+	if(!g_list_find(purple_connections_get_all(), gc)) {
 		purple_ssl_close(gsc);
 		return;
 	}
--- a/libpurple/protocols/jabber/buddy.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.c	Tue Jun 19 17:17:57 2007 +0000
@@ -385,6 +385,11 @@
 	xmlnode *vc_node;
 	struct tag_attr *tag_attr;
 
+	/* if we have't grabbed the remote vcard yet, we can't
+	 * assume that what we have here is correct */
+	if(!js->vcard_fetched)
+		return;
+
 	g_free(js->avatar_hash);
 	js->avatar_hash = NULL;
 
@@ -443,14 +448,9 @@
 
 void jabber_set_buddy_icon(PurpleConnection *gc, PurpleStoredImage *img)
 {
-	PurplePresence *gpresence;
-	PurpleStatus *status;
-
 	jabber_set_info(gc, purple_account_get_user_info(gc->account));
 
-	gpresence = purple_account_get_presence(gc->account);
-	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(gc->account, status);
+	jabber_presence_send(gc->account, NULL);
 }
 
 /*
@@ -739,6 +739,40 @@
 	}
 }
 
+static void jabber_vcard_save_mine(JabberStream *js, xmlnode *packet, gpointer data)
+{
+	xmlnode *vcard;
+	char *txt;
+	PurpleStoredImage *img;
+
+	if((vcard = xmlnode_get_child(packet, "vCard")) ||
+			(vcard = xmlnode_get_child_with_namespace(packet, "query", "vcard-temp")))
+	{
+		txt = xmlnode_to_str(vcard, NULL);
+		purple_account_set_user_info(purple_connection_get_account(js->gc), txt);
+
+		g_free(txt);
+	} else {
+		/* if we have no vCard, then lets not overwrite what we might have locally */
+	}
+
+	js->vcard_fetched = TRUE;
+
+	if(NULL != (img = purple_buddy_icons_find_account_icon(js->gc->account))) {
+		jabber_set_buddy_icon(js->gc, img);
+		purple_imgstore_unref(img);
+	}
+}
+
+void jabber_vcard_fetch_mine(JabberStream *js)
+{
+	JabberIq *iq = jabber_iq_new_query(js, JABBER_IQ_GET, "vcard-temp");
+
+	jabber_iq_set_callback(iq, jabber_vcard_save_mine, NULL);
+
+	jabber_iq_send(iq);
+}
+
 static void jabber_vcard_parse(JabberStream *js, xmlnode *packet, gpointer data)
 {
 	const char *id, *from;
--- a/libpurple/protocols/jabber/buddy.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/buddy.h	Tue Jun 19 17:17:57 2007 +0000
@@ -103,4 +103,6 @@
 
 void jabber_buddy_remove_all_pending_buddy_info_requests(JabberStream *js);
 
+void jabber_vcard_fetch_mine(JabberStream *js);
+
 #endif /* _PURPLE_JABBER_BUDDY_H_ */
--- a/libpurple/protocols/jabber/disco.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/disco.c	Tue Jun 19 17:17:57 2007 +0000
@@ -218,18 +218,15 @@
 static void
 jabber_disco_finish_server_info_result_cb(JabberStream *js)
 {
-	PurplePresence *gpresence;
-	PurpleStatus *status;
+
+	jabber_vcard_fetch_mine(js);
 
 	if (!(js->server_caps & JABBER_CAP_GOOGLE_ROSTER)) {
 		/* If the server supports JABBER_CAP_GOOGLE_ROSTER; we will have already requested it */
 		jabber_roster_request(js);
 	}
 
-	/* Send initial presence; this will trigger receipt of presence for contacts on the roster */
-	gpresence = purple_account_get_presence(js->gc->account);
-	status = purple_presence_get_active_status(gpresence);
-	jabber_presence_send(js->gc->account, status);
+	/* when we get the roster back, we'll send our initial presence */
 }
 
 static void
--- a/libpurple/protocols/jabber/google.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/google.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1,4 +1,3 @@
-
 /**
  * Purple is the legal property of its developers, whose names are too numerous
  * to list here.  Please refer to the COPYRIGHT file distributed with this
@@ -30,7 +29,7 @@
 #include "presence.h"
 #include "iq.h"
 
-static void 
+static void
 jabber_gmail_parse(JabberStream *js, xmlnode *packet, gpointer nul)
 {
 	const char *type = xmlnode_get_attrib(packet, "type");
@@ -40,57 +39,57 @@
 	const char *in_str;
 	char *to_name;
 	int i, count = 1, returned_count;
-	
+
 	const char **tos, **froms, **subjects, **urls;
-	
+
 	if (strcmp(type, "result"))
 		return;
-	
+
 	child = xmlnode_get_child(packet, "mailbox");
 	if (!child)
 		return;
 
 	in_str = xmlnode_get_attrib(child, "total-matched");
-	if (in_str && *in_str) 
+	if (in_str && *in_str)
 		count = atoi(in_str);
- 
-	if (count == 0) 
+
+	if (count == 0)
 		return;
 
 	message = xmlnode_get_child(child, "mail-thread-info");
-	
+
 	/* Loop once to see how many messages were returned so we can allocate arrays
 	 * accordingly */
-	if (!message) 
+	if (!message)
 		return;
 	for (returned_count = 0; message; returned_count++, message=xmlnode_get_next_twin(message));
-	
+
 	froms    = g_new0(const char* , returned_count);
 	tos      = g_new0(const char* , returned_count);
 	subjects = g_new0(const char* , returned_count);
 	urls     = g_new0(const char* , returned_count);
-	
+
 	to = xmlnode_get_attrib(packet, "to");
 	to_name = jabber_get_bare_jid(to);
 	url = xmlnode_get_attrib(child, "url");
 	if (!url || !*url)
 		url = "http://www.gmail.com";
-	
+
 	message= xmlnode_get_child(child, "mail-thread-info");
 	for (i=0; message; message = xmlnode_get_next_twin(message), i++) {
 		subject_node = xmlnode_get_child(message, "subject");
 		sender_node  = xmlnode_get_child(message, "senders");
 		sender_node  = xmlnode_get_child(sender_node, "sender");
 
-		while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") || 
+		while (sender_node && (!xmlnode_get_attrib(sender_node, "unread") ||
 		       !strcmp(xmlnode_get_attrib(sender_node, "unread"),"0")))
 			sender_node = xmlnode_get_next_twin(sender_node);
-		
+
 		if (!sender_node) {
 			i--;
 			continue;
 		}
-			
+
 		from = xmlnode_get_attrib(sender_node, "name");
 		if (!from || !*from)
 			from = xmlnode_get_attrib(sender_node, "address");
@@ -102,18 +101,18 @@
 		froms[i] = (from != NULL ?  from : "");
 		subjects[i] = (subject != NULL ? subject : "");
 		urls[i] = (url != NULL ? url : "");
-		
+
 		tid = xmlnode_get_attrib(message, "tid");
-		if (tid && 
+		if (tid &&
 		    (js->gmail_last_tid == NULL || strcmp(tid, js->gmail_last_tid) > 0)) {
 			g_free(js->gmail_last_tid);
 			js->gmail_last_tid = g_strdup(tid);
 		}
 	}
 
-	if (i>0) 
-		purple_notify_emails(js->gc, count, count == returned_count, subjects, froms, tos, 
-				   	   urls, NULL, NULL);
+	if (i>0)
+		purple_notify_emails(js->gc, count, count == returned_count, subjects, froms, tos,
+				urls, NULL, NULL);
 
 	g_free(to_name);
 	g_free(tos);
@@ -128,19 +127,19 @@
 	}
 }
 
-void 
-jabber_gmail_poke(JabberStream *js, xmlnode *packet) 
+void
+jabber_gmail_poke(JabberStream *js, xmlnode *packet)
 {
 	const char *type;
 	xmlnode *query;
 	JabberIq *iq;
-	
+
 	/* bail if the user isn't interested */
 	if (!purple_account_get_check_mail(js->gc->account))
 		return;
 
 	type = xmlnode_get_attrib(packet, "type");
-	
+
 
 	/* Is this an initial incoming mail notification? If so, send a request for more info */
 	if (strcmp(type, "set") || !xmlnode_get_child(packet, "new-mail"))
@@ -165,7 +164,7 @@
 void jabber_gmail_init(JabberStream *js) {
 	JabberIq *iq;
 
-	if (!purple_account_get_check_mail(js->gc->account)) 
+	if (!purple_account_get_check_mail(js->gc->account))
 		return;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "google:mail:notify");
@@ -180,7 +179,7 @@
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_GET, "jabber:iq:roster");
 	query = xmlnode_get_child(iq->node, "query");
-	
+
 	xmlnode_set_attrib(query, "xmlns:gr", "google:roster");
 	xmlnode_set_attrib(query, "gr:ext", "2");
 
@@ -218,14 +217,14 @@
 
 	const char *grt = xmlnode_get_attrib_with_namespace(item, "t", "google:roster");
 	const char *subscription = xmlnode_get_attrib(item, "subscription");
-	
+
 	if (!subscription || !strcmp(subscription, "none")) {
 		/* The Google Talk servers will automatically add people from your Gmail address book
 		 * with subscription=none. If we see someone with subscription=none, ignore them.
 		 */
 		return FALSE;
 	}
-	
+
 	while (list) {
 		if (!strcmp(jid_norm, (char*)list->data)) {
 			on_block_list = TRUE;
@@ -233,13 +232,13 @@
 		}
 		list = list->next;
 	}
-	
+
 	if (grt && (*grt == 'H' || *grt == 'h')) {
 		PurpleBuddy *buddy = purple_find_buddy(account, jid_norm);
 		purple_blist_remove_buddy(buddy);
 		return FALSE;
 	}
-	
+
 	if (!on_block_list && (grt && (*grt == 'B' || *grt == 'b'))) {
 		purple_debug_info("jabber", "Blocking %s\n", jid_norm);
 		purple_privacy_deny_add(account, jid_norm, TRUE);
@@ -250,7 +249,7 @@
 	return TRUE;
 }
 
-void jabber_google_roster_add_deny(PurpleConnection *gc, const char *who) 
+void jabber_google_roster_add_deny(PurpleConnection *gc, const char *who)
 {
 	JabberStream *js;
 	GSList *buddies;
@@ -262,7 +261,7 @@
 	JabberBuddy *jb;
 
 	js = (JabberStream*)(gc->proto_data);
-	
+
 	if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
 		return;
 
@@ -271,11 +270,11 @@
 	buddies = purple_find_buddies(js->gc->account, who);
 	if(!buddies)
 		return;
-	
+
 	b = buddies->data;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-	
+
 	query = xmlnode_get_child(iq->node, "query");
 	item = xmlnode_new_child(query, "item");
 
@@ -287,7 +286,7 @@
 
 		group = xmlnode_new_child(item, "group");
 		xmlnode_insert_data(group, g->name, -1);
-		
+
 		buddies = buddies->next;
 	}
 
@@ -333,20 +332,20 @@
 
 	g_return_if_fail(gc != NULL);
 	g_return_if_fail(who != NULL);
-	
+
 	js = (JabberStream*)(gc->proto_data);
-	
+
 	if (!js || !js->server_caps & JABBER_CAP_GOOGLE_ROSTER)
 		return;
-	
+
 	buddies = purple_find_buddies(js->gc->account, who);
 	if(!buddies)
 		return;
-	
+
 	b = buddies->data;
 
 	iq = jabber_iq_new_query(js, JABBER_IQ_SET, "jabber:iq:roster");
-	
+
 	query = xmlnode_get_child(iq->node, "query");
 	item = xmlnode_new_child(query, "item");
 
@@ -358,7 +357,7 @@
 
 		group = xmlnode_new_child(item, "group");
 		xmlnode_insert_data(group, g->name, -1);
-		
+
 		buddies = buddies->next;
 	}
 
@@ -440,15 +439,15 @@
 
 	for (p = text; *p != '\0'; p = g_utf8_next_char(p)) {
 		gunichar c = g_utf8_get_char(p);
- 
+
 		if (bold_count < 2 && italic_count < 2 && !in_bold && !in_italic) {
 			g_string_append(str, p);
 			return g_string_free(str, FALSE);
 		}
 
-		
+
 		if (c == '*' && !in_tag) {
-			if (in_bold && 
+			if (in_bold &&
 			    (g_unichar_isspace(*(p+1))||*(p+1)=='<')) { /* This is safe in UTF-8 */
 				str = g_string_append(str, "</b>");
 				in_bold = FALSE;
@@ -490,6 +489,6 @@
 		} else {
 			str = g_string_append_unichar(str, c);
 		}
-	}	
+	}
 	return g_string_free(str, FALSE);
 }
--- a/libpurple/protocols/jabber/iq.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/iq.c	Tue Jun 19 17:17:57 2007 +0000
@@ -208,14 +208,18 @@
 
 static void urn_xmpp_ping_parse(JabberStream *js, xmlnode *packet)
 {
-	const char *type, *from, *id;
+	const char *type, *id, *from;
 	JabberIq *iq;
-	xmlnode *query;
+
+	type = xmlnode_get_attrib(packet, "type");
+	from = xmlnode_get_attrib(packet, "from");
+	id = xmlnode_get_attrib(packet, "id");
 
 	if(type && !strcmp(type, "get")) {
 		iq = jabber_iq_new_query(js, JABBER_IQ_RESULT, "urn:xmpp:ping");
 
 		jabber_iq_set_id(iq, id);
+		xmlnode_set_attrib(iq->node, "to", from);
 
 		jabber_iq_send(iq);
 	} else {
--- a/libpurple/protocols/jabber/jabber.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1038,8 +1038,6 @@
 
 void jabber_stream_set_state(JabberStream *js, JabberStreamState state)
 {
-	PurpleStoredImage *img;
-
 	js->state = state;
 	switch(state) {
 		case JABBER_STREAM_OFFLINE:
@@ -1071,14 +1069,6 @@
 
 			break;
 		case JABBER_STREAM_CONNECTED:
-			/* lets make sure our buddy icon is up to date
-			 * before we go letting people know we're here */
-			img = purple_buddy_icons_find_account_icon(js->gc->account);
-			if(NULL != img) {
-				jabber_set_buddy_icon(js->gc, img);
-				purple_imgstore_unref(img);
-			}
-
 			/* now we can alert the core that we're ready to send status */
 			purple_connection_set_state(js->gc, PURPLE_CONNECTED);
 			jabber_disco_items_server(js);
--- a/libpurple/protocols/jabber/jabber.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/jabber.h	Tue Jun 19 17:17:57 2007 +0000
@@ -142,11 +142,17 @@
 #ifdef HAVE_CYRUS_SASL
 	sasl_conn_t *sasl;
 	sasl_callback_t *sasl_cb;
+#else /* keep the struct the same size */
+	void *sasl;
+	void *sasl_cb;
+#endif
+
 	int sasl_state;
 	int sasl_maxbuf;
 	GString *sasl_mechs;
 	char *serverFQDN;
-#endif
+
+	gboolean vcard_fetched;
 
 } JabberStream;
 
--- a/libpurple/protocols/jabber/jutil.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/jutil.c	Tue Jun 19 17:17:57 2007 +0000
@@ -221,7 +221,7 @@
 jabber_find_unnormalized_conv(const char *name, PurpleAccount *account)
 {
 	PurpleConversation *c = NULL;
-	const GList *cnv;
+	GList *cnv;
 
 	g_return_val_if_fail(name != NULL, NULL);
 
--- a/libpurple/protocols/jabber/presence.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/presence.c	Tue Jun 19 17:17:57 2007 +0000
@@ -102,6 +102,11 @@
 	JabberBuddyState state;
 	int priority;
 
+	if(NULL == status) {
+		PurplePresence *gpresence = purple_account_get_presence(account);
+		status = purple_presence_get_active_status(gpresence);
+	}
+
 	if(!purple_status_is_active(status))
 		return;
 
@@ -115,6 +120,12 @@
 	gc = purple_account_get_connection(account);
 	js = gc->proto_data;
 
+	/* we don't want to send presence before we've gotten our roster */
+	if(!js->roster_parsed) {
+		purple_debug_info("jabber", "attempt to send presence before roster retrieved\n");
+		return;
+	}
+
 	purple_status_to_jabber(status, &state, &stripped, &priority);
 
 
--- a/libpurple/protocols/jabber/roster.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/roster.c	Tue Jun 19 17:17:57 2007 +0000
@@ -153,8 +153,6 @@
 	if(!query)
 		return;
 
-	js->roster_parsed = TRUE;
-
 	for(item = xmlnode_get_child(query, "item"); item; item = xmlnode_get_next_twin(item))
 	{
 		const char *jid, *name, *subscription, *ask;
@@ -232,6 +230,14 @@
 			add_purple_buddies_to_groups(js, jid, name, groups);
 		}
 	}
+
+	/* if we're just now parsing the roster for the first time,
+	 * then now would be the time to send our initial presence */
+	if(!js->roster_parsed) {
+		js->roster_parsed = TRUE;
+
+		jabber_presence_send(js->gc->account, NULL);
+	}
 }
 
 static void jabber_roster_update(JabberStream *js, const char *name,
--- a/libpurple/protocols/jabber/xdata.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/jabber/xdata.c	Tue Jun 19 17:17:57 2007 +0000
@@ -93,7 +93,7 @@
 				case JABBER_X_DATA_LIST_SINGLE:
 				case JABBER_X_DATA_LIST_MULTI:
 					{
-					const GList *selected = purple_request_field_list_get_selected(field);
+					GList *selected = purple_request_field_list_get_selected(field);
 					char *value;
 					fieldnode = xmlnode_new_child(result, "field");
 					xmlnode_set_attrib(fieldnode, "var", id);
--- a/libpurple/protocols/msn/msn.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/msn/msn.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1463,7 +1463,7 @@
 	purple_debug_info("msn", "In msn_got_info\n");
 
 	/* Make sure the connection is still valid */
-	if (g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL)
+	if (g_list_find(purple_connections_get_all(), info_data->gc) == NULL)
 	{
 		purple_debug_warning("msn", "invalid connection. ignoring buddy info.\n");
 		g_free(info_data->name);
@@ -1883,7 +1883,7 @@
 
 	/* Make sure the connection is still valid if we got here by fetching a photo url */
 	if (url_text && (error_message != NULL ||
-					 g_list_find((GList *)purple_connections_get_all(), info_data->gc) == NULL))
+					 g_list_find(purple_connections_get_all(), info_data->gc) == NULL))
 	{
 		purple_debug_warning("msn", "invalid connection. ignoring buddy photo info.\n");
 		g_free(stripped);
@@ -1982,7 +1982,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/oscar/oscar.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Tue Jun 19 17:17:57 2007 +0000
@@ -2827,6 +2827,7 @@
 	va_list ap;
 	guint16 reason;
 	char *destn;
+	PurpleNotifyUserInfo *user_info;
 
 	va_start(ap, fr);
 	reason = (guint16) va_arg(ap, unsigned int);
@@ -2836,12 +2837,12 @@
 	if (destn == NULL)
 		return 1;
 
+	user_info = purple_notify_user_info_new();
 	buf = g_strdup_printf(_("User information not available: %s"), (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason."));
-	if (!purple_conv_present_error(destn, purple_connection_get_account((PurpleConnection*)od->gc), buf)) {
-		g_free(buf);
-		buf = g_strdup_printf(_("User information for %s unavailable:"), destn);
-		purple_notify_error(od->gc, NULL, buf, (reason < msgerrreasonlen) ? _(msgerrreason[reason]) : _("Unknown reason."));
-	}
+	purple_notify_user_info_add_pair(user_info, NULL, buf);
+	purple_notify_userinfo(od->gc, destn, user_info, NULL, NULL);
+	purple_notify_user_info_destroy(user_info);
+	purple_conv_present_error(destn, purple_connection_get_account(od->gc), buf);
 	g_free(buf);
 
 	return 1;
@@ -6558,7 +6559,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/qq/group_im.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/qq/group_im.c	Tue Jun 19 17:17:57 2007 +0000
@@ -341,7 +341,7 @@
 	read_packet_dw(data, cursor, data_len, &(im_group->member_uid));
 	read_packet_w(data, cursor, data_len, &unknown);	/* 0x0001? */
 	read_packet_w(data, cursor, data_len, &(im_group->msg_seq));
-	read_packet_dw(data, cursor, data_len, (guint32 *) & (im_group->send_time));
+	read_packet_time(data, cursor, data_len, &im_group->send_time);
 	read_packet_dw(data, cursor, data_len, &unknown4);	/* versionID */
 	/*
 	 * length includes font_attr
--- a/libpurple/protocols/qq/login_logout.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/qq/login_logout.c	Tue Jun 19 17:17:57 2007 +0000
@@ -181,7 +181,7 @@
 	/* 031-032: server listening port */
 	bytes += read_packet_w(data, &cursor, len, &lrop.server_port);
 	/* 033-036: login time for current session */
-	bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.login_time);
+	bytes += read_packet_time(data, &cursor, len, &lrop.login_time);
 	/* 037-062: 26 bytes, unknown */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown1, 26);
 	/* 063-066: unknown server1 ip address */
@@ -203,7 +203,7 @@
 	/* 123-126: login IP of last session */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.last_client_ip, 4);
 	/* 127-130: login time of last session */
-	bytes += read_packet_dw(data, &cursor, len, (guint32 *) &lrop.last_login_time);
+	bytes += read_packet_time(data, &cursor, len, &lrop.last_login_time);
 	/* 131-138: 8 bytes unknown */
 	bytes += read_packet_data(data, &cursor, len, (guint8 *) &lrop.unknown6, 8);
 
--- a/libpurple/protocols/qq/packet_parse.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/qq/packet_parse.c	Tue Jun 19 17:17:57 2007 +0000
@@ -65,6 +65,19 @@
 	}
 }
 
+/* read four bytes as "time_t" from buf,
+ * return the number of bytes read if succeeds, otherwise return -1
+ * This function is a wrapper around read_packet_dw() to avoid casting. */
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t)
+{
+	guint32 time;
+	gint ret = read_packet_dw(buf, cursor, buflen, &time);
+	if (ret != -1 ) {
+		*t = time;
+	}
+	return ret;
+}
+
 /* read datalen bytes from buf, 
  * return the number of bytes read if succeeds, otherwise return -1 */
 gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen) {
--- a/libpurple/protocols/qq/packet_parse.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/qq/packet_parse.h	Tue Jun 19 17:17:57 2007 +0000
@@ -26,6 +26,7 @@
 #define _QQ_PACKED_PARSE_H_
 
 #include <glib.h>
+#include <time.h>
 
 /* According to "UNIX Network Programming", all TCP/IP implementations
  * must support a minimum IP datagram size of 576 bytes, regardless of the MTU.
@@ -39,6 +40,7 @@
 gint read_packet_b(guint8 *buf, guint8 **cursor, gint buflen, guint8 *b);
 gint read_packet_w(guint8 *buf, guint8 **cursor, gint buflen, guint16 *w);
 gint read_packet_dw(guint8 *buf, guint8 **cursor, gint buflen, guint32 *dw);
+gint read_packet_time(guint8 *buf, guint8 **cursor, gint buflen, time_t *t);
 gint read_packet_data(guint8 *buf, guint8 **cursor, gint buflen, guint8 *data, gint datalen);
 gint create_packet_b(guint8 *buf, guint8 **cursor, guint8 b);
 gint create_packet_w(guint8 *buf, guint8 **cursor, guint16 w);
--- a/libpurple/protocols/sametime/sametime.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/sametime/sametime.c	Tue Jun 19 17:17:57 2007 +0000
@@ -2660,7 +2660,7 @@
   GString *str;
 
   PurpleMimeDocument *doc;
-  const GList *parts;
+  GList *parts;
 
   img_by_cid = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
   images = NULL;
@@ -3401,7 +3401,7 @@
 static void conf_select_prompt_invite(PurpleBuddy *buddy,
 				      PurpleRequestFields *fields) {
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
   const char *msg;
   
   f = purple_request_fields_get_field(fields, CHAT_KEY_INVITE);
@@ -5268,7 +5268,7 @@
 				       PurpleRequestFields *fields) {
   
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
 
   f = purple_request_fields_get_field(fields, "group");
   l = purple_request_field_list_get_items(f);
@@ -5334,7 +5334,7 @@
 static void remote_group_multi_cb(struct mwPurplePluginData *pd,
 				  PurpleRequestFields *fields) {
   PurpleRequestField *f;
-  const GList *l;
+  GList *l;
 
   f = purple_request_fields_get_field(fields, "group");
   l = purple_request_field_list_get_selected(f);
--- a/libpurple/protocols/silc/buddy.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/silc/buddy.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1117,7 +1117,7 @@
 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
 {
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcClientEntry client_entry;
 	SilcDList clients;
 
--- a/libpurple/protocols/silc/chat.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/silc/chat.c	Tue Jun 19 17:17:57 2007 +0000
@@ -291,7 +291,7 @@
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcPublicKey public_key;
 	SilcBuffer chpks, pk, chidp;
 	SilcUInt16 c = 0, ct;
--- a/libpurple/protocols/silc10/buddy.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/silc10/buddy.c	Tue Jun 19 17:17:57 2007 +0000
@@ -1118,7 +1118,7 @@
 silcpurple_add_buddy_select_cb(SilcPurpleBuddyRes r, PurpleRequestFields *fields)
 {
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcClientEntry client_entry;
 
 	f = purple_request_fields_get_field(fields, "list");
--- a/libpurple/protocols/silc10/chat.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/silc10/chat.c	Tue Jun 19 17:17:57 2007 +0000
@@ -278,7 +278,7 @@
 	SilcClient client = sg->client;
 	SilcClientConnection conn = sg->conn;
 	PurpleRequestField *f;
-	const GList *list;
+	GList *list;
 	SilcPublicKey public_key;
 	SilcBuffer chpks, pk, chidp;
 	SilcUInt16 c = 0, ct;
--- a/libpurple/protocols/yahoo/yahoo.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo.c	Tue Jun 19 17:17:57 2007 +0000
@@ -3861,7 +3861,7 @@
 		if (acct && !purple_account_is_connected(acct))
 			acct = NULL;
 	} else { /* Otherwise find an active account for the protocol */
-		const GList *l = purple_accounts_get_all();
+		GList *l = purple_accounts_get_all();
 		while (l) {
 			if (!strcmp(prpl, purple_account_get_protocol_id(l->data))
 					&& purple_account_is_connected(l->data)) {
--- a/libpurple/protocols/yahoo/yahoo_doodle.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoo_doodle.c	Tue Jun 19 17:17:57 2007 +0000
@@ -491,7 +491,8 @@
 
 	/* g_debug_debug("yahoo", "doodle: yahoo_doodle_end()\n"); */
 
-	yahoo_doodle_command_send_shutdown(gc, wb->who);
+	if (gc)
+		yahoo_doodle_command_send_shutdown(gc, wb->who);
 
 	g_free(wb->proto_data);
 }
--- a/libpurple/protocols/yahoo/yahoochat.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.c	Tue Jun 19 17:17:57 2007 +0000
@@ -633,10 +633,10 @@
  * I think conference names are always ascii.
  */
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who)
+void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who)
 {
 	struct yahoo_packet *pkt;
-	const GList *w;
+	GList *w;
 
 	purple_debug_misc("yahoo", "leaving conference %s\n", room);
 	
@@ -653,11 +653,11 @@
 }
 
 static int yahoo_conf_send(PurpleConnection *gc, const char *dn, const char *room,
-							const GList *members, const char *what)
+							GList *members, const char *what)
 {
 	struct yahoo_data *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
-	const GList *who;
+	GList *who;
 	char *msg, *msg2;
 	int utf8 = 1;
 
@@ -714,7 +714,7 @@
 {
 	struct yahoo_data *yd = gc->proto_data;
 	struct yahoo_packet *pkt;
-	const GList *members;
+	GList *members;
 	char *msg2 = NULL;
 
 	if (msg)
--- a/libpurple/protocols/yahoo/yahoochat.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/yahoo/yahoochat.h	Tue Jun 19 17:17:57 2007 +0000
@@ -50,7 +50,7 @@
 char *yahoo_get_chat_name(GHashTable *data);
 void yahoo_c_invite(PurpleConnection *gc, int id, const char *msg, const char *name);
 
-void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, const GList *who);
+void yahoo_conf_leave(struct yahoo_data *yd, const char *room, const char *dn, GList *who);
 
 void yahoo_chat_goto(PurpleConnection *gc, const char *name);
 
--- a/libpurple/protocols/zephyr/ZLocations.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/protocols/zephyr/ZLocations.c	Tue Jun 19 17:17:57 2007 +0000
@@ -36,7 +36,8 @@
     return (Z_SendLocation(LOGIN_CLASS, LOGIN_USER_FLUSH, ZAUTH, ""));
 }
 
-static char host[MAXHOSTNAMELEN], mytty[MAXPATHLEN];
+static char host[MAXHOSTNAMELEN];
+static char *mytty = NULL;
 static int reenter = 0;
 
 Code_t Z_SendLocation(class, opcode, auth, format)
@@ -87,21 +88,20 @@
 	    }
 #ifndef X_DISPLAY_MISSING
 	    if ((display = getenv("DISPLAY")) && *display) {
-		    (void) strncpy(mytty, display, sizeof(mytty));
+		    mytty = g_strdup(display);
 	    } else {
 #endif
 #ifdef WIN32
-              	    strncpy(mytty, "WinPurple", sizeof(mytty));
+		    mytty = g_strdup("WinPurple");
 #else
 		    ttyp = ttyname(0);
 		    if (ttyp && *ttyp) {
 			p = strchr(ttyp + 1, '/');
-			strcpy(mytty, (p) ? p + 1 : ttyp);
+			mytty = g_strdup((p) ? p + 1 : ttyp);
 		    } else {
-			strncpy(mytty, "unknown", sizeof(mytty));
+			mytty = g_strdup("unknown");
 		    }
 #endif
-		    mytty[sizeof(mytty)-1] = '\0';
 #ifndef X_DISPLAY_MISSING
 	    }
 #endif
@@ -114,7 +114,6 @@
     bptr[1][strlen(bptr[1])-1] = '\0';
     bptr[2] = mytty;
 
-	
     if ((retval = ZSendList(&notice, bptr, 3, auth)) != ZERR_NONE)
 	return (retval);
 
--- a/libpurple/prpl.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/prpl.c	Tue Jun 19 17:17:57 2007 +0000
@@ -265,7 +265,7 @@
 purple_prpl_get_statuses(PurpleAccount *account, PurplePresence *presence)
 {
 	GList *statuses = NULL;
-	const GList *l;
+	GList *l;
 	PurpleStatus *status;
 
 	g_return_val_if_fail(account  != NULL, NULL);
--- a/libpurple/request.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/request.c	Tue Jun 19 17:17:57 2007 +0000
@@ -111,7 +111,7 @@
 	return (g_hash_table_lookup(fields->fields, id) != NULL);
 }
 
-const GList *
+GList *
 purple_request_fields_get_required(const PurpleRequestFields *fields)
 {
 	g_return_val_if_fail(fields != NULL, NULL);
@@ -872,9 +872,9 @@
 }
 
 void
-purple_request_field_list_set_selected(PurpleRequestField *field, const GList *items)
+purple_request_field_list_set_selected(PurpleRequestField *field, GList *items)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(field != NULL);
 	g_return_if_fail(items != NULL);
@@ -883,7 +883,7 @@
 	purple_request_field_list_clear_selected(field);
 
 	if (!purple_request_field_list_get_multi_select(field) &&
-		g_list_length((GList*)items) > 1)
+		g_list_length(items) > 1)
 	{
 		purple_debug_warning("request",
 						   "More than one item added to non-multi-select "
@@ -913,7 +913,7 @@
 										item, NULL, NULL);
 }
 
-const GList *
+GList *
 purple_request_field_list_get_selected(const PurpleRequestField *field)
 {
 	g_return_val_if_fail(field != NULL, NULL);
@@ -922,7 +922,7 @@
 	return field->u.list.selected;
 }
 
-const GList *
+GList *
 purple_request_field_list_get_items(const PurpleRequestField *field)
 {
 	g_return_val_if_fail(field != NULL, NULL);
--- a/libpurple/request.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/request.h	Tue Jun 19 17:17:57 2007 +0000
@@ -285,9 +285,9 @@
  *
  * @param fields The fields list.
  *
- * @return The list of required fields.
+ * @constreturn The list of required fields.
  */
-const GList *purple_request_fields_get_required(const PurpleRequestFields *fields);
+GList *purple_request_fields_get_required(const PurpleRequestFields *fields);
 
 /**
  * Returns whether or not a field with the specified ID is required.
@@ -917,10 +917,10 @@
  * Sets a list of selected items in a list field.
  *
  * @param field The field.
- * @param items The list of selected items.
+ * @param items The list of selected items, which is not modified or freed.
  */
 void purple_request_field_list_set_selected(PurpleRequestField *field,
-										  const GList *items);
+										  GList *items);
 
 /**
  * Returns whether or not a particular item is selected in a list field.
@@ -941,9 +941,9 @@
  *
  * @param field The field.
  *
- * @return The list of selected items.
+ * @constreturn The list of selected items.
  */
-const GList *purple_request_field_list_get_selected(
+GList *purple_request_field_list_get_selected(
 	const PurpleRequestField *field);
 
 /**
@@ -951,9 +951,9 @@
  *
  * @param field The field.
  *
- * @return The list of items.
+ * @constreturn The list of items.
  */
-const GList *purple_request_field_list_get_items(const PurpleRequestField *field);
+GList *purple_request_field_list_get_items(const PurpleRequestField *field);
 
 /*@}*/
 
--- a/libpurple/savedstatuses.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/savedstatuses.c	Tue Jun 19 17:17:57 2007 +0000
@@ -747,7 +747,7 @@
 	return TRUE;
 }
 
-const GList *
+GList *
 purple_savedstatuses_get_all(void)
 {
 	return saved_statuses;
--- a/libpurple/savedstatuses.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/savedstatuses.h	Tue Jun 19 17:17:57 2007 +0000
@@ -161,9 +161,9 @@
 /**
  * Returns all saved statuses.
  *
- * @return A list of saved statuses.
+ * @constreturn A list of saved statuses.
  */
-const GList *purple_savedstatuses_get_all(void);
+GList *purple_savedstatuses_get_all(void);
 
 /**
  * Returns the n most popular saved statuses.  "Popularity" is
--- a/libpurple/status.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/status.c	Tue Jun 19 17:17:57 2007 +0000
@@ -451,7 +451,7 @@
 	return NULL;
 }
 
-const GList *
+GList *
 purple_status_type_get_attrs(const PurpleStatusType *status_type)
 {
 	g_return_val_if_fail(status_type != NULL, NULL);
@@ -548,7 +548,7 @@
 purple_status_new(PurpleStatusType *status_type, PurplePresence *presence)
 {
 	PurpleStatus *status;
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(status_type != NULL, NULL);
 	g_return_val_if_fail(presence    != NULL, NULL);
@@ -719,10 +719,10 @@
 
 void
 purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
-									   const GList *attrs)
+									   GList *attrs)
 {
 	gboolean changed = FALSE;
-	const GList *l;
+	GList *l;
 	GList *specified_attr_ids = NULL;
 	PurpleStatusType *status_type;
 
@@ -1168,9 +1168,9 @@
 }
 
 void
-purple_presence_add_list(PurplePresence *presence, const GList *source_list)
+purple_presence_add_list(PurplePresence *presence, GList *source_list)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_if_fail(presence    != NULL);
 	g_return_if_fail(source_list != NULL);
@@ -1396,7 +1396,7 @@
 	return presence->u.buddy.buddy;
 }
 
-const GList *
+GList *
 purple_presence_get_statuses(const PurplePresence *presence)
 {
 	g_return_val_if_fail(presence != NULL, NULL);
@@ -1408,7 +1408,7 @@
 purple_presence_get_status(const PurplePresence *presence, const char *status_id)
 {
 	PurpleStatus *status;
-	const GList *l = NULL;
+	GList *l = NULL;
 
 	g_return_val_if_fail(presence  != NULL, NULL);
 	g_return_val_if_fail(status_id != NULL, NULL);
@@ -1487,7 +1487,7 @@
 purple_presence_is_status_primitive_active(const PurplePresence *presence,
 		PurpleStatusPrimitive primitive)
 {
-	const GList *l;
+	GList *l;
 
 	g_return_val_if_fail(presence  != NULL,              FALSE);
 	g_return_val_if_fail(primitive != PURPLE_STATUS_UNSET, FALSE);
@@ -1535,7 +1535,7 @@
 	gboolean idle1, idle2;
 	time_t idle_time_1, idle_time_2;
 	int score1 = 0, score2 = 0;
-	const GList *l;
+	GList *l;
 
 	if (presence1 == presence2)
 		return 0;
--- a/libpurple/status.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/status.h	Tue Jun 19 17:17:57 2007 +0000
@@ -387,9 +387,9 @@
  *
  * @param status_type The status type.
  *
- * @return The list of attributes.
+ * @constreturn The list of attributes.
  */
-const GList *purple_status_type_get_attrs(const PurpleStatusType *status_type);
+GList *purple_status_type_get_attrs(const PurpleStatusType *status_type);
 
 /**
  * Find the PurpleStatusType with the given id.
@@ -515,10 +515,11 @@
  * @param active The active state.
  * @param attrs  A list of attributes to set on the status.  This list is
  *               composed of key/value pairs, where each key is a valid
- *               attribute name for this PurpleStatusType.
+ *               attribute name for this PurpleStatusType.  The list is
+ *               not modified or freed by this function.
  */
 void purple_status_set_active_with_attrs_list(PurpleStatus *status, gboolean active,
-											const GList *attrs);
+											GList *attrs);
 
 /**
  * Sets the boolean value of an attribute in a status with the specified ID.
@@ -768,9 +769,10 @@
  * Adds a list of statuses to the presence.
  *
  * @param presence    The presence.
- * @param source_list The source list of statuses to add.
+ * @param source_list The source list of statuses to add, which is not
+ *                    modified or freed by this function.
  */
-void purple_presence_add_list(PurplePresence *presence, const GList *source_list);
+void purple_presence_add_list(PurplePresence *presence, GList *source_list);
 
 /**
  * Sets the active state of a status in a presence.
@@ -869,9 +871,9 @@
  *
  * @param presence The presence.
  *
- * @return The statuses.
+ * @constreturn The statuses.
  */
-const GList *purple_presence_get_statuses(const PurplePresence *presence);
+GList *purple_presence_get_statuses(const PurplePresence *presence);
 
 /**
  * Returns the status with the specified ID from a presence.
--- a/libpurple/util.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/libpurple/util.c	Tue Jun 19 17:17:57 2007 +0000
@@ -66,8 +66,8 @@
 	unsigned long data_len;
 };
 
-static char custom_home_dir[MAXPATHLEN];
-static char home_dir[MAXPATHLEN] = "";
+static char *custom_user_dir = NULL;
+static char *home_dir = NULL;
 
 PurpleMenuAction *
 purple_menu_action_new(const char *label, PurpleCallback callback, gpointer data,
@@ -2396,27 +2396,22 @@
 const char *
 purple_user_dir(void)
 {
-	if (custom_home_dir != NULL && *custom_home_dir) {
-		strcpy ((char*) &home_dir, (char*) &custom_home_dir);
-	} else if (!*home_dir) {
-		const gchar *hd = purple_home_dir();
-
-		if (hd) {
-			g_strlcpy((char*) &home_dir, hd, sizeof(home_dir));
-			g_strlcat((char*) &home_dir, G_DIR_SEPARATOR_S ".purple",
-					sizeof(home_dir));
-		}
-	}
+	if (custom_user_dir != NULL)
+		return custom_user_dir;
+	else if (!home_dir)
+		home_dir = g_build_filename(purple_home_dir(), ".purple", NULL);
 
 	return home_dir;
 }
 
 void purple_util_set_user_dir(const char *dir)
 {
-	if (dir != NULL && strlen(dir) > 0) {
-		g_strlcpy((char*) &custom_home_dir, dir,
-				sizeof(custom_home_dir));
-	}
+	g_free(custom_user_dir);
+
+	if (dir != NULL && *dir)
+		custom_user_dir = g_strdup(dir);
+	else
+		custom_user_dir = NULL;
 }
 
 int purple_build_dir (const char *path, int mode)
@@ -3135,7 +3130,7 @@
 char *
 purple_str_size_to_units(size_t size)
 {
-	static const char *size_str[4] = { "bytes", "KB", "MB", "GB" };
+	static const char *size_str[4] = { "bytes", "KiB", "MiB", "GiB" };
 	float size_mag;
 	int size_index = 0;
 
--- a/pidgin/gtkaccount.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkaccount.c	Tue Jun 19 17:17:57 2007 +0000
@@ -697,7 +697,7 @@
 	PurpleAccountOption *option;
 	PurpleAccount *account;
 	GtkWidget *frame, *vbox, *check, *entry, *combo, *menu, *item;
-	const GList *list, *node;
+	GList *list, *node;
 	gint i, idx, int_value;
 	GtkListStore *model;
 	GtkTreeIter iter;
@@ -1586,7 +1586,7 @@
 
 	account = purple_connection_get_account(gc);
 	model = GTK_TREE_MODEL(accounts_window->model);
-	index = g_list_index((GList *)purple_accounts_get_all(), account);
+	index = g_list_index(purple_accounts_get_all(), account);
 
 	if (gtk_tree_model_iter_nth_child(model, &iter, NULL, index))
 	{
@@ -1789,13 +1789,13 @@
 				case GTK_TREE_VIEW_DROP_INTO_OR_AFTER:
 					move_account_after(dialog->model, &dialog->drag_iter,
 									   &iter);
-					dest_index = g_list_index((GList *)purple_accounts_get_all(),
+					dest_index = g_list_index(purple_accounts_get_all(),
 											  account) + 1;
 					break;
 
 				case GTK_TREE_VIEW_DROP_BEFORE:
 				case GTK_TREE_VIEW_DROP_INTO_OR_BEFORE:
-					dest_index = g_list_index((GList *)purple_accounts_get_all(),
+					dest_index = g_list_index(purple_accounts_get_all(),
 											  account);
 
 					move_account_before(dialog->model, &dialog->drag_iter,
@@ -2094,7 +2094,7 @@
 static gboolean
 populate_accounts_list(AccountsWindow *dialog)
 {
-	const GList *l;
+	GList *l;
 	gboolean ret = FALSE;
 	GdkPixbuf *global_buddyicon = NULL;
 	const char *path;
@@ -2298,7 +2298,7 @@
 global_buddyicon_changed(const char *name, PurplePrefType type,
 			gconstpointer value, gpointer window)
 {
-	const GList *list;
+	GList *list;
 	for (list = purple_accounts_get_all(); list; list = list->next) {
 		account_modified_cb(list->data, window);
 	}
@@ -2429,7 +2429,7 @@
 {
 	PurpleConnection *gc = purple_account_get_connection(data->account);
 
-	if (g_list_find((GList *)purple_connections_get_all(), gc))
+	if (g_list_find(purple_connections_get_all(), gc))
 	{
 		purple_blist_request_add_buddy(data->account, data->username,
 									 NULL, data->alias);
@@ -2686,3 +2686,4 @@
 	purple_signals_unregister_by_instance(pidgin_account_get_handle());
 }
 
+
--- a/pidgin/gtkblist.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkblist.c	Tue Jun 19 17:17:57 2007 +0000
@@ -696,7 +696,7 @@
 gboolean
 pidgin_blist_joinchat_is_showable()
 {
-	const GList *c;
+	GList *c;
 	PurpleConnection *gc;
 
 	for (c = purple_connections_get_all(); c != NULL; c = c->next) {
@@ -1551,7 +1551,7 @@
 add_buddies_from_vcard(const char *prpl_id, PurpleGroup *group, GList *list,
 					   const char *alias)
 {
-	const GList *l;
+	GList *l;
 	PurpleAccount *account = NULL;
 	PurpleConnection *gc;
 
@@ -2860,7 +2860,6 @@
 	{ N_("/Buddies/Add C_hat..."), NULL, pidgin_blist_add_chat_cb, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ N_("/Buddies/Add _Group..."), NULL, purple_blist_request_add_group, 0, "<StockItem>", GTK_STOCK_ADD },
 	{ "/Buddies/sep3", NULL, NULL, 0, "<Separator>", NULL },
-	{ N_("/Buddies/_About Pidgin"), NULL, pidgin_dialogs_about, 0,  "<Item>", NULL },
 	{ N_("/Buddies/_Quit"), "<CTL>Q", purple_core_quit, 0, "<StockItem>", GTK_STOCK_QUIT },
 
 	/* Accounts menu */
@@ -2877,7 +2876,6 @@
 	{ N_("/Tools/_File Transfers"), "<CTL>T", pidgin_xfer_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/R_oom List"), NULL, pidgin_roomlist_dialog_show, 0, "<Item>", NULL },
 	{ N_("/Tools/System _Log"), NULL, gtk_blist_show_systemlog_cb, 0, "<Item>", NULL },
-	{ N_("/Tools/_Debug Window"), NULL, toggle_debug, 0, "<Item>", NULL },
 	{ "/Tools/sep3", NULL, NULL, 0, "<Separator>", NULL },
 	{ N_("/Tools/Mute _Sounds"), "<CTL>S", pidgin_blist_mute_sounds_cb, 0, "<CheckItem>", NULL },
 	/* Help */
@@ -2909,7 +2907,7 @@
 		prpl = purple_find_prpl(purple_account_get_protocol_id(chat->account));
 		prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(prpl);
 
-		if (g_list_length((GList *)purple_connections_get_all()) > 1)
+		if (g_list_length(purple_connections_get_all()) > 1)
 		{
 			tmp = g_markup_escape_text(chat->account->username, -1);
 			g_string_append_printf(str, _("\n<b>Account:</b> %s"), tmp);
@@ -2974,7 +2972,7 @@
 		user_info = purple_notify_user_info_new();
 
 		/* Account */
-		if (full && g_list_length((GList *)purple_connections_get_all()) > 1)
+		if (full && g_list_length(purple_connections_get_all()) > 1)
 		{
 			tmp = g_markup_escape_text(purple_account_get_username(
 									   purple_buddy_get_account(b)), -1);
@@ -4234,7 +4232,7 @@
 				{"application/x-im-contact", 0, DRAG_BUDDY},
 				{"text/x-vcard", 0, DRAG_VCARD }};
 	if (gtkblist && gtkblist->window) {
-		purple_blist_set_visible(TRUE);
+		purple_blist_set_visible(purple_prefs_get_bool(PIDGIN_PREFS_ROOT "/blist/list_visible"));
 		return;
 	}
 
@@ -5030,6 +5028,7 @@
 	PurpleContact *contact;
 	PurpleBuddy *buddy;
 	struct _pidgin_blist_node *gtknode;
+
 	if (editing_blist)
 		return;
 
@@ -5128,6 +5127,7 @@
 	PurpleChat *chat;
 
 	g_return_if_fail(PURPLE_BLIST_NODE_IS_CHAT(node));
+
 	if (editing_blist)
 		return;
 
@@ -5731,7 +5731,7 @@
 {
 	PidginAddChatData *data;
 	PidginBuddyList *gtkblist;
-	const GList *l;
+	GList *l;
 	PurpleConnection *gc;
 	GtkWidget *label;
 	GtkWidget *rowbox;
@@ -6498,8 +6498,7 @@
 {
 	GtkWidget *menuitem = NULL, *submenu = NULL;
 	GtkAccelGroup *accel_group = NULL;
-	GList *l = NULL;
-	const GList *accounts;
+	GList *l = NULL, *accounts = NULL;
 	gboolean disabled_accounts = FALSE;
 
 	if (accountmenu == NULL)
@@ -6736,3 +6735,4 @@
 	if (activeitem)
 		gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(activeitem), TRUE);
 }
+
--- a/pidgin/gtkconv.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkconv.c	Tue Jun 19 17:17:57 2007 +0000
@@ -2690,7 +2690,7 @@
 										gboolean hidden_only,
 										guint max_count)
 {
-	const GList *l;
+	GList *l;
 	GList *r = NULL;
 	guint c = 0;
 
@@ -3850,7 +3850,7 @@
 		g_list_free(list);
 	} else if (purple_conversation_get_type(conv) == PURPLE_CONV_TYPE_CHAT) {
 		PurpleConvChat *chat = PURPLE_CONV_CHAT(conv);
-		const GList *l = purple_conv_chat_get_users(chat);
+		GList *l = purple_conv_chat_get_users(chat);
 		GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(PIDGIN_CONVERSATION(conv)->u.chat->list));
 		GtkTreeIter iter;
 		int f;
@@ -5446,7 +5446,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
 
-	num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
+	num_users = g_list_length(purple_conv_chat_get_users(chat));
 
 	g_snprintf(tmp, sizeof(tmp),
 			   ngettext("%d person in room", "%d people in room",
@@ -5540,7 +5540,7 @@
 	gtkconv = PIDGIN_CONVERSATION(conv);
 	gtkchat = gtkconv->u.chat;
 
-	num_users = g_list_length((GList *)purple_conv_chat_get_users(chat));
+	num_users = g_list_length(purple_conv_chat_get_users(chat));
 
 	for (l = users; l != NULL; l = l->next) {
 		model = gtk_tree_view_get_model(GTK_TREE_VIEW(gtkchat->list));
@@ -6537,7 +6537,7 @@
 close_on_tabs_pref_cb(const char *name, PurplePrefType type,
 					  gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 
@@ -6561,7 +6561,7 @@
 				   gconstpointer value, gpointer data)
 {
 #ifdef USE_GTKSPELL
-	const GList *cl;
+	GList *cl;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	GtkSpell *spell;
@@ -6608,7 +6608,7 @@
 show_timestamps_pref_cb(const char *name, PurplePrefType type,
 						gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6636,7 +6636,7 @@
 show_formatting_toolbar_pref_cb(const char *name, PurplePrefType type,
 								gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6666,7 +6666,7 @@
 animate_buddy_icons_pref_cb(const char *name, PurplePrefType type,
 							gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
 	PidginWindow *win;
@@ -6693,7 +6693,7 @@
 show_buddy_icons_pref_cb(const char *name, PurplePrefType type,
 						 gconstpointer value, gpointer data)
 {
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		PurpleConversation *conv = l->data;
@@ -6819,7 +6819,7 @@
 static void
 account_signed_off_cb(PurpleConnection *gc, gpointer event)
 {
-	const GList *iter;
+	GList *iter;
 
 	for (iter = purple_get_conversations(); iter; iter = iter->next)
 	{
--- a/pidgin/gtkdocklet.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkdocklet.c	Tue Jun 19 17:17:57 2007 +0000
@@ -109,8 +109,7 @@
 static gboolean
 docklet_update_status()
 {
-	GList *convs;
-	const GList *l;
+	GList *convs, *l;
 	int count;
 	PurpleSavedStatus *saved_status;
 	PurpleStatusPrimitive newstatus = PURPLE_STATUS_OFFLINE;
@@ -214,7 +213,8 @@
 static gboolean
 online_account_supports_chat()
 {
-	const GList *c = purple_connections_get_all();
+	GList *c = NULL;
+	c = purple_connections_get_all();
 
 	while(c != NULL) {
 		PurpleConnection *gc = c->data;
--- a/pidgin/gtkft.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkft.c	Tue Jun 19 17:17:57 2007 +0000
@@ -130,7 +130,7 @@
 	kbps    = (elapsed > 0 ? (kb_sent / elapsed) : 0);
 
 	if (kbsec != NULL) {
-		*kbsec = g_strdup_printf(_("%.2f KB/s"), kbps);
+		*kbsec = g_strdup_printf(_("%.2f KiB/s"), kbps);
 	}
 
 	if (time_elapsed != NULL)
--- a/pidgin/gtkimhtmltoolbar.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkimhtmltoolbar.c	Tue Jun 19 17:17:57 2007 +0000
@@ -865,41 +865,21 @@
                     gboolean          *push_in,
                     gpointer          data)
 {
+	GtkWidget *widget = GTK_WIDGET(data);
 	GtkRequisition menu_req;
-	GtkTextDirection direction;
-	GdkRectangle monitor;
-	gint monitor_num;
-	GdkScreen *screen;
-	GtkWidget *widget = GTK_WIDGET(data);
-
-	gtk_widget_size_request (GTK_WIDGET (menu), &menu_req);
-
-	direction = gtk_widget_get_direction (widget);
-
-	screen = gtk_widget_get_screen (GTK_WIDGET (menu));
-	monitor_num = gdk_screen_get_monitor_at_window (screen, widget->window);
-	if (monitor_num < 0)
-		monitor_num = 0;
-	gdk_screen_get_monitor_geometry (screen, monitor_num, &monitor);
+	gint ythickness = widget->style->ythickness;
+	int savy;
 
-	gdk_window_get_origin (widget->window, x, y);
+	gtk_widget_size_request(GTK_WIDGET (menu), &menu_req);
+	gdk_window_get_origin(widget->window, x, y);
 	*x += widget->allocation.x;
-	*y += widget->allocation.y;
-
-	if (direction == GTK_TEXT_DIR_LTR)
-		*x += MAX (widget->allocation.width - menu_req.width, 0);
-	else if (menu_req.width > widget->allocation.width)
-		*x -= menu_req.width - widget->allocation.width;
+	*y += widget->allocation.y + widget->allocation.height;
+	savy = *y;
 
-	if ((*y + widget->allocation.height + menu_req.height) <= monitor.y + monitor.height)
-		*y += widget->allocation.height;
-	else if ((*y - menu_req.height) >= monitor.y)
-		*y -= menu_req.height;
-	else if (monitor.y + monitor.height - (*y + widget->allocation.height) > *y)
-		*y += widget->allocation.height;
-	else
-		*y -= menu_req.height;
-	*push_in = FALSE;
+	pidgin_menu_position_func_helper(menu, x, y, push_in, data);
+
+	if (savy > *y + ythickness + 1)
+		*y -= widget->allocation.height;
 }
 
 static void pidgin_menu_clicked(GtkWidget *button, GtkMenu *menu)
--- a/pidgin/gtklog.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtklog.c	Tue Jun 19 17:17:57 2007 +0000
@@ -757,7 +757,7 @@
 
 void pidgin_syslog_show()
 {
-	const GList *accounts;
+	GList *accounts = NULL;
 	GList *logs = NULL;
 
 	if (syslog_viewer != NULL) {
--- a/pidgin/gtkmain.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkmain.c	Tue Jun 19 17:17:57 2007 +0000
@@ -125,7 +125,7 @@
 		}
 		g_strfreev(names);
 	} else { /* no name given, use the first account */
-		const GList *accounts;
+		GList *accounts;
 
 		accounts = purple_accounts_get_all();
 		if (accounts != NULL)
@@ -372,6 +372,7 @@
 		       "  -c, --config=DIR    use DIR for config files\n"
 		       "  -d, --debug         print debugging messages to stdout\n"
 		       "  -h, --help          display this help and exit\n"
+		       "  -m, --multiple      do not ensure single instance\n"
 		       "  -n, --nologin       don't automatically login\n"
 		       "  -l, --login[=NAME]  automatically login (optional argument NAME specifies\n"
 		       "                      account(s) to use, separated by commas)\n"
@@ -431,11 +432,12 @@
 	gboolean opt_login = FALSE;
 	gboolean opt_nologin = FALSE;
 	gboolean opt_version = FALSE;
+	gboolean opt_si = TRUE;     /* Check for single instance? */
 	char *opt_config_dir_arg = NULL;
 	char *opt_login_arg = NULL;
 	char *opt_session_arg = NULL;
 	char *search_path;
-	const GList *accounts;
+	GList *accounts;
 #ifdef HAVE_SIGNAL_H
 	int sig_indx;	/* for setting up signal catching */
 	sigset_t sigset;
@@ -457,6 +459,7 @@
 		{"debug",    no_argument,       NULL, 'd'},
 		{"help",     no_argument,       NULL, 'h'},
 		{"login",    optional_argument, NULL, 'l'},
+		{"multiple", no_argument,       NULL, 'm'},
 		{"nologin",  no_argument,       NULL, 'n'},
 		{"session",  required_argument, NULL, 's'},
 		{"version",  no_argument,       NULL, 'v'},
@@ -471,7 +474,7 @@
 
 	/* This is the first Glib function call. Make sure to initialize GThread bfeore then */
 	g_thread_init(NULL);
-	
+
 #ifdef ENABLE_NLS
 	bindtextdomain(PACKAGE, LOCALEDIR);
 	bind_textdomain_codeset(PACKAGE, "UTF-8");
@@ -570,7 +573,7 @@
 	opterr = 1;
 	while ((opt = getopt_long(argc, argv,
 #ifndef _WIN32
-				  "c:dhnl::s:v",
+				  "c:dhmnl::s:v",
 #else
 				  "c:dhnl::v",
 #endif
@@ -602,6 +605,9 @@
 		case 'v':	/* version */
 			opt_version = TRUE;
 			break;
+		case 'm':   /* do not ensure single instance. */
+			opt_si = FALSE;
+			break;
 		case '?':	/* show terse help */
 		default:
 			show_usage(argv[0], TRUE);
@@ -728,7 +734,7 @@
 		abort();
 	}
 
-	if (!purple_core_ensure_single_instance()) {
+	if (opt_si && !purple_core_ensure_single_instance()) {
 		purple_core_quit();
 #ifdef HAVE_SIGNAL_H
 		g_free(segfault_message);
@@ -849,6 +855,7 @@
 	winpidgin_post_init();
 #endif
 
+	g_set_application_name(_("Pidgin"));
 	gtk_main();
 
 #ifdef HAVE_SIGNAL_H
--- a/pidgin/gtkpounce.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkpounce.c	Tue Jun 19 17:17:57 2007 +0000
@@ -211,12 +211,12 @@
 static void
 populate_pounces_list(PouncesManager *dialog)
 {
-	const GList *pounces;
+	GList *pounces;
 
 	gtk_list_store_clear(dialog->model);
 
-	for (pounces = purple_pounces_get_all(); pounces != NULL;
-			pounces = g_list_next(pounces))
+	for (pounces = purple_pounces_get_all_for_ui(PIDGIN_UI); pounces != NULL;
+			pounces = g_list_delete_link(pounces, pounces))
 	{
 		add_pounce_to_treeview(dialog->model, pounces->data);
 	}
@@ -496,7 +496,7 @@
 	}
 	else
 	{
-		const GList *connections = purple_connections_get_all();
+		GList *connections = purple_connections_get_all();
 		PurpleConnection *gc;
 
 		if (connections != NULL)
--- a/pidgin/gtkrequest.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkrequest.c	Tue Jun 19 17:17:57 2007 +0000
@@ -974,7 +974,7 @@
 	GtkTreeSelection *sel;
 	GtkTreeViewColumn *column;
 	GtkTreeIter iter;
-	const GList *l;
+	GList *l;
 
 	/* Create the scrolled window */
 	sw = gtk_scrolled_window_new(NULL, NULL);
--- a/pidgin/gtkroomlist.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkroomlist.c	Tue Jun 19 17:17:57 2007 +0000
@@ -343,7 +343,7 @@
 gboolean
 pidgin_roomlist_is_showable()
 {
-	const GList *c;
+	GList *c;
 	PurpleConnection *gc;
 
 	for (c = purple_connections_get_all(); c != NULL; c = c->next) {
--- a/pidgin/gtksavedstatuses.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtksavedstatuses.c	Tue Jun 19 17:17:57 2007 +0000
@@ -413,7 +413,7 @@
 static void
 populate_saved_status_list(StatusWindow *dialog)
 {
-	const GList *saved_statuses;
+	GList *saved_statuses;
 
 	gtk_list_store_clear(dialog->model);
 
@@ -1065,7 +1065,7 @@
 static void
 status_editor_populate_list(StatusEditor *dialog, PurpleSavedStatus *saved_status)
 {
-	const GList *iter;
+	GList *iter;
 	PurpleSavedStatusSub *substatus;
 
 	gtk_list_store_clear(dialog->model);
@@ -1446,7 +1446,7 @@
 	GtkTreeIter iter;
 	GtkCellRenderer *rend;
 	const char *status_id = NULL;
-	const GList *list;
+	GList *list;
 	gboolean select = FALSE;
 
 	g_return_if_fail(status_editor != NULL);
--- a/pidgin/gtkstatusbox.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkstatusbox.c	Tue Jun 19 17:17:57 2007 +0000
@@ -192,7 +192,7 @@
 static void
 update_to_reflect_account_status(PidginStatusBox *status_box, PurpleAccount *account, PurpleStatus *newstatus)
 {
-	const GList *l;
+	GList *l;
 	int status_no = -1;
 	const PurpleStatusType *statustype = NULL;
 	const char *message;
@@ -733,7 +733,7 @@
 static PurpleStatusType *
 find_status_type_by_index(const PurpleAccount *account, gint active)
 {
-	const GList *l = purple_account_get_status_types(account);
+	GList *l = purple_account_get_status_types(account);
 	gint i;
 
 	for (i = 0; l; l = l->next) {
@@ -942,7 +942,7 @@
 {
 	PurpleAccount *acct = NULL, *acct2;
 	GList *tmp, *tmp2, *active_accts = purple_accounts_get_all_active();
-	const GList *s, *s1, *s2;
+	GList *s, *s1, *s2;
 
 	for (tmp = active_accts; tmp; tmp = tmp->next) {
 		acct = tmp->data;
@@ -990,7 +990,7 @@
 add_account_statuses(PidginStatusBox *status_box, PurpleAccount *account)
 {
 	/* Per-account */
-	const GList *l;
+	GList *l;
 	GdkPixbuf *pixbuf;
 
 	for (l = purple_account_get_status_types(account); l != NULL; l = l->next)
@@ -1441,7 +1441,7 @@
 			}
 		}
 	} else {
-		const GList *accounts;
+		GList *accounts;
 		for (accounts = purple_accounts_get_all(); accounts != NULL; accounts = accounts->next) {
 			PurpleAccount *account = accounts->data;
 			PurplePlugin *plug = purple_find_prpl(purple_account_get_protocol_id(account));
@@ -2294,7 +2294,7 @@
 		{
 			/* Manually find the appropriate transient acct */
 			if (status_box->token_status_account) {
-				const GList *iter = purple_savedstatuses_get_all();
+				GList *iter = purple_savedstatuses_get_all();
 				GList *tmp, *active_accts = purple_accounts_get_all_active();
 
 				for (; iter != NULL; iter = iter->next) {
--- a/pidgin/gtkthemes.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkthemes.c	Tue Jun 19 17:17:57 2007 +0000
@@ -237,7 +237,7 @@
 	}
 
 	if (load) {
-		const GList *cnv;
+		GList *cnv;
 
 		if (current_smiley_theme)
 			pidgin_themes_destroy_smiley_theme(current_smiley_theme);
--- a/pidgin/gtkutils.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkutils.c	Tue Jun 19 17:17:57 2007 +0000
@@ -525,7 +525,7 @@
 {
 	PurplePluginProtocolInfo *prpl_info;
 	const char *protoname = NULL;
-	char buf[MAXPATHLEN];
+	char *tmp;
 	char *filename = NULL;
 	GdkPixbuf *pixbuf;
 
@@ -541,12 +541,14 @@
 	 * Status icons will be themeable too, and then it will look up
 	 * protoname from the theme
 	 */
-	g_snprintf(buf, sizeof(buf), "%s.png", protoname);
+	tmp = g_strconcat(protoname, ".png", NULL);
 
 	filename = g_build_filename(DATADIR, "pixmaps", "pidgin", "protocols",
 				    size == PIDGIN_PRPL_ICON_SMALL ? "16" :
 				    size == PIDGIN_PRPL_ICON_MEDIUM ? "22" : "48",
-				    buf, NULL);
+				    tmp, NULL);
+	g_free(tmp);
+
 	pixbuf = gdk_pixbuf_new_from_file(filename, NULL);
 	g_free(filename);
 
@@ -687,8 +689,8 @@
 	AopMenu *aop_menu = NULL;
 	PurpleAccount *account;
 	GdkPixbuf *pixbuf = NULL;
-	const GList *list;
-	const GList *p;
+	GList *list;
+	GList *p;
 	GtkSizeGroup *sg;
 	int i;
 	char buf[256];
@@ -995,9 +997,9 @@
 		/* Check for a compatible account. */
 		if (ret_account != NULL)
 		{
-			const GList *list;
+			GList *list;
 			PurpleAccount *account = NULL;
-			const GList *l;
+			GList *l;
 			const char *protoname;
 
 			if (all_accounts)
@@ -1139,14 +1141,14 @@
 	g_object_unref (relation);
 }
 
-#if GTK_CHECK_VERSION(2,2,0)
-static void
-pidgin_menu_position_func(GtkMenu *menu,
+void
+pidgin_menu_position_func_helper(GtkMenu *menu,
 							gint *x,
 							gint *y,
 							gboolean *push_in,
 							gpointer data)
 {
+#if GTK_CHECK_VERSION(2,2,0)
 	GtkWidget *widget;
 	GtkRequisition requisition;
 	GdkScreen *screen;
@@ -1287,9 +1289,9 @@
 	{
 		*y = monitor.y;
 	}
+#endif
 }
 
-#endif
 
 void
 pidgin_treeview_popup_menu_position_func(GtkMenu *menu,
@@ -1311,9 +1313,7 @@
 
 	*x += rect.x+rect.width;
 	*y += rect.y+rect.height+ythickness;
-#if GTK_CHECK_VERSION(2,2,0)
-	pidgin_menu_position_func (menu, x, y, push_in, data);
-#endif
+	pidgin_menu_position_func_helper(menu, x, y, push_in, data);
 }
 
 enum {
@@ -3090,3 +3090,4 @@
 	return path;
 }
 #endif
+
--- a/pidgin/gtkutils.h	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/gtkutils.h	Tue Jun 19 17:17:57 2007 +0000
@@ -359,6 +359,21 @@
 void pidgin_set_accessible_label(GtkWidget *w, GtkWidget *l);
 
 /**
+ * A helper function for GtkMenuPositionFuncs. This ensures the menu will
+ * be kept on screen if possible.
+ *
+ * @param menu The menu we are positioning.
+ * @param x Address of the gint representing the horizontal position
+ *        where the menu shall be drawn. This is an output parameter.
+ * @param y Address of the gint representing the vertical position
+ *        where the menu shall be drawn. This is an output parameter.
+ * @param push_in This is an output parameter?
+ * @param user_data Not used by this particular position function.
+ */
+void pidgin_menu_position_func_helper(GtkMenu *menu, gint *x, gint *y,
+										gboolean *push_in, gpointer data);
+
+/**
  * A valid GtkMenuPositionFunc.  This is used to determine where 
  * to draw context menu's when the menu is activated with the 
  * keyboard (shift+F10).  If the menu is activated with the mouse, 
--- a/pidgin/plugins/gestures/gestures.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/gestures/gestures.c	Tue Jun 19 17:17:57 2007 +0000
@@ -176,7 +176,7 @@
 plugin_load(PurplePlugin *plugin)
 {
 	PurpleConversation *conv;
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		conv = (PurpleConversation *)l->data;
@@ -199,7 +199,7 @@
 {
 	PurpleConversation *conv;
 	PidginConversation *gtkconv;
-	const GList *l;
+	GList *l;
 
 	for (l = purple_get_conversations(); l != NULL; l = l->next) {
 		conv = (PurpleConversation *)l->data;
--- a/pidgin/plugins/gevolution/add_buddy_dialog.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/gevolution/add_buddy_dialog.c	Tue Jun 19 17:17:57 2007 +0000
@@ -162,7 +162,7 @@
 		GList *list, const char *id)
 {
 	PurpleAccount *account = NULL;
-	const GList *l;
+	GList *l;
 	GtkTreeIter iter;
 	GdkPixbuf *pixbuf;
 
--- a/pidgin/plugins/gevolution/gevolution.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/gevolution/gevolution.c	Tue Jun 19 17:17:57 2007 +0000
@@ -69,8 +69,7 @@
 						const char *prpl_id, EContactField field)
 {
 	GList *ims = e_contact_get(contact, field);
-	const GList *l;
-	const GList *l2;
+	GList *l, *l2;
 
 	if (ims == NULL)
 		return;
@@ -119,9 +118,9 @@
 }
 
 static void
-contacts_changed_cb(EBookView *book_view, const GList *contacts)
+contacts_changed_cb(EBookView *book_view, GList *contacts)
 {
-	const GList *l;
+	GList *l;
 
 	if (purple_connections_get_all() == NULL)
 		return;
@@ -401,7 +400,7 @@
 	GtkCellRenderer *renderer;
 	GdkPixbuf *pixbuf;
 	GtkListStore *model;
-	const GList *l;
+	GList *l;
 
 	/* Outside container */
 	ret = gtk_vbox_new(FALSE, 18);
--- a/pidgin/plugins/notify.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/notify.c	Tue Jun 19 17:17:57 2007 +0000
@@ -624,7 +624,7 @@
 static void
 apply_method()
 {
-	const GList *convs;
+	GList *convs;
 	PidginWindow *purplewin = NULL;
 
 	for (convs = purple_get_conversations(); convs != NULL;
@@ -644,7 +644,7 @@
 static void
 apply_notify()
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 
 	while (convs) {
 		PurpleConversation *conv = (PurpleConversation *)convs->data;
@@ -818,7 +818,7 @@
 static gboolean
 plugin_load(PurplePlugin *plugin)
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 	void *conv_handle = purple_conversations_get_handle();
 	void *gtk_conv_handle = pidgin_conversations_get_handle();
 
@@ -860,7 +860,7 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
-	const GList *convs = purple_get_conversations();
+	GList *convs = purple_get_conversations();
 
 	while (convs) {
 		PurpleConversation *conv = (PurpleConversation *)convs->data;
--- a/pidgin/plugins/spellchk.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/spellchk.c	Tue Jun 19 17:17:57 2007 +0000
@@ -2118,7 +2118,7 @@
 plugin_load(PurplePlugin *plugin)
 {
 	void *conv_handle = purple_conversations_get_handle();
-	const GList *convs;
+	GList *convs;
 
 	load_conf();
 
@@ -2137,7 +2137,7 @@
 static gboolean
 plugin_unload(PurplePlugin *plugin)
 {
-	const GList *convs;
+	GList *convs;
 
 	/* Detach from existing conversations */
 	for (convs = purple_get_conversations(); convs != NULL; convs = convs->next)
--- a/pidgin/plugins/timestamp.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/timestamp.c	Tue Jun 19 17:17:57 2007 +0000
@@ -77,7 +77,7 @@
 	time_t now = time(NULL) / interval * interval;
 	time_t then;
 
-	if (!g_list_find((GList *)purple_get_conversations(), conv))
+	if (!g_list_find(purple_get_conversations(), conv))
 		return FALSE;
 
 	then = GPOINTER_TO_INT(purple_conversation_get_data(
@@ -98,7 +98,7 @@
 	PidginConversation *gtk_conv = PIDGIN_CONVERSATION(conv);
 	GtkTextBuffer *buffer;
 
-	if (!g_list_find((GList *)purple_get_conversations(), conv))
+	if (!g_list_find(purple_get_conversations(), conv))
 		return;
 
 	buffer = gtk_text_view_get_buffer(GTK_TEXT_VIEW(gtk_conv->imhtml));
--- a/pidgin/plugins/xmppconsole.c	Sun Jun 17 18:03:03 2007 +0000
+++ b/pidgin/plugins/xmppconsole.c	Tue Jun 19 17:17:57 2007 +0000
@@ -731,7 +731,7 @@
 	GtkWidget *label;
 	GtkTextBuffer *buffer;
 	GtkWidget *toolbar;
-	const GList *connections;
+	GList *connections;
 #if GTK_CHECK_VERSION(2,4,0)
 	GtkToolItem *button;
 #endif