changeset 20726:2bb82b05d30a

merge of '07d5798f8a0b64518b4697e0376f5ceeddbb61e2' and 'da7520dee75fbe063aa7747c5452551d0030abee'
author Will Thompson <will.thompson@collabora.co.uk>
date Sun, 30 Sep 2007 16:55:19 +0000
parents 2e5ee1bf5300 (diff) 3e569b1b0371 (current diff)
children bcda8512dce4
files finch/gntconv.c libpurple/protocols/oscar/oscar.c
diffstat 9 files changed, 298 insertions(+), 26 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog	Sun Sep 30 16:53:34 2007 +0000
+++ b/ChangeLog	Sun Sep 30 16:55:19 2007 +0000
@@ -1,6 +1,6 @@
 Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul
 
-Version 2.2.2:
+version 2.2.2:
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.2
 		NOTE: Due to the backporting that happened for the 2.2.1
 		      release, it is possible bugs this release fixes bugs
@@ -30,9 +30,9 @@
 	* The "Smiley" menu has been moved to the top-level of the toolbar.
 	* Pidgin's display is now saved with the command line for session
 	  restoration.  (David Mohr)
-	* ICQ Birthday notifications are shown as buddy list emblems
+	* ICQ Birthday notifications are shown as buddy list emblems.
 
-Version 2.2.1:
+version 2.2.1 (09/29/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.1
 		NOTE: Due to the backporting that happened for the actual
 		      release, it is possible bugs marked as fixed in 2.2.1
@@ -43,24 +43,28 @@
 	* Cancelling the password prompt for an account will no longer leave
 	  it in an ambiguous state.  (It will be disabled.)
 	* Fixed an erroneous size display for MSN file transfers. (galt)
+	* Fixed multiple memory leaks, particularly in XMPP and MySpace
+	  protocols
+	* Fixed remembering proxy preferences and status scores
 	* Gmail notifications are better tracked
 
 	Pidgin:
 	* Fixed keyboard tab reordering to move tabs one step instead of two.
 	* You should no longer lose proxy settings when Pidgin is restarted.
+	* Fixed detection of X11 when compiling
 
 	Finch:
 	* Pressing 'Insert' in the buddylist will bring up the 'Add Buddy'
 	  dialog.
 
-Version 2.2.0 (09/13/2007):
+version 2.2.0 (09/13/2007):
 	http://developer.pidgin.im/query?status=closed&milestone=2.2.0
 
 	Libpurple:
 	* New protocol plugin: MySpaceIM (Jeff Connelly, Google Summer of
 	  Code)
 	* XMPP enhancements. See
- 	  http://www.adiumx.com/blog/2007/07/soc-xmpp-update.php (Andreas 
+	  http://www.adiumx.com/blog/2007/07/soc-xmpp-update.php (Andreas 
 	  Monitzer, Google Summer of Code for Adium)
 	* Certificate management. Libpurple will validate certificates on
 	  SSL-encrypted protocols (William Ehlhardt, Google Summer of Code)
@@ -2296,4 +2300,4 @@
 	* Fixed WindowMaker Appicon
 	* Version Number in About Box
 	* Gaim Slogan in about box :)
-	* Created Changelog File :)
\ No newline at end of file
+	* Created Changelog File :)
--- a/finch/gntconv.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/finch/gntconv.c	Sun Sep 30 16:55:19 2007 +0000
@@ -959,7 +959,7 @@
 {
 	FinchConv *fc = FINCH_CONV(conv);
 	if (fc && fc->window)
-		return gnt_window_present(fc->window);
+		gnt_window_present(fc->window);
 }
 
 static gboolean
--- a/finch/gntplugin.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/finch/gntplugin.c	Sun Sep 30 16:55:19 2007 +0000
@@ -32,6 +32,7 @@
 
 #include "finch.h"
 
+#include "debug.h"
 #include "notify.h"
 #include "request.h"
 
@@ -127,8 +128,8 @@
 	/* XXX: Use formatting and stuff */
 	gnt_text_view_clear(GNT_TEXT_VIEW(plugins.aboot));
 	text = g_strdup_printf(_("Name: %s\nVersion: %s\nDescription: %s\nAuthor: %s\nWebsite: %s\nFilename: %s\n"),
-			SAFE(plugin->info->name), SAFE(plugin->info->version), SAFE(plugin->info->description),
-			SAFE(plugin->info->author), SAFE(plugin->info->homepage), SAFE(plugin->path));
+			SAFE(_(plugin->info->name)), SAFE(_(plugin->info->version)), SAFE(_(plugin->info->description)),
+			SAFE(_(plugin->info->author)), SAFE(_(plugin->info->homepage)), SAFE(plugin->path));
 	gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(plugins.aboot),
 			text, GNT_TEXT_FLAG_NORMAL);
 	gnt_text_view_scroll(GNT_TEXT_VIEW(plugins.aboot), 0);
@@ -237,6 +238,93 @@
 	}
 }
 
+static void
+install_selected_file_cb(gpointer handle, const char *filename)
+{
+	/* Try to init the selected file.
+	 * If it succeeds, try to make a copy of the file in $USERDIR/plugins/.
+	 * If the copy succeeds, unload and destroy the plugin in the original
+	 *  location and init+load the new one.
+	 * Select the plugin in the plugin list.
+	 */
+	char *path;
+	PurplePlugin *plugin;
+
+	g_return_if_fail(plugins.window);
+	
+	plugin = purple_plugin_probe(filename);
+	if (!plugin) {
+		purple_notify_error(handle, _("Error loading plugin"),
+				_("The selected file is not a valid plugin."),
+				_("Please open the debug window and try again to see the exact error message."));
+		return;
+	}
+	if (g_list_find(gnt_tree_get_rows(GNT_TREE(plugins.tree)), plugin)) {
+		purple_plugin_load(plugin);
+		gnt_tree_set_choice(GNT_TREE(plugins.tree), plugin, purple_plugin_is_loaded(plugin));
+		gnt_tree_set_selected(GNT_TREE(plugins.tree), plugin);
+		return;
+	}
+
+	path = g_build_filename(purple_user_dir(), "plugins", NULL);
+	if (purple_build_dir(path, S_IRUSR | S_IWUSR | S_IXUSR) == 0) {
+		char *content = NULL;
+		gsize length = 0;
+
+		if (g_file_get_contents(filename, &content, &length, NULL)) {
+			char *file = g_path_get_basename(filename);
+			g_free(path);
+			path = g_build_filename(purple_user_dir(), "plugins", file, NULL);
+			if (purple_util_write_data_to_file_absolute(path, content, length)) {
+				purple_plugin_destroy(plugin);
+				plugin = purple_plugin_probe(path);
+				if (!plugin) {
+					purple_debug_warning("gntplugin", "This is really strange. %s can be loaded, but %s can't!\n",
+							filename, path);
+					g_unlink(path);
+					plugin = purple_plugin_probe(filename);
+				}
+			} else {
+			}
+		}
+		g_free(content);
+	}
+	g_free(path);
+
+	purple_plugin_load(plugin);
+
+	if (plugin->info->type == PURPLE_PLUGIN_LOADER) {
+		GList *cur;
+		for (cur = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts; cur != NULL;
+				cur = cur->next)
+			purple_plugins_probe(cur->data);
+		return;
+	}
+
+	if (plugin->info->type != PURPLE_PLUGIN_STANDARD ||
+			(plugin->info->flags & PURPLE_PLUGIN_FLAG_INVISIBLE) ||
+			plugin->error)
+		return;
+
+	gnt_tree_add_choice(GNT_TREE(plugins.tree), plugin,
+			gnt_tree_create_row(GNT_TREE(plugins.tree), plugin->info->name), NULL, NULL);
+	gnt_tree_set_choice(GNT_TREE(plugins.tree), plugin, purple_plugin_is_loaded(plugin));
+	gnt_tree_set_row_flags(GNT_TREE(plugins.tree), plugin, GNT_TEXT_FLAG_BOLD);
+	gnt_tree_set_selected(GNT_TREE(plugins.tree), plugin);
+}
+
+static void
+install_plugin_cb(GntWidget *w, gpointer null)
+{
+	static int handle;
+
+	purple_request_close_with_handle(&handle);
+	purple_request_file(&handle, _("Select plugin to install"), NULL,
+			FALSE, G_CALLBACK(install_selected_file_cb), NULL,
+			NULL, NULL, NULL, &handle);
+	g_signal_connect_swapped(G_OBJECT(w), "destroy", G_CALLBACK(purple_request_close_with_handle), &handle);
+}
+
 void finch_plugins_show_all()
 {
 	GntWidget *window, *tree, *box, *aboot, *button;
@@ -272,6 +360,7 @@
 	gnt_box_add_widget(GNT_BOX(box), gnt_vline_new());
 
 	plugins.aboot = aboot = gnt_text_view_new();
+	gnt_text_view_set_flag(GNT_TEXT_VIEW(aboot), GNT_TEXT_VIEW_TOP_ALIGN);
 	gnt_widget_set_size(aboot, 40, 20);
 	gnt_box_add_widget(GNT_BOX(box), aboot);
 
@@ -307,6 +396,10 @@
 	box = gnt_hbox_new(FALSE);
 	gnt_box_add_widget(GNT_BOX(window), box);
 
+	button = gnt_button_new(_("Install Plugin..."));
+	gnt_box_add_widget(GNT_BOX(box), button);
+	g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(install_plugin_cb), NULL);
+
 	button = gnt_button_new(_("Close"));
 	gnt_box_add_widget(GNT_BOX(box), button);
 	g_signal_connect_swapped(G_OBJECT(button), "activate",
--- a/finch/gntpounce.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/finch/gntpounce.c	Sun Sep 30 16:55:19 2007 +0000
@@ -964,10 +964,15 @@
 						PURPLE_CALLBACK(signed_on_off_cb), NULL);
 }
 
+static void
+dummy_pounce_cb(PurplePounce *pounce, PurplePounceEvent events, void *data)
+{
+}
+
 /* XXX: There's no such thing in pidgin. Perhaps there should be? */
 void finch_pounces_uninit()
 {
-	purple_pounces_register_handler(FINCH_UI, NULL, NULL, NULL);
+	purple_pounces_register_handler(FINCH_UI, dummy_pounce_cb, NULL, NULL);
 
 	purple_signals_disconnect_by_handle(finch_pounces_get_handle());
 }
--- a/finch/libgnt/pygnt/gntmodule.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/finch/libgnt/pygnt/gntmodule.c	Sun Sep 30 16:55:19 2007 +0000
@@ -1,7 +1,74 @@
 #include <pygobject.h>
+#include "gnt.h"
  
 void gnt_register_classes (PyObject *d); 
 extern PyMethodDef gnt_functions[];
+
+static void
+gnt_add_string_constants(PyObject *module)
+{
+#define define_key(x) if (GNT_KEY_##x && *(GNT_KEY_##x))  PyModule_AddStringConstant(module, "KEY_" #x, GNT_KEY_##x)
+
+	define_key(POPUP);
+
+	define_key(LEFT);
+	define_key(RIGHT);
+	define_key(UP);
+	define_key(DOWN);
+
+	define_key(CTRL_UP);
+	define_key(CTRL_DOWN);
+	define_key(CTRL_RIGHT);
+	define_key(CTRL_LEFT);
+
+	define_key(PGUP);
+	define_key(PGDOWN);
+	define_key(HOME);
+	define_key(END);
+
+	define_key(ENTER);
+
+	define_key(BACKSPACE);
+	define_key(DEL);
+	define_key(INS);
+	define_key(BACK_TAB);
+
+	define_key(CTRL_A);
+	define_key(CTRL_B);
+	define_key(CTRL_D);
+	define_key(CTRL_E);
+	define_key(CTRL_F);
+	define_key(CTRL_G);
+	define_key(CTRL_H);
+	define_key(CTRL_I);
+	define_key(CTRL_J);
+	define_key(CTRL_K);
+	define_key(CTRL_L);
+	define_key(CTRL_M);
+	define_key(CTRL_N);
+	define_key(CTRL_O);
+	define_key(CTRL_P);
+	define_key(CTRL_R);
+	define_key(CTRL_T);
+	define_key(CTRL_U);
+	define_key(CTRL_V);
+	define_key(CTRL_W);
+	define_key(CTRL_X);
+	define_key(CTRL_Y);
+
+	define_key(F1);
+	define_key(F2);
+	define_key(F3);
+	define_key(F4);
+	define_key(F5);
+	define_key(F6);
+	define_key(F7);
+	define_key(F8);
+	define_key(F9);
+	define_key(F10);
+	define_key(F11);
+	define_key(F12);
+}
  
 DL_EXPORT(void)
 initgnt(void)
@@ -19,5 +86,8 @@
     if (PyErr_Occurred ()) {
         Py_FatalError ("can't initialise module sad");
     }
+
+	gnt_init();
+	gnt_add_string_constants(m);
 }
 
--- a/finch/libgnt/pygnt/gnttree.override	Sun Sep 30 16:53:34 2007 +0000
+++ b/finch/libgnt/pygnt/gnttree.override	Sun Sep 30 16:55:19 2007 +0000
@@ -62,13 +62,14 @@
 {
 	static char *kwlist[] = {"key", "row", "parent", "bigbro", NULL};
 	PyObject *py_list;
-	gpointer key, parent, bigbro;
+	gpointer key, parent, bigbro = NULL;
 	int len, i;
 	GList *list = NULL;
 	GntTreeRow *row;
+	gboolean insert_last = FALSE;
 
 	if (!PyArg_ParseTuple(args,
-				"OOOO:GntTree.add_row_after",
+				"OOO|O:GntTree.add_row_after",
 				&key,
 				&py_list,
 				&parent,
@@ -92,13 +93,20 @@
 		parent = NULL;
 	if (bigbro == Py_None)
 		bigbro = NULL;
+	else if (bigbro == NULL)
+		insert_last = TRUE;
+
+	Py_INCREF((PyObject*)key);
 
 	list = g_list_reverse(list);
 	row = gnt_tree_create_row_from_list(GNT_TREE(self->obj), list);
-	gnt_tree_add_row_after(GNT_TREE(self->obj),
-			key,
-			row,
-			parent, bigbro);
+	if (insert_last)
+		gnt_tree_add_row_last(GNT_TREE(self->obj),
+				key, row, parent);
+	else
+		gnt_tree_add_row_after(GNT_TREE(self->obj),
+				key, row,
+				parent, bigbro);
 	g_list_free(list);
 
 	Py_INCREF(Py_None);
@@ -179,4 +187,27 @@
 	Py_INCREF(Py_None);
 	return Py_None;
 }
+%%
+override gnt_tree_set_compare_func
+static PyObject *
+_wrap_gnt_tree_set_compare_func(PyGObject *self, PyObject *args)
+{
+	static char *kwlist[] = {"compare_func", NULL};
+	PyGObject *compare;
 
+	if (!PyArg_ParseTuple(args, "O:GntTree.set_compare_func", &compare)) {
+		return NULL;
+	}
+
+	if (!PyCallable_Check(compare)) {
+		PyErr_SetString(PyExc_TypeError, "the callback must be callable ... doh!");
+		return NULL;
+	}
+
+	Py_INCREF(compare);
+	gnt_tree_set_compare_func(GNT_TREE(self->obj), (GCompareFunc)compare->obj);
+
+	Py_INCREF(Py_None);
+	return Py_None;
+}
+
--- a/libpurple/plugin.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/libpurple/plugin.c	Sun Sep 30 16:55:19 2007 +0000
@@ -1275,13 +1275,9 @@
 		if (basename)
 			basename = purple_plugin_get_basename(filename);
 
-		if ((plugin = purple_plugins_find_with_filename(filename)) != NULL)
-		{
-			purple_debug_info("plugins", "Loading saved plugin %s\n",
-							plugin->path);
-			purple_plugin_load(plugin);
-		}
-		else if (basename && (plugin = purple_plugins_find_with_basename(basename)) != NULL)
+		if (((plugin = purple_plugins_find_with_filename(filename)) != NULL) ||
+				(basename && (plugin = purple_plugins_find_with_basename(basename)) != NULL) ||
+				((plugin = purple_plugin_probe(filename)) != NULL))
 		{
 			purple_debug_info("plugins", "Loading saved plugin %s\n",
 							plugin->path);
--- a/libpurple/protocols/oscar/odc.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/libpurple/protocols/oscar/odc.c	Sun Sep 30 16:55:19 2007 +0000
@@ -27,6 +27,8 @@
 #include "imgstore.h"
 #include "util.h"
 
+#define DIRECTIM_MAX_FILESIZE 52428800
+
 /**
  * Free any ODC related data and print a message to the conversation
  * window based on conn->disconnect_reason.
@@ -587,6 +589,27 @@
 
 	if (frame->payload.len > 0)
 	{
+		if (frame->payload.len > DIRECTIM_MAX_FILESIZE)
+		{
+			gchar *tmp, *size1, *size2;
+			PurpleAccount *account;
+			PurpleConversation *conv;
+
+			size1 = purple_str_size_to_units(frame->payload.len);
+			size2 = purple_str_size_to_units(DIRECTIM_MAX_FILESIZE);
+			tmp = g_strdup_printf(_("%s tried to send you a %s file, but we only allow files up to %s over Direct IM.  Try using file transfer instead.\n"), conn->sn, size1, size2);
+			g_free(size1);
+			g_free(size2);
+
+			account = purple_connection_get_account(conn->od->gc);
+			conv = purple_conversation_new(PURPLE_CONV_TYPE_IM, account, conn->sn);
+			purple_conversation_write(conv, NULL, tmp, PURPLE_MESSAGE_SYSTEM, time(NULL));
+			g_free(tmp);
+
+			peer_connection_destroy(conn, OSCAR_DISCONNECT_LOCAL_CLOSED, NULL);
+			return;
+		}
+
 		/* We have payload data!  Switch to the ODC watcher to read it. */
 		frame->payload.data = g_new(guint8, frame->payload.len);
 		frame->payload.offset = 0;
--- a/libpurple/protocols/oscar/oscar.c	Sun Sep 30 16:53:34 2007 +0000
+++ b/libpurple/protocols/oscar/oscar.c	Sun Sep 30 16:55:19 2007 +0000
@@ -2184,12 +2184,14 @@
 {
 	PurpleConnection *gc;
 	OscarData *od;
+	PurpleAccount *account;
 	PurpleBuddy *buddy;
 	PurpleGroup *group;
 
 	gc = data->gc;
 	od = gc->proto_data;
-	buddy = purple_find_buddy(purple_connection_get_account(gc), data->name);
+	account = purple_connection_get_account(gc);
+	buddy = purple_find_buddy(account, data->name);
 	if (buddy != NULL)
 		group = purple_buddy_get_group(buddy);
 	else
@@ -2201,7 +2203,19 @@
 				   buddy->name, group->name);
 		aim_ssi_sendauthrequest(od, data->name, msg ? msg : _("Please authorize me so I can add you to my buddy list."));
 		if (!aim_ssi_itemlist_finditem(od->ssi.local, group->name, buddy->name, AIM_SSI_TYPE_BUDDY))
+		{
 			aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, TRUE);
+
+			/* Mobile users should always be online */
+			if (buddy->name[0] == '+') {
+				purple_prpl_got_user_status(account,
+						purple_buddy_get_name(buddy),
+						OSCAR_STATUS_ID_AVAILABLE, NULL);
+				purple_prpl_got_user_status(account,
+						purple_buddy_get_name(buddy),
+						OSCAR_STATUS_ID_MOBILE, NULL);
+			}
+		}
 	}
 }
 
@@ -4621,12 +4635,16 @@
 
 void
 oscar_add_buddy(PurpleConnection *gc, PurpleBuddy *buddy, PurpleGroup *group) {
-	OscarData *od = (OscarData *)gc->proto_data;
+	OscarData *od;
+	PurpleAccount *account;
+
+	od = (OscarData *)gc->proto_data;
+	account = purple_connection_get_account(gc);
 
 	if (!aim_snvalid(buddy->name)) {
 		gchar *buf;
 		buf = g_strdup_printf(_("Could not add the buddy %s because the screen name is invalid.  Screen names must be a valid email address, or start with a letter and contain only letters, numbers and spaces, or contain only numbers."), buddy->name);
-		if (!purple_conv_present_error(buddy->name, purple_connection_get_account(gc), buf))
+		if (!purple_conv_present_error(buddy->name, account, buf))
 			purple_notify_error(gc, NULL, _("Unable To Add"), buf);
 		g_free(buf);
 
@@ -4640,6 +4658,16 @@
 		purple_debug_info("oscar",
 				   "ssi: adding buddy %s to group %s\n", buddy->name, group->name);
 		aim_ssi_addbuddy(od, buddy->name, group->name, NULL, purple_buddy_get_alias_only(buddy), NULL, NULL, 0);
+
+		/* Mobile users should always be online */
+		if (buddy->name[0] == '+') {
+			purple_prpl_got_user_status(account,
+					purple_buddy_get_name(buddy),
+					OSCAR_STATUS_ID_AVAILABLE, NULL);
+			purple_prpl_got_user_status(account,
+					purple_buddy_get_name(buddy),
+					OSCAR_STATUS_ID_MOBILE, NULL);
+		}
 	}
 
 	/* XXX - Should this be done from AIM accounts, as well? */
@@ -4955,6 +4983,17 @@
 							g_free(comment);
 						}
 					}
+
+					/* Mobile users should always be online */
+					if (b->name[0] == '+') {
+						purple_prpl_got_user_status(account,
+								purple_buddy_get_name(b),
+								OSCAR_STATUS_ID_AVAILABLE, NULL);
+						purple_prpl_got_user_status(account,
+								purple_buddy_get_name(b),
+								OSCAR_STATUS_ID_MOBILE, NULL);
+					}
+
 					g_free(gname_utf8);
 					g_free(alias_utf8);
 				}
@@ -5145,6 +5184,17 @@
 		purple_debug_info("oscar",
 				   "ssi: adding buddy %s to group %s to local list\n", name, gname_utf8 ? gname_utf8 : _("Orphans"));
 		purple_blist_add_buddy(b, NULL, g, NULL);
+
+		/* Mobile users should always be online */
+		if (b->name[0] == '+') {
+			purple_prpl_got_user_status(account,
+					purple_buddy_get_name(b),
+					OSCAR_STATUS_ID_AVAILABLE, NULL);
+			purple_prpl_got_user_status(account,
+					purple_buddy_get_name(b),
+					OSCAR_STATUS_ID_MOBILE, NULL);
+		}
+
 	}
 
 	g_free(gname_utf8);