1 /*
2 * Copyright (C) 2000 Akira Tagoh <tagoh@src.gnome.org>
3 * Copyright (C) 2000 Reinhard Müller <reinhard@src.gnome.org>
4 * Copyright (C) 2000 - 2005 Rodrigo Moya <rodrigo@gnome-db.org>
5 * Copyright (C) 2001 - 2013 Vivien Malerba <malerba@gnome-db.org>
6 * Copyright (C) 2002 - 2003 Gonzalo Paniagua Javier <gonzalo@gnome-db.org>
7 * Copyright (C) 2002 Zbigniew Chyla <cyba@gnome.pl>
8 * Copyright (C) 2003 Akira TAGOH <tagoh@gnome-db.org>
9 * Copyright (C) 2003 - 2004 Laurent Sansonetti <lrz@gnome.org>
10 * Copyright (C) 2003 - 2010 Murray Cumming <murrayc@murrayc.com>
11 * Copyright (C) 2004 Alan Knowles <alank@src.gnome.org>
12 * Copyright (C) 2004 Dani Baeyens <daniel.baeyens@hispalinux.es>
13 * Copyright (C) 2005 Stanislav Brabec <sbrabec@suse.de>
14 * Copyright (C) 2008 Przemysław Grzegorczyk <pgrzegorczyk@gmail.com>
15 * Copyright (C) 2009 Bas Driessen <bas.driessen@xobas.com>
16 * Copyright (C) 2010 David King <davidk@openismus.com>
17 * Copyright (C) 2010 Jonh Wendell <jwendell@gnome.org>
18 *
19 * This library is free software; you can redistribute it and/or
20 * modify it under the terms of the GNU Lesser General Public
21 * License as published by the Free Software Foundation; either
22 * version 2 of the License, or (at your option) any later version.
23 *
24 * This library is distributed in the hope that it will be useful,
25 * but WITHOUT ANY WARRANTY; without even the implied warranty of
26 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
27 * Lesser General Public License for more details.
28 *
29 * You should have received a copy of the GNU Lesser General Public
30 * License along with this library; if not, write to the
31 * Free Software Foundation, Inc., 51 Franklin St, Fifth Floor,
32 * Boston, MA 02110-1301, USA.
33 */
34
35 #include <unistd.h>
36 #include <stdio.h>
37 #include <gmodule.h>
38 #include <libgda/gda-config.h>
39 #include <glib/gi18n-lib.h>
40 #include <glib/gstdio.h>
41 #include "gda-marshal.h"
42 #include <string.h>
43 #include <libgda/binreloc/gda-binreloc.h>
44 #include <libgda/gda-data-model-array.h>
45 #include <libgda/gda-data-model-dsn-list.h>
46 #include <libgda/gda-set.h>
47 #include <libgda/gda-holder.h>
48 #include <libgda/gda-log.h>
49 #include <libgda/gda-util.h>
50 #include <libgda/sqlite/gda-sqlite-provider.h>
51
52 #ifdef HAVE_GIO
53 #include <gio/gio.h>
54 #else
55 #endif
56 #ifdef G_OS_WIN32
57 #include <io.h>
58 #endif
59
60 #ifdef HAVE_LIBSECRET
61 #include <libsecret/secret.h>
62 #else
63 #ifdef HAVE_GNOME_KEYRING
64 #include <gnome-keyring.h>
65 #endif
66 #endif
67
68 /*
69 Register GdaDsnInfo type
70 */
71 GType
gda_dsn_info_get_type(void)72 gda_dsn_info_get_type (void)
73 {
74 static GType type = 0;
75
76 if (G_UNLIKELY (type == 0)) {
77 if (type == 0)
78 type = g_boxed_type_register_static ("GdaDsnInfo",
79 (GBoxedCopyFunc) gda_dsn_info_copy,
80 (GBoxedFreeFunc) gda_dsn_info_free);
81 }
82
83 return type;
84 }
85
86 /**
87 * gda_dsn_info_new:
88 *
89 * Creates a new #GdaDsnInfo struct.
90 *
91 * Returns: (transfer full): a new #GdaDsnInfo struct.
92 *
93 * Since: 5.2
94 */
95 GdaDsnInfo*
gda_dsn_info_new(void)96 gda_dsn_info_new (void)
97 {
98 GdaDsnInfo *dsn = g_new0 (GdaDsnInfo, 1);
99 dsn->name = NULL;
100 dsn->provider = NULL;
101 dsn->description = NULL;
102 dsn->cnc_string = NULL;
103 dsn->auth_string = NULL;
104 dsn->is_system = FALSE;
105 return dsn;
106 }
107
108 /**
109 * gda_dsn_info_copy:
110 * @source: a #GdaDsnInfo to copy from
111 *
112 * Copy constructor.
113 *
114 * Returns: (transfer full): a new #GdaDsnInfo
115 *
116 * Since: 5.2
117 */
118 GdaDsnInfo *
gda_dsn_info_copy(GdaDsnInfo * source)119 gda_dsn_info_copy (GdaDsnInfo *source)
120 {
121 GdaDsnInfo *n;
122 g_return_val_if_fail (source, NULL);
123 n = gda_dsn_info_new ();
124 n->name = source->name;
125 n->provider = source->provider;
126 n->description = source->description;
127 n->cnc_string = source->cnc_string;
128 n->auth_string = source->auth_string;
129 n->is_system = source->is_system;;
130 return n;
131 }
132
133 /**
134 * gda_dsn_info_free:
135 * @dsn: (allow-none): a #GdaDsnInfo struct to free
136 *
137 * Frees any resources taken by @dsn struct. If @dsn is %NULL, then nothing happens.
138 *
139 * Since: 5.2
140 */
141 void
gda_dsn_info_free(GdaDsnInfo * dsn)142 gda_dsn_info_free (GdaDsnInfo *dsn)
143 {
144 g_return_if_fail(dsn);
145 g_free (dsn);
146 }
147
148
149 typedef struct {
150 GdaProviderInfo pinfo;
151 GModule *handle;
152 GdaServerProvider *instance;
153 } InternalProvider;
154
155 struct _GdaConfigPrivate {
156 gchar *user_file;
157 gchar *system_file;
158 gboolean system_config_allowed;
159 GSList *dsn_list; /* list of GdaDsnInfo structures */
160 GSList *prov_list; /* list of InternalProvider structures */
161 gboolean providers_loaded; /* TRUE if providers list has already been scanned */
162
163 gboolean emit_signals;
164 };
165
166 static void gda_config_class_init (GdaConfigClass *klass);
167 static GObject *gda_config_constructor (GType type,
168 guint n_construct_properties,
169 GObjectConstructParam *construct_properties);
170 static void gda_config_init (GdaConfig *conf, GdaConfigClass *klass);
171 static void gda_config_dispose (GObject *object);
172 static void gda_config_set_property (GObject *object,
173 guint param_id,
174 const GValue *value,
175 GParamSpec *pspec);
176 static void gda_config_get_property (GObject *object,
177 guint param_id,
178 GValue *value,
179 GParamSpec *pspec);
180 static GdaConfig *unique_instance = NULL;
181 #ifdef HAVE_LIBSECRET
182 static gboolean sync_keyring = FALSE;
183 #else
184 #ifdef HAVE_GNOME_KEYRING
185 static gboolean sync_keyring = FALSE;
186 #endif
187 #endif
188
189 static gint data_source_info_compare (GdaDsnInfo *infoa, GdaDsnInfo *infob);
190 static void data_source_info_free (GdaDsnInfo *info);
191 static void internal_provider_free (InternalProvider *ip);
192 static void load_config_file (const gchar *file, gboolean is_system);
193 static void save_config_file (gboolean is_system);
194 static void load_all_providers (void);
195 static void reload_dsn_configuration (void);
196
197
198 enum {
199 DSN_ADDED,
200 DSN_TO_BE_REMOVED,
201 DSN_REMOVED,
202 DSN_CHANGED,
203 LAST_SIGNAL
204 };
205
206 static gint gda_config_signals[LAST_SIGNAL] = { 0, 0, 0, 0 };
207
208 /* properties */
209 enum {
210 PROP_0,
211 PROP_USER_FILE,
212 PROP_SYSTEM_FILE
213 };
214
215 static GObjectClass *parent_class = NULL;
216
217 #ifdef HAVE_GIO
218 /*
219 * GIO static variables
220 */
221 static GFileMonitor *mon_conf_user = NULL;
222 static GFileMonitor *mon_conf_global = NULL;
223 gulong user_notify_changes = 0;
224 gulong global_notify_changes = 0;
225
226 static void conf_file_changed (GFileMonitor *mon, GFile *file, GFile *other_file,
227 GFileMonitorEvent event_type, gpointer data);
228 static void lock_notify_changes (void);
229 static void unlock_notify_changes (void);
230 #endif
231
232 static GRecMutex gda_rmutex;
233 #define GDA_CONFIG_LOCK() g_rec_mutex_lock(&gda_rmutex)
234 #define GDA_CONFIG_UNLOCK() g_rec_mutex_unlock(&gda_rmutex)
235
236 /* GdaServerProvider for SQLite as a shortcut, available
237 * even if the SQLite provider is not installed
238 */
239 GdaServerProvider *_gda_config_sqlite_provider = NULL;
240
241 /*
242 * GdaConfig class implementation
243 * @klass:
244 */
245 static void
gda_config_class_init(GdaConfigClass * klass)246 gda_config_class_init (GdaConfigClass *klass)
247 {
248 GObjectClass *object_class = G_OBJECT_CLASS (klass);
249
250 parent_class = g_type_class_peek_parent (klass);
251
252 /**
253 * GdaConfig::dsn-added:
254 * @conf: the #GdaConfig object
255 * @new_dsn: a #GdaDsnInfo
256 *
257 * Gets emitted whenever a new DSN has been defined
258 */
259 gda_config_signals[DSN_ADDED] =
260 g_signal_new ("dsn-added",
261 G_TYPE_FROM_CLASS (object_class),
262 G_SIGNAL_RUN_FIRST,
263 G_STRUCT_OFFSET (GdaConfigClass, dsn_added),
264 NULL, NULL,
265 _gda_marshal_VOID__POINTER,
266 G_TYPE_NONE, 1, G_TYPE_POINTER);
267 /**
268 * GdaConfig::dsn-to-be-removed:
269 * @conf: the #GdaConfig object
270 * @old_dsn: a #GdaDsnInfo
271 *
272 * Gets emitted whenever a DSN is about to be removed
273 */
274 gda_config_signals[DSN_TO_BE_REMOVED] =
275 g_signal_new ("dsn-to-be-removed",
276 G_TYPE_FROM_CLASS (object_class),
277 G_SIGNAL_RUN_FIRST,
278 G_STRUCT_OFFSET (GdaConfigClass, dsn_to_be_removed),
279 NULL, NULL,
280 _gda_marshal_VOID__POINTER,
281 G_TYPE_NONE, 1, G_TYPE_POINTER);
282 /**
283 * GdaConfig::dsn-removed:
284 * @conf: the #GdaConfig object
285 * @old_dsn: a #GdaDsnInfo
286 *
287 * Gets emitted whenever a DSN has been removed
288 */
289 gda_config_signals[DSN_REMOVED] =
290 g_signal_new ("dsn-removed",
291 G_TYPE_FROM_CLASS (object_class),
292 G_SIGNAL_RUN_FIRST,
293 G_STRUCT_OFFSET (GdaConfigClass, dsn_removed),
294 NULL, NULL,
295 _gda_marshal_VOID__POINTER,
296 G_TYPE_NONE, 1, G_TYPE_POINTER);
297 /**
298 * GdaConfig::dsn-changed:
299 * @conf: the #GdaConfig object
300 * @dsn: a #GdaDsnInfo
301 *
302 * Gets emitted whenever a DSN's definition has been changed
303 */
304 gda_config_signals[DSN_CHANGED] =
305 g_signal_new ("dsn-changed",
306 G_TYPE_FROM_CLASS (object_class),
307 G_SIGNAL_RUN_FIRST,
308 G_STRUCT_OFFSET (GdaConfigClass, dsn_changed),
309 NULL, NULL,
310 _gda_marshal_VOID__POINTER,
311 G_TYPE_NONE, 1, G_TYPE_POINTER);
312
313 /* Properties */
314 object_class->set_property = gda_config_set_property;
315 object_class->get_property = gda_config_get_property;
316
317 /**
318 * GdaConfig:user-filename:
319 *
320 * File to use for per-user DSN list. When changed, the whole list of DSN will be reloaded.
321 */
322 /* To translators: DSN stands for Data Source Name, it's a named connection string defined in $XDG_DATA_HOME/libgda/config */
323 g_object_class_install_property (object_class, PROP_USER_FILE,
324 g_param_spec_string ("user-filename", NULL,
325 "File to use for per-user DSN list",
326 NULL,
327 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
328 /**
329 * GdaConfig:system-filename:
330 *
331 * File to use for system-wide DSN list. When changed, the whole list of DSN will be reloaded.
332 */
333 /* To translators: DSN stands for Data Source Name, it's a named connection string defined in $PREFIX/etc/libgda-5.0/config */
334 g_object_class_install_property (object_class, PROP_SYSTEM_FILE,
335 g_param_spec_string ("system-filename", NULL,
336 "File to use for system-wide DSN list",
337 NULL,
338 (G_PARAM_READABLE | G_PARAM_WRITABLE)));
339
340 object_class->constructor = gda_config_constructor;
341 object_class->dispose = gda_config_dispose;
342 }
343
344 static void
gda_config_init(GdaConfig * conf,G_GNUC_UNUSED GdaConfigClass * klass)345 gda_config_init (GdaConfig *conf, G_GNUC_UNUSED GdaConfigClass *klass)
346 {
347 g_return_if_fail (GDA_IS_CONFIG (conf));
348
349 conf->priv = g_new0 (GdaConfigPrivate, 1);
350 conf->priv->user_file = NULL;
351 conf->priv->system_file = NULL;
352 conf->priv->system_config_allowed = FALSE;
353 conf->priv->prov_list = NULL;
354 conf->priv->dsn_list = NULL;
355 conf->priv->providers_loaded = FALSE;
356 conf->priv->emit_signals = TRUE;
357 }
358
359 #ifdef HAVE_LIBSECRET
360 static void
secret_password_found_cb(GObject * source_object,GAsyncResult * res,gchar * dsnname)361 secret_password_found_cb (GObject *source_object, GAsyncResult *res, gchar *dsnname)
362 {
363 gchar *auth;
364 GError *error = NULL;
365 auth = secret_password_lookup_finish (res, &error);
366 if (auth) {
367 GdaDsnInfo *dsn;
368 dsn = gda_config_get_dsn_info (dsnname);
369 if (dsn) {
370 if (dsn->auth_string && auth && !strcmp (dsn->auth_string, auth))
371 return;
372
373 g_free (dsn->auth_string);
374 dsn->auth_string = g_strdup (auth);
375 }
376 /*g_print ("Loaded auth info for '%s'\n", dsnname);*/
377 if (unique_instance->priv->emit_signals)
378 g_signal_emit (unique_instance, gda_config_signals [DSN_CHANGED], 0, dsn);
379 g_free (auth);
380 }
381 else if (error) {
382 gda_log_message (_("Error loading authentication information for '%s' DSN: %s"),
383 dsnname, error->message ? error->message : _("No detail"));
384 g_clear_error (&error);
385 }
386 g_free (dsnname);
387 }
388 #else
389 #ifdef HAVE_GNOME_KEYRING
390 static void
password_found_cb(GnomeKeyringResult res,const gchar * password,const gchar * dsnname)391 password_found_cb (GnomeKeyringResult res, const gchar *password, const gchar *dsnname)
392 {
393 if (res == GNOME_KEYRING_RESULT_OK) {
394 GdaDsnInfo *dsn;
395 dsn = gda_config_get_dsn_info (dsnname);
396 if (dsn) {
397 if (dsn->auth_string && password && !strcmp (dsn->auth_string, password))
398 return;
399
400 g_free (dsn->auth_string);
401 dsn->auth_string = g_strdup (password);
402 }
403 /*g_print ("Loaded auth info for '%s'\n", dsnname);*/
404 if (unique_instance->priv->emit_signals)
405 g_signal_emit (unique_instance, gda_config_signals [DSN_CHANGED], 0, dsn);
406 }
407 else if (res != GNOME_KEYRING_RESULT_NO_MATCH)
408 gda_log_message (_("Error loading authentication information for '%s' DSN: %s"),
409 dsnname, gnome_keyring_result_to_message (res));
410 }
411 #endif
412 #endif
413
414 static void
load_config_file(const gchar * file,gboolean is_system)415 load_config_file (const gchar *file, gboolean is_system)
416 {
417 xmlDocPtr doc;
418 xmlNodePtr root;
419
420 if (!g_file_test (file, G_FILE_TEST_EXISTS))
421 return;
422
423 doc = xmlParseFile (file);
424 if (!doc)
425 return;
426
427 root = xmlDocGetRootElement (doc);
428 if (root) {
429 xmlNodePtr node;
430 for (node = root->children; node; node = node->next) { /* iter over the <section> tags */
431 if (strcmp ((gchar *) node->name, "section"))
432 continue;
433
434 xmlChar *prop;
435 gchar *ptr;
436 GdaDsnInfo *info;
437 gboolean is_new = FALSE;
438 xmlNodePtr entry;
439
440 prop = xmlGetProp (node, BAD_CAST "path");
441 if (!prop)
442 continue;
443 for (ptr = ((gchar *) prop) + strlen ((gchar *) prop) - 1; ptr >= (gchar *) prop; ptr--) {
444 if (*ptr == '/') {
445 ptr++;
446 break;
447 }
448 }
449 info = gda_config_get_dsn_info (ptr);
450 if (!info) {
451 info = g_new0 (GdaDsnInfo, 1);
452 info->name = g_strdup (ptr);
453 is_new = TRUE;
454 }
455 else {
456 g_free (info->provider); info->provider = NULL;
457 g_free (info->cnc_string); info->cnc_string = NULL;
458 g_free (info->description); info->description = NULL;
459 g_free (info->auth_string); info->auth_string = NULL;
460 }
461 info->is_system = is_system;
462 xmlFree (prop);
463
464 gchar *username = NULL, *password = NULL;
465 for (entry = node->children; entry; entry = entry->next) { /* iter over the <entry> tags */
466 xmlChar *value;
467 if (strcmp ((gchar *)entry->name, "entry"))
468 continue;
469 prop = xmlGetProp (entry, BAD_CAST "name");
470 if (!prop)
471 continue;
472 value = xmlGetProp (entry, BAD_CAST "value");
473 if (!value) {
474 xmlFree (prop);
475 continue;
476 }
477 if (!strcmp ((gchar *) prop, "DSN"))
478 info->cnc_string = g_strdup ((gchar *)value);
479 else if (!strcmp ((gchar *) prop, "Provider")) {
480 GdaProviderInfo *pinfo;
481 pinfo = gda_config_get_provider_info ((gchar *)value);
482 if (pinfo)
483 info->provider = g_strdup (pinfo->id);
484 else
485 info->provider = g_strdup ((gchar *)value);
486 }
487 else if (!strcmp ((gchar *) prop, "Description"))
488 info->description = g_strdup ((gchar *)value);
489 if (!strcmp ((gchar *) prop, "Auth"))
490 info->auth_string = g_strdup ((gchar *)value);
491 else if (!strcmp ((gchar *) prop, "Username"))
492 username = g_strdup ((gchar*) value);
493 else if (!strcmp ((gchar *) prop, "Password"))
494 password = g_strdup ((gchar*) value);
495 xmlFree (prop);
496 xmlFree (value);
497 }
498
499 if (username && *username) {
500 if (!info->auth_string) {
501 /* migrate username/password to auth_string */
502 gchar *s1;
503 s1 = gda_rfc1738_encode (username);
504 if (password) {
505 gchar *s2;
506 s2 = gda_rfc1738_encode (password);
507 info->auth_string = g_strdup_printf ("USERNAME=%s;PASSWORD=%s", s1, s2);
508 g_free (s2);
509 }
510 else
511 info->auth_string = g_strdup_printf ("USERNAME=%s", s1);
512 g_free (s1);
513 }
514 }
515 g_free (username);
516 g_free (password);
517
518 #ifdef HAVE_LIBSECRET
519 if (! is_system) {
520 if (sync_keyring) {
521 GError *error = NULL;
522 gchar *auth = NULL;
523 auth = secret_password_lookup_sync (SECRET_SCHEMA_COMPAT_NETWORK,
524 NULL, &error,
525 "server", info->name, NULL);
526 if (auth) {
527 /*g_print ("Loaded sync. auth info for '%s': %s\n", info->name, auth);*/
528 info->auth_string = g_strdup (auth);
529 g_free (auth);
530 }
531 else if (error) {
532 gda_log_message (_("Error loading authentication information for '%s' DSN: %s"),
533 info->name, error->message ? error->message : _("No detail"));
534 g_clear_error (&error);
535 }
536 }
537 else {
538 secret_password_lookup (SECRET_SCHEMA_COMPAT_NETWORK,
539 NULL, (GAsyncReadyCallback) secret_password_found_cb,
540 g_strdup (info->name),
541 "server", info->name, NULL);
542 }
543 }
544 #else
545 #ifdef HAVE_GNOME_KEYRING
546 if (! is_system) {
547 if (sync_keyring) {
548 GnomeKeyringResult res;
549 gchar *auth = NULL;
550 res = gnome_keyring_find_password_sync (GNOME_KEYRING_NETWORK_PASSWORD, &auth,
551 "server", info->name, NULL);
552 if (res == GNOME_KEYRING_RESULT_OK) {
553 /*g_print ("Loaded sync. auth info for '%s': %s\n", info->name, auth);*/
554 info->auth_string = g_strdup (auth);
555 }
556 else if (res != GNOME_KEYRING_RESULT_NO_MATCH)
557 gda_log_message (_("Error loading authentication information for '%s' DSN: %s"),
558 info->name, gnome_keyring_result_to_message (res));
559 if (auth)
560 gnome_keyring_free_password (auth);
561 }
562 else {
563 gchar *tmp = g_strdup (info->name);
564 gnome_keyring_find_password (GNOME_KEYRING_NETWORK_PASSWORD,
565 (GnomeKeyringOperationGetStringCallback) password_found_cb,
566 tmp, g_free,
567 "server", tmp, NULL);
568 }
569 }
570 #endif
571 #endif
572 /* signals */
573 if (is_new) {
574 unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, info,
575 (GCompareFunc) data_source_info_compare);
576 if (unique_instance->priv->emit_signals)
577 g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, info);
578 }
579 else if (unique_instance->priv->emit_signals)
580 g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, info);
581 }
582 }
583 xmlFreeDoc (doc);
584 }
585
586 static void
save_config_file(gboolean is_system)587 save_config_file (gboolean is_system)
588 {
589 xmlDocPtr doc;
590 xmlNodePtr root;
591 GSList *list;
592
593 if (!unique_instance)
594 gda_config_get ();
595
596 if ((!is_system && !unique_instance->priv->user_file) ||
597 (is_system && !unique_instance->priv->system_file)) {
598 return;
599 }
600
601 doc = xmlNewDoc (BAD_CAST "1.0");
602 root = xmlNewDocNode (doc, NULL, BAD_CAST "libgda-config", NULL);
603 xmlDocSetRootElement (doc, root);
604 for (list = unique_instance->priv->dsn_list; list; list = list->next) {
605 GdaDsnInfo *info = (GdaDsnInfo*) list->data;
606 if (info->is_system != is_system)
607 continue;
608
609 xmlNodePtr section, entry;
610 gchar *prop;
611 section = xmlNewChild (root, NULL, BAD_CAST "section", NULL);
612 prop = g_strdup_printf ("/apps/libgda/Datasources/%s", info->name);
613 xmlSetProp (section, BAD_CAST "path", BAD_CAST prop);
614 g_free (prop);
615
616 /* provider */
617 entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
618 xmlSetProp (entry, BAD_CAST "name", BAD_CAST "Provider");
619 xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
620 xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->provider));
621
622 /* DSN */
623 entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
624 xmlSetProp (entry, BAD_CAST "name", BAD_CAST "DSN");
625 xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
626 xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->cnc_string));
627
628 #if !defined (HAVE_GNOME_KEYRING) && !defined (HAVE_LIBSECRET)
629 if (! is_system) {
630 /* auth */
631 entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
632 xmlSetProp (entry, BAD_CAST "name", BAD_CAST "Auth");
633 xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
634 xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->auth_string));
635 }
636 #endif
637
638 /* description */
639 entry = xmlNewChild (section, NULL, BAD_CAST "entry", NULL);
640 xmlSetProp (entry, BAD_CAST "name", BAD_CAST "Description");
641 xmlSetProp (entry, BAD_CAST "type", BAD_CAST "string");
642 xmlSetProp (entry, BAD_CAST "value", BAD_CAST (info->description));
643 }
644
645 #ifdef HAVE_GIO
646 lock_notify_changes ();
647 #endif
648 if (!is_system && unique_instance->priv->user_file) {
649 if (xmlSaveFormatFile (unique_instance->priv->user_file, doc, TRUE) == -1)
650 gda_log_error ("Error saving config data to '%s'", unique_instance->priv->user_file);
651 }
652 else if (is_system && unique_instance->priv->system_file) {
653 if (xmlSaveFormatFile (unique_instance->priv->system_file, doc, TRUE) == -1)
654 gda_log_error ("Error saving config data to '%s'", unique_instance->priv->system_file);
655 }
656 fflush (NULL);
657 #ifdef HAVE_GIO
658 unlock_notify_changes ();
659 #endif
660 xmlFreeDoc (doc);
661 }
662
663 static GObject *
gda_config_constructor(GType type,guint n_construct_properties,GObjectConstructParam * construct_properties)664 gda_config_constructor (GType type,
665 guint n_construct_properties,
666 GObjectConstructParam *construct_properties)
667 {
668 GObject *object;
669
670 if (!unique_instance) {
671 #if defined(HAVE_LIBSECRET) || defined(HAVE_GNOME_KEYRING)
672 if (g_getenv ("GDA_CONFIG_SYNCHRONOUS"))
673 sync_keyring = TRUE;
674 #endif
675
676 guint i;
677 gboolean user_file_set = FALSE, system_file_set = FALSE;
678
679 object = G_OBJECT_CLASS (parent_class)->constructor (type,
680 n_construct_properties,
681 construct_properties);
682 for (i = 0; i< n_construct_properties; i++) {
683 GObjectConstructParam *prop = &(construct_properties[i]);
684 if (!strcmp (g_param_spec_get_name (prop->pspec), "user-filename")) {
685 user_file_set = TRUE;
686 /*g_print ("GdaConfig user dir set\n");*/
687 }
688 else if (!strcmp (g_param_spec_get_name (prop->pspec), "system-filename")) {
689 system_file_set = TRUE;
690 /*g_print ("GdaConfig system dir set\n");*/
691 }
692 }
693
694 unique_instance = GDA_CONFIG (object);
695 g_object_ref (object); /* keep one reference for the library */
696
697 /* define user and system dirs. if not already defined */
698 if (!user_file_set) {
699 gchar *confdir, *conffile;
700 gboolean setup_ok = TRUE;
701 confdir = g_build_path (G_DIR_SEPARATOR_S, g_get_user_data_dir (), "libgda", NULL);
702 conffile = g_build_filename (confdir, "config", NULL);
703
704 if (!g_file_test (confdir, G_FILE_TEST_EXISTS)) {
705 gchar *old_path;
706 old_path = g_build_path (G_DIR_SEPARATOR_S, g_get_home_dir (), ".libgda", NULL); /* Flawfinder: ignore */
707 if (g_file_test (old_path, G_FILE_TEST_EXISTS)) {
708 /* using $HOME/.libgda because it exists */
709 g_free (confdir);
710 confdir = old_path;
711 g_free (conffile);
712 conffile = g_build_filename (confdir, "config", NULL);
713 }
714 else {
715 g_free (old_path);
716 if (g_mkdir_with_parents (confdir, 0700)) {
717 setup_ok = FALSE;
718 gda_log_error (_("Error creating user specific "
719 "configuration directory '%s'"),
720 confdir);
721 }
722 if (setup_ok) {
723 gchar *str;
724 gchar *full_file;
725 gsize len;
726 #define DB_FILE "sales_test.db"
727 #define DEFAULT_CONFIG \
728 "<?xml version=\"1.0\"?>\n" \
729 "<libgda-config>\n" \
730 " <section path=\"/apps/libgda/Datasources/SalesTest\">\n" \
731 " <entry name=\"DSN\" type=\"string\" value=\"DB_DIR=%s;DB_NAME=sales_test.db\"/>\n" \
732 " <entry name=\"Description\" type=\"string\" value=\"Test database for a sales department\"/>\n" \
733 " <entry name=\"Provider\" type=\"string\" value=\"SQLite\"/>\n" \
734 " </section>\n" \
735 "</libgda-config>\n"
736 #define DEFAULT_CONFIG_EMPTY \
737 "<?xml version=\"1.0\"?>\n" \
738 "<libgda-config>\n" \
739 " <!-- User specific data sources go here -->\n" \
740 "</libgda-config>\n"
741
742 str = gda_gbr_get_file_path (GDA_ETC_DIR,
743 LIBGDA_ABI_NAME, DB_FILE, NULL);
744 if (g_file_get_contents (str, &full_file, &len, NULL)) {
745 gchar *dbfile;
746
747 /* copy the Sales test database */
748 dbfile = g_build_filename (confdir, DB_FILE, NULL);
749 if (g_file_set_contents (dbfile, full_file, len, NULL)) {
750 gchar *str2;
751 str2 = g_strdup_printf (DEFAULT_CONFIG, confdir);
752 g_file_set_contents (conffile, str2, -1, NULL);
753 g_free (str2);
754 }
755 else
756 g_file_set_contents (conffile, DEFAULT_CONFIG_EMPTY, -1, NULL);
757 g_free (dbfile);
758 g_free (full_file);
759 }
760 else
761 g_file_set_contents (conffile, DEFAULT_CONFIG_EMPTY, -1, NULL);
762 g_free (str);
763 }
764 }
765 if (setup_ok && !g_file_test (confdir, G_FILE_TEST_IS_DIR)) {
766 setup_ok = FALSE;
767 gda_log_message (_("User specific "
768 "configuration directory '%s' exists and is not a directory"),
769 confdir);
770 }
771 g_free (confdir);
772
773 if (setup_ok)
774 unique_instance->priv->user_file = conffile;
775 else
776 g_free (conffile);
777 }
778 else {
779 if (!g_file_test (confdir, G_FILE_TEST_IS_DIR)) {
780 gda_log_message (_("User specific "
781 "configuration directory '%s' exists and is not a directory"),
782 confdir);
783 g_free (conffile);
784 }
785 else
786 unique_instance->priv->user_file = conffile;
787 g_free (confdir);
788 }
789 }
790 if (!system_file_set)
791 unique_instance->priv->system_file = gda_gbr_get_file_path (GDA_ETC_DIR,
792 LIBGDA_ABI_NAME, "config", NULL);
793 unique_instance->priv->system_config_allowed = FALSE;
794 if (unique_instance->priv->system_file) {
795 #ifdef G_OS_WIN32
796
797 FILE *file;
798 file = fopen (unique_instance->priv->system_file, "a"); /* Flawfinder: ignore */
799 if (file) {
800 unique_instance->priv->system_config_allowed = TRUE;
801 fclose (file);
802 }
803 #else
804 struct stat stbuf;
805 if (stat (unique_instance->priv->system_file, &stbuf) == 0) {
806 /* use effective user and group IDs */
807 uid_t euid;
808 gid_t egid;
809 euid = geteuid ();
810 egid = getegid ();
811 if (euid == stbuf.st_uid) {
812 if ((stbuf.st_mode & S_IWUSR) && (stbuf.st_mode & S_IRUSR))
813 unique_instance->priv->system_config_allowed = TRUE;
814 }
815 else if (egid == stbuf.st_gid) {
816 if ((stbuf.st_mode & S_IWGRP) && (stbuf.st_mode & S_IRGRP))
817 unique_instance->priv->system_config_allowed = TRUE;
818 }
819 else if ((stbuf.st_mode & S_IWOTH) && (stbuf.st_mode & S_IROTH))
820 unique_instance->priv->system_config_allowed = TRUE;
821 }
822 #endif
823 }
824
825 /* Setup file monitoring */
826 #ifdef HAVE_GIO
827 if (unique_instance->priv->user_file) {
828 GFile *gf;
829 gf = g_file_new_for_path (unique_instance->priv->user_file);
830 mon_conf_user = g_file_monitor_file (gf, G_FILE_MONITOR_NONE, NULL, NULL);
831 if (mon_conf_user)
832 g_signal_connect (G_OBJECT (mon_conf_user), "changed",
833 G_CALLBACK (conf_file_changed), NULL);
834 g_object_unref (gf);
835 }
836
837 if (unique_instance->priv->system_file) {
838 GFile *gf;
839 gf = g_file_new_for_path (unique_instance->priv->system_file);
840 mon_conf_global = g_file_monitor_file (gf, G_FILE_MONITOR_NONE, NULL, NULL);
841 if (mon_conf_user)
842 g_signal_connect (G_OBJECT (mon_conf_global), "changed",
843 G_CALLBACK (conf_file_changed), NULL);
844 g_object_unref (gf);
845 }
846 #endif
847 /* load existing DSN definitions */
848 if (unique_instance->priv->system_file)
849 load_config_file (unique_instance->priv->system_file, TRUE);
850 if (unique_instance->priv->user_file)
851 load_config_file (unique_instance->priv->user_file, FALSE);
852 }
853 else
854 object = g_object_ref (G_OBJECT (unique_instance));
855
856 return object;
857 }
858
859 static void
gda_config_dispose(GObject * object)860 gda_config_dispose (GObject *object)
861 {
862 GdaConfig *conf = (GdaConfig *) object;
863
864 g_return_if_fail (GDA_IS_CONFIG (conf));
865
866 if (conf->priv) {
867 g_free (conf->priv->user_file);
868 g_free (conf->priv->system_file);
869
870 if (conf->priv->dsn_list) {
871 g_slist_foreach (conf->priv->dsn_list, (GFunc) data_source_info_free, NULL);
872 g_slist_free (conf->priv->dsn_list);
873 }
874 if (conf->priv->prov_list) {
875 g_slist_foreach (conf->priv->prov_list, (GFunc) internal_provider_free, NULL);
876 g_slist_free (conf->priv->prov_list);
877 }
878 g_free (conf->priv);
879 conf->priv = NULL;
880 }
881
882 /* chain to parent class */
883 parent_class->dispose (object);
884 }
885
886
887 /* module error */
gda_config_error_quark(void)888 GQuark gda_config_error_quark (void)
889 {
890 static GQuark quark;
891 if (!quark)
892 quark = g_quark_from_static_string ("gda_config_error");
893 return quark;
894 }
895
896 /**
897 * gda_config_get_type:
898 *
899 * Registers the #GdaConfig class on the GLib type system.
900 *
901 * Returns: the GType identifying the class.
902 */
903 GType
gda_config_get_type(void)904 gda_config_get_type (void)
905 {
906 static GType type = 0;
907
908 if (G_UNLIKELY (type == 0)) {
909 static GTypeInfo info = {
910 sizeof (GdaConfigClass),
911 (GBaseInitFunc) NULL,
912 (GBaseFinalizeFunc) NULL,
913 (GClassInitFunc) gda_config_class_init,
914 NULL, NULL,
915 sizeof (GdaConfig),
916 0,
917 (GInstanceInitFunc) gda_config_init,
918 0
919 };
920 GDA_CONFIG_LOCK ();
921 if (type == 0)
922 type = g_type_register_static (G_TYPE_OBJECT, "GdaConfig", &info, 0);
923 GDA_CONFIG_UNLOCK ();
924 }
925
926 return type;
927 }
928
929 static void
gda_config_set_property(GObject * object,guint param_id,const GValue * value,GParamSpec * pspec)930 gda_config_set_property (GObject *object,
931 guint param_id,
932 const GValue *value,
933 GParamSpec *pspec)
934 {
935 GdaConfig *conf;
936 const gchar *cstr;
937
938 conf = GDA_CONFIG (object);
939 if (conf->priv) {
940 switch (param_id) {
941 case PROP_USER_FILE:
942 cstr = g_value_get_string (value);
943 if ((cstr && conf->priv->user_file &&
944 !strcmp (cstr, conf->priv->user_file)) ||
945 (! cstr && !conf->priv->user_file)) {
946 /* nothing to do */
947 break;
948 }
949 g_free (conf->priv->user_file);
950 conf->priv->user_file = NULL;
951 if (g_value_get_string (value))
952 conf->priv->user_file = g_strdup (cstr);
953 reload_dsn_configuration ();
954 break;
955 case PROP_SYSTEM_FILE:
956 cstr = g_value_get_string (value);
957 if ((cstr && conf->priv->system_file &&
958 !strcmp (cstr, conf->priv->system_file)) ||
959 (! cstr && !conf->priv->system_file)) {
960 /* nothing to do */
961 break;
962 }
963 g_free (conf->priv->system_file);
964 conf->priv->system_file = NULL;
965 if (g_value_get_string (value))
966 conf->priv->system_file = g_strdup (cstr);
967 reload_dsn_configuration ();
968 break;
969 default:
970 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
971 break;
972 }
973 }
974 }
975
976 static void
gda_config_get_property(GObject * object,guint param_id,GValue * value,GParamSpec * pspec)977 gda_config_get_property (GObject *object,
978 guint param_id,
979 GValue *value,
980 GParamSpec *pspec)
981 {
982 GdaConfig *conf;
983
984 conf = GDA_CONFIG (object);
985 if (conf->priv) {
986 switch (param_id) {
987 case PROP_USER_FILE:
988 g_value_set_string (value, conf->priv->user_file);
989 break;
990 case PROP_SYSTEM_FILE:
991 g_value_set_string (value, conf->priv->system_file);
992 break;
993 default:
994 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
995 break;
996 }
997 }
998 }
999
1000 /**
1001 * gda_config_get:
1002 *
1003 * Get a pointer to the global (unique) #GdaConfig object. This functions increments
1004 * the reference count of the object, so you need to call g_object_unref() on it once finished.
1005 *
1006 * Returns: (transfer full): a non %NULL pointer to the unique #GdaConfig
1007 */
1008 GdaConfig*
gda_config_get(void)1009 gda_config_get (void)
1010 {
1011 GDA_CONFIG_LOCK ();
1012 g_object_new (GDA_TYPE_CONFIG, NULL);
1013 g_assert (unique_instance);
1014 GDA_CONFIG_UNLOCK ();
1015 return unique_instance;
1016 }
1017
1018 /**
1019 * gda_config_get_dsn_info:
1020 * @dsn_name: the name of the DSN to look for
1021 *
1022 * Get information about the DSN named @dsn_name.
1023 *
1024 * @dsn_name's format is "[<username>[:<password>]@]<DSN>" (if <username>
1025 * and optionally <password> are provided, they are ignored). Also see the gda_dsn_split() utility
1026 * function.
1027 *
1028 * Returns: (transfer none): a pointer to read-only #GdaDsnInfo structure, or %NULL if not found
1029 */
1030 GdaDsnInfo *
gda_config_get_dsn_info(const gchar * dsn_name)1031 gda_config_get_dsn_info (const gchar *dsn_name)
1032 {
1033 GSList *list;
1034
1035 g_return_val_if_fail (dsn_name, NULL);
1036
1037 gchar *user, *pass, *real_dsn;
1038 gda_dsn_split (dsn_name, &real_dsn, &user, &pass);
1039 g_free (user);
1040 g_free (pass);
1041 if (!real_dsn) {
1042 gda_log_message (_("Malformed data source name '%s'"), dsn_name);
1043 return NULL;
1044 }
1045
1046 GDA_CONFIG_LOCK ();
1047 if (!unique_instance)
1048 gda_config_get ();
1049
1050 for (list = unique_instance->priv->dsn_list; list; list = list->next)
1051 if (!strcmp (((GdaDsnInfo*) list->data)->name, real_dsn)) {
1052 GDA_CONFIG_UNLOCK ();
1053 g_free (real_dsn);
1054 return (GdaDsnInfo*) list->data;
1055 }
1056 GDA_CONFIG_UNLOCK ();
1057 g_free (real_dsn);
1058 return NULL;
1059 }
1060
1061 #ifdef HAVE_LIBSECRET
1062 static void
secret_password_stored_cb(GObject * source_object,GAsyncResult * res,gchar * dsnname)1063 secret_password_stored_cb (GObject *source_object, GAsyncResult *res, gchar *dsnname)
1064 {
1065 GError *error = NULL;
1066 if (! secret_password_store_finish (res, &error)) {
1067 gda_log_error (_("Couldn't save authentication information for DSN '%s': %s"),
1068 dsnname, error && error->message ? error->message : _("No detail"));
1069 g_clear_error (&error);
1070 }
1071 g_free (dsnname);
1072 }
1073 #else
1074 #ifdef HAVE_GNOME_KEYRING
1075 static void
password_stored_cb(GnomeKeyringResult res,const gchar * dsnname)1076 password_stored_cb (GnomeKeyringResult res, const gchar *dsnname)
1077 {
1078 if (res != GNOME_KEYRING_RESULT_OK)
1079 gda_log_error (_("Couldn't save authentication information for DSN '%s': %s"), dsnname,
1080 gnome_keyring_result_to_message (res));
1081 }
1082 #endif
1083 #endif
1084
1085 /**
1086 * gda_config_define_dsn:
1087 * @info: a pointer to a filled GdaDsnInfo structure
1088 * @error: a place to store errors, or %NULL
1089 *
1090 * Add or update a DSN from the definition in @info.
1091 *
1092 * This method may fail with a %GDA_CONFIG_ERROR domain error (see the #GdaConfigError error codes).
1093 *
1094 * Returns: TRUE if no error occurred
1095 */
1096 gboolean
gda_config_define_dsn(const GdaDsnInfo * info,GError ** error)1097 gda_config_define_dsn (const GdaDsnInfo *info, GError **error)
1098 {
1099 GdaDsnInfo *einfo;
1100 gboolean save_user = FALSE;
1101 gboolean save_system = FALSE;
1102
1103 g_return_val_if_fail (info, FALSE);
1104 g_return_val_if_fail (info->name, FALSE);
1105
1106 GDA_CONFIG_LOCK ();
1107 if (!unique_instance)
1108 gda_config_get ();
1109
1110 if (info->is_system && !unique_instance->priv->system_config_allowed) {
1111 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PERMISSION_ERROR,
1112 "%s", _("Can't manage system-wide configuration"));
1113 GDA_CONFIG_UNLOCK ();
1114 return FALSE;
1115 }
1116
1117 if (info->is_system)
1118 save_system = TRUE;
1119 else
1120 save_user = TRUE;
1121 einfo = gda_config_get_dsn_info (info->name);
1122 if (einfo) {
1123 g_free (einfo->provider); einfo->provider = NULL;
1124 g_free (einfo->cnc_string); einfo->cnc_string = NULL;
1125 g_free (einfo->description); einfo->description = NULL;
1126 g_free (einfo->auth_string); einfo->auth_string = NULL;
1127 if (info->provider)
1128 einfo->provider = g_strdup (info->provider);
1129 if (info->cnc_string)
1130 einfo->cnc_string = g_strdup (info->cnc_string);
1131 if (info->description)
1132 einfo->description = g_strdup (info->description);
1133 if (info->auth_string)
1134 einfo->auth_string = g_strdup (info->auth_string);
1135
1136 if (info->is_system != einfo->is_system) {
1137 save_system = TRUE;
1138 save_user = TRUE;
1139 einfo->is_system = info->is_system ? TRUE : FALSE;
1140 }
1141 if (unique_instance->priv->emit_signals)
1142 g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, einfo);
1143 }
1144 else {
1145 einfo = g_new0 (GdaDsnInfo, 1);
1146 einfo->name = g_strdup (info->name);
1147 if (info->provider)
1148 einfo->provider = g_strdup (info->provider);
1149 if (info->cnc_string)
1150 einfo->cnc_string = g_strdup (info->cnc_string);
1151 if (info->description)
1152 einfo->description = g_strdup (info->description);
1153 if (info->auth_string)
1154 einfo->auth_string = g_strdup (info->auth_string);
1155 einfo->is_system = info->is_system ? TRUE : FALSE;
1156
1157 unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, einfo,
1158 (GCompareFunc) data_source_info_compare);
1159 if (unique_instance->priv->emit_signals)
1160 g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, einfo);
1161 }
1162
1163 #ifdef HAVE_LIBSECRET
1164 if (! info->is_system && info->auth_string) {
1165 /* save to keyring */
1166 gchar *tmp;
1167 tmp = g_strdup_printf (_("Authentication for the '%s' DSN"), info->name);
1168 if (sync_keyring) {
1169 gboolean res;
1170 GError *error = NULL;
1171 res = secret_password_store_sync (SECRET_SCHEMA_COMPAT_NETWORK,
1172 SECRET_COLLECTION_DEFAULT,
1173 tmp, info->auth_string,
1174 NULL, &error,
1175 "server", info->name, NULL);
1176 if (!res) {
1177 gda_log_error (_("Couldn't save authentication information for DSN '%s': %s"),
1178 info->name,
1179 error && error->message ? error->message : _("No detail"));
1180 g_clear_error (&error);
1181 }
1182 }
1183 else {
1184 secret_password_store (SECRET_SCHEMA_COMPAT_NETWORK,
1185 SECRET_COLLECTION_DEFAULT,
1186 tmp, info->auth_string,
1187 NULL,
1188 (GAsyncReadyCallback) secret_password_stored_cb,
1189 g_strdup (info->name),
1190 "server", info->name, NULL);
1191 }
1192 g_free (tmp);
1193 }
1194 #else
1195 #ifdef HAVE_GNOME_KEYRING
1196 if (! info->is_system && info->auth_string) {
1197 /* save to keyring */
1198 gchar *tmp;
1199 tmp = g_strdup_printf (_("Authentication for the '%s' DSN"), info->name);
1200 if (sync_keyring) {
1201 GnomeKeyringResult res;
1202 res = gnome_keyring_store_password_sync (GNOME_KEYRING_NETWORK_PASSWORD, GNOME_KEYRING_DEFAULT,
1203 tmp, info->auth_string,
1204 "server", info->name, NULL);
1205 password_stored_cb (res, info->name);
1206 }
1207 else {
1208 gchar *tmp1;
1209 tmp1 = g_strdup (info->name);
1210 gnome_keyring_store_password (GNOME_KEYRING_NETWORK_PASSWORD,
1211 GNOME_KEYRING_DEFAULT,
1212 tmp, info->auth_string,
1213 (GnomeKeyringOperationDoneCallback) password_stored_cb, tmp1, g_free,
1214 "server", info->name, NULL);
1215 }
1216 g_free (tmp);
1217 }
1218 #endif
1219 #endif
1220
1221 if (save_system)
1222 save_config_file (TRUE);
1223 if (save_user)
1224 save_config_file (FALSE);
1225
1226 GDA_CONFIG_UNLOCK ();
1227 return TRUE;
1228 }
1229
1230 #ifdef HAVE_LIBSECRET
1231 static void
secret_password_deleted_cb(GObject * source_object,GAsyncResult * res,gchar * dsnname)1232 secret_password_deleted_cb (GObject *source_object, GAsyncResult *res, gchar *dsnname)
1233 {
1234 GError *error = NULL;
1235 if (! secret_password_clear_finish (res, &error)) {
1236 gda_log_error (_("Couldn't delete authentication information for DSN '%s': %s"), dsnname,
1237 error && error->message ? error->message : _("No detail"));
1238 g_clear_error (&error);
1239 }
1240 g_free (dsnname);
1241 }
1242 #else
1243 #ifdef HAVE_GNOME_KEYRING
1244 static void
password_deleted_cb(GnomeKeyringResult res,const gchar * dsnname)1245 password_deleted_cb (GnomeKeyringResult res, const gchar *dsnname)
1246 {
1247 if (res != GNOME_KEYRING_RESULT_OK)
1248 gda_log_error (_("Couldn't delete authentication information for DSN '%s': %s"), dsnname,
1249 gnome_keyring_result_to_message (res));
1250 }
1251 #endif
1252 #endif
1253
1254 /**
1255 * gda_config_remove_dsn:
1256 * @dsn_name: the name of the DSN to remove
1257 * @error: a place to store errors, or %NULL
1258 *
1259 * Remove the DSN named @dsn_name.
1260 *
1261 * This method may fail with a %GDA_CONFIG_ERROR domain error (see the #GdaConfigError error codes).
1262 *
1263 * Returns: TRUE if no error occurred
1264 */
1265 gboolean
gda_config_remove_dsn(const gchar * dsn_name,GError ** error)1266 gda_config_remove_dsn (const gchar *dsn_name, GError **error)
1267 {
1268 GdaDsnInfo *info;
1269 gboolean save_user = FALSE;
1270 gboolean save_system = FALSE;
1271
1272 g_return_val_if_fail (dsn_name, FALSE);
1273
1274 GDA_CONFIG_LOCK ();
1275 if (!unique_instance)
1276 gda_config_get ();
1277
1278 info = gda_config_get_dsn_info (dsn_name);
1279 if (!info) {
1280 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_DSN_NOT_FOUND_ERROR,
1281 _("Unknown DSN '%s'"), dsn_name);
1282 GDA_CONFIG_UNLOCK ();
1283 return FALSE;
1284 }
1285 if (info->is_system && !unique_instance->priv->system_config_allowed) {
1286 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PERMISSION_ERROR,
1287 "%s", _("Can't manage system-wide configuration"));
1288 GDA_CONFIG_UNLOCK ();
1289 return FALSE;
1290 }
1291
1292 if (info->is_system)
1293 save_system = TRUE;
1294 else
1295 save_user = TRUE;
1296
1297 if (unique_instance->priv->emit_signals)
1298 g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
1299 unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
1300 if (unique_instance->priv->emit_signals)
1301 g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
1302 data_source_info_free (info);
1303
1304 #ifdef HAVE_LIBSECRET
1305 if (! info->is_system) {
1306 /* remove from keyring */
1307 if (sync_keyring) {
1308 GError *error = NULL;
1309 if (! secret_password_clear_sync (SECRET_SCHEMA_COMPAT_NETWORK,
1310 NULL, &error,
1311 "server", info->name, NULL)) {
1312 gda_log_error (_("Couldn't delete authentication information for DSN '%s': %s"),
1313 info->name,
1314 error && error->message ? error->message : _("No detail"));
1315 g_clear_error (&error);
1316 }
1317 }
1318 else {
1319 secret_password_clear (SECRET_SCHEMA_COMPAT_NETWORK,
1320 NULL, (GAsyncReadyCallback) secret_password_deleted_cb,
1321 g_strdup (info->name),
1322 "server", info->name, NULL);
1323 }
1324 }
1325 #else
1326 #ifdef HAVE_GNOME_KEYRING
1327 if (! info->is_system) {
1328 /* remove from keyring */
1329 if (sync_keyring) {
1330 GnomeKeyringResult res;
1331 res = gnome_keyring_delete_password_sync (GNOME_KEYRING_NETWORK_PASSWORD, GNOME_KEYRING_DEFAULT,
1332 "server", info->name, NULL);
1333 password_deleted_cb (res, info->name);
1334 }
1335 else {
1336 gchar *tmp;
1337 tmp = g_strdup (dsn_name);
1338 gnome_keyring_delete_password (GNOME_KEYRING_NETWORK_PASSWORD,
1339 (GnomeKeyringOperationDoneCallback) password_deleted_cb,
1340 tmp, g_free,
1341 "server", info->name, NULL);
1342 }
1343 }
1344 #endif
1345 #endif
1346
1347 if (save_system)
1348 save_config_file (TRUE);
1349 if (save_user)
1350 save_config_file (FALSE);
1351
1352 GDA_CONFIG_UNLOCK ();
1353 return TRUE;
1354 }
1355
1356 /**
1357 * gda_config_dsn_needs_authentication:
1358 * @dsn_name: the name of a DSN, in the "[<username>[:<password>]@]<DSN>" format
1359 *
1360 * Tells if the data source identified as @dsn_name needs any authentication. If a <username>
1361 * and optionally a <password> are specified, they are ignored.
1362 *
1363 * Returns: TRUE if an authentication is needed
1364 */
1365 gboolean
gda_config_dsn_needs_authentication(const gchar * dsn_name)1366 gda_config_dsn_needs_authentication (const gchar *dsn_name)
1367 {
1368 GdaDsnInfo *info;
1369 GdaProviderInfo *pinfo;
1370
1371 info = gda_config_get_dsn_info (dsn_name);
1372 if (!info)
1373 return FALSE;
1374 pinfo = gda_config_get_provider_info (info->provider);
1375 if (!pinfo) {
1376 gda_log_message (_("Provider '%s' not found"), info->provider);
1377 return FALSE;
1378 }
1379 if (pinfo->auth_params && pinfo->auth_params->holders)
1380 return TRUE;
1381 else
1382 return FALSE;
1383 }
1384
1385 /**
1386 * gda_config_list_dsn:
1387 *
1388 * Get a #GdaDataModel representing all the configured DSN, and keeping itself up to date with
1389 * the changes in the declared DSN.
1390 *
1391 * The returned data model is composed of the following columns:
1392 * <itemizedlist>
1393 * <listitem><para>DSN name</para></listitem>
1394 * <listitem><para>Provider name</para></listitem>
1395 * <listitem><para>Description</para></listitem>
1396 * <listitem><para>Connection string</para></listitem>
1397 * <listitem><para>Username if it exists</para></listitem>
1398 * </itemizedlist>
1399 *
1400 * Returns: (transfer full): a new #GdaDataModel
1401 */
1402 GdaDataModel *
gda_config_list_dsn(void)1403 gda_config_list_dsn (void)
1404 {
1405 GdaDataModel *model;
1406 GDA_CONFIG_LOCK ();
1407 if (!unique_instance)
1408 gda_config_get ();
1409
1410 model = GDA_DATA_MODEL (g_object_new (GDA_TYPE_DATA_MODEL_DSN_LIST, NULL));
1411 GDA_CONFIG_UNLOCK ();
1412 return model;
1413 }
1414
1415 /**
1416 * gda_config_get_nb_dsn:
1417 *
1418 * Get the number of defined DSN
1419 *
1420 * Returns: the number of defined DSN
1421 */
1422 gint
gda_config_get_nb_dsn(void)1423 gda_config_get_nb_dsn (void)
1424 {
1425 gint ret;
1426 GDA_CONFIG_LOCK ();
1427 if (!unique_instance)
1428 gda_config_get ();
1429
1430 ret = g_slist_length (unique_instance->priv->dsn_list);
1431 GDA_CONFIG_UNLOCK ();
1432 return ret;
1433 }
1434
1435 /**
1436 * gda_config_get_dsn_info_index:
1437 * @dsn_name: a DSN
1438 *
1439 * Get the index (starting at 0) of the DSN named @dsn_name
1440 *
1441 * Returns: the index or -1 if not found
1442 */
1443 gint
gda_config_get_dsn_info_index(const gchar * dsn_name)1444 gda_config_get_dsn_info_index (const gchar *dsn_name)
1445 {
1446 GdaDsnInfo *info;
1447 gint ret = -1;
1448
1449 g_return_val_if_fail (dsn_name, -1);
1450 GDA_CONFIG_LOCK ();
1451 if (!unique_instance)
1452 gda_config_get ();
1453
1454 info = gda_config_get_dsn_info (dsn_name);
1455 if (info)
1456 ret = g_slist_index (unique_instance->priv->dsn_list, info);
1457
1458 GDA_CONFIG_UNLOCK ();
1459 return ret;
1460 }
1461
1462 /**
1463 * gda_config_get_dsn_info_at_index:
1464 * @index: an index
1465 *
1466 * Get a pointer to a read-only #GdaDsnInfo at the @index position
1467 *
1468 * Returns: (transfer none):the pointer or %NULL if no DSN exists at position @index
1469 */
1470 GdaDsnInfo *
gda_config_get_dsn_info_at_index(gint index)1471 gda_config_get_dsn_info_at_index (gint index)
1472 {
1473 GdaDsnInfo *ret;
1474 GDA_CONFIG_LOCK ();
1475 if (!unique_instance)
1476 gda_config_get ();
1477 ret = g_slist_nth_data (unique_instance->priv->dsn_list, index);
1478 GDA_CONFIG_UNLOCK ();
1479 return ret;
1480 }
1481
1482 /**
1483 * gda_config_can_modify_system_config:
1484 *
1485 * Tells if the global (system) configuration can be modified (considering
1486 * system permissions and settings)
1487 *
1488 * Returns: TRUE if system-wide configuration can be modified
1489 */
1490 gboolean
gda_config_can_modify_system_config(void)1491 gda_config_can_modify_system_config (void)
1492 {
1493 gboolean retval;
1494 GDA_CONFIG_LOCK ();
1495 if (!unique_instance)
1496 gda_config_get ();
1497 retval = unique_instance->priv->system_config_allowed;
1498 GDA_CONFIG_UNLOCK ();
1499 return retval;
1500 }
1501
1502 /**
1503 * gda_config_get_provider_info:
1504 * @provider_name: a database provider
1505 *
1506 * Get some information about the a database provider (adapter) named
1507 *
1508 * Returns: (transfer none): a pointer to read-only #GdaProviderInfo structure, or %NULL if not found
1509 */
1510 GdaProviderInfo *
gda_config_get_provider_info(const gchar * provider_name)1511 gda_config_get_provider_info (const gchar *provider_name)
1512 {
1513 GSList *list;
1514 g_return_val_if_fail (provider_name, NULL);
1515 GDA_CONFIG_LOCK ();
1516 if (!unique_instance)
1517 gda_config_get ();
1518
1519 if (!unique_instance->priv->providers_loaded)
1520 load_all_providers ();
1521
1522 if (!g_ascii_strcasecmp (provider_name, "MS Access")) {
1523 GDA_CONFIG_UNLOCK ();
1524 return gda_config_get_provider_info ("MSAccess");
1525 }
1526
1527 for (list = unique_instance->priv->prov_list; list; list = list->next)
1528 if (!g_ascii_strcasecmp (((GdaProviderInfo*) list->data)->id, provider_name)) {
1529 GDA_CONFIG_UNLOCK ();
1530 return (GdaProviderInfo*) list->data;
1531 }
1532 GDA_CONFIG_UNLOCK ();
1533 return NULL;
1534 }
1535
1536 /**
1537 * gda_config_get_provider:
1538 * @provider_name: a database provider
1539 * @error: a place to store errors, or %NULL
1540 *
1541 * Get a pointer to the session-wide #GdaServerProvider for the
1542 * provider named @provider_name. The caller must not call g_object_unref() on the
1543 * returned object.
1544 *
1545 * This method may fail with a %GDA_CONFIG_ERROR domain error (see the #GdaConfigError error codes).
1546 *
1547 * Returns: (transfer none): a pointer to the #GdaServerProvider, or %NULL if an error occurred
1548 */
1549 GdaServerProvider *
gda_config_get_provider(const gchar * provider_name,GError ** error)1550 gda_config_get_provider (const gchar *provider_name, GError **error)
1551 {
1552 InternalProvider *ip;
1553 GdaServerProvider *(*plugin_create_provider) (void);
1554 GdaServerProvider *(*plugin_create_sub_provider) (const gchar *provider_name);
1555
1556 g_return_val_if_fail (provider_name, NULL);
1557 GDA_CONFIG_LOCK ();
1558 ip = (InternalProvider *) gda_config_get_provider_info (provider_name);
1559 if (!ip) {
1560 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PROVIDER_NOT_FOUND_ERROR,
1561 _("No provider '%s' installed"), provider_name);
1562 GDA_CONFIG_UNLOCK ();
1563 return NULL;
1564 }
1565 if (ip->instance) {
1566 GDA_CONFIG_UNLOCK ();
1567 return ip->instance;
1568 }
1569
1570 /* need to actually create the provider object */
1571 if (!ip->handle) {
1572 GdaProviderInfo *info = (GdaProviderInfo*) ip;
1573 ip->handle = g_module_open (info->location, G_MODULE_BIND_LAZY);
1574 if (!ip->handle) {
1575 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PROVIDER_CREATION_ERROR,
1576 _("Can't load provider: %s"), g_module_error ());
1577 return NULL;
1578 }
1579
1580 void (*plugin_init) (const gchar *);
1581 if (g_module_symbol (ip->handle, "plugin_init", (gpointer *) &plugin_init)) {
1582 gchar *dirname = g_path_get_dirname (info->location);
1583 plugin_init (dirname);
1584 g_free (dirname);
1585 }
1586 }
1587
1588 g_module_symbol (ip->handle, "plugin_create_provider", (gpointer) &plugin_create_provider);
1589 if (plugin_create_provider)
1590 ip->instance = plugin_create_provider ();
1591 else {
1592 g_module_symbol (ip->handle, "plugin_create_sub_provider", (gpointer) &plugin_create_sub_provider);
1593 if (plugin_create_sub_provider)
1594 ip->instance = plugin_create_sub_provider (provider_name);
1595 }
1596
1597 if (!ip->instance) {
1598 g_set_error (error, GDA_CONFIG_ERROR, GDA_CONFIG_PROVIDER_CREATION_ERROR,
1599 _("Can't instantiate provider '%s'"), provider_name);
1600 GDA_CONFIG_UNLOCK ();
1601 return NULL;
1602 }
1603
1604 GDA_CONFIG_UNLOCK ();
1605 return ip->instance;
1606 }
1607
1608 /**
1609 * gda_config_list_providers:
1610 *
1611 * Get a #GdaDataModel representing all the installed database providers.
1612 *
1613 * The returned data model is composed of the following columns:
1614 * <itemizedlist>
1615 * <listitem><para>Provider name</para></listitem>
1616 * <listitem><para>Description</para></listitem>
1617 * <listitem><para>DSN parameters</para></listitem>
1618 * <listitem><para>Authentication parameters</para></listitem>
1619 * <listitem><para>File name of the plugin</para></listitem>
1620 * </itemizedlist>
1621 *
1622 * Returns: (transfer full): a new #GdaDataModel
1623 */
1624 GdaDataModel *
gda_config_list_providers(void)1625 gda_config_list_providers (void)
1626 {
1627 GSList *list;
1628 GdaDataModel *model;
1629
1630 GDA_CONFIG_LOCK ();
1631 if (!unique_instance)
1632 gda_config_get ();
1633
1634 if (!unique_instance->priv->providers_loaded)
1635 load_all_providers ();
1636
1637 model = gda_data_model_array_new_with_g_types (5,
1638 G_TYPE_STRING,
1639 G_TYPE_STRING,
1640 G_TYPE_STRING,
1641 G_TYPE_STRING,
1642 G_TYPE_STRING);
1643 gda_data_model_set_column_title (model, 0, _("Provider"));
1644 gda_data_model_set_column_title (model, 1, _("Description"));
1645 gda_data_model_set_column_title (model, 2, _("DSN parameters"));
1646 gda_data_model_set_column_title (model, 3, _("Authentication"));
1647 gda_data_model_set_column_title (model, 4, _("File"));
1648 g_object_set_data (G_OBJECT (model), "name", _("List of installed providers"));
1649
1650 for (list = unique_instance->priv->prov_list; list; list = list->next) {
1651 GdaProviderInfo *info = (GdaProviderInfo *) list->data;
1652 GValue *value;
1653 gint row;
1654
1655 row = gda_data_model_append_row (model, NULL);
1656
1657 value = gda_value_new_from_string (info->id, G_TYPE_STRING);
1658 gda_data_model_set_value_at (model, 0, row, value, NULL);
1659 gda_value_free (value);
1660
1661 if (info->description)
1662 value = gda_value_new_from_string (info->description, G_TYPE_STRING);
1663 else
1664 value = gda_value_new_null ();
1665 gda_data_model_set_value_at (model, 1, row, value, NULL);
1666 gda_value_free (value);
1667
1668 if (info->dsn_params) {
1669 GSList *params;
1670 GString *string = g_string_new ("");
1671 for (params = info->dsn_params->holders;
1672 params; params = params->next) {
1673 const gchar *id;
1674
1675 id = gda_holder_get_id (GDA_HOLDER (params->data));
1676 if (params != info->dsn_params->holders)
1677 g_string_append (string, ",\n");
1678 g_string_append (string, id);
1679 }
1680 value = gda_value_new_from_string (string->str, G_TYPE_STRING);
1681 g_string_free (string, TRUE);
1682 gda_data_model_set_value_at (model, 2, row, value, NULL);
1683 gda_value_free (value);
1684 }
1685
1686 if (info->auth_params) {
1687 GSList *params;
1688 GString *string = g_string_new ("");
1689 for (params = info->auth_params->holders;
1690 params; params = params->next) {
1691 const gchar *id;
1692
1693 id = gda_holder_get_id (GDA_HOLDER (params->data));
1694 if (params != info->auth_params->holders)
1695 g_string_append (string, ",\n");
1696 g_string_append (string, id);
1697 }
1698 value = gda_value_new_from_string (string->str, G_TYPE_STRING);
1699 g_string_free (string, TRUE);
1700 gda_data_model_set_value_at (model, 3, row, value, NULL);
1701 gda_value_free (value);
1702 }
1703
1704 value = gda_value_new_from_string (info->location, G_TYPE_STRING);
1705 gda_data_model_set_value_at (model, 4, row, value, NULL);
1706 gda_value_free (value);
1707 }
1708 g_object_set (G_OBJECT (model), "read-only", TRUE, NULL);
1709
1710 GDA_CONFIG_UNLOCK ();
1711 return model;
1712 }
1713
1714 static gint
internal_provider_sort_func(InternalProvider * a,InternalProvider * b)1715 internal_provider_sort_func (InternalProvider *a, InternalProvider *b)
1716 {
1717 return strcmp (a->pinfo.id, b->pinfo.id);
1718 }
1719
1720 static void load_providers_from_dir (const gchar *dirname, gboolean recurs);
1721 static void
load_all_providers(void)1722 load_all_providers (void)
1723 {
1724 const gchar *dirname;
1725 g_assert (unique_instance);
1726
1727 dirname = g_getenv ("GDA_TOP_BUILD_DIR");
1728 if (dirname) {
1729 gchar *pdir;
1730 pdir = g_build_path (G_DIR_SEPARATOR_S, dirname, "providers", NULL);
1731 load_providers_from_dir (pdir, TRUE);
1732 g_free (pdir);
1733 }
1734 else {
1735 gchar *str;
1736 str = gda_gbr_get_file_path (GDA_LIB_DIR, LIBGDA_ABI_NAME, "providers", NULL);
1737 load_providers_from_dir (str, FALSE);
1738 g_free (str);
1739 }
1740 unique_instance->priv->providers_loaded = TRUE;
1741
1742 /* find SQLite provider, and instantiate it if not installed */
1743 _gda_config_sqlite_provider = gda_config_get_provider ("SQLite", NULL);
1744 if (!_gda_config_sqlite_provider) {
1745 _gda_config_sqlite_provider = (GdaServerProvider*)
1746 g_object_new (GDA_TYPE_SQLITE_PROVIDER, NULL);
1747 }
1748
1749 /* sort providers by name */
1750 unique_instance->priv->prov_list = g_slist_sort (unique_instance->priv->prov_list,
1751 (GCompareFunc) internal_provider_sort_func);
1752 }
1753
1754 static InternalProvider *
create_internal_provider(const gchar * path,const gchar * prov_name,const gchar * prov_descr,gchar * dsn_spec,gchar * auth_spec)1755 create_internal_provider (const gchar *path,
1756 const gchar *prov_name, const gchar *prov_descr,
1757 gchar *dsn_spec, gchar *auth_spec)
1758 {
1759 InternalProvider *ip;
1760 GdaProviderInfo *info;
1761
1762 ip = g_new0 (InternalProvider, 1);
1763 ip->handle = NULL;
1764 info = (GdaProviderInfo*) ip;
1765 info->location = g_strdup (path);
1766
1767 info->id = g_strdup (prov_name);
1768 info->description = g_strdup (prov_descr);
1769
1770 /* DSN parameters */
1771 info->dsn_params = NULL;
1772 if (dsn_spec) {
1773 GError *error = NULL;
1774 info->dsn_params = gda_set_new_from_spec_string (dsn_spec, &error);
1775 if (!info->dsn_params) {
1776 gda_log_message ("Invalid format for provider '%s' DSN spec : %s",
1777 info->id,
1778 error ? error->message : "Unknown error");
1779 g_clear_error (&error);
1780
1781 /* there may be traces of the provider installed but some parts are missing,
1782 forget about that provider... */
1783 internal_provider_free (ip);
1784 g_free (dsn_spec);
1785 return NULL;
1786 }
1787 g_free (dsn_spec);
1788 }
1789 else
1790 gda_log_message ("Provider '%s' does not provide a DSN spec", info->id);
1791
1792 /* Authentication parameters */
1793 info->auth_params = NULL;
1794 if (auth_spec) {
1795 GError *error = NULL;
1796
1797 info->auth_params = gda_set_new_from_spec_string (auth_spec, &error);
1798 if (!info->auth_params) {
1799 gda_log_message ("Invalid format for provider '%s' AUTH spec : %s",
1800 info->id,
1801 error ? error->message : "Unknown error");
1802 if (error)
1803 g_error_free (error);
1804 }
1805
1806 if (!info->auth_params) {
1807 /* there may be traces of the provider installed but some parts are missing,
1808 forget about that provider... */
1809 internal_provider_free (ip);
1810 g_free (auth_spec);
1811 return NULL;
1812 }
1813 g_free (auth_spec);
1814 }
1815 else {
1816 /* default to username/password */
1817 GdaHolder *h;
1818 info->auth_params = gda_set_new_inline (2, "USERNAME", G_TYPE_STRING, NULL,
1819 "PASSWORD", G_TYPE_STRING, NULL);
1820 h = gda_set_get_holder (info->auth_params, "USERNAME");
1821 g_object_set (G_OBJECT (h), "name", _("Username"), "not-null", TRUE, NULL);
1822 h = gda_set_get_holder (info->auth_params, "PASSWORD");
1823 g_object_set (G_OBJECT (h), "name", _("Password"), "not-null", TRUE, NULL);
1824
1825 GValue *value;
1826 #define GDAUI_ATTRIBUTE_PLUGIN "__gdaui_attr_plugin"
1827 value = gda_value_new_from_string ("string:HIDDEN=true", G_TYPE_STRING);
1828 gda_holder_set_attribute_static (h, GDAUI_ATTRIBUTE_PLUGIN, value);
1829 gda_value_free (value);
1830 }
1831 return ip;
1832 }
1833
1834 static void
load_providers_from_dir(const gchar * dirname,gboolean recurs)1835 load_providers_from_dir (const gchar *dirname, gboolean recurs)
1836 {
1837 GDir *dir;
1838 GError *err = NULL;
1839 const gchar *name;
1840
1841 /* read the plugin directory */
1842 #ifdef GDA_DEBUG_NO
1843 g_print ("Loading providers in %s\n", dirname);
1844 #endif
1845 dir = g_dir_open (dirname, 0, &err);
1846 if (err) {
1847 gda_log_error (err->message);
1848 g_error_free (err);
1849 return;
1850 }
1851
1852 while ((name = g_dir_read_name (dir))) {
1853 GModule *handle;
1854 gchar *path;
1855
1856 /* initialization method */
1857 void (*plugin_init) (const gchar *);
1858
1859 /* methods for shared libraries which provide only one type of provider */
1860 const gchar * (* plugin_get_name) (void);
1861 const gchar * (* plugin_get_description) (void);
1862 gchar * (* plugin_get_dsn_spec) (void);
1863 gchar * (* plugin_get_auth_spec) (void);
1864
1865 /* methods for shared libraries which provide several types of providers (ODBC, JDBC, ...) */
1866 const gchar ** (* plugin_get_sub_names) (void);
1867 const gchar * (* plugin_get_sub_description) (const gchar *name);
1868 gchar * (* plugin_get_sub_dsn_spec) (const gchar *name);
1869 gchar * (* plugin_get_sub_auth_spec) (const gchar *name);
1870
1871 if (recurs) {
1872 gchar *cname;
1873 cname = g_build_filename (dirname, name, NULL);
1874 if (g_file_test (cname, G_FILE_TEST_IS_DIR))
1875 load_providers_from_dir (cname, TRUE);
1876 g_free (cname);
1877 }
1878
1879 if (!g_str_has_suffix (name, "." G_MODULE_SUFFIX))
1880 continue;
1881 #ifdef G_WITH_CYGWIN
1882 if (!g_str_has_prefix (name, "cyggda"))
1883 #else
1884 if (!g_str_has_prefix (name, "libgda"))
1885 #endif
1886 continue;
1887
1888 path = g_build_path (G_DIR_SEPARATOR_S, dirname,
1889 name, NULL);
1890 handle = g_module_open (path, G_MODULE_BIND_LAZY);
1891 if (!handle) {
1892 if (g_getenv ("GDA_SHOW_PROVIDER_LOADING_ERROR"))
1893 gda_log_message (_("Error loading provider '%s': %s"), path, g_module_error ());
1894 g_free (path);
1895 continue;
1896 }
1897
1898 if (g_module_symbol (handle, "plugin_init", (gpointer *) &plugin_init)) {
1899 plugin_init (dirname);
1900 }
1901 else {
1902 g_module_close (handle);
1903 g_free (path);
1904 continue;
1905 }
1906 g_module_symbol (handle, "plugin_get_name",
1907 (gpointer *) &plugin_get_name);
1908 g_module_symbol (handle, "plugin_get_description",
1909 (gpointer *) &plugin_get_description);
1910 g_module_symbol (handle, "plugin_get_dsn_spec",
1911 (gpointer *) &plugin_get_dsn_spec);
1912 g_module_symbol (handle, "plugin_get_auth_spec",
1913 (gpointer *) &plugin_get_auth_spec);
1914 g_module_symbol (handle, "plugin_get_sub_names",
1915 (gpointer *) &plugin_get_sub_names);
1916 g_module_symbol (handle, "plugin_get_sub_description",
1917 (gpointer *) &plugin_get_sub_description);
1918 g_module_symbol (handle, "plugin_get_sub_dsn_spec",
1919 (gpointer *) &plugin_get_sub_dsn_spec);
1920 g_module_symbol (handle, "plugin_get_sub_auth_spec",
1921 (gpointer *) &plugin_get_sub_auth_spec);
1922
1923 if (plugin_get_sub_names) {
1924 const gchar **subnames = plugin_get_sub_names ();
1925 const gchar **ptr;
1926 for (ptr = subnames; ptr && *ptr; ptr++) {
1927 InternalProvider *ip;
1928
1929 ip = create_internal_provider (path, *ptr,
1930 plugin_get_sub_description ?
1931 plugin_get_sub_description (*ptr) : NULL,
1932 plugin_get_sub_dsn_spec ?
1933 plugin_get_sub_dsn_spec (*ptr) : NULL,
1934 plugin_get_sub_auth_spec ?
1935 plugin_get_sub_auth_spec (*ptr) : NULL);
1936 if (ip) {
1937 unique_instance->priv->prov_list =
1938 g_slist_prepend (unique_instance->priv->prov_list, ip);
1939 #ifdef GDA_DEBUG_NO
1940 g_print ("Loaded '%s' sub-provider\n", ((GdaProviderInfo*) ip)->id);
1941 #endif
1942 }
1943 }
1944 }
1945 else {
1946 InternalProvider *ip;
1947 ip = create_internal_provider (path,
1948 plugin_get_name ? plugin_get_name () : name,
1949 plugin_get_description ? plugin_get_description () : NULL,
1950 plugin_get_dsn_spec ? plugin_get_dsn_spec () : NULL,
1951 plugin_get_auth_spec ? plugin_get_auth_spec () : NULL);
1952 if (ip) {
1953 unique_instance->priv->prov_list =
1954 g_slist_prepend (unique_instance->priv->prov_list, ip);
1955 #ifdef GDA_DEBUG_NO
1956 g_print ("Loaded '%s' provider\n", ((GdaProviderInfo*) ip)->id);
1957 #endif
1958 }
1959 }
1960 g_free (path);
1961 g_module_close (handle);
1962 }
1963
1964 /* free memory */
1965 g_dir_close (dir);
1966 }
1967
1968
1969
1970 /* sorting function */
1971 static gint
data_source_info_compare(GdaDsnInfo * infoa,GdaDsnInfo * infob)1972 data_source_info_compare (GdaDsnInfo *infoa, GdaDsnInfo *infob)
1973 {
1974 if (!infoa && !infob)
1975 return 0;
1976 if (infoa) {
1977 if (!infob)
1978 return 1;
1979 else {
1980 gchar *u8a, *u8b;
1981 gint res;
1982 u8a = g_utf8_casefold (infoa->name, -1);
1983 u8b = g_utf8_casefold (infob->name, -1);
1984 res = strcmp (u8a, u8b);
1985 g_free (u8a);
1986 g_free (u8b);
1987 return res;
1988 }
1989 }
1990 else
1991 return -1;
1992 }
1993
1994 static void
data_source_info_free(GdaDsnInfo * info)1995 data_source_info_free (GdaDsnInfo *info)
1996 {
1997 g_free (info->provider);
1998 g_free (info->cnc_string);
1999 g_free (info->description);
2000 g_free (info->auth_string);
2001 g_free (info);
2002 }
2003
2004 static void
internal_provider_free(InternalProvider * ip)2005 internal_provider_free (InternalProvider *ip)
2006 {
2007 GdaProviderInfo *info = (GdaProviderInfo*) ip;
2008 if (ip->instance)
2009 g_object_unref (ip->instance);
2010 if (ip->handle)
2011 g_module_close (ip->handle);
2012
2013 g_free (info->id);
2014 g_free (info->location);
2015 g_free (info->description);
2016 if (info->dsn_params)
2017 g_object_unref (info->dsn_params);
2018 g_free (ip);
2019 }
2020
2021 static gboolean
str_equal(const gchar * str1,const gchar * str2)2022 str_equal (const gchar *str1, const gchar *str2)
2023 {
2024 if (str1 && str2) {
2025 if (!strcmp (str1, str2))
2026 return TRUE;
2027 else
2028 return FALSE;
2029 }
2030 else if (!str1 && !str2)
2031 return TRUE;
2032 return FALSE;
2033 }
2034
2035 static void
reload_dsn_configuration(void)2036 reload_dsn_configuration (void)
2037 {
2038 GSList *list, *current_dsn_list, *new_dsn_list;
2039 if (!unique_instance) {
2040 /* object not yet created */
2041 return;
2042 }
2043
2044 GDA_CONFIG_LOCK ();
2045 #ifdef GDA_DEBUG_NO
2046 gboolean is_system = (mon == mon_conf_global) ? TRUE : FALSE;
2047 g_print ("Reloading config files (%s config has changed)\n", is_system ? "global" : "user");
2048 for (list = unique_instance->priv->dsn_list; list; list = list->next) {
2049 GdaDsnInfo *info = (GdaDsnInfo *) list->data;
2050 g_print ("[info %p]: %s/%s\n", info, info->provider, info->name);
2051 }
2052 #endif
2053 current_dsn_list = unique_instance->priv->dsn_list;
2054 unique_instance->priv->dsn_list = NULL;
2055
2056 unique_instance->priv->emit_signals = FALSE;
2057 #ifdef HAVE_GIO
2058 lock_notify_changes ();
2059 #endif
2060 if (unique_instance->priv->system_file)
2061 load_config_file (unique_instance->priv->system_file, TRUE);
2062 if (unique_instance->priv->user_file)
2063 load_config_file (unique_instance->priv->user_file, FALSE);
2064 #ifdef HAVE_GIO
2065 unlock_notify_changes ();
2066 #endif
2067 unique_instance->priv->emit_signals = TRUE;
2068
2069 new_dsn_list = unique_instance->priv->dsn_list;
2070 unique_instance->priv->dsn_list = current_dsn_list;
2071 current_dsn_list = NULL;
2072
2073 /* handle new or updated DSN */
2074 GHashTable *hash = g_hash_table_new (g_str_hash, g_str_equal);
2075 for (list = new_dsn_list; list; list = list->next) {
2076 GdaDsnInfo *ninfo, *oinfo;
2077 ninfo = (GdaDsnInfo *) list->data;
2078 oinfo = gda_config_get_dsn_info (ninfo->name);
2079 if (!oinfo) {
2080 /* add ninfo */
2081 unique_instance->priv->dsn_list = g_slist_insert_sorted (unique_instance->priv->dsn_list, ninfo,
2082 (GCompareFunc) data_source_info_compare);
2083 if (unique_instance->priv->emit_signals)
2084 g_signal_emit (unique_instance, gda_config_signals[DSN_ADDED], 0, ninfo);
2085 g_hash_table_insert (hash, ninfo->name, (gpointer) 0x1);
2086 }
2087 else {
2088 /* signal changed if updated */
2089 if (str_equal (oinfo->provider, ninfo->provider) &&
2090 str_equal (oinfo->description, ninfo->description) &&
2091 str_equal (oinfo->cnc_string, ninfo->cnc_string) &&
2092 #if !defined (HAVE_GNOME_KEYRING) && !defined (HAVE_LIBSECRET)
2093 str_equal (oinfo->auth_string, ninfo->auth_string) &&
2094 #endif
2095 (oinfo->is_system == ninfo->is_system)) {
2096 /* no change for this DSN */
2097 data_source_info_free (ninfo);
2098 }
2099 else {
2100 GdaDsnInfo tmp;
2101 tmp = *oinfo;
2102 *oinfo = *ninfo;
2103 *ninfo = tmp;
2104 if (unique_instance->priv->emit_signals)
2105 g_signal_emit (unique_instance, gda_config_signals[DSN_CHANGED], 0, oinfo);
2106 data_source_info_free (ninfo);
2107 }
2108 g_hash_table_insert (hash, oinfo->name, (gpointer) 0x1);
2109 }
2110 }
2111 g_slist_free (new_dsn_list);
2112
2113 /* remove old DSN */
2114 for (list = unique_instance->priv->dsn_list; list; ) {
2115 GdaDsnInfo *info;
2116 info = (GdaDsnInfo *) list->data;
2117 list = list->next;
2118 if (g_hash_table_lookup (hash, info->name))
2119 continue;
2120
2121 if (unique_instance->priv->emit_signals)
2122 g_signal_emit (unique_instance, gda_config_signals[DSN_TO_BE_REMOVED], 0, info);
2123 unique_instance->priv->dsn_list = g_slist_remove (unique_instance->priv->dsn_list, info);
2124 if (unique_instance->priv->emit_signals)
2125 g_signal_emit (unique_instance, gda_config_signals[DSN_REMOVED], 0, info);
2126 data_source_info_free (info);
2127 }
2128 g_hash_table_destroy (hash);
2129
2130 GDA_CONFIG_UNLOCK ();
2131 }
2132
2133 /*
2134 * File monitoring actions
2135 */
2136 #ifdef HAVE_GIO
2137
2138 static void
conf_file_changed(G_GNUC_UNUSED GFileMonitor * mon,G_GNUC_UNUSED GFile * file,G_GNUC_UNUSED GFile * other_file,GFileMonitorEvent event_type,G_GNUC_UNUSED gpointer data)2139 conf_file_changed (G_GNUC_UNUSED GFileMonitor *mon, G_GNUC_UNUSED GFile *file,
2140 G_GNUC_UNUSED GFile *other_file, GFileMonitorEvent event_type,
2141 G_GNUC_UNUSED gpointer data)
2142 {
2143 if (event_type != G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT)
2144 return;
2145 reload_dsn_configuration ();
2146 }
2147
2148 static void
lock_notify_changes(void)2149 lock_notify_changes (void)
2150 {
2151 if (user_notify_changes != 0)
2152 g_signal_handler_block (mon_conf_user, user_notify_changes);
2153 if (global_notify_changes != 0)
2154 g_signal_handler_block (mon_conf_global, global_notify_changes);
2155 }
2156
2157 static void
unlock_notify_changes(void)2158 unlock_notify_changes (void)
2159 {
2160 if (user_notify_changes != 0)
2161 g_signal_handler_unblock (mon_conf_user, user_notify_changes);
2162 if (global_notify_changes != 0)
2163 g_signal_handler_unblock (mon_conf_global, global_notify_changes);
2164 }
2165
2166 #endif
2167