[libgda] Use Gnome Keyring if available to store DSN's authentification
- From: Vivien Malerba <vivien src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [libgda] Use Gnome Keyring if available to store DSN's authentification
- Date: Wed, 14 Jul 2010 15:13:23 +0000 (UTC)
commit 83010e35e673b14fd7d91b6811e0b93b1ab110ad
Author: Vivien Malerba <malerba gnome-db org>
Date: Wed Jul 14 16:35:24 2010 +0200
Use Gnome Keyring if available to store DSN's authentification
if it is found, this disables saving authentification information
in the config file
configure.ac | 26 ++++++-
libgda/Makefile.am | 4 +-
libgda/gda-config.c | 216 +++++++++++++++++++++++++++++++++++++++++++++------
3 files changed, 220 insertions(+), 26 deletions(-)
---
diff --git a/configure.ac b/configure.ac
index f7577dd..5c60ff2 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1632,7 +1632,7 @@ AC_ARG_WITH(libsoup,
if test "$with_libsoup" = "auto" -o "$with_libsoup" = "yes"
then
PKG_CHECK_MODULES(LIBSOUP, libsoup-2.4, [
- AC_DEFINE(HAVE_LIBSOUP, [1], [libsoup support enable])
+ AC_DEFINE(HAVE_LIBSOUP, [1], [libsoup support enabled])
have_libsoup=yes], [
if test "$with_libsoup" = "yes"
then
@@ -1645,6 +1645,30 @@ AC_SUBST(LIBSOUP_CFLAGS)
AC_SUBST(LIBSOUP_LIBS)
+dnl ************************
+dnl Check for gnome-keyring
+dnl ************************
+
+AC_ARG_WITH(gnome-keyring,
+ AS_HELP_STRING([--with-gnome-keyring], [Enable gnome-keyring support]),
+ ,with_gnome_keyring=auto)
+
+if test "$with_gnome_keyring" = "auto" -o "$with_gnome_keyring" = "yes"
+then
+ PKG_CHECK_MODULES(GNOME_KEYRING, gnome-keyring-1, [
+ AC_DEFINE(HAVE_GNOME_KEYRING, [1], [gnome-keyring support enabled])
+ have_gnome_keyring=yes], [
+ if test "$with_gnome_keyring" = "yes"
+ then
+ AC_MSG_ERROR([gnome-keyring support requested but not found.])
+ fi
+ have_gnome_keyring=no])
+fi
+AM_CONDITIONAL(GNOME_KEYRING, test "$have_gnome_keyring" = "yes")
+AC_SUBST(GNOME_KEYRING_CFLAGS)
+AC_SUBST(GNOME_KEYRING_LIBS)
+
+
dnl **************************
dnl Check for readline/history
dnl **************************
diff --git a/libgda/Makefile.am b/libgda/Makefile.am
index 1563260..dba8d60 100644
--- a/libgda/Makefile.am
+++ b/libgda/Makefile.am
@@ -20,7 +20,7 @@ AM_CPPFLAGS = \
$(FAM_CFLAGS) \
$(BDB_CFLAGS) \
-DBDB_LIB=\""$(BDB_LIB)"\" \
- $(GIO_CFLAGS) $(GNOMEVFS_CFLAGS)
+ $(GIO_CFLAGS) $(GNOMEVFS_CFLAGS) $(GNOME_KEYRING_CFLAGS)
_gda_marshal_built_files = gda-marshal.h gda-marshal.c
@@ -226,7 +226,7 @@ libgda_4_0_la_LIBADD = \
sqlite/libgda-sqlite.la \
thread-wrapper/libgda_threadwrapper-4.0.la \
$(LIBGDA_LIBS) $(FAM_LIBS) \
- $(GIO_LIBS) $(GNOMEVFS_LIBS)
+ $(GIO_LIBS) $(GNOMEVFS_LIBS) $(GNOME_KEYRING_LIBS)
if PLATFORM_WIN32
libgda_4_0_la_LDFLAGS += -export-symbols $(builddir)/libgda.def
diff --git a/libgda/gda-config.c b/libgda/gda-config.c
index a19cb1a..a89fd8b 100644
--- a/libgda/gda-config.c
+++ b/libgda/gda-config.c
@@ -54,6 +54,10 @@
#include <io.h>
#endif
+#ifdef HAVE_GNOME_KEYRING
+#include <gnome-keyring.h>
+#endif
+
typedef struct {
GdaProviderInfo pinfo;
GModule *handle;
@@ -67,6 +71,8 @@ struct _GdaConfigPrivate {
GSList *dsn_list; /* list of GdaDsnInfo structures */
GSList *prov_list; /* list of InternalProvider structures */
gboolean providers_loaded; /* TRUE if providers list has already been scanned */
+
+ gboolean emit_signals;
};
static void gda_config_class_init (GdaConfigClass *klass);
@@ -258,8 +264,30 @@ gda_config_init (GdaConfig *conf, GdaConfigClass *klass)
conf->priv->prov_list = NULL;
conf->priv->dsn_list = NULL;
conf->priv->providers_loaded = FALSE;
+ conf->priv->emit_signals = TRUE;
}
+#ifdef HAVE_GNOME_KEYRING
+static void
+password_found (GnomeKeyringResult res, const gchar *password, const gchar *dsnname)
+{
+ if (res == GNOME_KEYRING_RESULT_OK) {
+ GdaDsnInfo *dsn;
+ dsn = gda_config_get_dsn_info (dsnname);
+ if (dsn) {
+ if (dsn->auth_string && password && !strcmp (dsn->auth_string, password))
+ return;
+
+ g_free (dsn->auth_string);
+ dsn->auth_string = g_strdup (password);
+ }
+ /*g_print ("Loaded auth info for '%s'\n", dsnname);*/
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals [DSN_CHANGED], 0, dsn);
+ }
+}
+#endif
+
static void
load_config_file (const gchar *file, gboolean is_system)
{
@@ -361,14 +389,23 @@ load_config_file (const gchar *file, gboolean is_system)
g_free (username);
g_free (password);
+#ifdef HAVE_GNOME_KEYRING
+ if (! is_system) {
+ gchar *tmp = g_strdup (info->name);
+ gnome_keyring_find_password (GNOME_KEYRING_NETWORK_PASSWORD,
+ (GnomeKeyringOperationGetStringCallback) password_found, tmp, g_free,
+ "server", tmp, NULL);
+ }
+#endif
/* signals */
if (is_new) {
unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, info,
(GCompareFunc) data_source_info_compare);
- g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, info);
}
- else
+ else if (unique_instance->priv->emit_signals)
g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, info);
}
}
@@ -417,11 +454,15 @@ save_config_file (gboolean is_system)
xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->cnc_string));
- /* auth */
- entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
- xmlSetProp (entry, BAD_CAST "name", BAD_CAST "Auth");
- xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
- xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->auth_string));
+#ifndef HAVE_GNOME_KEYRING
+ if (! is_system) {
+ /* auth */
+ entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
+ xmlSetProp (entry, BAD_CAST "name", BAD_CAST "Auth");
+ xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
+ xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->auth_string));
+ }
+#endif
/* description */
entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
@@ -848,6 +889,17 @@ gda_config_get_dsn_info (const gchar *dsn_name)
return NULL;
}
+#ifdef HAVE_GNOME_KEYRING
+static void
+password_stored_cb (GnomeKeyringResult res, const gchar *dsnname)
+{
+ /* user_data will be the same as was passed to gnome_keyring_store_password() */
+ if (res != GNOME_KEYRING_RESULT_OK)
+ g_warning (_("Couldn't save authentification information for DSN '%s': %s"), dsnname,
+ gnome_keyring_result_to_message (res));
+}
+#endif
+
/**
* gda_config_define_dsn:
* @info: a pointer to a filled GdaDsnInfo structure
@@ -902,7 +954,8 @@ gda_config_define_dsn (const GdaDsnInfo *info, GError **error)
save_user = TRUE;
einfo->is_system = info->is_system ? TRUE : FALSE;
}
- g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, einfo);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, einfo);
}
else {
einfo = g_new0 (GdaDsnInfo, 1);
@@ -919,8 +972,24 @@ gda_config_define_dsn (const GdaDsnInfo *info, GError **error)
unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, einfo,
(GCompareFunc) data_source_info_compare);
- g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, einfo);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, einfo);
}
+
+#ifdef HAVE_GNOME_KEYRING
+ if (! info->is_system) {
+ /* save to keyring */
+ gchar *tmp, *tmp1;
+ tmp = g_strdup_printf (_("Authentification for the '%s' DSN"), info->name);
+ tmp1 = g_strdup (info->name);
+ gnome_keyring_store_password (GNOME_KEYRING_NETWORK_PASSWORD,
+ GNOME_KEYRING_DEFAULT,
+ tmp, info->auth_string,
+ (GnomeKeyringOperationDoneCallback) password_stored_cb, tmp1, g_free,
+ "server", info->name, NULL);
+ g_free (tmp);
+ }
+#endif
if (save_system)
save_config_file (TRUE);
@@ -931,6 +1000,16 @@ gda_config_define_dsn (const GdaDsnInfo *info, GError **error)
return TRUE;
}
+#ifdef HAVE_GNOME_KEYRING
+static void
+password_deleted_cb (GnomeKeyringResult res, const gchar *dsnname)
+{
+ if (res != GNOME_KEYRING_RESULT_OK)
+ g_warning (_("Couldn't delete authentication information for DSN '%s': %s"), dsnname,
+ gnome_keyring_result_to_message (res));
+}
+#endif
+
/**
* gda_config_remove_dsn:
* @dsn_name: the name of the DSN to remove
@@ -972,11 +1051,24 @@ gda_config_remove_dsn (const gchar *dsn_name, GError **error)
else
save_user = TRUE;
- g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
- g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
data_source_info_free (info);
-
+
+#ifdef HAVE_GNOME_KEYRING
+ if (! info->is_system) {
+ /* remove from keyring */
+ gchar *tmp;
+ tmp = g_strdup (dsn_name);
+ gnome_keyring_delete_password (GNOME_KEYRING_NETWORK_PASSWORD,
+ (GnomeKeyringOperationDoneCallback) password_deleted_cb, tmp, g_free,
+ "server", tmp, NULL);
+ }
+#endif
+
if (save_system)
save_config_file (TRUE);
if (save_user)
@@ -1643,38 +1735,114 @@ internal_provider_free (InternalProvider *ip)
* File monitoring actions
*/
#ifdef HAVE_GIO
+
+static gboolean
+str_equal (const gchar *str1, const gchar *str2)
+{
+ if (str1 && str2) {
+ if (!strcmp (str1, str2))
+ return TRUE;
+ else
+ return FALSE;
+ }
+ else if (!str1 && !str2)
+ return TRUE;
+ return FALSE;
+}
+
static void
conf_file_changed (GFileMonitor *mon, GFile *file, GFile *other_file,
GFileMonitorEvent event_type, gpointer data)
{
+ GSList *list, *current_dsn_list, *new_dsn_list;
g_assert (unique_instance);
if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
return;
+ GDA_CONFIG_LOCK ();
#ifdef GDA_DEBUG_NO
gboolean is_system = (mon == mon_conf_global) ? TRUE : FALSE;
g_print ("Reloading config files (%s config has changed)\n", is_system ? "global" : "user");
- GSList *list;
for (list = unique_instance->priv->dsn_list; list; list = list->next) {
GdaDsnInfo *info = (GdaDsnInfo *) list->data;
g_print ("[info %p]: %s/%s\n", info, info->provider, info->name);
}
#endif
- while (unique_instance->priv->dsn_list) {
- GdaDsnInfo *info = (GdaDsnInfo *) unique_instance->priv->dsn_list->data;
- g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
- unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
- g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
- data_source_info_free (info);
- }
-
+ current_dsn_list = unique_instance->priv->dsn_list;
+ unique_instance->priv->dsn_list = NULL;
+
+ unique_instance->priv->emit_signals = FALSE;
lock_notify_changes ();
if (unique_instance->priv->system_file)
load_config_file (unique_instance->priv->system_file, TRUE);
if (unique_instance->priv->user_file)
load_config_file (unique_instance->priv->user_file, FALSE);
unlock_notify_changes ();
+ unique_instance->priv->emit_signals = TRUE;
+
+ new_dsn_list = unique_instance->priv->dsn_list;
+ unique_instance->priv->dsn_list = current_dsn_list;
+ current_dsn_list = NULL;
+
+ /* handle new or updated DSN */
+ GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
+ for (list = new_dsn_list; list; list = list->next) {
+ GdaDsnInfo *ninfo, *oinfo;
+ ninfo = (GdaDsnInfo *) list->data;
+ oinfo = gda_config_get_dsn_info (ninfo->name);
+ if (!oinfo) {
+ /* add ninfo */
+ unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, ninfo,
+ (GCompareFunc) data_source_info_compare);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, ninfo);
+ g_hash_table_insert (hash, ninfo->name, (gpointer) 0x1);
+ }
+ else {
+ /* signal changed if updated */
+ if (str_equal (oinfo->provider, ninfo->provider) &&
+ str_equal (oinfo->description, ninfo->description) &&
+ str_equal (oinfo->cnc_string, ninfo->cnc_string) &&
+#ifndef HAVE_GNOME_KEYRING
+ str_equal (oinfo->auth_string, ninfo->auth_string) &&
+#endif
+ (oinfo->is_system == ninfo->is_system)) {
+ /* no change for this DSN */
+ data_source_info_free (ninfo);
+ }
+ else {
+ GdaDsnInfo tmp;
+ tmp = *oinfo;
+ *oinfo = *ninfo;
+ *ninfo = tmp;
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, oinfo);
+ data_source_info_free (ninfo);
+ }
+ g_hash_table_insert (hash, oinfo->name, (gpointer) 0x1);
+ }
+ }
+ g_slist_free (new_dsn_list);
+
+ /* remove old DSN */
+ for (list = unique_instance->priv->dsn_list; list; ) {
+ GdaDsnInfo *info;
+ info = (GdaDsnInfo *) list->data;
+ list = list->next;
+ if (g_hash_table_lookup (hash, info->name))
+ continue;
+
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
+ unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
+ data_source_info_free (info);
+ }
+ g_hash_table_destroy (hash);
+
+ GDA_CONFIG_UNLOCK ();
}
static void
@@ -1752,9 +1920,11 @@ fam_callback (GIOChannel *source, GIOCondition condition, gpointer data)
#endif
while (unique_instance->priv->dsn_list) {
GdaDsnInfo *info = (GdaDsnInfo *) unique_instance->priv->dsn_list->data;
- g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
- g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
+ if (unique_instance->priv->emit_signals)
+ g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
data_source_info_free (info);
}
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]