コード例 #1
0
ファイル: gtkbuddynote.c プロジェクト: asimperson/creole
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;
}
コード例 #2
0
ファイル: plugin.c プロジェクト: Distrotech/pidgin
void
purple_plugins_load_saved(const char *key)
{
#ifdef PURPLE_PLUGINS
	GList *f, *files;

	g_return_if_fail(key != NULL);

	files = purple_prefs_get_path_list(key);

	for (f = files; f; f = f->next)
	{
		char *filename;
		char *basename;
		PurplePlugin *plugin;

		if (f->data == NULL)
			continue;

		filename = f->data;

		/*
		 * We don't know if the filename uses Windows or Unix path
		 * separators (because people might be sharing a prefs.xml
		 * file across systems), so we find the last occurrence
		 * of either.
		 */
		basename = strrchr(filename, '/');
		if ((basename == NULL) || (basename < strrchr(filename, '\\')))
			basename = strrchr(filename, '\\');
		if (basename != NULL)
			basename++;

		/* Strip the extension */
		if (basename)
			basename = purple_plugin_get_basename(basename);

		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);
			purple_plugin_load(plugin);
		}
		else
		{
			purple_debug_error("plugins", "Unable to find saved plugin %s\n",
							 filename);
		}

		g_free(basename);

		g_free(f->data);
	}

	g_list_free(files);
#endif /* PURPLE_PLUGINS */
}
コード例 #3
0
ファイル: plugin.c プロジェクト: Distrotech/pidgin
PurplePlugin *
purple_plugin_probe(const char *filename)
{
#ifdef PURPLE_PLUGINS
	PurplePlugin *plugin = NULL;
	PurplePlugin *loader;
	gpointer unpunned;
	gchar *basename = NULL;
	gboolean (*purple_init_plugin)(PurplePlugin *);

	purple_debug_misc("plugins", "probing %s\n", filename);
	g_return_val_if_fail(filename != NULL, NULL);

	if (!g_file_test(filename, G_FILE_TEST_EXISTS))
		return NULL;

	/* If this plugin has already been probed then exit */
	basename = purple_plugin_get_basename(filename);
	plugin = purple_plugins_find_with_basename(basename);
	g_free(basename);
	if (plugin != NULL)
	{
		if (purple_strequal(filename, plugin->path))
			return plugin;
		else if (!purple_plugin_is_unloadable(plugin))
		{
			purple_debug_warning("plugins", "Not loading %s. "
							"Another plugin with the same name (%s) has already been loaded.\n",
							filename, plugin->path);
			return plugin;
		}
		else
		{
			/* The old plugin was a different file and it was unloadable.
			 * There's no guarantee that this new file with the same name
			 * will be loadable, but unless it fails in one of the silent
			 * ways and the first one didn't, it's not any worse.  The user
			 * will still see a greyed-out plugin, which is what we want. */
			purple_plugin_destroy(plugin);
		}
	}

	plugin = purple_plugin_new(has_file_extension(filename, G_MODULE_SUFFIX), filename);

	if (plugin->native_plugin) {
		const char *error;
#ifdef _WIN32
		/* Suppress error popups for failing to load plugins */
		UINT old_error_mode = SetErrorMode(SEM_FAILCRITICALERRORS);
#endif

		/*
		 * We pass G_MODULE_BIND_LOCAL here to prevent symbols from
		 * plugins being added to the global name space.
		 *
		 * G_MODULE_BIND_LOCAL was added in glib 2.3.3.
		 */
		plugin->handle = g_module_open(filename, G_MODULE_BIND_LOCAL);

		if (plugin->handle == NULL)
		{
			const char *error = g_module_error();
			if (error != NULL && purple_str_has_prefix(error, filename))
			{
				error = error + strlen(filename);

				/* These are just so we don't crash.  If we
				 * got this far, they should always be true. */
				if (*error == ':')
					error++;
				if (*error == ' ')
					error++;
			}

			if (error == NULL || !*error)
			{
				plugin->error = g_strdup(_("Unknown error"));
				purple_debug_error("plugins", "%s is not loadable: Unknown error\n",
						 plugin->path);
			}
			else
			{
				plugin->error = g_strdup(error);
				purple_debug_error("plugins", "%s is not loadable: %s\n",
						 plugin->path, plugin->error);
			}
			plugin->handle = g_module_open(filename, G_MODULE_BIND_LAZY | G_MODULE_BIND_LOCAL);

			if (plugin->handle == NULL)
			{
#ifdef _WIN32
				/* Restore the original error mode */
				SetErrorMode(old_error_mode);
#endif
				purple_plugin_destroy(plugin);
				return NULL;
			}
			else
			{
				/* We were able to load the plugin with lazy symbol binding.
				 * This means we're missing some symbol.  Mark it as
				 * unloadable and keep going so we get the info to display
				 * to the user so they know to rebuild this plugin. */
				plugin->unloadable = TRUE;
			}
		}

		if (!g_module_symbol(plugin->handle, "purple_init_plugin",
							 &unpunned))
		{
			purple_debug_error("plugins", "%s is not usable because the "
							 "'purple_init_plugin' symbol could not be "
							 "found.  Does the plugin call the "
							 "PURPLE_INIT_PLUGIN() macro?\n", plugin->path);

			g_module_close(plugin->handle);
			error = g_module_error();
			if (error != NULL)
				purple_debug_error("plugins", "Error closing module %s: %s\n",
								 plugin->path, error);
			plugin->handle = NULL;

#ifdef _WIN32
			/* Restore the original error mode */
			SetErrorMode(old_error_mode);
#endif
			purple_plugin_destroy(plugin);
			return NULL;
		}
		purple_init_plugin = unpunned;

#ifdef _WIN32
		/* Restore the original error mode */
		SetErrorMode(old_error_mode);
#endif
	}
	else {
		loader = find_loader_for_plugin(plugin);

		if (loader == NULL) {
			purple_plugin_destroy(plugin);
			return NULL;
		}

		purple_init_plugin = PURPLE_PLUGIN_LOADER_INFO(loader)->probe;
	}

	if (!purple_init_plugin(plugin) || plugin->info == NULL)
	{
		purple_plugin_destroy(plugin);
		return NULL;
	}
	else if (plugin->info->ui_requirement &&
			!purple_strequal(plugin->info->ui_requirement, purple_core_get_ui()))
	{
		plugin->error = g_strdup_printf(_("You are using %s, but this plugin requires %s."),
					purple_core_get_ui(), plugin->info->ui_requirement);
		purple_debug_error("plugins", "%s is not loadable: The UI requirement is not met. (%s)\n", plugin->path, plugin->error);
		plugin->unloadable = TRUE;
		return plugin;
	}

	/*
	 * Check to make sure a plugin has defined an id.
	 * Not having this check caused purple_plugin_unload to
	 * enter an infinite loop in certain situations by passing
	 * purple_find_plugin_by_id a NULL value. -- ecoffey
	 */
	if (plugin->info->id == NULL || *plugin->info->id == '\0')
	{
		plugin->error = g_strdup(_("This plugin has not defined an ID."));
		purple_debug_error("plugins", "%s is not loadable: info->id is not defined.\n", plugin->path);
		plugin->unloadable = TRUE;
		return plugin;
	}

	/* Really old plugins. */
	if (plugin->info->magic != PURPLE_PLUGIN_MAGIC)
	{
		if (plugin->info->magic >= 2 && plugin->info->magic <= 4)
		{
			struct _PurplePluginInfo2
			{
				unsigned int api_version;
				PurplePluginType type;
				char *ui_requirement;
				unsigned long flags;
				GList *dependencies;
				PurplePluginPriority priority;

				char *id;
				char *name;
				char *version;
				char *summary;
				char *description;
				char *author;
				char *homepage;

				gboolean (*load)(PurplePlugin *plugin);
				gboolean (*unload)(PurplePlugin *plugin);
				void (*destroy)(PurplePlugin *plugin);

				void *ui_info;
				void *extra_info;
				PurplePluginUiInfo *prefs_info;
				GList *(*actions)(PurplePlugin *plugin, gpointer context);
			} *info2 = (struct _PurplePluginInfo2 *)plugin->info;

			/* This leaks... but only for ancient plugins, so deal with it. */
			plugin->info = g_new0(PurplePluginInfo, 1);

			/* We don't really need all these to display the plugin info, but
			 * I'm copying them all for good measure. */
			plugin->info->magic          = info2->api_version;
			plugin->info->type           = info2->type;
			plugin->info->ui_requirement = info2->ui_requirement;
			plugin->info->flags          = info2->flags;
			plugin->info->dependencies   = info2->dependencies;
			plugin->info->id             = info2->id;
			plugin->info->name           = info2->name;
			plugin->info->version        = info2->version;
			plugin->info->summary        = info2->summary;
			plugin->info->description    = info2->description;
			plugin->info->author         = info2->author;
			plugin->info->homepage       = info2->homepage;
			plugin->info->load           = info2->load;
			plugin->info->unload         = info2->unload;
			plugin->info->destroy        = info2->destroy;
			plugin->info->ui_info        = info2->ui_info;
			plugin->info->extra_info     = info2->extra_info;

			if (info2->api_version >= 3)
				plugin->info->prefs_info = info2->prefs_info;

			if (info2->api_version >= 4)
				plugin->info->actions    = info2->actions;


			plugin->error = g_strdup_printf(_("Plugin magic mismatch %d (need %d)"),
							 plugin->info->magic, PURPLE_PLUGIN_MAGIC);
			purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
					  plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
			plugin->unloadable = TRUE;
			return plugin;
		}

		purple_debug_error("plugins", "%s is not loadable: Plugin magic mismatch %d (need %d)\n",
				 plugin->path, plugin->info->magic, PURPLE_PLUGIN_MAGIC);
		purple_plugin_destroy(plugin);
		return NULL;
	}

	if (plugin->info->major_version != PURPLE_MAJOR_VERSION ||
			plugin->info->minor_version > PURPLE_MINOR_VERSION)
	{
		plugin->error = g_strdup_printf(_("ABI version mismatch %d.%d.x (need %d.%d.x)"),
						 plugin->info->major_version, plugin->info->minor_version,
						 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
		purple_debug_error("plugins", "%s is not loadable: ABI version mismatch %d.%d.x (need %d.%d.x)\n",
				 plugin->path, plugin->info->major_version, plugin->info->minor_version,
				 PURPLE_MAJOR_VERSION, PURPLE_MINOR_VERSION);
		plugin->unloadable = TRUE;
		return plugin;
	}

	if (plugin->info->type == PURPLE_PLUGIN_PROTOCOL)
	{
		/* If plugin is a PRPL, make sure it implements the required functions */
		if ((PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->list_icon == NULL) ||
		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->login == NULL) ||
		    (PURPLE_PLUGIN_PROTOCOL_INFO(plugin)->close == NULL))
		{
			plugin->error = g_strdup(_("Plugin does not implement all required functions (list_icon, login and close)"));
			purple_debug_error("plugins", "%s is not loadable: %s\n",
					 plugin->path, plugin->error);
			plugin->unloadable = TRUE;
			return plugin;
		}

		/* For debugging, let's warn about prpl prefs. */
		if (plugin->info->prefs_info != NULL)
		{
			purple_debug_error("plugins", "%s has a prefs_info, but is a prpl. This is no longer supported.\n",
			                 plugin->path);
		}
	}

	return plugin;
#else
	return NULL;
#endif /* !PURPLE_PLUGINS */
}