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 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* 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 * 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 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 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 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 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 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 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 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 * 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 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 */ 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 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 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 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* 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 * 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 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 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 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 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 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 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 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 * 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 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 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 * 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 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 * 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 * 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 * 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 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 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 * 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 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 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 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 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 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 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 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 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 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