# HG changeset patch # User Richard Laager # Date 1191988659 0 # Node ID 8a89c2caf9d8f274a03e4dd993852083428e6dbe # Parent 34fc2a999977f2a3f5453ff943d3f9e0a7d9f54d# Parent 3a63d0d2a5fe806267c2a96ce8ee35c84b3ac6f7 propagate from branch 'im.pidgin.pidgin' (head 1e697229b1c9a564fa1e509cc9a4a83da6e664df) to branch 'im.pidgin.pidgin.next.minor' (head 74cedc552bbe5f33b7933fdfb6fe0b7105f6c576) diff -r 34fc2a999977 -r 8a89c2caf9d8 ChangeLog --- a/ChangeLog Wed Oct 10 02:18:48 2007 +0000 +++ b/ChangeLog Wed Oct 10 03:57:39 2007 +0000 @@ -1,5 +1,24 @@ Pidgin and Finch: The Pimpin' Penguin IM Clients That're Good for the Soul +version 2.3.0: + http://developer.pidgin.im/query?status=closed&milestone=2.3.0 + + libpurple: + * We now honor a PURPLE_DISABLE_DEPRECATED define to allow plugins to + catch deprecated functions earlier rather than later. + + Pidgin: + * If a plugin says it can't be unloaded, we now display an error and + remove the plugin from the list of saved plugins so it won't load + at the next startup. Previously, we were ignoring this case, which + could lead to crashes. + + Finch: + * If a plugin says it can't be unloaded, we now display an error and + remove the plugin from the list of saved plugins so it won't load + at the next startup. Previously, we were ignoring this case, which + could lead to crashes. + version 2.2.2: http://developer.pidgin.im/query?status=closed&milestone=2.2.2 NOTE: Due to 2.2.1 being a security fix release, some bugs diff -r 34fc2a999977 -r 8a89c2caf9d8 ChangeLog.API --- a/ChangeLog.API Wed Oct 10 02:18:48 2007 +0000 +++ b/ChangeLog.API Wed Oct 10 03:57:39 2007 +0000 @@ -7,7 +7,23 @@ has been changed to gssize instead of a size_t to correctly indicate that -1 can be used for a nul-delimited string. -Version 2.2.0 (09/13/2007): +version 2.3.0 (??/??/????): + libpurple: + Added: + * purple_plugin_disable(), which is intended to be called when + a purple_plugin_unload()--which was called when a user tried + to unload a plugin--fails. This then prevents the plugin + from being saved in the saved plugins list, so it'll won't + be loaded at the next startup. + + Changed: + * purple_plugin_unload() now honors the return value of a + plugin's unload function and can actually return FALSE now. + * purple_plugin_unload() no longer does its own notifications + when a dependent plugin fails to unload. The UI should do + something appropriate. + +version 2.2.0 (09/13/2007): libpurple: Added: * PURPLE_MESSAGE_INVISIBLE flag, which can be used by @@ -64,7 +80,7 @@ * gnt_util_parse_xhtml_to_textview to parse XHTML strings in a GntTextView (this works only if libxml2 is available) -Version 2.1.1 (08/20/2007): +version 2.1.1 (08/20/2007): libpurple: Changed: * PurpleAccountUiOps.request_authorize's authorize_cb and diff -r 34fc2a999977 -r 8a89c2caf9d8 configure.ac --- a/configure.ac Wed Oct 10 02:18:48 2007 +0000 +++ b/configure.ac Wed Oct 10 03:57:39 2007 +0000 @@ -45,8 +45,8 @@ # m4_define([purple_lt_current], [2]) m4_define([purple_major_version], [2]) -m4_define([purple_minor_version], [2]) -m4_define([purple_micro_version], [2]) +m4_define([purple_minor_version], [3]) +m4_define([purple_micro_version], [0]) m4_define([purple_version_suffix], []) m4_define([purple_version], [purple_major_version.purple_minor_version.purple_micro_version]) diff -r 34fc2a999977 -r 8a89c2caf9d8 finch/gntplugin.c --- a/finch/gntplugin.c Wed Oct 10 02:18:48 2007 +0000 +++ b/finch/gntplugin.c Wed Oct 10 03:57:39 2007 +0000 @@ -83,6 +83,7 @@ if (!purple_plugin_unload(plugin)) { purple_notify_error(NULL, _("ERROR"), _("unloading plugin failed"), NULL); + purple_plugin_disable(plugin); gnt_tree_set_choice(GNT_TREE(tree), plugin, TRUE); } diff -r 34fc2a999977 -r 8a89c2caf9d8 libpurple/blist.h --- a/libpurple/blist.h Wed Oct 10 02:18:48 2007 +0000 +++ b/libpurple/blist.h Wed Oct 10 03:57:39 2007 +0000 @@ -482,6 +482,7 @@ */ PurpleBuddy *purple_contact_get_priority_buddy(PurpleContact *contact); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Sets the alias for a contact. * @@ -491,6 +492,7 @@ * @deprecated Use purple_blist_alias_contact() instead. */ void purple_contact_set_alias(PurpleContact *contact, const char *alias); +#endif /** * Gets the alias for a contact. diff -r 34fc2a999977 -r 8a89c2caf9d8 libpurple/notify.h --- a/libpurple/notify.h Wed Oct 10 02:18:48 2007 +0000 +++ b/libpurple/notify.h Wed Oct 10 03:57:39 2007 +0000 @@ -289,7 +289,7 @@ */ void purple_notify_searchresults_row_add(PurpleNotifySearchResults *results, GList *row); - +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a number of the rows in the search results object. * @@ -308,7 +308,9 @@ * @return Number of the result rows. */ guint purple_notify_searchresults_get_rows_count(PurpleNotifySearchResults *results); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a number of the columns in the search results object. * @@ -327,7 +329,9 @@ * @return Number of the columns. */ guint purple_notify_searchresults_get_columns_count(PurpleNotifySearchResults *results); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a row of the results from the search results object. * @@ -348,7 +352,9 @@ */ GList *purple_notify_searchresults_row_get(PurpleNotifySearchResults *results, unsigned int row_id); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Returns a title of the search results object's column. * @@ -367,6 +373,7 @@ */ char *purple_notify_searchresults_column_get_title(PurpleNotifySearchResults *results, unsigned int column_id); +#endif /*@}*/ diff -r 34fc2a999977 -r 8a89c2caf9d8 libpurple/plugin.c --- a/libpurple/plugin.c Wed Oct 10 02:18:48 2007 +0000 +++ b/libpurple/plugin.c Wed Oct 10 03:57:39 2007 +0000 @@ -58,13 +58,9 @@ #ifdef PURPLE_PLUGINS static GList *load_queue = NULL; static GList *plugin_loaders = NULL; +static GList *plugins_to_disable = NULL; #endif -/* - * TODO: I think the intention was to allow multiple load and unload - * callback functions. Perhaps using a GList instead of a - * pointer to a single function. - */ static void (*probe_cb)(void *) = NULL; static void *probe_cb_data = NULL; static void (*load_cb)(PurplePlugin *, void *) = NULL; @@ -254,7 +250,6 @@ * plugins being added to the global name space. * * G_MODULE_BIND_LOCAL was added in glib 2.3.3. - * TODO: I guess there's nothing we can do about that? */ #if GLIB_CHECK_VERSION(2,3,3) plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL); @@ -625,7 +620,6 @@ plugin->loaded = TRUE; - /* TODO */ if (load_cb != NULL) load_cb(plugin, load_cb_data); @@ -643,43 +637,37 @@ { #ifdef PURPLE_PLUGINS GList *l; + GList *ll; g_return_val_if_fail(plugin != NULL, FALSE); - - loaded_plugins = g_list_remove(loaded_plugins, plugin); - if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) - protocol_plugins = g_list_remove(protocol_plugins, plugin); - g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); - /* cancel any pending dialogs the plugin has */ - purple_request_close_with_handle(plugin); - purple_notify_close_with_handle(plugin); - - plugin->loaded = FALSE; - /* Unload all plugins that depend on this plugin. */ - while ((l = plugin->dependent_plugins) != NULL) - { + for (l = plugin->dependent_plugins; l != NULL; l = ll) { const char * dep_name = (const char *)l->data; PurplePlugin *dep_plugin; + /* Store a pointer to the next element in the list. + * This is because we'll be modifying this list in the loop. */ + ll = l->next; + dep_plugin = purple_plugins_find_with_id(dep_name); if (dep_plugin != NULL && purple_plugin_is_loaded(dep_plugin)) { if (!purple_plugin_unload(dep_plugin)) { - char *tmp; - - tmp = g_strdup_printf(_("The dependent plugin %s failed to unload."), - _(dep_plugin->info->name)); - - purple_notify_error(NULL, NULL, - _("There were errors unloading the plugin."), tmp); - g_free(tmp); + g_free(plugin->error); + plugin->error = g_strdup_printf(_("%s requires %s, but it failed to unload."), + _(plugin->info->name), + _(dep_plugin->info->name)); + return FALSE; + } + else + { + plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); } } } @@ -699,8 +687,8 @@ } if (plugin->native_plugin) { - if (plugin->info->unload != NULL) - plugin->info->unload(plugin); + if (plugin->info->unload && !plugin->info->unload(plugin)) + return FALSE; if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { PurplePluginProtocolInfo *prpl_info; @@ -724,8 +712,7 @@ prpl_info->protocol_options = NULL; } } - } - else { + } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; @@ -736,14 +723,30 @@ loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); - if (loader_info->unload != NULL) - loader_info->unload(plugin); + if (loader_info->unload && !loader_info->unload(plugin)) + return FALSE; } + /* cancel any pending dialogs the plugin has */ + purple_request_close_with_handle(plugin); + purple_notify_close_with_handle(plugin); + purple_signals_disconnect_by_handle(plugin); purple_plugin_ipc_unregister_all(plugin); - /* TODO */ + loaded_plugins = g_list_remove(loaded_plugins, plugin); + if ((plugin->info != NULL) && PURPLE_IS_PROTOCOL_PLUGIN(plugin)) + protocol_plugins = g_list_remove(protocol_plugins, plugin); + plugins_to_disable = g_list_remove(plugins_to_disable, plugin); + plugin->loaded = FALSE; + + /* We wouldn't be anywhere near here if the plugin wasn't loaded, so + * if plugin->error is set at all, it had to be from a previous + * unload failure. It's obviously okay now. + */ + g_free(plugin->error); + plugin->error = NULL; + if (unload_cb != NULL) unload_cb(plugin, unload_cb_data); @@ -757,6 +760,15 @@ #endif /* PURPLE_PLUGINS */ } +void +purple_plugin_disable(PurplePlugin *plugin) +{ + g_return_if_fail(plugin != NULL); + + if (!g_list_find(plugins_to_disable, plugin)) + plugins_to_disable = g_list_prepend(plugins_to_disable, plugin); +} + gboolean purple_plugin_reload(PurplePlugin *plugin) { @@ -1222,14 +1234,14 @@ #ifdef PURPLE_PLUGINS GList *pl; GList *files = NULL; - PurplePlugin *p; for (pl = purple_plugins_get_loaded(); pl != NULL; pl = pl->next) { - p = pl->data; + PurplePlugin *plugin = pl->data; - if (p->info->type != PURPLE_PLUGIN_PROTOCOL && - p->info->type != PURPLE_PLUGIN_LOADER) { - files = g_list_append(files, p->path); + if (plugin->info->type != PURPLE_PLUGIN_PROTOCOL && + plugin->info->type != PURPLE_PLUGIN_LOADER && + !g_list_find(plugins_to_disable, plugin)) { + files = g_list_append(files, plugin->path); } } @@ -1391,6 +1403,7 @@ if (probe_cb != NULL) probe_cb(probe_cb_data); + #endif /* PURPLE_PLUGINS */ } @@ -1464,7 +1477,6 @@ void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data) { - /* TODO */ probe_cb = func; probe_cb_data = data; } @@ -1472,7 +1484,6 @@ void purple_plugins_unregister_probe_notify_cb(void (*func)(void *)) { - /* TODO */ probe_cb = NULL; probe_cb_data = NULL; } @@ -1481,7 +1492,6 @@ purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), void *data) { - /* TODO */ load_cb = func; load_cb_data = data; } @@ -1489,7 +1499,6 @@ void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)) { - /* TODO */ load_cb = NULL; load_cb_data = NULL; } @@ -1498,7 +1507,6 @@ purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), void *data) { - /* TODO */ unload_cb = func; unload_cb_data = data; } @@ -1506,7 +1514,6 @@ void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)) { - /* TODO */ unload_cb = NULL; unload_cb_data = NULL; } diff -r 34fc2a999977 -r 8a89c2caf9d8 libpurple/plugin.h --- a/libpurple/plugin.h Wed Oct 10 02:18:48 2007 +0000 +++ b/libpurple/plugin.h Wed Oct 10 03:57:39 2007 +0000 @@ -70,11 +70,6 @@ * * This is used in the version 2.0 API and up. */ -/* TODO We need to figure out exactly what parts of this are required. The - * dependent plugin unloading stuff was causing crashes with perl and tcl - * plugins because they didn't set ids and the dependency code was requiring - * them. Then we need to actually make sure that plugins have all the right - * parts before loading them. */ struct _PurplePluginInfo { unsigned int magic; @@ -296,6 +291,18 @@ gboolean purple_plugin_unload(PurplePlugin *plugin); /** + * Disable a plugin. + * + * This function adds the plugin to a list of plugins to "disable at the next + * startup" by excluding said plugins from the list of plugins to save. The + * UI needs to call purple_plugins_save_loaded() after calling this for it + * to have any effect. + * + * @since 2.3.0 + */ +void purple_plugin_disable(PurplePlugin *plugin); + +/** * Reloads a plugin. * * @param plugin The old plugin handle. @@ -525,53 +532,71 @@ */ gboolean purple_plugins_enabled(void); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when probing is finished. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated If you need this, ask for a plugin-probe signal to be added. */ void purple_plugins_register_probe_notify_cb(void (*func)(void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when probing is finished. * * @param func The callback function. + * @deprecated If you need this, ask for a plugin-probe signal to be added. */ void purple_plugins_unregister_probe_notify_cb(void (*func)(void *)); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when a plugin is loaded. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated Use the plugin-load signal instead. */ void purple_plugins_register_load_notify_cb(void (*func)(PurplePlugin *, void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when a plugin is loaded. * * @param func The callback function. + * @deprecated Use the plugin-load signal instead. */ void purple_plugins_unregister_load_notify_cb(void (*func)(PurplePlugin *, void *)); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Registers a function that will be called when a plugin is unloaded. * * @param func The callback function. * @param data Data to pass to the callback. + * @deprecated Use the plugin-unload signal instead. */ void purple_plugins_register_unload_notify_cb(void (*func)(PurplePlugin *, void *), void *data); +#endif +#ifndef PURPLE_DISABLE_DEPRECATED /** * Unregisters a function that would be called when a plugin is unloaded. * * @param func The callback function. + * @deprecated Use the plugin-unload signal instead. */ void purple_plugins_unregister_unload_notify_cb(void (*func)(PurplePlugin *, void *)); +#endif /** * Finds a plugin with the specified name. diff -r 34fc2a999977 -r 8a89c2caf9d8 libpurple/sslconn.h --- a/libpurple/sslconn.h Wed Oct 10 02:18:48 2007 +0000 +++ b/libpurple/sslconn.h Wed Oct 10 03:57:39 2007 +0000 @@ -185,6 +185,7 @@ PurpleSslErrorFunction error_func, void *data); +#ifndef PURPLE_DISABLE_DEPRECATED /** * Makes a SSL connection using an already open file descriptor. * @@ -202,6 +203,7 @@ PurpleSslInputFunction func, PurpleSslErrorFunction error_func, void *data); +#endif /** * Makes a SSL connection using an already open file descriptor. diff -r 34fc2a999977 -r 8a89c2caf9d8 pidgin/gtknotify.c --- a/pidgin/gtknotify.c Wed Oct 10 02:18:48 2007 +0000 +++ b/pidgin/gtknotify.c Wed Oct 10 03:57:39 2007 +0000 @@ -270,8 +270,9 @@ primary_esc = g_markup_escape_text(primary, -1); secondary_esc = (secondary != NULL) ? g_markup_escape_text(secondary, -1) : NULL; g_snprintf(label_text, sizeof(label_text), - "%s\n\n%s", - primary_esc, (secondary ? secondary_esc : "")); + "%s%s%s", + primary_esc, (secondary ? "\n\n" : ""), + (secondary ? secondary_esc : "")); g_free(primary_esc); g_free(secondary_esc); diff -r 34fc2a999977 -r 8a89c2caf9d8 pidgin/gtkplugin.c --- a/pidgin/gtkplugin.c Wed Oct 10 02:18:48 2007 +0000 +++ b/pidgin/gtkplugin.c Wed Oct 10 03:57:39 2007 +0000 @@ -303,7 +303,24 @@ { pidgin_set_cursor(plugin_dialog, GDK_WATCH); - purple_plugin_unload(plug); + if (!purple_plugin_unload(plug)) + { + const char *primary = _("Could not unload plugin"); + const char *reload = _("The plugin could not be unloaded now, but will be disabled at the next startup."); + + if (!plug->error) + { + purple_notify_warning(NULL, NULL, primary, reload); + } + else + { + char *tmp = g_strdup_printf("%s\n\n%s", reload, plug->error); + purple_notify_warning(NULL, NULL, primary, tmp); + g_free(tmp); + } + + purple_plugin_disable(plug); + } pidgin_clear_cursor(plugin_dialog); }