[krb5-auth-dialog] Add plugin infrastructure



commit 69ce38151c7a08fe980d981108c782762bf72e81
Author: Guido Günther <agx sigxcpu org>
Date:   Tue Apr 20 22:21:54 2010 +0200

    Add plugin infrastructure

 configure.ac           |   10 +++-
 src/Makefile.am        |    7 ++
 src/ka-plugin-loader.c |  161 ++++++++++++++++++++++++++++++++++++++++++++++++
 src/ka-plugin-loader.h |   58 +++++++++++++++++
 src/ka-plugin.c        |  133 +++++++++++++++++++++++++++++++++++++++
 src/ka-plugin.h        |   75 ++++++++++++++++++++++
 src/krb5-auth-applet.c |   10 +++-
 7 files changed, 452 insertions(+), 2 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index 334be38..bb41970 100644
--- a/configure.ac
+++ b/configure.ac
@@ -42,6 +42,7 @@ PKG_CHECK_MODULES(DBUS, dbus-glib-1 >= $DBUS_REQUIRED)
 PKG_CHECK_MODULES(GCONF, gconf-2.0 >= $GCONF_REQUIRED)
 PKG_CHECK_MODULES(GIO_UNIX, gio-unix-2.0 >= $GIO_UNIX_REQUIRED)
 PKG_CHECK_MODULES(GIO, gio-2.0 >= $GIO_REQUIRED)
+PKG_CHECK_MODULES(GMODULE, gmodule-2.0)
 
 AM_GCONF_SOURCE_2
 
@@ -218,10 +219,17 @@ AC_SUBST(check_interval)
 minimum_lifetime=30
 AC_DEFINE_UNQUOTED(MINUTES_BEFORE_PROMPTING,[$minimum_lifetime],
 		   [Define the to the minimum amount of time (m) a credential
-		    will have to be valid before we'll ask the user to get
+		    will have to be valid before we will ask the user to get
 		    fresh credentials.])
 AC_SUBST(minimum_lifetime)
 
+dnl
+dnl Plugins
+dnl
+KA_PLUGINS_DIR="$libdir/krb5-auth-dialog/plugins"
+AC_SUBST(KA_PLUGINS_DIR)
+
+dnl Final stage
 AC_OUTPUT([
 Makefile
 krb5-auth-dialog.spec
diff --git a/src/Makefile.am b/src/Makefile.am
index 4f921ab..f46583a 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -38,6 +38,10 @@ krb5_auth_dialog_SOURCES =	\
 	krb5-auth-tools.h	\
 	krb5-auth-tickets.c	\
 	krb5-auth-tickets.h	\
+	ka-plugin.c		\
+	ka-plugin.h		\
+	ka-plugin-loader.c	\
+	ka-plugin-loader.h	\
 	ka-closures.h		\
 	ka-closures.c		\
 	dummy-strings.c		\
@@ -50,10 +54,12 @@ krb5_auth_dialog_CPPFLAGS = \
 	-DDATA_DIR=\""$(datadir)"\" \
 	-DLOCALE_DIR=\""$(localedir)/"\" \
 	-DBIN_DIR=\""$(bindir)/"\" \
+	-DKA_PLUGINS_DIR=\""$(KA_PLUGINS_DIR)"\" \
 	$(AM_CPPFLAGS) \
 	$(NULL)
 
 krb5_auth_dialog_CFLAGS = \
+	$(GMODULE_CFLAGS) \
 	$(GTK_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	$(GCONF_CFLAGS) \
@@ -74,6 +80,7 @@ krb5_auth_dialog_LDADD = \
 	$(DBUS_LIBS) \
 	$(GCONF_LIBS) \
 	$(GIO_LIBS) \
+	$(GMODULE_LIBS) \
 	$(GTK_LIBS) \
 	$(NULL)
 
diff --git a/src/ka-plugin-loader.c b/src/ka-plugin-loader.c
new file mode 100644
index 0000000..a56595e
--- /dev/null
+++ b/src/ka-plugin-loader.c
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2010 Guido Guenther <agx sigxcpu org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ka-plugin-loader.h"
+#include "ka-plugin.h"
+
+#include <gmodule.h>
+
+G_DEFINE_TYPE (KaPluginLoader, ka_plugin_loader, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), KA_TYPE_PLUGIN_LOADER, KaPluginLoaderPrivate))
+
+typedef struct _KaPluginLoaderPrivate KaPluginLoaderPrivate;
+
+struct _KaPluginLoaderPrivate {
+	KaApplet *applet;
+};
+
+
+static KaPlugin*
+load_plugin (KaPluginLoader *self, const char *path)
+{
+	KaPlugin *plugin = NULL;
+	KaPluginLoaderPrivate *priv = GET_PRIVATE (self);
+	GModule *module;
+	KaPluginCreateFunc plugin_create_func;
+	int *major_plugin_version, *minor_plugin_version;
+
+	module = g_module_open (path, G_MODULE_BIND_LAZY);
+	if (!module) {
+		g_warning ("Could not load plugin %s: %s", path, g_module_error ());
+		return NULL;
+	}
+
+	if (!g_module_symbol (module, "ka_plugin_major_version",(gpointer *) &major_plugin_version)) {
+		g_warning ("Could not load plugin %s: Missing major version info", path);
+		goto out;
+	}
+
+	if (*major_plugin_version != KA_PLUGIN_MAJOR_VERSION) {
+		g_warning ("Could not load plugin %s: Plugin major version %d, %d is required",
+				   path, *major_plugin_version, KA_PLUGIN_MAJOR_VERSION);
+		goto out;
+	}
+
+	if (!g_module_symbol (module, "ka_plugin_minor_version", (gpointer *) &minor_plugin_version)) {
+		g_warning ("Could not load plugin %s: Missing minor version info", path);
+		goto out;
+	}
+
+	if (*minor_plugin_version != KA_PLUGIN_MINOR_VERSION) {
+		g_warning ("Could not load plugin %s: Plugin minor version %d, %d is required",
+				   path, *minor_plugin_version, KA_PLUGIN_MINOR_VERSION);
+		goto out;
+	}
+
+	if (!g_module_symbol (module, "ka_plugin_create", (gpointer *) &plugin_create_func)) {
+		g_warning ("Could not load plugin %s: %s", path, g_module_error ());
+		goto out;
+	}
+
+	plugin = (*plugin_create_func) ();
+	if (plugin) {
+		g_object_weak_ref (G_OBJECT (plugin), (GWeakNotify) g_module_close, module);
+		g_message ("Loaded plugin %s", ka_plugin_get_name (plugin));
+	} else
+		g_warning ("Could not load plugin %s: initialization failed", path);
+
+	ka_plugin_activate(plugin, priv->applet);
+
+out:
+	if (!plugin)
+		g_module_close (module);
+
+	return plugin;
+}
+
+
+static void
+load_plugins (KaPluginLoader *self)
+{
+	GDir *dir;
+	const char *fname;
+
+	if (!g_module_supported ()) {
+		g_warning ("GModules are not supported on your platform!");
+		return;
+	}
+
+	dir = g_dir_open (KA_PLUGINS_DIR, 0, NULL);
+	if (!dir) {
+		g_warning ("No plugins found");
+		return;
+	}
+
+	while ((fname = g_dir_read_name (dir)) != NULL) {
+		char *path;
+		KaPlugin *plugin;
+
+		if (!g_str_has_suffix (fname, G_MODULE_SUFFIX))
+			continue;
+
+		path = g_module_build_path (KA_PLUGINS_DIR, fname);
+		plugin = load_plugin (self, path);
+		g_free (path);
+	}
+	g_dir_close (dir);
+}
+
+
+static void
+ka_plugin_loader_class_init (KaPluginLoaderClass *klass)
+{
+	g_type_class_add_private (klass, sizeof (KaPluginLoaderPrivate));
+
+}
+
+
+static void
+ka_plugin_loader_init (KaPluginLoader *self G_GNUC_UNUSED)
+{
+}
+
+
+static KaPluginLoader*
+ka_plugin_loader_new (void)
+{
+	return g_object_new (KA_TYPE_PLUGIN_LOADER, NULL);
+}
+
+
+KaPluginLoader*
+ka_plugin_loader_create (KaApplet* applet)
+{
+	KaPluginLoader *loader;
+	KaPluginLoaderPrivate *priv ;
+
+	loader = ka_plugin_loader_new();
+	priv = GET_PRIVATE (loader);
+	priv->applet = applet;
+
+	load_plugins (loader);
+
+	return loader;
+}
diff --git a/src/ka-plugin-loader.h b/src/ka-plugin-loader.h
new file mode 100644
index 0000000..6f0560a
--- /dev/null
+++ b/src/ka-plugin-loader.h
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2010 Guido Guenther <agx sigxcpu org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KA_PLUGIN_LOADER
+#define _KA_PLUGIN_LOADER
+
+#include <glib-object.h>
+#include "ka-applet.h"
+
+G_BEGIN_DECLS
+
+#define KA_TYPE_PLUGIN_LOADER ka_plugin_loader_get_type()
+
+#define KA_PLUGIN_LOADER(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), KA_TYPE_PLUGIN_LOADER, KaPluginLoader))
+
+#define KA_PLUGIN_LOADER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), KA_TYPE_PLUGIN_LOADER, KaPluginLoaderClass))
+
+#define KA_IS_PLUGIN_LOADER(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KA_TYPE_PLUGIN_LOADER))
+
+#define KA_IS_PLUGIN_LOADER_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), KA_TYPE_PLUGIN_LOADER))
+
+#define KA_PLUGIN_LOADER_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), KA_TYPE_PLUGIN_LOADER, KaPluginLoaderClass))
+
+typedef struct {
+  GObject parent;
+} KaPluginLoader;
+
+typedef struct {
+  GObjectClass parent_class;
+} KaPluginLoaderClass;
+
+GType ka_plugin_loader_get_type (void);
+
+KaPluginLoader* ka_plugin_loader_create (KaApplet *applet);
+
+G_END_DECLS
+
+#endif /* _KA_PLUGIN_LOADER */
diff --git a/src/ka-plugin.c b/src/ka-plugin.c
new file mode 100644
index 0000000..88fec34
--- /dev/null
+++ b/src/ka-plugin.c
@@ -0,0 +1,133 @@
+/*
+ * Copyright (C) 2010 Guido Guenther <agx sigxcpu org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#include "ka-plugin.h"
+
+G_DEFINE_TYPE (KaPlugin, ka_plugin, G_TYPE_OBJECT)
+
+#define GET_PRIVATE(o) \
+  (G_TYPE_INSTANCE_GET_PRIVATE ((o), KA_TYPE_PLUGIN, KaPluginPrivate))
+
+enum {
+	PROP_0,
+	PROP_NAME,
+	LAST_PROP
+};
+
+typedef struct _KaPluginPrivate KaPluginPrivate;
+struct _KaPluginPrivate {
+	char *name;
+};
+
+const char*
+ka_plugin_get_name (KaPlugin *self)
+{
+	g_return_val_if_fail (KA_IS_PLUGIN (self), NULL);
+	KaPluginPrivate *priv = GET_PRIVATE (self);
+
+	return priv->name;
+}
+
+
+static void
+set_property (GObject *object, guint prop_id,
+              const GValue *value, GParamSpec *pspec)
+{
+	KaPluginPrivate *priv = GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_NAME:
+		/* construct only */
+		priv->name = g_value_dup_string (value);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+
+static void
+get_property (GObject *object, guint prop_id,
+              GValue *value, GParamSpec *pspec)
+{
+	KaPluginPrivate *priv = GET_PRIVATE (object);
+
+	switch (prop_id) {
+	case PROP_NAME:
+		g_value_set_string (value, priv->name);
+		break;
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+		break;
+	}
+}
+
+
+static void
+finalize (GObject *object)
+{
+	KaPluginPrivate *priv = GET_PRIVATE (object);
+
+	g_free (priv->name);
+}
+
+
+void
+ka_plugin_activate (KaPlugin *self, KaApplet *applet)
+{
+        g_return_if_fail (KA_IS_PLUGIN (self));
+
+        KA_PLUGIN_GET_CLASS (self)->activate (self, applet);
+}
+
+
+void
+ka_plugin_deactivate (KaPlugin *self, KaApplet *applet)
+{
+        g_return_if_fail (KA_IS_PLUGIN (self));
+
+        KA_PLUGIN_GET_CLASS (self)->deactivate (self, applet);
+}
+
+
+static void
+ka_plugin_class_init (KaPluginClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (KaPluginPrivate));
+
+	object_class->get_property = get_property;
+	object_class->set_property = set_property;
+	object_class->finalize = finalize;
+
+	g_object_class_install_property
+			(object_class, PROP_NAME,
+			g_param_spec_string (KA_PLUGIN_PROP_NAME,
+			"Name",
+			"Plugin Name",
+			NULL,
+			G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+}
+
+
+static void
+ka_plugin_init (KaPlugin *self G_GNUC_UNUSED)
+{
+}
diff --git a/src/ka-plugin.h b/src/ka-plugin.h
new file mode 100644
index 0000000..ead9b96
--- /dev/null
+++ b/src/ka-plugin.h
@@ -0,0 +1,75 @@
+/*
+ * Copyright (C) 2010 Guido Guenther <agx sigxcpu org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2, or (at your option)
+ * any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ */
+
+#ifndef _KA_PLUGIN
+#define _KA_PLUGIN
+
+#include <glib-object.h>
+#include "ka-applet.h"
+
+G_BEGIN_DECLS
+
+#define KA_PLUGIN_MAJOR_VERSION 0
+#define KA_PLUGIN_MINOR_VERSION 0
+
+#define KA_TYPE_PLUGIN ka_plugin_get_type()
+
+#define KA_PLUGIN(obj) \
+  (G_TYPE_CHECK_INSTANCE_CAST ((obj), KA_TYPE_PLUGIN, KaPlugin))
+
+#define KA_PLUGIN_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_CAST ((klass), KA_TYPE_PLUGIN, KaPluginClass))
+
+#define KA_IS_PLUGIN(obj) \
+  (G_TYPE_CHECK_INSTANCE_TYPE ((obj), KA_TYPE_PLUGIN))
+
+#define KA_IS_PLUGIN_CLASS(klass) \
+  (G_TYPE_CHECK_CLASS_TYPE ((klass), KA_TYPE_PLUGIN))
+
+#define KA_PLUGIN_GET_CLASS(obj) \
+  (G_TYPE_INSTANCE_GET_CLASS ((obj), KA_TYPE_PLUGIN, KaPluginClass))
+
+#define KA_PLUGIN_PROP_NAME "name"
+
+typedef struct {
+  GObject parent;
+} KaPlugin;
+
+typedef struct {
+  GObjectClass parent_class;
+
+  void (*activate)   (KaPlugin *self, KaApplet* applet);
+  void (*deactivate) (KaPlugin *self, KaApplet* applet);
+
+  /* we'll add functions for prefs handling later */
+  void (*dummy1) (KaPlugin *self, KaApplet* applet);
+  void (*dummy2) (KaPlugin *self, KaApplet* applet);
+} KaPluginClass;
+
+GType ka_plugin_get_type (void);
+
+KaPlugin* ka_plugin_new (void);
+
+typedef KaPlugin *(*KaPluginCreateFunc) (void);
+const char* ka_plugin_get_name (KaPlugin *self);
+void ka_plugin_activate (KaPlugin *self, KaApplet *applet);
+void ka_plugin_deactivate (KaPlugin *self, KaApplet *applet);
+
+G_END_DECLS
+
+#endif /* _KA_PLUGIN */
diff --git a/src/krb5-auth-applet.c b/src/krb5-auth-applet.c
index 30fa77e..e9bd534 100644
--- a/src/krb5-auth-applet.c
+++ b/src/krb5-auth-applet.c
@@ -28,6 +28,7 @@
 #include "krb5-auth-gconf.h"
 #include "krb5-auth-tools.h"
 #include "krb5-auth-tickets.h"
+#include "ka-plugin-loader.h"
 #include "ka-closures.h"
 #ifdef HAVE_LIBNOTIFY
 #include <libnotify/notify.h>
@@ -78,6 +79,7 @@ struct _KaAppletPrivate
 
 	KaPwDialog *pwdialog;		/* the password dialog */
 	int	   pw_prompt_secs;	/* when to start prompting for a password */
+	KaPluginLoader *loader;		/* Plugin loader */
 
 #ifdef HAVE_LIBNOTIFY
 	NotifyNotification* notification;/* notification messages */
@@ -220,6 +222,10 @@ ka_applet_dispose(GObject* object)
 		g_object_unref(applet->priv->uixml);
 		applet->priv->uixml = NULL;
 	}
+	if (applet->priv->loader) {
+		g_object_unref(applet->priv->loader);
+		applet->priv->loader = NULL;
+	}
 
 	if (parent_class->dispose != NULL)
 		parent_class->dispose (object);
@@ -928,7 +934,9 @@ ka_applet_create()
 	applet->priv->gconf = ka_gconf_init (applet);
 	g_return_val_if_fail (applet->priv->gconf != NULL, NULL);
 
-	ka_tickets_dialog_create(applet->priv->uixml);
+	ka_tickets_dialog_create (applet->priv->uixml);
+	applet->priv->loader = ka_plugin_loader_create (applet);
+	g_return_val_if_fail (applet->priv->loader != NULL, NULL);
 
 	return applet;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]