static gboolean check_for_buddynote(gpointer data) { PurplePlugin *buddynote = NULL; PurplePlugin *plugin = (PurplePlugin *)data; buddynote = purple_plugins_find_with_id("core-plugin_pack-buddynote"); if (buddynote == NULL) { buddynote = purple_plugins_find_with_basename("buddynote"); } if (buddynote != NULL) { PurplePluginInfo *bninfo = buddynote->info; bninfo->flags = PURPLE_PLUGIN_FLAG_INVISIBLE; /* If non-gtk buddy note plugin is loaded, but we are not, then load * ourselves, otherwise people upgrading from pre-gtkbuddynote days * will not have 'Buddy Notes' showing as loaded in the plugins list. * We also trigger a save on the list of plugins because it's not been * loaded through the UI. */ if (purple_plugin_is_loaded(buddynote) && !purple_plugin_is_loaded(plugin)) { purple_plugin_load(plugin); pidgin_plugins_save(); } } else { info.flags = PURPLE_PLUGIN_FLAG_INVISIBLE; } return FALSE; }
void purple_plugins_unload(PurplePluginType type) { #ifdef PURPLE_PLUGINS GList *l; for (l = plugins; l; l = l->next) { PurplePlugin *plugin = l->data; if (plugin->info->type == type && purple_plugin_is_loaded(plugin)) purple_plugin_unload(plugin); } #endif /* PURPLE_PLUGINS */ }
static void decide_conf_button(PurplePlugin *plugin) { if (purple_plugin_is_loaded(plugin) && ((PURPLE_IS_GNT_PLUGIN(plugin) && FINCH_PLUGIN_UI_INFO(plugin) != NULL) || (plugin->info->prefs_info && plugin->info->prefs_info->get_plugin_pref_frame))) gnt_widget_set_visible(plugins.conf, TRUE); else gnt_widget_set_visible(plugins.conf, FALSE); gnt_box_readjust(GNT_BOX(plugins.window)); gnt_widget_draw(plugins.window); }
gboolean purple_plugin_reload(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS g_return_val_if_fail(plugin != NULL, FALSE); g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); if (!purple_plugin_unload(plugin)) return FALSE; if (!purple_plugin_load(plugin)) return FALSE; return TRUE; #else return TRUE; #endif /* !PURPLE_PLUGINS */ }
static gboolean has_prefs(PurplePlugin *plugin) { PurplePluginInfo *info = purple_plugin_get_info(plugin); FinchPluginInfoPrivate *priv = NULL; gboolean ret; g_return_val_if_fail(plugin != NULL, FALSE); if (!purple_plugin_is_loaded(plugin)) return FALSE; if (FINCH_IS_PLUGIN_INFO(info)) priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info); ret = ((priv && priv->pref_frame_cb) || purple_plugin_info_get_pref_frame_cb(info) || purple_plugin_info_get_pref_request_cb(info)); return ret; }
static gboolean ssl_init(void) { PurplePlugin *plugin; PurpleSslOps *ops; if (_ssl_initialized) return FALSE; plugin = purple_plugins_find_with_id("core-ssl"); if (plugin != NULL && !purple_plugin_is_loaded(plugin)) purple_plugin_load(plugin); ops = purple_ssl_get_ops(); if ((ops == NULL) || (ops->init == NULL) || (ops->uninit == NULL) || (ops->connectfunc == NULL) || (ops->close == NULL) || (ops->read == NULL) || (ops->write == NULL)) { return FALSE; } return (_ssl_initialized = ops->init()); }
void finch_plugins_show_all(void) { GntWidget *window, *tree, *box, *aboot, *button; GList *plugin_list, *iter; GList *seen; if (plugins.window) { gnt_window_present(plugins.window); return; } purple_plugins_refresh(); plugins.window = window = gnt_vbox_new(FALSE); gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), _("Plugins")); gnt_box_set_pad(GNT_BOX(window), 0); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); gnt_box_add_widget(GNT_BOX(window), gnt_label_new(_("You can (un)load plugins from the following list."))); gnt_box_add_widget(GNT_BOX(window), gnt_hline_new()); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(window), box); gnt_box_add_widget(GNT_BOX(window), gnt_hline_new()); gnt_box_set_pad(GNT_BOX(box), 0); plugins.tree = tree = gnt_tree_new(); gnt_tree_set_compare_func(GNT_TREE(tree), (GCompareFunc)plugin_compare); GNT_WIDGET_SET_FLAGS(tree, GNT_WIDGET_NO_BORDER); gnt_box_add_widget(GNT_BOX(box), tree); 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); seen = purple_prefs_get_path_list("/finch/plugins/seen"); plugin_list = purple_plugins_find_all(); for (iter = plugin_list; iter; iter = iter->next) { PurplePlugin *plug = PURPLE_PLUGIN(iter->data); if (purple_plugin_is_internal(plug)) continue; gnt_tree_add_choice(GNT_TREE(tree), plug, gnt_tree_create_row(GNT_TREE(tree), purple_plugin_info_get_name(purple_plugin_get_info(plug))), NULL, NULL); gnt_tree_set_choice(GNT_TREE(tree), plug, purple_plugin_is_loaded(plug)); if (!g_list_find_custom(seen, purple_plugin_get_filename(plug), (GCompareFunc)strcmp)) gnt_tree_set_row_flags(GNT_TREE(tree), plug, GNT_TEXT_FLAG_BOLD); } g_list_free(plugin_list); gnt_tree_set_col_width(GNT_TREE(tree), 0, 30); g_signal_connect(G_OBJECT(tree), "toggled", G_CALLBACK(plugin_toggled_cb), NULL); g_signal_connect(G_OBJECT(tree), "selection_changed", G_CALLBACK(selection_changed), NULL); g_object_set_data(G_OBJECT(tree), "seen-list", seen); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(window), box); #if 0 button = gnt_button_new(_("Install Plugin...")); gnt_box_add_widget(GNT_BOX(box), button); gnt_util_set_trigger_widget(GNT_WIDGET(tree), GNT_KEY_INS, button); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(install_plugin_cb), NULL); #endif button = gnt_button_new(_("Close")); gnt_box_add_widget(GNT_BOX(box), button); g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window); plugins.conf = button = gnt_button_new(_("Configure Plugin")); gnt_box_add_widget(GNT_BOX(box), button); g_signal_connect(G_OBJECT(button), "activate", G_CALLBACK(configure_plugin_cb), NULL); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(reset_plugin_window), NULL); gnt_widget_show(window); decide_conf_button(gnt_tree_get_selection_data(GNT_TREE(tree))); }
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."), NULL); 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 configure_plugin_cb(GntWidget *button, gpointer null) { PurplePlugin *plugin; PurplePluginInfo *info; FinchPluginInfoPrivate *priv = NULL; FinchPluginUiData *ui_data; g_return_if_fail(plugins.tree != NULL); plugin = gnt_tree_get_selection_data(GNT_TREE(plugins.tree)); if (!purple_plugin_is_loaded(plugin)) { purple_notify_error(plugin, _("Error"), _("Plugin need to be loaded before you can configure it."), NULL, NULL); return; } info = purple_plugin_get_info(plugin); if (purple_plugin_info_get_ui_data(info)) return; ui_data = g_new0(FinchPluginUiData, 1); purple_plugin_info_set_ui_data(info, ui_data); if (FINCH_IS_PLUGIN_INFO(info)) priv = FINCH_PLUGIN_INFO_GET_PRIVATE(info); if (priv && priv->pref_frame_cb != NULL) { GntWidget *window = gnt_vbox_new(FALSE); GntWidget *box, *button; gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), purple_plugin_info_get_name(info)); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); box = priv->pref_frame_cb(); gnt_box_add_widget(GNT_BOX(window), box); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(window), box); button = gnt_button_new(_("Close")); gnt_box_add_widget(GNT_BOX(box), button); g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(remove_confwin), plugin); gnt_widget_show(window); ui_data->type = FINCH_PLUGIN_UI_DATA_TYPE_WINDOW; ui_data->u.window = window; } else if (purple_plugin_info_get_pref_request_cb(info)) { PurplePluginPrefRequestCb pref_request_cb = purple_plugin_info_get_pref_request_cb(info); gpointer handle; ui_data->type = FINCH_PLUGIN_UI_DATA_TYPE_REQUEST; ui_data->u.request_handle = handle = pref_request_cb(plugin); purple_request_add_close_notify(handle, purple_callback_set_zero, &info->ui_data); purple_request_add_close_notify(handle, g_free, ui_data); } else if (purple_plugin_info_get_pref_frame_cb(info)) { PurplePluginPrefFrameCb pref_frame_cb = purple_plugin_info_get_pref_frame_cb(info); GntWidget *win = process_pref_frame(pref_frame_cb(plugin)); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(remove_confwin), plugin); ui_data->type = FINCH_PLUGIN_UI_DATA_TYPE_WINDOW; ui_data->u.window = win; } else { purple_notify_info(plugin, _("Error"), _("No configuration " "options for this plugin."), NULL, NULL); g_free(ui_data); purple_plugin_info_set_ui_data(info, NULL); } }
static void configure_plugin_cb(GntWidget *button, gpointer null) { PurplePlugin *plugin; FinchPluginFrame callback; g_return_if_fail(plugins.tree != NULL); plugin = gnt_tree_get_selection_data(GNT_TREE(plugins.tree)); if (!purple_plugin_is_loaded(plugin)) { purple_notify_error(plugin, _("Error"), _("Plugin need to be loaded before you can configure it."), NULL); return; } if (confwins && g_hash_table_lookup(confwins, plugin)) return; if (PURPLE_IS_GNT_PLUGIN(plugin) && (callback = FINCH_PLUGIN_UI_INFO(plugin)) != NULL) { GntWidget *window = gnt_vbox_new(FALSE); GntWidget *box, *button; gnt_box_set_toplevel(GNT_BOX(window), TRUE); gnt_box_set_title(GNT_BOX(window), plugin->info->name); gnt_box_set_alignment(GNT_BOX(window), GNT_ALIGN_MID); box = callback(); gnt_box_add_widget(GNT_BOX(window), box); box = gnt_hbox_new(FALSE); gnt_box_add_widget(GNT_BOX(window), box); button = gnt_button_new(_("Close")); gnt_box_add_widget(GNT_BOX(box), button); g_signal_connect_swapped(G_OBJECT(button), "activate", G_CALLBACK(gnt_widget_destroy), window); g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(remove_confwin), plugin); gnt_widget_show(window); if (confwins == NULL) confwin_init(); g_hash_table_insert(confwins, plugin, window); } else if (plugin->info->prefs_info && plugin->info->prefs_info->get_plugin_pref_frame) { GntWidget *win = process_pref_frame(plugin->info->prefs_info->get_plugin_pref_frame(plugin)); if (confwins == NULL) confwin_init(); g_signal_connect(G_OBJECT(win), "destroy", G_CALLBACK(remove_confwin), plugin); g_hash_table_insert(confwins, plugin, win); return; } else { purple_notify_info(plugin, _("Error"), _("No configuration options for this plugin."), NULL); return; } }
void purple_plugin_destroy(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS g_return_if_fail(plugin != NULL); if (purple_plugin_is_loaded(plugin)) purple_plugin_unload(plugin); plugins = g_list_remove(plugins, plugin); if (load_queue != NULL) load_queue = g_list_remove(load_queue, plugin); /* true, this may leak a little memory if there is a major version * mismatch, but it's a lot better than trying to free something * we shouldn't, and crashing while trying to load an old plugin */ if(plugin->info == NULL || plugin->info->magic != PURPLE_PLUGIN_MAGIC || plugin->info->major_version != PURPLE_MAJOR_VERSION) { if(plugin->handle) g_module_close(plugin->handle); g_free(plugin->path); g_free(plugin->error); PURPLE_DBUS_UNREGISTER_POINTER(plugin); g_free(plugin); return; } if (plugin->info != NULL) g_list_free(plugin->info->dependencies); if (plugin->native_plugin) { if (plugin->info != NULL && plugin->info->type == PURPLE_PLUGIN_LOADER) { PurplePluginLoaderInfo *loader_info; GList *exts, *l, *next_l; PurplePlugin *p2; loader_info = PURPLE_PLUGIN_LOADER_INFO(plugin); if (loader_info != NULL && loader_info->exts != NULL) { for (exts = PURPLE_PLUGIN_LOADER_INFO(plugin)->exts; exts != NULL; exts = exts->next) { for (l = purple_plugins_get_all(); l != NULL; l = next_l) { next_l = l->next; p2 = l->data; if (p2->path != NULL && has_file_extension(p2->path, exts->data)) { purple_plugin_destroy(p2); } } } g_list_free(loader_info->exts); loader_info->exts = NULL; } plugin_loaders = g_list_remove(plugin_loaders, plugin); } if (plugin->info != NULL && plugin->info->destroy != NULL) plugin->info->destroy(plugin); /* * I find it extremely useful to do this when using valgrind, as * it keeps all the plugins open, meaning that valgrind is able to * resolve symbol names in leak traces from plugins. */ if (!g_getenv("PURPLE_LEAKCHECK_HELP") && !RUNNING_ON_VALGRIND) { if (plugin->handle != NULL) g_module_close(plugin->handle); } } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; loader = find_loader_for_plugin(plugin); if (loader != NULL) { loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); if (loader_info->destroy != NULL) loader_info->destroy(plugin); } } g_free(plugin->path); g_free(plugin->error); PURPLE_DBUS_UNREGISTER_POINTER(plugin); g_free(plugin); #endif /* !PURPLE_PLUGINS */ }
gboolean purple_plugin_unload(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS GList *l; GList *ll; g_return_val_if_fail(plugin != NULL, FALSE); g_return_val_if_fail(purple_plugin_is_loaded(plugin), FALSE); purple_debug_info("plugins", "Unloading plugin %s\n", plugin->info->name); /* Unload all plugins that depend on this plugin. */ 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)) { 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 { #if 0 /* This isn't necessary. This has already been done when unloading dep_plugin. */ plugin->dependent_plugins = g_list_delete_link(plugin->dependent_plugins, l); #endif } } } /* Remove this plugin from each dependency's dependent_plugins list. */ for (l = plugin->info->dependencies; l != NULL; l = l->next) { const char *dep_name = (const char *)l->data; PurplePlugin *dependency; dependency = purple_plugins_find_with_id(dep_name); if (dependency != NULL) dependency->dependent_plugins = g_list_remove(dependency->dependent_plugins, plugin->info->id); else purple_debug_error("plugins", "Unable to remove from dependency list for %s\n", dep_name); } if (plugin->native_plugin) { if (plugin->info->unload && !plugin->info->unload(plugin)) return FALSE; if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL) { PurplePluginProtocolInfo *prpl_info; GList *l; prpl_info = PURPLE_PLUGIN_PROTOCOL_INFO(plugin); for (l = prpl_info->user_splits; l != NULL; l = l->next) purple_account_user_split_destroy(l->data); for (l = prpl_info->protocol_options; l != NULL; l = l->next) purple_account_option_destroy(l->data); if (prpl_info->user_splits != NULL) { g_list_free(prpl_info->user_splits); prpl_info->user_splits = NULL; } if (prpl_info->protocol_options != NULL) { g_list_free(prpl_info->protocol_options); prpl_info->protocol_options = NULL; } } } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; loader = find_loader_for_plugin(plugin); if (loader == NULL) return FALSE; loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); 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); 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; purple_signal_emit(purple_plugins_get_handle(), "plugin-unload", plugin); purple_prefs_disconnect_by_handle(plugin); return TRUE; #else return TRUE; #endif /* PURPLE_PLUGINS */ }
gboolean purple_plugin_load(PurplePlugin *plugin) { #ifdef PURPLE_PLUGINS GList *dep_list = NULL; GList *l; g_return_val_if_fail(plugin != NULL, FALSE); if (purple_plugin_is_loaded(plugin)) return TRUE; if (purple_plugin_is_unloadable(plugin)) return FALSE; g_return_val_if_fail(plugin->error == NULL, FALSE); /* * Go through the list of the plugin's dependencies. * * First pass: Make sure all the plugins needed are probed. */ for (l = plugin->info->dependencies; l != NULL; l = l->next) { const char *dep_name = (const char *)l->data; PurplePlugin *dep_plugin; dep_plugin = purple_plugins_find_with_id(dep_name); if (dep_plugin == NULL) { char *tmp; tmp = g_strdup_printf(_("The required plugin %s was not found. " "Please install this plugin and try again."), dep_name); purple_notify_error(NULL, NULL, _("Unable to load the plugin"), tmp, NULL); g_free(tmp); g_list_free(dep_list); return FALSE; } dep_list = g_list_append(dep_list, dep_plugin); } /* Second pass: load all the required plugins. */ for (l = dep_list; l != NULL; l = l->next) { PurplePlugin *dep_plugin = (PurplePlugin *)l->data; if (!purple_plugin_is_loaded(dep_plugin)) { if (!purple_plugin_load(dep_plugin)) { char *tmp; tmp = g_strdup_printf(_("The required plugin %s was unable to load."), plugin->info->name); purple_notify_error(NULL, NULL, _("Unable to load your plugin."), tmp, NULL); g_free(tmp); g_list_free(dep_list); return FALSE; } } } /* Third pass: note that other plugins are dependencies of this plugin. * This is done separately in case we had to bail out earlier. */ for (l = dep_list; l != NULL; l = l->next) { PurplePlugin *dep_plugin = (PurplePlugin *)l->data; dep_plugin->dependent_plugins = g_list_prepend(dep_plugin->dependent_plugins, (gpointer)plugin->info->id); } g_list_free(dep_list); if (plugin->native_plugin) { if (plugin->info->load != NULL && !plugin->info->load(plugin)) return FALSE; } else { PurplePlugin *loader; PurplePluginLoaderInfo *loader_info; loader = find_loader_for_plugin(plugin); if (loader == NULL) return FALSE; loader_info = PURPLE_PLUGIN_LOADER_INFO(loader); if (loader_info->load != NULL) { if (!loader_info->load(plugin)) return FALSE; } } loaded_plugins = g_list_insert_sorted(loaded_plugins, plugin, compare_plugins); plugin->loaded = TRUE; purple_signal_emit(purple_plugins_get_handle(), "plugin-load", plugin); return TRUE; #else return TRUE; #endif /* !PURPLE_PLUGINS */ }