1 /* GConf
2  * Copyright (C) 1999, 2000 Red Hat Inc.
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
17  * Boston, MA 02110-1301, USA.
18  */
19 
20 #if HAVE_CORBA
21 #include "GConfX.h"
22 #endif
23 
24 #include "gconf.h"
25 #include "gconf-internals.h"
26 #include "gconf-sources.h"
27 #include "gconf-locale.h"
28 #include <string.h>
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <time.h>
33 #include <sys/types.h>
34 #ifdef HAVE_SYS_WAIT_H
35 #include <sys/wait.h>
36 #endif
37 #include <sys/time.h>
38 #include <unistd.h>
39 
40 #ifdef HAVE_CORBA
41 /* Returns TRUE if there was an error, frees exception, sets err */
42 static gboolean gconf_handle_corba_exception(CORBA_Environment* ev, GError** err);
43 /* just returns TRUE if there's an exception indicating the server is
44    probably hosed; no side effects */
45 static gboolean gconf_server_broken(CORBA_Environment* ev);
46 static void gconf_detach_config_server(void);
47 
48 /* Maximum number of times to try re-spawning the server if it's down. */
49 #define MAX_RETRIES 1
50 #endif /* HAVE_CORBA */
51 
52 /* copied from gutf8.c where it exists as a (unfortunately) non-exported function */
53 static gchar *
utf8_make_valid(const gchar * name)54 utf8_make_valid (const gchar *name)
55 {
56   GString *string;
57   const gchar *remainder, *invalid;
58   gint remaining_bytes, valid_bytes;
59 
60   string = NULL;
61   remainder = name;
62   remaining_bytes = strlen (name);
63 
64   while (remaining_bytes != 0)
65     {
66       if (g_utf8_validate (remainder, remaining_bytes, &invalid))
67         break;
68       valid_bytes = invalid - remainder;
69 
70       if (string == NULL)
71         string = g_string_sized_new (remaining_bytes);
72 
73       g_string_append_len (string, remainder, valid_bytes);
74       /* append U+FFFD REPLACEMENT CHARACTER */
75       g_string_append (string, "\357\277\275");
76 
77       remaining_bytes -= valid_bytes + 1;
78       remainder = invalid + 1;
79     }
80 
81   if (string == NULL)
82     return g_strdup (name);
83 
84   g_string_append (string, remainder);
85 
86   g_assert (g_utf8_validate (string->str, -1, NULL));
87 
88   return g_string_free (string, FALSE);
89 }
90 
91 gboolean
gconf_key_check(const gchar * key,GError ** err)92 gconf_key_check(const gchar* key, GError** err)
93 {
94   gchar* why = NULL;
95 
96   if (key == NULL)
97     {
98       if (err)
99         *err = gconf_error_new (GCONF_ERROR_BAD_KEY,
100 				_("Key is NULL"));
101       return FALSE;
102     }
103   else if (!gconf_valid_key (key, &why))
104     {
105       if (err) {
106         gchar *utf8_key = utf8_make_valid (key);
107         *err = gconf_error_new (GCONF_ERROR_BAD_KEY, _("\"%s\": %s"),
108                                 utf8_key, why);
109         g_free (utf8_key);
110       }
111       g_free(why);
112       return FALSE;
113     }
114   return TRUE;
115 }
116 
117 #ifdef HAVE_CORBA
118 typedef struct _CnxnTable CnxnTable;
119 
120 struct _GConfEngine {
121   guint refcount;
122 
123   ConfigDatabase database;
124 
125   CnxnTable* ctable;
126 
127   /* If non-NULL, this is a local engine;
128      local engines don't do notification! */
129   GConfSources* local_sources;
130 
131   /* A list of addresses that make up this db;
132    * NULL if it uses the default db
133    */
134   GSList *addresses;
135 
136   /* A concatentation of the addresses above.
137    */
138   char *persistent_address;
139 
140   gpointer user_data;
141   GDestroyNotify dnotify;
142 
143   gpointer owner;
144   int owner_use_count;
145 
146   /* If TRUE, this is a local engine (and therefore
147    * has no ctable and no notifications)
148    */
149   guint is_local : 1;
150 };
151 
152 typedef struct _GConfCnxn GConfCnxn;
153 
154 struct _GConfCnxn {
155   gchar* namespace_section;
156   guint client_id;
157   CORBA_unsigned_long server_id; /* id returned from server */
158   GConfEngine* conf;             /* engine we're associated with */
159   GConfNotifyFunc func;
160   gpointer user_data;
161 };
162 
163 static GConfEngine *default_engine = NULL;
164 
165 static GConfCnxn* gconf_cnxn_new     (GConfEngine         *conf,
166                                       const gchar         *namespace_section,
167                                       CORBA_unsigned_long  server_id,
168                                       GConfNotifyFunc      func,
169                                       gpointer             user_data);
170 static void       gconf_cnxn_destroy (GConfCnxn           *cnxn);
171 static void       gconf_cnxn_notify  (GConfCnxn           *cnxn,
172                                       GConfEntry          *entry);
173 
174 
175 static ConfigServer   gconf_get_config_server    (gboolean     start_if_not_found,
176                                                   GError **err);
177 
178 /* Forget our current server object reference, so the next call to
179    gconf_get_config_server will have to try to respawn the server */
180 static ConfigListener gconf_get_config_listener  (void);
181 
182 static void           gconf_engine_detach       (GConfEngine     *conf);
183 static gboolean       gconf_engine_connect      (GConfEngine     *conf,
184                                                  gboolean         start_if_not_found,
185                                                  GError         **err);
186 static void           gconf_engine_set_database (GConfEngine     *conf,
187                                                  ConfigDatabase   db);
188 static ConfigDatabase gconf_engine_get_database (GConfEngine     *conf,
189                                                  gboolean         start_if_not_found,
190                                                  GError         **err);
191 
192 
193 #define CHECK_OWNER_USE(engine)   \
194   do { if ((engine)->owner && (engine)->owner_use_count == 0) \
195      g_warning ("%s: You can't use a GConfEngine that has an active GConfClient wrapper object. Use GConfClient API instead.", G_STRFUNC);  \
196   } while (0)
197 
198 static void         register_engine           (GConfEngine    *conf);
199 static void         unregister_engine         (GConfEngine    *conf);
200 static GConfEngine *lookup_engine             (GSList         *addresses);
201 static GConfEngine *lookup_engine_by_database (ConfigDatabase  db);
202 
203 
204 /* We'll use client-specific connection numbers to return to library
205    users, so if gconfd dies we can transparently re-register all our
206    listener functions.  */
207 
208 struct _CnxnTable {
209   /* Hash from server-returned connection ID to GConfCnxn */
210   GHashTable* server_ids;
211   /* Hash from our connection ID to GConfCnxn */
212   GHashTable* client_ids;
213 };
214 
215 static CnxnTable* ctable_new                 (void);
216 static void       ctable_destroy             (CnxnTable           *ct);
217 static void       ctable_insert              (CnxnTable           *ct,
218                                               GConfCnxn           *cnxn);
219 static void       ctable_remove              (CnxnTable           *ct,
220                                               GConfCnxn           *cnxn);
221 static GSList*    ctable_remove_by_conf      (CnxnTable           *ct,
222                                               GConfEngine         *conf);
223 static GConfCnxn* ctable_lookup_by_client_id (CnxnTable           *ct,
224                                               guint                client_id);
225 static GConfCnxn* ctable_lookup_by_server_id (CnxnTable           *ct,
226                                               CORBA_unsigned_long  server_id);
227 static void       ctable_reinstall           (CnxnTable           *ct,
228                                               GConfCnxn           *cnxn,
229                                               guint                old_server_id,
230                                               guint                new_server_id);
231 
232 
233 static GConfEngine*
gconf_engine_blank(gboolean remote)234 gconf_engine_blank (gboolean remote)
235 {
236   GConfEngine* conf;
237 
238   _gconf_init_i18n ();
239 
240   conf = g_new0(GConfEngine, 1);
241 
242   conf->refcount = 1;
243 
244   conf->owner = NULL;
245   conf->owner_use_count = 0;
246 
247   if (remote)
248     {
249       conf->database = CORBA_OBJECT_NIL;
250       conf->ctable = ctable_new();
251       conf->local_sources = NULL;
252       conf->is_local = FALSE;
253     }
254   else
255     {
256       conf->database = CORBA_OBJECT_NIL;
257       conf->ctable = NULL;
258       conf->local_sources = NULL;
259       conf->is_local = TRUE;
260     }
261 
262   return conf;
263 }
264 
265 void
gconf_engine_set_owner(GConfEngine * engine,gpointer client)266 gconf_engine_set_owner (GConfEngine *engine,
267                         gpointer     client)
268 {
269   g_return_if_fail (engine->owner_use_count == 0);
270 
271   engine->owner = client;
272 }
273 
274 void
gconf_engine_push_owner_usage(GConfEngine * engine,gpointer client)275 gconf_engine_push_owner_usage (GConfEngine *engine,
276                                gpointer     client)
277 {
278   g_return_if_fail (engine->owner == client);
279 
280   engine->owner_use_count += 1;
281 }
282 
283 void
gconf_engine_pop_owner_usage(GConfEngine * engine,gpointer client)284 gconf_engine_pop_owner_usage  (GConfEngine *engine,
285                                gpointer     client)
286 {
287   g_return_if_fail (engine->owner == client);
288   g_return_if_fail (engine->owner_use_count > 0);
289 
290   engine->owner_use_count -= 1;
291 }
292 
293 static GHashTable *engines_by_db = NULL;
294 
295 static GConfEngine *
lookup_engine_by_database(ConfigDatabase db)296 lookup_engine_by_database (ConfigDatabase db)
297 {
298   if (engines_by_db)
299     return g_hash_table_lookup (engines_by_db, db);
300   else
301     return NULL;
302 }
303 
304 static void
database_rec_release(gpointer rec)305 database_rec_release (gpointer rec)
306 {
307   GConfEngine *conf = rec;
308   CORBA_Environment ev;
309 
310   CORBA_exception_init (&ev);
311 
312   CORBA_Object_release (conf->database, &ev);
313   conf->database = CORBA_OBJECT_NIL;
314 
315   CORBA_exception_free (&ev);
316 }
317 
318 /* This takes ownership of the ConfigDatabase */
319 static void
gconf_engine_set_database(GConfEngine * conf,ConfigDatabase db)320 gconf_engine_set_database (GConfEngine *conf,
321                            ConfigDatabase db)
322 {
323   gconf_engine_detach (conf);
324 
325   conf->database = db;
326 
327   if (engines_by_db == NULL)
328     engines_by_db = g_hash_table_new_full (
329 	    (GHashFunc) gconf_CORBA_Object_hash,
330 	    (GCompareFunc) gconf_CORBA_Object_equal,
331 	    NULL,
332 	    database_rec_release);
333 
334   g_hash_table_insert (engines_by_db, conf->database, conf);
335 }
336 
337 static void
gconf_engine_detach(GConfEngine * conf)338 gconf_engine_detach (GConfEngine *conf)
339 {
340   if (conf->database != CORBA_OBJECT_NIL)
341     {
342       g_hash_table_remove (engines_by_db, conf->database);
343     }
344 }
345 
346 static gboolean
gconf_engine_connect(GConfEngine * conf,gboolean start_if_not_found,GError ** err)347 gconf_engine_connect (GConfEngine *conf,
348                       gboolean start_if_not_found,
349                       GError **err)
350 {
351   ConfigServer cs;
352   ConfigDatabase db;
353   int tries = 0;
354   CORBA_Environment ev;
355 
356   g_return_val_if_fail (!conf->is_local, TRUE);
357 
358   CORBA_exception_init(&ev);
359 
360   if (!CORBA_Object_is_nil (conf->database, &ev))
361     return TRUE;
362 
363  RETRY:
364 
365   cs = gconf_get_config_server(start_if_not_found, err);
366 
367   if (cs == CORBA_OBJECT_NIL)
368     return FALSE; /* Error should already be set */
369 
370   if (conf->addresses == NULL)
371     {
372       db = ConfigServer_get_default_database (cs, &ev);
373     }
374   else if (conf->addresses->next == NULL) /* single element list */
375     {
376       db = ConfigServer_get_database (cs, conf->addresses->data, &ev);
377     }
378   else
379     {
380       ConfigServer2_AddressList *address_list;
381       GSList                    *tmp;
382       int                        i;
383 
384       address_list = ConfigServer2_AddressList__alloc ();
385       address_list->_length  = address_list->_maximum = g_slist_length (conf->addresses);
386       address_list->_buffer  = ConfigServer2_AddressList_allocbuf (address_list->_length);
387       address_list->_release = CORBA_TRUE;
388 
389       i = 0;
390       tmp = conf->addresses;
391       while (tmp != NULL)
392         {
393           g_assert (i < address_list->_length);
394 
395           address_list->_buffer [i] = CORBA_string_dup (tmp->data);
396 
397           tmp = tmp->next;
398           i++;
399         }
400 
401       db = ConfigServer2_get_database_for_addresses ((ConfigServer2) cs, address_list, &ev);
402 
403       CORBA_free (address_list);
404     }
405 
406   if (gconf_server_broken(&ev))
407     {
408       if (tries < MAX_RETRIES)
409         {
410           ++tries;
411           CORBA_exception_free(&ev);
412           gconf_detach_config_server();
413           goto RETRY;
414         }
415     }
416 
417   if (gconf_handle_corba_exception(&ev, err))
418     return FALSE;
419 
420   if (CORBA_Object_is_nil (db, &ev))
421     {
422       if (err)
423         *err = gconf_error_new(GCONF_ERROR_BAD_ADDRESS,
424                                _("Server couldn't resolve the address `%s'"),
425                                conf->persistent_address);
426 
427       return FALSE;
428     }
429 
430   gconf_engine_set_database (conf, db);
431 
432   return TRUE;
433 }
434 
435 static ConfigDatabase
gconf_engine_get_database(GConfEngine * conf,gboolean start_if_not_found,GError ** err)436 gconf_engine_get_database (GConfEngine *conf,
437                            gboolean start_if_not_found,
438                            GError **err)
439 {
440   if (!gconf_engine_connect (conf, start_if_not_found, err))
441     return CORBA_OBJECT_NIL;
442   else
443     return conf->database;
444 }
445 
446 static gboolean
gconf_engine_is_local(GConfEngine * conf)447 gconf_engine_is_local(GConfEngine* conf)
448 {
449   return conf->is_local;
450 }
451 
452 static GHashTable *engines_by_address = NULL;
453 
454 static void
register_engine(GConfEngine * conf)455 register_engine (GConfEngine *conf)
456 {
457   g_return_if_fail (conf->addresses != NULL);
458 
459   g_assert (conf->persistent_address == NULL);
460 
461   conf->persistent_address =
462           gconf_address_list_get_persistent_name (conf->addresses);
463 
464   if (engines_by_address == NULL)
465     engines_by_address = g_hash_table_new (g_str_hash, g_str_equal);
466 
467   g_hash_table_insert (engines_by_address, conf->persistent_address, conf);
468 }
469 
470 static void
unregister_engine(GConfEngine * conf)471 unregister_engine (GConfEngine *conf)
472 {
473   g_return_if_fail (engines_by_address != NULL);
474 
475   g_assert (conf->persistent_address != NULL);
476 
477   g_hash_table_remove (engines_by_address, conf->persistent_address);
478   g_free (conf->persistent_address);
479   conf->persistent_address = NULL;
480 
481   if (g_hash_table_size (engines_by_address) == 0)
482     {
483       g_hash_table_destroy (engines_by_address);
484 
485       engines_by_address = NULL;
486     }
487 }
488 
489 static GConfEngine *
lookup_engine(GSList * addresses)490 lookup_engine (GSList *addresses)
491 {
492   if (engines_by_address != NULL)
493     {
494       GConfEngine *retval;
495       char        *key;
496 
497       key = gconf_address_list_get_persistent_name (addresses);
498 
499       retval = g_hash_table_lookup (engines_by_address, key);
500 
501       g_free (key);
502 
503       return retval;
504     }
505 
506   return NULL;
507 }
508 
509 
510 /*
511  *  Public Interface
512  */
513 
514 GConfEngine*
gconf_engine_get_local(const gchar * address,GError ** err)515 gconf_engine_get_local      (const gchar* address,
516                              GError** err)
517 {
518   GConfEngine* conf;
519   GConfSource* source;
520   GConfSources* sources;
521 
522   g_return_val_if_fail(address != NULL, NULL);
523   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
524 
525   source = gconf_resolve_address(address, err);
526 
527   if (source == NULL)
528     return NULL;
529 
530   sources = gconf_sources_new_from_source(source);
531   if (sources == NULL)
532     return NULL;
533 
534   conf = gconf_engine_blank(FALSE);
535 
536   conf->local_sources = sources;
537 
538   g_assert (gconf_engine_is_local (conf));
539 
540   return conf;
541 }
542 
543 GConfEngine *
gconf_engine_get_local_for_addresses(GSList * addresses,GError ** err)544 gconf_engine_get_local_for_addresses (GSList  *addresses,
545 				      GError **err)
546 {
547   GConfEngine *conf;
548   GConfSources* sources;
549 
550   g_return_val_if_fail (addresses != NULL, NULL);
551   g_return_val_if_fail (err == NULL || *err == NULL, NULL);
552 
553   sources = gconf_sources_new_from_addresses (addresses, err);
554 
555   if (sources == NULL)
556     return NULL;
557 
558   conf = gconf_engine_blank (FALSE);
559 
560   conf->local_sources = sources;
561 
562   g_assert (gconf_engine_is_local (conf));
563 
564   return conf;
565 }
566 
567 /**
568  * gconf_engine_get_default: (skip)
569  *
570  * Returns the default #GConfEngine. All clients should use this, unless
571  * they are special configuration-related tools. The caller of this
572  * function assumes one reference count, and must call
573  * gconf_engine_unref() at some point. It's fairly important to unref the
574  * #GConfEngine, to cleanly close the connection to
575  * <application>gconfd</application>. So if possible close the connection
576  * before exiting your application.
577  *
578  * Return value: (transfer full): the default #GConfEngine.
579  */
580 GConfEngine*
gconf_engine_get_default(void)581 gconf_engine_get_default (void)
582 {
583   GConfEngine* conf = NULL;
584   const gchar* source_path;
585   GError* err = NULL;
586 
587   if (default_engine)
588     conf = default_engine;
589 
590   if (conf == NULL)
591     {
592       conf = gconf_engine_blank(TRUE);
593 
594       default_engine = conf;
595 
596       source_path = g_getenv ("GCONF_DEFAULT_SOURCE_PATH");
597       if (source_path != NULL)
598 	{
599 	  conf->addresses = gconf_load_source_path (source_path, &err);
600 	  if (err)
601 	    {
602 	      g_warning ("Could not parse GCONF_DEFAULT_SOURCE_PATH: %s",
603 			 err->message);
604 	      g_error_free (err);
605 	    }
606 	}
607       else
608 	conf->addresses = NULL;
609 
610       /* Ignore errors, we never return a NULL default database, and
611        * since we aren't starting if it isn't found, we'll probably
612        * get errors half the time anyway.
613        */
614       gconf_engine_connect (conf, FALSE, NULL);
615     }
616   else
617     conf->refcount += 1;
618 
619   return conf;
620 }
621 
622 GConfEngine*
gconf_engine_get_for_address(const char * address,GError ** err)623 gconf_engine_get_for_address (const char  *address,
624 			      GError     **err)
625 {
626   GConfEngine *conf;
627   GSList      *addresses;
628 
629   addresses = g_slist_append (NULL, g_strdup (address));
630 
631   conf = lookup_engine (addresses);
632 
633   if (conf == NULL)
634     {
635       conf = gconf_engine_blank (TRUE);
636 
637       conf->addresses = addresses;
638 
639       if (!gconf_engine_connect (conf, TRUE, err))
640         {
641           gconf_engine_unref (conf);
642           return NULL;
643         }
644 
645       register_engine (conf);
646     }
647   else
648     {
649       g_free (addresses->data);
650       g_slist_free (addresses);
651       conf->refcount += 1;
652     }
653 
654   return conf;
655 }
656 
657 GConfEngine*
gconf_engine_get_for_addresses(GSList * addresses,GError ** err)658 gconf_engine_get_for_addresses (GSList *addresses, GError** err)
659 {
660   GConfEngine* conf;
661 
662   conf = lookup_engine (addresses);
663 
664   if (conf == NULL)
665     {
666       GSList *tmp;
667 
668       conf = gconf_engine_blank (TRUE);
669 
670       conf->addresses = NULL;
671 
672       tmp = addresses;
673       while (tmp != NULL)
674         {
675           conf->addresses = g_slist_append (conf->addresses,
676                                             g_strdup (tmp->data));
677           tmp = tmp->next;
678         }
679 
680       if (!gconf_engine_connect (conf, TRUE, err))
681         {
682           gconf_engine_unref (conf);
683           return NULL;
684         }
685 
686       register_engine (conf);
687     }
688   else
689     conf->refcount += 1;
690 
691   return conf;
692 }
693 
694 void
gconf_engine_ref(GConfEngine * conf)695 gconf_engine_ref(GConfEngine* conf)
696 {
697   g_return_if_fail(conf != NULL);
698   g_return_if_fail(conf->refcount > 0);
699 
700   conf->refcount += 1;
701 }
702 
703 void
gconf_engine_unref(GConfEngine * conf)704 gconf_engine_unref(GConfEngine* conf)
705 {
706   g_return_if_fail(conf != NULL);
707   g_return_if_fail(conf->refcount > 0);
708 
709   conf->refcount -= 1;
710 
711   if (conf->refcount == 0)
712     {
713       if (gconf_engine_is_local(conf))
714         {
715           if (conf->local_sources != NULL)
716             gconf_sources_free(conf->local_sources);
717         }
718       else
719         {
720           /* Remove all connections associated with this GConf */
721           GSList* removed;
722           GSList* tmp;
723           CORBA_Environment ev;
724 
725           CORBA_exception_init(&ev);
726 
727           /* FIXME CnxnTable only has entries for this GConfEngine now,
728            * it used to be global and shared among GConfEngine objects.
729            */
730           removed = ctable_remove_by_conf (conf->ctable, conf);
731 
732           tmp = removed;
733           while (tmp != NULL)
734             {
735               GConfCnxn* gcnxn = tmp->data;
736 
737               if (!CORBA_Object_is_nil (conf->database, &ev))
738                 {
739                   GError* err = NULL;
740 
741                   ConfigDatabase_remove_listener(conf->database,
742                                                  gcnxn->server_id,
743                                                  &ev);
744 
745                   if (gconf_handle_corba_exception(&ev, &err))
746                     {
747                       /* Don't set error because realistically this
748                          doesn't matter to clients */
749 #ifdef GCONF_ENABLE_DEBUG
750                       g_warning("Failure removing listener %u from the configuration server: %s",
751                                 (guint)gcnxn->server_id,
752                                 err->message);
753 #endif
754                     }
755                 }
756 
757               gconf_cnxn_destroy(gcnxn);
758 
759               tmp = g_slist_next(tmp);
760             }
761 
762           g_slist_free(removed);
763 
764           if (conf->dnotify)
765             {
766               (* conf->dnotify) (conf->user_data);
767             }
768 
769           if (conf->addresses)
770 	    {
771 	      gconf_address_list_free (conf->addresses);
772 	      conf->addresses = NULL;
773 	    }
774 
775 	  if (conf->persistent_address)
776 	    {
777 	      unregister_engine (conf);
778 	    }
779 
780           /* Release the ConfigDatabase */
781           gconf_engine_detach (conf);
782 
783           ctable_destroy (conf->ctable);
784         }
785 
786       if (conf == default_engine)
787         default_engine = NULL;
788 
789       g_free(conf);
790     }
791 }
792 
793 void
gconf_engine_set_user_data(GConfEngine * engine,gpointer data,GDestroyNotify dnotify)794 gconf_engine_set_user_data  (GConfEngine   *engine,
795                              gpointer       data,
796                              GDestroyNotify dnotify)
797 {
798   if (engine->dnotify)
799     {
800       (* engine->dnotify) (engine->user_data);
801     }
802 
803   engine->dnotify = dnotify;
804   engine->user_data = data;
805 }
806 
807 gpointer
gconf_engine_get_user_data(GConfEngine * engine)808 gconf_engine_get_user_data  (GConfEngine   *engine)
809 {
810   return engine->user_data;
811 }
812 
813 /**
814  * gconf_engine_notify_add: (skip)
815  * @conf: a #GConfEngine to monitor for changes.
816  * @namespace_section: the directory or key to watch; you will be notified of changes at or below this point.
817  * @func: the callback to invoke when a notification is received from the server.
818  * @user_data: the data to pass to the callback.
819  * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
820  * Return value: an ID for the notification request, or 0 on error.
821  *
822  * Registers a notification request with the <application>gconfd</application>
823  * server.  The server will notify the client when any key at or below
824  * @namespace_section is set or unset. Try to watch the smallest possible part of
825  * the namespace; otherwise you will slow down the server and your application with
826  * unnecessary notifications. Note that you should prefer gconf_client_notify_add()
827  * if you're using the #GObject wrapper library, because
828  * gconf_client_notify_add() does not require a client-server conversation for
829  * every callback. gconf_engine_notify_add() requests a different server notification for
830  * every callback. The function returns an ID you can use to remove the
831  * notification request; 0 is an invalid ID, and is returned if an error occurs.
832  *
833  * Returns value: an ID for the notification request, or 0 on error.
834  */
835 guint
gconf_engine_notify_add(GConfEngine * conf,const gchar * namespace_section,GConfNotifyFunc func,gpointer user_data,GError ** err)836 gconf_engine_notify_add(GConfEngine* conf,
837                         const gchar* namespace_section,
838                         GConfNotifyFunc func,
839                         gpointer user_data,
840                         GError** err)
841 {
842   ConfigDatabase db;
843   ConfigListener cl;
844   gulong id;
845   CORBA_Environment ev;
846   GConfCnxn* cnxn;
847   gint tries = 0;
848   ConfigDatabase3_PropList properties;
849 #define NUM_PROPERTIES 1
850   ConfigStringProperty properties_buffer[1];
851 
852   g_return_val_if_fail(!gconf_engine_is_local(conf), 0);
853 
854   CHECK_OWNER_USE (conf);
855 
856   if (gconf_engine_is_local(conf))
857     {
858       if (err)
859         *err = gconf_error_new(GCONF_ERROR_LOCAL_ENGINE,
860                                _("Can't add notifications to a local configuration source"));
861 
862       return 0;
863     }
864 
865   properties._buffer = properties_buffer;
866   properties._length = NUM_PROPERTIES;
867   properties._maximum = NUM_PROPERTIES;
868   properties._release = CORBA_FALSE; /* don't free static buffer */
869 
870   properties._buffer[0].key = "name";
871   properties._buffer[0].value = g_get_prgname ();
872   if (properties._buffer[0].value == NULL)
873     properties._buffer[0].value = "unknown";
874 
875   CORBA_exception_init(&ev);
876 
877  RETRY:
878 
879   db = gconf_engine_get_database (conf, TRUE, err);
880 
881   if (db == CORBA_OBJECT_NIL)
882     return 0;
883 
884   cl = gconf_get_config_listener ();
885 
886   /* Should have aborted the program in this case probably */
887   g_return_val_if_fail(cl != CORBA_OBJECT_NIL, 0);
888 
889   id = ConfigDatabase3_add_listener_with_properties (db,
890                                                      (gchar*)namespace_section,
891                                                      cl,
892                                                      &properties,
893                                                      &ev);
894 
895   if (ev._major == CORBA_SYSTEM_EXCEPTION &&
896       CORBA_exception_id (&ev) &&
897       strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
898     {
899       CORBA_exception_free (&ev);
900       CORBA_exception_init (&ev);
901 
902       id = ConfigDatabase_add_listener(db,
903                                        (gchar*)namespace_section,
904                                        cl, &ev);
905     }
906 
907   if (gconf_server_broken(&ev))
908     {
909       if (tries < MAX_RETRIES)
910         {
911           ++tries;
912           CORBA_exception_free(&ev);
913           gconf_engine_detach (conf);
914           goto RETRY;
915         }
916     }
917 
918   if (gconf_handle_corba_exception(&ev, err))
919     return 0;
920 
921   cnxn = gconf_cnxn_new(conf, namespace_section, id, func, user_data);
922 
923   ctable_insert(conf->ctable, cnxn);
924 
925   return cnxn->client_id;
926 }
927 
928 void
gconf_engine_notify_remove(GConfEngine * conf,guint client_id)929 gconf_engine_notify_remove(GConfEngine* conf,
930                            guint client_id)
931 {
932   GConfCnxn* gcnxn;
933   CORBA_Environment ev;
934   ConfigDatabase db;
935   gint tries = 0;
936 
937   CHECK_OWNER_USE (conf);
938 
939   if (gconf_engine_is_local(conf))
940     return;
941 
942   CORBA_exception_init(&ev);
943 
944  RETRY:
945 
946   db = gconf_engine_get_database (conf, TRUE, NULL);
947 
948   if (db == CORBA_OBJECT_NIL)
949     return;
950 
951   gcnxn = ctable_lookup_by_client_id(conf->ctable, client_id);
952 
953   g_return_if_fail(gcnxn != NULL);
954 
955   ConfigDatabase_remove_listener(db,
956                                  gcnxn->server_id,
957                                  &ev);
958 
959   if (gconf_server_broken(&ev))
960     {
961       if (tries < MAX_RETRIES)
962         {
963           ++tries;
964           CORBA_exception_free(&ev);
965           gconf_engine_detach (conf);
966           goto RETRY;
967         }
968     }
969 
970   if (gconf_handle_corba_exception(&ev, NULL))
971     {
972       ; /* do nothing */
973     }
974 
975 
976   /* We want to do this even if the CORBA fails, so if we restart gconfd and
977      reinstall listeners we don't reinstall this one. */
978   ctable_remove(conf->ctable, gcnxn);
979 
980   gconf_cnxn_destroy(gcnxn);
981 }
982 
983 GConfValue *
gconf_engine_get_fuller(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,gboolean * is_default_p,gboolean * is_writable_p,gchar ** schema_name_p,GError ** err)984 gconf_engine_get_fuller (GConfEngine *conf,
985                          const gchar *key,
986                          const gchar *locale,
987                          gboolean use_schema_default,
988                          gboolean *is_default_p,
989                          gboolean *is_writable_p,
990                          gchar   **schema_name_p,
991                          GError **err)
992 {
993   GConfValue* val;
994   ConfigValue* cv;
995   CORBA_Environment ev;
996   ConfigDatabase db;
997   gint tries = 0;
998   CORBA_boolean is_default = FALSE;
999   CORBA_boolean is_writable = TRUE;
1000   CORBA_char *corba_schema_name = NULL;
1001 
1002   g_return_val_if_fail(conf != NULL, NULL);
1003   g_return_val_if_fail(key != NULL, NULL);
1004   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1005 
1006   CHECK_OWNER_USE (conf);
1007 
1008   if (!gconf_key_check(key, err))
1009     return NULL;
1010 
1011   if (gconf_engine_is_local(conf))
1012     {
1013       gchar** locale_list;
1014       gboolean tmp_is_default = FALSE;
1015       gboolean tmp_is_writable = TRUE;
1016       gchar *tmp_schema_name = NULL;
1017 
1018       locale_list = gconf_split_locale(locale);
1019 
1020       val = gconf_sources_query_value(conf->local_sources,
1021                                       key,
1022                                       (const gchar**)locale_list,
1023                                       use_schema_default,
1024                                       &tmp_is_default,
1025                                       &tmp_is_writable,
1026                                       schema_name_p ? &tmp_schema_name : NULL,
1027                                       err);
1028 
1029       if (locale_list != NULL)
1030         g_strfreev(locale_list);
1031 
1032       if (is_default_p)
1033         *is_default_p = tmp_is_default;
1034 
1035       if (is_writable_p)
1036         *is_writable_p = tmp_is_writable;
1037 
1038       if (schema_name_p)
1039         *schema_name_p = tmp_schema_name;
1040       else
1041         g_free (tmp_schema_name);
1042 
1043       return val;
1044     }
1045 
1046   g_assert(!gconf_engine_is_local(conf));
1047 
1048   CORBA_exception_init(&ev);
1049 
1050  RETRY:
1051 
1052   db = gconf_engine_get_database (conf, TRUE, err);
1053 
1054   if (db == CORBA_OBJECT_NIL)
1055     {
1056       g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1057 
1058       return NULL;
1059     }
1060 
1061   if (schema_name_p)
1062     *schema_name_p = NULL;
1063 
1064 
1065   corba_schema_name = NULL;
1066   cv = ConfigDatabase2_lookup_with_schema_name (db,
1067                                                 (gchar*)key, (gchar*)
1068                                                 (locale ? locale : gconf_current_locale()),
1069                                                 use_schema_default,
1070                                                 &corba_schema_name,
1071                                                 &is_default,
1072                                                 &is_writable,
1073                                                 &ev);
1074 
1075   if (ev._major == CORBA_SYSTEM_EXCEPTION &&
1076       CORBA_exception_id (&ev) &&
1077       strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
1078     {
1079       CORBA_exception_free (&ev);
1080       CORBA_exception_init (&ev);
1081 
1082       cv = ConfigDatabase_lookup_with_locale(db,
1083                                              (gchar*)key, (gchar*)
1084                                              (locale ? locale : gconf_current_locale()),
1085                                              use_schema_default,
1086                                              &is_default,
1087                                              &is_writable,
1088                                              &ev);
1089     }
1090 
1091   if (gconf_server_broken(&ev))
1092     {
1093       if (tries < MAX_RETRIES)
1094         {
1095           ++tries;
1096           CORBA_exception_free(&ev);
1097           gconf_engine_detach (conf);
1098           goto RETRY;
1099         }
1100     }
1101 
1102   if (gconf_handle_corba_exception(&ev, err))
1103     {
1104       /* NOTE: don't free cv since we got an exception! */
1105       return NULL;
1106     }
1107   else
1108     {
1109       val = gconf_value_from_corba_value(cv);
1110       CORBA_free(cv);
1111 
1112       if (is_default_p)
1113         *is_default_p = !!is_default;
1114       if (is_writable_p)
1115         *is_writable_p = !!is_writable;
1116 
1117       /* we can't get a null pointer through corba
1118        * so the server sent us an empty string
1119        */
1120       if (corba_schema_name && corba_schema_name[0] != '/')
1121         {
1122           CORBA_free (corba_schema_name);
1123           corba_schema_name = NULL;
1124         }
1125 
1126       if (schema_name_p)
1127         *schema_name_p = g_strdup (corba_schema_name);
1128 
1129       if (corba_schema_name)
1130         CORBA_free (corba_schema_name);
1131 
1132       return val;
1133     }
1134 }
1135 
1136 
1137 GConfValue *
gconf_engine_get_full(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,gboolean * is_default_p,gboolean * is_writable_p,GError ** err)1138 gconf_engine_get_full (GConfEngine *conf,
1139                        const gchar *key,
1140                        const gchar *locale,
1141                        gboolean use_schema_default,
1142                        gboolean *is_default_p,
1143                        gboolean *is_writable_p,
1144                        GError **err)
1145 {
1146   return gconf_engine_get_fuller (conf, key, locale, use_schema_default,
1147                                   is_default_p, is_writable_p,
1148                                   NULL, err);
1149 }
1150 
1151 GConfEntry*
gconf_engine_get_entry(GConfEngine * conf,const gchar * key,const gchar * locale,gboolean use_schema_default,GError ** err)1152 gconf_engine_get_entry(GConfEngine* conf,
1153                        const gchar* key,
1154                        const gchar* locale,
1155                        gboolean use_schema_default,
1156                        GError** err)
1157 {
1158   gboolean is_writable = TRUE;
1159   gboolean is_default = FALSE;
1160   GConfValue *val;
1161   GError *error;
1162   GConfEntry *entry;
1163   gchar *schema_name;
1164 
1165   CHECK_OWNER_USE (conf);
1166 
1167   schema_name = NULL;
1168   error = NULL;
1169   val = gconf_engine_get_fuller (conf, key, locale, use_schema_default,
1170                                  &is_default, &is_writable,
1171                                  &schema_name, &error);
1172   if (error != NULL)
1173     {
1174       g_propagate_error (err, error);
1175       return NULL;
1176     }
1177 
1178   entry = gconf_entry_new_nocopy (g_strdup (key),
1179                                   val);
1180 
1181   gconf_entry_set_is_default (entry, is_default);
1182   gconf_entry_set_is_writable (entry, is_writable);
1183   gconf_entry_set_schema_name (entry, schema_name);
1184   g_free (schema_name);
1185 
1186   return entry;
1187 }
1188 
1189 GConfValue*
gconf_engine_get(GConfEngine * conf,const gchar * key,GError ** err)1190 gconf_engine_get (GConfEngine* conf, const gchar* key, GError** err)
1191 {
1192   return gconf_engine_get_with_locale(conf, key, NULL, err);
1193 }
1194 
1195 GConfValue*
gconf_engine_get_with_locale(GConfEngine * conf,const gchar * key,const gchar * locale,GError ** err)1196 gconf_engine_get_with_locale(GConfEngine* conf, const gchar* key,
1197                              const gchar* locale,
1198                              GError** err)
1199 {
1200   return gconf_engine_get_full(conf, key, locale, TRUE,
1201                                NULL, NULL, err);
1202 }
1203 
1204 GConfValue*
gconf_engine_get_without_default(GConfEngine * conf,const gchar * key,GError ** err)1205 gconf_engine_get_without_default(GConfEngine* conf, const gchar* key,
1206                                  GError** err)
1207 {
1208   return gconf_engine_get_full(conf, key, NULL, FALSE, NULL, NULL, err);
1209 }
1210 
1211 GConfValue*
gconf_engine_get_default_from_schema(GConfEngine * conf,const gchar * key,GError ** err)1212 gconf_engine_get_default_from_schema (GConfEngine* conf,
1213                                       const gchar* key,
1214                                       GError** err)
1215 {
1216   GConfValue* val;
1217   ConfigValue* cv;
1218   CORBA_Environment ev;
1219   ConfigDatabase db;
1220   gint tries = 0;
1221 
1222   g_return_val_if_fail(conf != NULL, NULL);
1223   g_return_val_if_fail(key != NULL, NULL);
1224   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1225 
1226   CHECK_OWNER_USE (conf);
1227 
1228   if (!gconf_key_check(key, err))
1229     return NULL;
1230 
1231   if (gconf_engine_is_local(conf))
1232     {
1233       gchar** locale_list;
1234 
1235       locale_list = gconf_split_locale(gconf_current_locale());
1236 
1237       val = gconf_sources_query_default_value(conf->local_sources,
1238                                               key,
1239                                               (const gchar**)locale_list,
1240                                               NULL,
1241                                               err);
1242 
1243       if (locale_list != NULL)
1244         g_strfreev(locale_list);
1245 
1246       return val;
1247     }
1248 
1249   g_assert(!gconf_engine_is_local(conf));
1250 
1251   CORBA_exception_init(&ev);
1252 
1253  RETRY:
1254 
1255   db = gconf_engine_get_database (conf, TRUE, err);
1256 
1257   if (db == CORBA_OBJECT_NIL)
1258     {
1259       g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1260 
1261       return NULL;
1262     }
1263 
1264   cv = ConfigDatabase_lookup_default_value(db,
1265                                            (gchar*)key,
1266                                            (gchar*)gconf_current_locale(),
1267                                            &ev);
1268 
1269   if (gconf_server_broken(&ev))
1270     {
1271       if (tries < MAX_RETRIES)
1272         {
1273           ++tries;
1274           CORBA_exception_free(&ev);
1275           gconf_engine_detach (conf);
1276           goto RETRY;
1277         }
1278     }
1279 
1280   if (gconf_handle_corba_exception(&ev, err))
1281     {
1282       /* NOTE: don't free cv since we got an exception! */
1283       return NULL;
1284     }
1285   else
1286     {
1287       val = gconf_value_from_corba_value(cv);
1288       CORBA_free(cv);
1289 
1290       return val;
1291     }
1292 }
1293 
1294 gboolean
gconf_engine_set(GConfEngine * conf,const gchar * key,const GConfValue * value,GError ** err)1295 gconf_engine_set (GConfEngine* conf, const gchar* key,
1296                   const GConfValue* value, GError** err)
1297 {
1298   ConfigValue* cv;
1299   CORBA_Environment ev;
1300   ConfigDatabase db;
1301   gint tries = 0;
1302 
1303   g_return_val_if_fail(conf != NULL, FALSE);
1304   g_return_val_if_fail(key != NULL, FALSE);
1305   g_return_val_if_fail(value != NULL, FALSE);
1306   g_return_val_if_fail(value->type != GCONF_VALUE_INVALID, FALSE);
1307   g_return_val_if_fail( (value->type != GCONF_VALUE_STRING) ||
1308                         (gconf_value_get_string(value) != NULL) , FALSE );
1309   g_return_val_if_fail( (value->type != GCONF_VALUE_LIST) ||
1310                         (gconf_value_get_list_type(value) != GCONF_VALUE_INVALID), FALSE);
1311   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
1312 
1313   CHECK_OWNER_USE (conf);
1314 
1315   if (!gconf_key_check(key, err))
1316     return FALSE;
1317 
1318   if (!gconf_value_validate (value, err))
1319     return FALSE;
1320 
1321   if (gconf_engine_is_local(conf))
1322     {
1323       GError* error = NULL;
1324 
1325       gconf_sources_set_value(conf->local_sources, key, value, NULL, &error);
1326 
1327       if (error != NULL)
1328         {
1329           if (err)
1330             *err = error;
1331           else
1332             {
1333               g_error_free(error);
1334             }
1335           return FALSE;
1336         }
1337 
1338       return TRUE;
1339     }
1340 
1341   g_assert(!gconf_engine_is_local(conf));
1342 
1343   CORBA_exception_init(&ev);
1344 
1345  RETRY:
1346 
1347   db = gconf_engine_get_database (conf, TRUE, err);
1348 
1349   if (db == CORBA_OBJECT_NIL)
1350     {
1351       g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
1352 
1353       return FALSE;
1354     }
1355 
1356   cv = gconf_corba_value_from_gconf_value (value);
1357 
1358   ConfigDatabase_set(db,
1359                      (gchar*)key, cv,
1360                      &ev);
1361 
1362   CORBA_free(cv);
1363 
1364   if (gconf_server_broken(&ev))
1365     {
1366       if (tries < MAX_RETRIES)
1367         {
1368           ++tries;
1369           CORBA_exception_free(&ev);
1370           gconf_engine_detach (conf);
1371           goto RETRY;
1372         }
1373     }
1374 
1375   if (gconf_handle_corba_exception(&ev, err))
1376     return FALSE;
1377 
1378   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
1379 
1380   return TRUE;
1381 }
1382 
1383 gboolean
gconf_engine_unset(GConfEngine * conf,const gchar * key,GError ** err)1384 gconf_engine_unset (GConfEngine* conf, const gchar* key, GError** err)
1385 {
1386   CORBA_Environment ev;
1387   ConfigDatabase db;
1388   gint tries = 0;
1389 
1390   g_return_val_if_fail (conf != NULL, FALSE);
1391   g_return_val_if_fail (key != NULL, FALSE);
1392   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1393 
1394   CHECK_OWNER_USE (conf);
1395 
1396   if (!gconf_key_check(key, err))
1397     return FALSE;
1398 
1399   if (gconf_engine_is_local(conf))
1400     {
1401       GError* error = NULL;
1402 
1403       gconf_sources_unset_value(conf->local_sources, key, NULL, NULL, &error);
1404 
1405       if (error != NULL)
1406         {
1407           if (err)
1408             *err = error;
1409           else
1410             {
1411               g_error_free(error);
1412             }
1413           return FALSE;
1414         }
1415 
1416       return TRUE;
1417     }
1418 
1419   g_assert(!gconf_engine_is_local(conf));
1420 
1421   CORBA_exception_init(&ev);
1422 
1423  RETRY:
1424 
1425   db = gconf_engine_get_database (conf, TRUE, err);
1426 
1427   if (db == CORBA_OBJECT_NIL)
1428     {
1429       g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
1430 
1431       return FALSE;
1432     }
1433 
1434   ConfigDatabase_unset (db,
1435                         (gchar*)key,
1436                         &ev);
1437 
1438   if (gconf_server_broken (&ev))
1439     {
1440       if (tries < MAX_RETRIES)
1441         {
1442           ++tries;
1443           CORBA_exception_free(&ev);
1444           gconf_engine_detach(conf);
1445           goto RETRY;
1446         }
1447     }
1448 
1449   if (gconf_handle_corba_exception (&ev, err))
1450     return FALSE;
1451 
1452   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1453 
1454   return TRUE;
1455 }
1456 
1457 /**
1458  * gconf_engine_recursive_unset:
1459  * @engine: a #GConfEngine
1460  * @key: a key or directory name
1461  * @flags: change how the unset is done
1462  * @err: return location for a #GError, or %NULL to ignore errors
1463  *
1464  * Unsets all keys below @key, including @key itself.  If any unset
1465  * fails, continues on to unset as much as it can. The first
1466  * failure is returned in @err.
1467  *
1468  * Returns: %FALSE if error is set
1469  **/
1470 gboolean
gconf_engine_recursive_unset(GConfEngine * conf,const char * key,GConfUnsetFlags flags,GError ** err)1471 gconf_engine_recursive_unset (GConfEngine    *conf,
1472                               const char     *key,
1473                               GConfUnsetFlags flags,
1474                               GError        **err)
1475 {
1476   CORBA_Environment ev;
1477   ConfigDatabase3 db;
1478   gint tries = 0;
1479   ConfigDatabase3_UnsetFlags corba_flags;
1480 
1481   g_return_val_if_fail (conf != NULL, FALSE);
1482   g_return_val_if_fail (key != NULL, FALSE);
1483   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1484 
1485   CHECK_OWNER_USE (conf);
1486 
1487   if (!gconf_key_check (key, err))
1488     return FALSE;
1489 
1490   if (gconf_engine_is_local (conf))
1491     {
1492       GError* error = NULL;
1493 
1494       gconf_sources_recursive_unset (conf->local_sources, key, NULL,
1495                                      flags, NULL, &error);
1496 
1497       if (error != NULL)
1498         {
1499           if (err)
1500             *err = error;
1501           else
1502             {
1503               g_error_free (error);
1504             }
1505           return FALSE;
1506         }
1507 
1508       return TRUE;
1509     }
1510 
1511   g_assert (!gconf_engine_is_local (conf));
1512 
1513   CORBA_exception_init(&ev);
1514 
1515   corba_flags = 0;
1516   if (flags & GCONF_UNSET_INCLUDING_SCHEMA_NAMES)
1517     corba_flags |= ConfigDatabase3_UNSET_INCLUDING_SCHEMA_NAMES;
1518 
1519  RETRY:
1520 
1521   db = (ConfigDatabase3) gconf_engine_get_database (conf, TRUE, err);
1522 
1523   if (db == CORBA_OBJECT_NIL)
1524     {
1525       g_return_val_if_fail (err == NULL || *err != NULL, FALSE);
1526 
1527       return FALSE;
1528     }
1529 
1530   ConfigDatabase3_recursive_unset (db, key, corba_flags, &ev);
1531 
1532   if (gconf_server_broken (&ev))
1533     {
1534       if (tries < MAX_RETRIES)
1535         {
1536           ++tries;
1537           CORBA_exception_free(&ev);
1538           gconf_engine_detach(conf);
1539           goto RETRY;
1540         }
1541     }
1542 
1543   if (gconf_handle_corba_exception (&ev, err))
1544     return FALSE;
1545 
1546   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1547 
1548   return TRUE;
1549 }
1550 
1551 gboolean
gconf_engine_associate_schema(GConfEngine * conf,const gchar * key,const gchar * schema_key,GError ** err)1552 gconf_engine_associate_schema  (GConfEngine* conf, const gchar* key,
1553                                 const gchar* schema_key, GError** err)
1554 {
1555   CORBA_Environment ev;
1556   ConfigDatabase db;
1557   gint tries = 0;
1558 
1559   g_return_val_if_fail (conf != NULL, FALSE);
1560   g_return_val_if_fail (key != NULL, FALSE);
1561   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1562 
1563   if (!gconf_key_check (key, err))
1564     return FALSE;
1565 
1566   if (schema_key && !gconf_key_check (schema_key, err))
1567     return FALSE;
1568 
1569   if (gconf_engine_is_local(conf))
1570     {
1571       GError* error = NULL;
1572 
1573       gconf_sources_set_schema (conf->local_sources, key, schema_key, &error);
1574 
1575       if (error != NULL)
1576         {
1577           if (err)
1578             *err = error;
1579           else
1580             {
1581               g_error_free(error);
1582             }
1583           return FALSE;
1584         }
1585 
1586       return TRUE;
1587     }
1588 
1589   g_assert (!gconf_engine_is_local (conf));
1590 
1591   CORBA_exception_init (&ev);
1592 
1593  RETRY:
1594 
1595   db = gconf_engine_get_database (conf, TRUE, err);
1596 
1597   if (db == CORBA_OBJECT_NIL)
1598     {
1599       g_return_val_if_fail (err == NULL || *err != NULL, FALSE);
1600 
1601       return FALSE;
1602     }
1603 
1604   ConfigDatabase_set_schema (db,
1605                              key,
1606                              /* empty string means unset */
1607                              schema_key ? schema_key : "",
1608                              &ev);
1609 
1610   if (gconf_server_broken (&ev))
1611     {
1612       if (tries < MAX_RETRIES)
1613         {
1614           ++tries;
1615           CORBA_exception_free (&ev);
1616           gconf_engine_detach (conf);
1617           goto RETRY;
1618         }
1619     }
1620 
1621   if (gconf_handle_corba_exception(&ev, err))
1622     return FALSE;
1623 
1624   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
1625 
1626   return TRUE;
1627 }
1628 
1629 
1630 static void
qualify_entries(GSList * entries,const char * dir)1631 qualify_entries (GSList *entries, const char *dir)
1632 {
1633   GSList *tmp = entries;
1634   while (tmp != NULL)
1635     {
1636       GConfEntry *entry = tmp->data;
1637       gchar *full;
1638 
1639       full = gconf_concat_dir_and_key (dir, entry->key);
1640 
1641       g_free (entry->key);
1642       entry->key = full;
1643 
1644       tmp = g_slist_next (tmp);
1645     }
1646 }
1647 
1648 /**
1649  * gconf_engine_all_entries:
1650  * @conf: a #GConfEngine.
1651  * @dir: Directory to list.
1652  * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
1653  *
1654  * Lists the key-value pairs in @dir. Does not list subdirectories; for
1655  * that use gconf_engine_all_dirs(). The returned list contains #GConfEntry
1656  * objects. A #GConfEntry contains an <emphasis>absolute</emphasis> key
1657  * and a value. The list is not recursive, it contains only the immediate
1658  * children of @dir.  To free the returned list, gconf_entry_free()
1659  * each list element, then g_slist_free() the list itself.
1660  *
1661  * Returns value: (element-type GConfEntry) (transfer full): List of #GConfEntry.
1662  */
1663 GSList*
gconf_engine_all_entries(GConfEngine * conf,const gchar * dir,GError ** err)1664 gconf_engine_all_entries(GConfEngine* conf, const gchar* dir, GError** err)
1665 {
1666   GSList* pairs = NULL;
1667   ConfigDatabase_ValueList* values;
1668   ConfigDatabase_KeyList* keys;
1669   ConfigDatabase_IsDefaultList* is_defaults;
1670   ConfigDatabase_IsWritableList* is_writables;
1671   ConfigDatabase2_SchemaNameList *schema_names;
1672   CORBA_Environment ev;
1673   ConfigDatabase db;
1674   guint i;
1675   gint tries = 0;
1676 
1677   g_return_val_if_fail(conf != NULL, NULL);
1678   g_return_val_if_fail(dir != NULL, NULL);
1679   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1680 
1681   CHECK_OWNER_USE (conf);
1682 
1683   if (!gconf_key_check(dir, err))
1684     return NULL;
1685 
1686 
1687   if (gconf_engine_is_local(conf))
1688     {
1689       GError* error = NULL;
1690       gchar** locale_list;
1691       GSList* retval;
1692 
1693       locale_list = gconf_split_locale(gconf_current_locale());
1694 
1695       retval = gconf_sources_all_entries(conf->local_sources,
1696                                          dir,
1697                                          (const gchar**)locale_list,
1698                                          &error);
1699 
1700       if (locale_list)
1701         g_strfreev(locale_list);
1702 
1703       if (error != NULL)
1704         {
1705           if (err)
1706             *err = error;
1707           else
1708             {
1709               g_error_free(error);
1710             }
1711 
1712           g_assert(retval == NULL);
1713 
1714           return NULL;
1715         }
1716 
1717       qualify_entries (retval, dir);
1718 
1719       return retval;
1720     }
1721 
1722   g_assert(!gconf_engine_is_local(conf));
1723 
1724   CORBA_exception_init(&ev);
1725 
1726  RETRY:
1727 
1728   db = gconf_engine_get_database (conf, TRUE, err);
1729 
1730   if (db == CORBA_OBJECT_NIL)
1731     {
1732       g_return_val_if_fail(err == NULL || *err != NULL, NULL);
1733 
1734       return NULL;
1735     }
1736 
1737   schema_names = NULL;
1738 
1739   ConfigDatabase2_all_entries_with_schema_name (db,
1740                                                 (gchar*)dir,
1741                                                 (gchar*)gconf_current_locale(),
1742                                                 &keys, &values, &schema_names,
1743                                                 &is_defaults, &is_writables,
1744                                                 &ev);
1745 
1746   if (ev._major == CORBA_SYSTEM_EXCEPTION &&
1747       CORBA_exception_id (&ev) &&
1748       strcmp (CORBA_exception_id (&ev), "IDL:CORBA/BAD_OPERATION:1.0") == 0)
1749     {
1750       CORBA_exception_free (&ev);
1751       CORBA_exception_init (&ev);
1752 
1753       ConfigDatabase_all_entries(db,
1754                                  (gchar*)dir,
1755                                  (gchar*)gconf_current_locale(),
1756                                  &keys, &values, &is_defaults, &is_writables,
1757                                  &ev);
1758     }
1759 
1760   if (gconf_server_broken(&ev))
1761     {
1762       if (tries < MAX_RETRIES)
1763         {
1764           ++tries;
1765           CORBA_exception_free(&ev);
1766           gconf_engine_detach (conf);
1767           goto RETRY;
1768         }
1769     }
1770 
1771   if (gconf_handle_corba_exception(&ev, err))
1772     return NULL;
1773 
1774   if (keys->_length != values->_length)
1775     {
1776       g_warning("Received unmatched key/value sequences in %s",
1777                 G_STRFUNC);
1778       return NULL;
1779     }
1780 
1781   i = 0;
1782   while (i < keys->_length)
1783     {
1784       GConfEntry* pair;
1785 
1786       pair =
1787         gconf_entry_new_nocopy(gconf_concat_dir_and_key (dir, keys->_buffer[i]),
1788                                gconf_value_from_corba_value(&(values->_buffer[i])));
1789 
1790       gconf_entry_set_is_default (pair, is_defaults->_buffer[i]);
1791       gconf_entry_set_is_writable (pair, is_writables->_buffer[i]);
1792       if (schema_names)
1793         {
1794           /* empty string means no schema name */
1795           if (*(schema_names->_buffer[i]) != '\0')
1796             gconf_entry_set_schema_name (pair, schema_names->_buffer[i]);
1797         }
1798 
1799       pairs = g_slist_prepend(pairs, pair);
1800 
1801       ++i;
1802     }
1803 
1804   CORBA_free(keys);
1805   CORBA_free(values);
1806   CORBA_free(is_defaults);
1807   CORBA_free(is_writables);
1808   if (schema_names)
1809     CORBA_free (schema_names);
1810 
1811   return pairs;
1812 }
1813 
1814 
1815 static void
qualify_keys(GSList * keys,const char * dir)1816 qualify_keys (GSList *keys, const char *dir)
1817 {
1818   GSList *tmp = keys;
1819   while (tmp != NULL)
1820     {
1821       char *key = tmp->data;
1822       gchar *full;
1823 
1824       full = gconf_concat_dir_and_key (dir, key);
1825 
1826       g_free (tmp->data);
1827       tmp->data = full;
1828 
1829       tmp = g_slist_next (tmp);
1830     }
1831 }
1832 
1833 /**
1834  * gconf_engine_all_dirs:
1835  * @conf: a #GConfEngine.
1836  * @dir: Directory to get subdirectories from.
1837  * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
1838  *
1839  * Lists the subdirectories in @dir. The returned list contains
1840  * allocated strings. Each string is the absolute path of a
1841  * subdirectory. You should g_free() each string in the list, then
1842  * g_slist_free() the list itself.
1843  *
1844  * Returns value: (element-type utf8) (transfer full): List of allocated subdirectory names.
1845  */
1846 GSList*
gconf_engine_all_dirs(GConfEngine * conf,const gchar * dir,GError ** err)1847 gconf_engine_all_dirs(GConfEngine* conf, const gchar* dir, GError** err)
1848 {
1849   GSList* subdirs = NULL;
1850   ConfigDatabase_KeyList* keys;
1851   CORBA_Environment ev;
1852   ConfigDatabase db;
1853   guint i;
1854   gint tries = 0;
1855 
1856   g_return_val_if_fail(conf != NULL, NULL);
1857   g_return_val_if_fail(dir != NULL, NULL);
1858   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
1859 
1860   CHECK_OWNER_USE (conf);
1861 
1862   if (!gconf_key_check(dir, err))
1863     return NULL;
1864 
1865   if (gconf_engine_is_local(conf))
1866     {
1867       GError* error = NULL;
1868       GSList* retval;
1869 
1870       retval = gconf_sources_all_dirs(conf->local_sources,
1871                                       dir,
1872                                       &error);
1873 
1874       if (error != NULL)
1875         {
1876           if (err)
1877             *err = error;
1878           else
1879             {
1880               g_error_free(error);
1881             }
1882 
1883           g_assert(retval == NULL);
1884 
1885           return NULL;
1886         }
1887 
1888       qualify_keys (retval, dir);
1889 
1890       return retval;
1891     }
1892 
1893   g_assert(!gconf_engine_is_local(conf));
1894 
1895   CORBA_exception_init(&ev);
1896 
1897  RETRY:
1898 
1899   db = gconf_engine_get_database (conf, TRUE, err);
1900 
1901   if (db == CORBA_OBJECT_NIL)
1902     {
1903       g_return_val_if_fail(((err == NULL) || (*err && ((*err)->code == GCONF_ERROR_NO_SERVER))), NULL);
1904 
1905       return NULL;
1906     }
1907 
1908   ConfigDatabase_all_dirs(db,
1909                           (gchar*)dir,
1910                           &keys,
1911                           &ev);
1912 
1913   if (gconf_server_broken(&ev))
1914     {
1915       if (tries < MAX_RETRIES)
1916         {
1917           ++tries;
1918           CORBA_exception_free(&ev);
1919           gconf_engine_detach (conf);
1920           goto RETRY;
1921         }
1922     }
1923 
1924   if (gconf_handle_corba_exception(&ev, err))
1925     return NULL;
1926 
1927   i = 0;
1928   while (i < keys->_length)
1929     {
1930       gchar* s;
1931 
1932       s = gconf_concat_dir_and_key (dir, keys->_buffer[i]);
1933 
1934       subdirs = g_slist_prepend(subdirs, s);
1935 
1936       ++i;
1937     }
1938 
1939   CORBA_free(keys);
1940 
1941   return subdirs;
1942 }
1943 
1944 /* annoyingly, this is REQUIRED for local sources */
1945 void
gconf_engine_suggest_sync(GConfEngine * conf,GError ** err)1946 gconf_engine_suggest_sync(GConfEngine* conf, GError** err)
1947 {
1948   CORBA_Environment ev;
1949   ConfigDatabase db;
1950   gint tries = 0;
1951 
1952   g_return_if_fail(conf != NULL);
1953   g_return_if_fail(err == NULL || *err == NULL);
1954 
1955   CHECK_OWNER_USE (conf);
1956 
1957   if (gconf_engine_is_local(conf))
1958     {
1959       GError* error = NULL;
1960 
1961       gconf_sources_sync_all(conf->local_sources,
1962                              &error);
1963 
1964       if (error != NULL)
1965         {
1966           if (err)
1967             *err = error;
1968           else
1969             {
1970               g_error_free(error);
1971             }
1972           return;
1973         }
1974 
1975       return;
1976     }
1977 
1978   g_assert(!gconf_engine_is_local(conf));
1979 
1980   CORBA_exception_init(&ev);
1981 
1982  RETRY:
1983 
1984   db = gconf_engine_get_database (conf, TRUE, err);
1985 
1986   if (db == CORBA_OBJECT_NIL)
1987     {
1988       g_return_if_fail(err == NULL || *err != NULL);
1989 
1990       return;
1991     }
1992 
1993   ConfigDatabase_sync(db, &ev);
1994 
1995   if (gconf_server_broken(&ev))
1996     {
1997       if (tries < MAX_RETRIES)
1998         {
1999           ++tries;
2000           CORBA_exception_free(&ev);
2001           gconf_engine_detach (conf);
2002           goto RETRY;
2003         }
2004     }
2005 
2006   if (gconf_handle_corba_exception(&ev, err))
2007     ; /* nothing additional */
2008 }
2009 
2010 void
gconf_clear_cache(GConfEngine * conf,GError ** err)2011 gconf_clear_cache(GConfEngine* conf, GError** err)
2012 {
2013   CORBA_Environment ev;
2014   ConfigDatabase db;
2015   gint tries = 0;
2016 
2017   g_return_if_fail(conf != NULL);
2018   g_return_if_fail(err == NULL || *err == NULL);
2019 
2020   /* don't disallow non-owner use here since you can't do this
2021    * via GConfClient API and calling this function won't break
2022    * GConfClient anyway
2023    */
2024 
2025   if (gconf_engine_is_local(conf))
2026     {
2027       gconf_sources_clear_cache(conf->local_sources);
2028 
2029       return;
2030     }
2031 
2032   g_assert(!gconf_engine_is_local(conf));
2033 
2034   CORBA_exception_init(&ev);
2035 
2036  RETRY:
2037 
2038   db = gconf_engine_get_database (conf, TRUE, err);
2039 
2040   if (db == CORBA_OBJECT_NIL)
2041     {
2042       g_return_if_fail(err == NULL || *err != NULL);
2043 
2044       return;
2045     }
2046 
2047   ConfigDatabase_clear_cache(db, &ev);
2048 
2049   if (gconf_server_broken(&ev))
2050     {
2051       if (tries < MAX_RETRIES)
2052         {
2053           ++tries;
2054           CORBA_exception_free(&ev);
2055           gconf_engine_detach (conf);
2056           goto RETRY;
2057         }
2058     }
2059 
2060   if (gconf_handle_corba_exception(&ev, err))
2061     ; /* nothing additional */
2062 }
2063 
2064 void
gconf_synchronous_sync(GConfEngine * conf,GError ** err)2065 gconf_synchronous_sync(GConfEngine* conf, GError** err)
2066 {
2067   CORBA_Environment ev;
2068   ConfigDatabase db;
2069   gint tries = 0;
2070 
2071   g_return_if_fail(conf != NULL);
2072   g_return_if_fail(err == NULL || *err == NULL);
2073 
2074   if (gconf_engine_is_local(conf))
2075     {
2076       GError* error = NULL;
2077 
2078       gconf_sources_sync_all(conf->local_sources, &error);
2079 
2080       if (error != NULL)
2081         {
2082           if (err)
2083             *err = error;
2084           else
2085             {
2086               g_error_free(error);
2087             }
2088           return;
2089         }
2090 
2091       return;
2092     }
2093 
2094   g_assert(!gconf_engine_is_local(conf));
2095 
2096   CORBA_exception_init(&ev);
2097 
2098  RETRY:
2099 
2100   db = gconf_engine_get_database (conf, TRUE, err);
2101 
2102   if (db == CORBA_OBJECT_NIL)
2103     {
2104       g_return_if_fail(err == NULL || *err != NULL);
2105 
2106       return;
2107     }
2108 
2109   ConfigDatabase_synchronous_sync(db, &ev);
2110 
2111   if (gconf_server_broken(&ev))
2112     {
2113       if (tries < MAX_RETRIES)
2114         {
2115           ++tries;
2116           CORBA_exception_free(&ev);
2117           gconf_engine_detach (conf);
2118           goto RETRY;
2119         }
2120     }
2121 
2122   if (gconf_handle_corba_exception(&ev, err))
2123     ; /* nothing additional */
2124 }
2125 
2126 gboolean
gconf_engine_dir_exists(GConfEngine * conf,const gchar * dir,GError ** err)2127 gconf_engine_dir_exists(GConfEngine *conf, const gchar *dir, GError** err)
2128 {
2129   CORBA_Environment ev;
2130   ConfigDatabase db;
2131   CORBA_boolean server_ret;
2132   gint tries = 0;
2133 
2134   g_return_val_if_fail(conf != NULL, FALSE);
2135   g_return_val_if_fail(dir != NULL, FALSE);
2136   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
2137 
2138   CHECK_OWNER_USE (conf);
2139 
2140   if (!gconf_key_check(dir, err))
2141     return FALSE;
2142 
2143   if (gconf_engine_is_local(conf))
2144     {
2145       return gconf_sources_dir_exists(conf->local_sources,
2146                                       dir,
2147                                       err);
2148     }
2149 
2150   g_assert(!gconf_engine_is_local(conf));
2151 
2152   CORBA_exception_init(&ev);
2153 
2154  RETRY:
2155 
2156   db = gconf_engine_get_database(conf, TRUE, err);
2157 
2158   if (db == CORBA_OBJECT_NIL)
2159     {
2160       g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
2161 
2162       return FALSE;
2163     }
2164 
2165   server_ret = ConfigDatabase_dir_exists(db,
2166                                          (gchar*)dir,
2167                                          &ev);
2168 
2169   if (gconf_server_broken(&ev))
2170     {
2171       if (tries < MAX_RETRIES)
2172         {
2173           ++tries;
2174           CORBA_exception_free(&ev);
2175           gconf_engine_detach (conf);
2176           goto RETRY;
2177         }
2178     }
2179 
2180   if (gconf_handle_corba_exception(&ev, err))
2181     ; /* nothing */
2182 
2183   return (server_ret == CORBA_TRUE);
2184 }
2185 
2186 void
gconf_engine_remove_dir(GConfEngine * conf,const gchar * dir,GError ** err)2187 gconf_engine_remove_dir (GConfEngine* conf,
2188                          const gchar* dir,
2189                          GError** err)
2190 {
2191   CORBA_Environment ev;
2192   ConfigDatabase db;
2193   gint tries = 0;
2194 
2195   g_return_if_fail(conf != NULL);
2196   g_return_if_fail(dir != NULL);
2197   g_return_if_fail(err == NULL || *err == NULL);
2198 
2199   /* FIXME we have no GConfClient method for doing this */
2200   /*   CHECK_OWNER_USE (conf); */
2201 
2202   if (!gconf_key_check(dir, err))
2203     return;
2204 
2205   if (gconf_engine_is_local(conf))
2206     {
2207       gconf_sources_remove_dir(conf->local_sources, dir, err);
2208       return;
2209     }
2210 
2211   CORBA_exception_init(&ev);
2212 
2213  RETRY:
2214 
2215   db = gconf_engine_get_database (conf, TRUE, err);
2216 
2217   if (db == CORBA_OBJECT_NIL)
2218     {
2219       g_return_if_fail(err == NULL || *err != NULL);
2220       return;
2221     }
2222 
2223   ConfigDatabase_remove_dir(db, (gchar*)dir, &ev);
2224 
2225   if (gconf_server_broken(&ev))
2226     {
2227       if (tries < MAX_RETRIES)
2228         {
2229           ++tries;
2230           CORBA_exception_free(&ev);
2231           gconf_engine_detach (conf);
2232           goto RETRY;
2233         }
2234     }
2235   gconf_handle_corba_exception(&ev, err);
2236 
2237   return;
2238 }
2239 
2240 gboolean
gconf_engine_key_is_writable(GConfEngine * conf,const gchar * key,GError ** err)2241 gconf_engine_key_is_writable  (GConfEngine *conf,
2242                                const gchar *key,
2243                                GError     **err)
2244 {
2245   gboolean is_writable = TRUE;
2246   GConfValue *val;
2247 
2248   CHECK_OWNER_USE (conf);
2249 
2250   /* FIXME implement IDL to allow getting only writability
2251    * (not that urgent since GConfClient caches this crap
2252    * anyway)
2253    */
2254 
2255   val = gconf_engine_get_full(conf, key, NULL, TRUE,
2256                               NULL, &is_writable, err);
2257 
2258   gconf_value_free (val);
2259 
2260   return is_writable;
2261 }
2262 
2263 /*
2264  * Connection maintenance
2265  */
2266 
2267 static GConfCnxn*
gconf_cnxn_new(GConfEngine * conf,const gchar * namespace_section,CORBA_unsigned_long server_id,GConfNotifyFunc func,gpointer user_data)2268 gconf_cnxn_new(GConfEngine* conf,
2269                const gchar* namespace_section,
2270                CORBA_unsigned_long server_id,
2271                GConfNotifyFunc func,
2272                gpointer user_data)
2273 {
2274   GConfCnxn* cnxn;
2275   static guint next_id = 1;
2276 
2277   cnxn = g_new0(GConfCnxn, 1);
2278 
2279   cnxn->namespace_section = g_strdup(namespace_section);
2280   cnxn->conf = conf;
2281   cnxn->server_id = server_id;
2282   cnxn->client_id = next_id;
2283   cnxn->func = func;
2284   cnxn->user_data = user_data;
2285 
2286   ++next_id;
2287 
2288   return cnxn;
2289 }
2290 
2291 static void
gconf_cnxn_destroy(GConfCnxn * cnxn)2292 gconf_cnxn_destroy(GConfCnxn* cnxn)
2293 {
2294   g_free(cnxn->namespace_section);
2295   g_free(cnxn);
2296 }
2297 
2298 static void
gconf_cnxn_notify(GConfCnxn * cnxn,GConfEntry * entry)2299 gconf_cnxn_notify(GConfCnxn* cnxn,
2300                   GConfEntry *entry)
2301 {
2302   (*cnxn->func)(cnxn->conf, cnxn->client_id,
2303                 entry,
2304                 cnxn->user_data);
2305 }
2306 
2307 /*
2308  *  CORBA glue
2309  */
2310 
2311 static ConfigServer   server = CORBA_OBJECT_NIL;
2312 
2313 /* errors in here should be GCONF_ERROR_NO_SERVER */
2314 static ConfigServer
try_to_contact_server(gboolean start_if_not_found,GError ** err)2315 try_to_contact_server (gboolean start_if_not_found,
2316                        GError **err)
2317 {
2318   CORBA_Environment ev;
2319 
2320   /* Try to launch server */
2321   server = gconf_activate_server (start_if_not_found,
2322                                   err);
2323 
2324   /* Try to ping server, by adding ourselves as a client */
2325   CORBA_exception_init (&ev);
2326 
2327   if (!CORBA_Object_is_nil (server, &ev))
2328     {
2329       ConfigServer_add_client (server,
2330                                gconf_get_config_listener (),
2331                                &ev);
2332 
2333       if (ev._major != CORBA_NO_EXCEPTION)
2334 	{
2335           g_set_error (err,
2336                        GCONF_ERROR,
2337                        GCONF_ERROR_NO_SERVER,
2338                        _("Adding client to server's list failed, CORBA error: %s"),
2339                        CORBA_exception_id (&ev));
2340 
2341 	  CORBA_Object_release (server, &ev);
2342 	  server = CORBA_OBJECT_NIL;
2343           CORBA_exception_free(&ev);
2344 	}
2345     }
2346 
2347 #ifdef GCONF_ENABLE_DEBUG
2348   if (server == CORBA_OBJECT_NIL && start_if_not_found)
2349     g_return_val_if_fail (err == NULL || *err != NULL, server);
2350 #endif
2351 
2352   return server;
2353 }
2354 
2355 /* All errors set in here should be GCONF_ERROR_NO_SERVER; should
2356    only set errors if start_if_not_found is TRUE */
2357 static ConfigServer
gconf_get_config_server(gboolean start_if_not_found,GError ** err)2358 gconf_get_config_server(gboolean start_if_not_found, GError** err)
2359 {
2360   g_return_val_if_fail(err == NULL || *err == NULL, server);
2361 
2362   if (server != CORBA_OBJECT_NIL)
2363     return server;
2364 
2365   server = try_to_contact_server(start_if_not_found, err);
2366 
2367   return server; /* return what we have, NIL or not */
2368 }
2369 
2370 static ConfigListener listener = CORBA_OBJECT_NIL;
2371 
2372 static void
gconf_detach_config_server(void)2373 gconf_detach_config_server(void)
2374 {
2375   CORBA_Environment ev;
2376 
2377   CORBA_exception_init(&ev);
2378 
2379   if (listener != CORBA_OBJECT_NIL)
2380     {
2381       CORBA_Object_release(listener, &ev);
2382       listener = CORBA_OBJECT_NIL;
2383     }
2384 
2385   if (server != CORBA_OBJECT_NIL)
2386     {
2387       CORBA_Object_release(server, &ev);
2388 
2389       if (ev._major != CORBA_NO_EXCEPTION)
2390         {
2391           g_warning("Exception releasing gconfd server object: %s",
2392                     CORBA_exception_id(&ev));
2393         }
2394 
2395       server = CORBA_OBJECT_NIL;
2396     }
2397 
2398   CORBA_exception_free(&ev);
2399 
2400   if (engines_by_db != NULL)
2401     {
2402       g_hash_table_destroy (engines_by_db);
2403       engines_by_db = NULL;
2404     }
2405 }
2406 
2407 /**
2408  * gconf_debug_shutdown:
2409  * @void:
2410  *
2411  * Detach from the configuration server and release
2412  * all related resources.
2413  *
2414  * Returns: 1 if an exception occurs, 0 otherwise.
2415  **/
2416 int
gconf_debug_shutdown(void)2417 gconf_debug_shutdown (void)
2418 {
2419   gconf_detach_config_server ();
2420 
2421   return gconf_orb_release ();
2422 }
2423 
2424 static void notify                  (PortableServer_Servant     servant,
2425                                      ConfigDatabase             db,
2426                                      CORBA_unsigned_long        cnxn,
2427                                      const CORBA_char          *key,
2428                                      const ConfigValue         *value,
2429                                      CORBA_boolean              is_default,
2430                                      CORBA_boolean              is_writable,
2431                                      CORBA_Environment         *ev);
2432 static void ping                    (PortableServer_Servant     _servant,
2433                                      CORBA_Environment         *ev);
2434 static void update_listener         (PortableServer_Servant     _servant,
2435                                      ConfigDatabase             db,
2436                                      const CORBA_char          *address,
2437                                      const CORBA_unsigned_long  old_cnxn,
2438                                      const CORBA_char          *key,
2439                                      const CORBA_unsigned_long  new_cnxn,
2440                                      CORBA_Environment         *ev);
2441 static void invalidate_cached_values(PortableServer_Servant     _servant,
2442                                      ConfigDatabase             database,
2443                                      const ConfigListener_KeyList *keys,
2444                                      CORBA_Environment         *ev);
2445 static void drop_all_caches         (PortableServer_Servant     _servant,
2446                                      CORBA_Environment         *ev);
2447 
2448 
2449 
2450 static PortableServer_ServantBase__epv base_epv = {
2451   NULL,
2452   NULL,
2453   NULL
2454 };
2455 
2456 static POA_ConfigListener__epv listener_epv = {
2457   NULL,
2458   notify,
2459   ping,
2460   update_listener,
2461   invalidate_cached_values,
2462   drop_all_caches
2463 };
2464 
2465 static POA_ConfigListener__vepv poa_listener_vepv = { &base_epv, &listener_epv };
2466 static POA_ConfigListener poa_listener_servant = { NULL, &poa_listener_vepv };
2467 
2468 static void
notify(PortableServer_Servant servant,ConfigDatabase db,CORBA_unsigned_long server_id,const CORBA_char * key,const ConfigValue * value,CORBA_boolean is_default,CORBA_boolean is_writable,CORBA_Environment * ev)2469 notify(PortableServer_Servant servant,
2470        ConfigDatabase db,
2471        CORBA_unsigned_long server_id,
2472        const CORBA_char* key,
2473        const ConfigValue* value,
2474        CORBA_boolean is_default,
2475        CORBA_boolean is_writable,
2476        CORBA_Environment *ev)
2477 {
2478   GConfCnxn* cnxn;
2479   GConfValue* gvalue;
2480   GConfEngine* conf;
2481   GConfEntry* entry;
2482 
2483   conf = lookup_engine_by_database (db);
2484 
2485   if (conf == NULL)
2486     {
2487 #ifdef GCONF_ENABLE_DEBUG
2488       g_warning ("Client received notify for unknown database object");
2489 #endif
2490       return;
2491     }
2492 
2493   cnxn = ctable_lookup_by_server_id(conf->ctable, server_id);
2494 
2495   if (cnxn == NULL)
2496     {
2497 #ifdef GCONF_ENABLE_DEBUG
2498       g_warning("Client received notify for unknown connection ID %u",
2499                 (guint)server_id);
2500 #endif
2501       return;
2502     }
2503 
2504   gvalue = gconf_value_from_corba_value(value);
2505 
2506   entry = gconf_entry_new_nocopy (g_strdup (key),
2507                                   gvalue);
2508   gconf_entry_set_is_default (entry, is_default);
2509   gconf_entry_set_is_writable (entry, is_writable);
2510 
2511   gconf_cnxn_notify(cnxn, entry);
2512 
2513   gconf_entry_free (entry);
2514 }
2515 
2516 static void
ping(PortableServer_Servant _servant,CORBA_Environment * ev)2517 ping (PortableServer_Servant _servant, CORBA_Environment * ev)
2518 {
2519   /* This one is easy :-) */
2520 
2521   return;
2522 }
2523 
2524 static void
update_listener(PortableServer_Servant _servant,ConfigDatabase db,const CORBA_char * address,const CORBA_unsigned_long old_cnxn_id,const CORBA_char * key,const CORBA_unsigned_long new_cnxn_id,CORBA_Environment * ev_ignored)2525 update_listener (PortableServer_Servant _servant,
2526                  ConfigDatabase             db,
2527                  const CORBA_char          *address,
2528                  const CORBA_unsigned_long  old_cnxn_id,
2529                  const CORBA_char          *key,
2530                  const CORBA_unsigned_long  new_cnxn_id,
2531                  CORBA_Environment         *ev_ignored)
2532 {
2533   GConfCnxn* cnxn;
2534   GConfEngine* conf;
2535   CORBA_Environment ev;
2536 
2537   conf = lookup_engine_by_database (db);
2538 
2539   /* See if we have an old engine with a now-invalid object
2540      reference, and update its reference. */
2541   if (conf == NULL)
2542     {
2543       CORBA_exception_init (&ev);
2544 
2545       if (strcmp (address, "def") == 0)
2546         conf = default_engine;
2547       else
2548         {
2549           GSList  *addresses;
2550 
2551           addresses = gconf_persistent_name_get_address_list (address);
2552 
2553           conf = lookup_engine (addresses);
2554 
2555           gconf_address_list_free (addresses);
2556         }
2557 
2558       if (conf)
2559         gconf_engine_set_database (conf,
2560                                    CORBA_Object_duplicate (db, &ev));
2561     }
2562 
2563   if (conf == NULL)
2564     {
2565 #ifdef GCONF_ENABLE_DEBUG
2566       g_warning("Client received listener update for unknown database "
2567                 "(this is not a big deal, this warning only appears if GConf is compiled with debugging)");
2568 #endif
2569       return;
2570     }
2571 
2572   cnxn = ctable_lookup_by_server_id (conf->ctable, old_cnxn_id);
2573 
2574   if (cnxn == NULL)
2575     {
2576 #ifdef GCONF_ENABLE_DEBUG
2577       g_warning("Client received listener update for unknown listener ID %u "
2578                 "(this is not a big deal, this warning only appears if GConf is compiled with debugging)",
2579                 (guint)old_cnxn_id);
2580 #endif
2581       return;
2582     }
2583 
2584   ctable_reinstall (conf->ctable, cnxn, old_cnxn_id, new_cnxn_id);
2585 }
2586 
2587 static void
invalidate_cached_values(PortableServer_Servant _servant,ConfigDatabase database,const ConfigListener_KeyList * keys,CORBA_Environment * ev)2588 invalidate_cached_values (PortableServer_Servant     _servant,
2589                           ConfigDatabase             database,
2590                           const ConfigListener_KeyList *keys,
2591                           CORBA_Environment         *ev)
2592 {
2593 #if 0
2594   g_warning ("FIXME process %d received request to invalidate some cached GConf values from the server, but right now we don't know how to do that (not implemented).", (int) getpid());
2595 #endif
2596 }
2597 
2598 static void
drop_all_caches(PortableServer_Servant _servant,CORBA_Environment * ev)2599 drop_all_caches (PortableServer_Servant     _servant,
2600                  CORBA_Environment         *ev)
2601 {
2602 #if 0
2603   g_warning ("FIXME process %d received request to invalidate all cached GConf values from the server, but right now we don't know how to do that (not implemented).", (int) getpid());
2604 #endif
2605 }
2606 
2607 static ConfigListener
gconf_get_config_listener(void)2608 gconf_get_config_listener(void)
2609 {
2610   if (listener == CORBA_OBJECT_NIL)
2611     {
2612       CORBA_Environment ev;
2613       PortableServer_POA poa;
2614       PortableServer_POAManager poa_mgr;
2615 
2616       CORBA_exception_init (&ev);
2617       POA_ConfigListener__init (&poa_listener_servant, &ev);
2618 
2619       g_assert (ev._major == CORBA_NO_EXCEPTION);
2620 
2621       poa =
2622         (PortableServer_POA) CORBA_ORB_resolve_initial_references (gconf_orb_get (),
2623                                                                    "RootPOA", &ev);
2624 
2625       g_assert (ev._major == CORBA_NO_EXCEPTION);
2626 
2627       poa_mgr = PortableServer_POA__get_the_POAManager (poa, &ev);
2628       PortableServer_POAManager_activate (poa_mgr, &ev);
2629 
2630       g_assert (ev._major == CORBA_NO_EXCEPTION);
2631 
2632       listener = PortableServer_POA_servant_to_reference(poa,
2633                                                          &poa_listener_servant,
2634                                                          &ev);
2635 
2636       CORBA_Object_release ((CORBA_Object) poa_mgr, &ev);
2637       CORBA_Object_release ((CORBA_Object) poa, &ev);
2638 
2639       g_assert (listener != CORBA_OBJECT_NIL);
2640       g_assert (ev._major == CORBA_NO_EXCEPTION);
2641     }
2642 
2643   return listener;
2644 }
2645 #endif /* HAVE_CORBA */
2646 
2647 void
gconf_preinit(gpointer app,gpointer mod_info)2648 gconf_preinit (gpointer app, gpointer mod_info)
2649 {
2650   /* Deprecated */
2651 }
2652 
2653 void
gconf_postinit(gpointer app,gpointer mod_info)2654 gconf_postinit (gpointer app, gpointer mod_info)
2655 {
2656   /* Deprecated */
2657 }
2658 
2659 /* All deprecated */
2660 const char gconf_version[] = VERSION;
2661 
2662 struct
2663 {
2664     const char * longName;
2665     char shortName;
2666     int argInfo;
2667     void * arg;
2668     int val;
2669     const char * descrip;
2670     const char * argDescrip;
2671 } gconf_options[] = { { NULL } };
2672 
2673 /* Also deprecated */
2674 gboolean
gconf_init(int argc,char ** argv,GError ** err)2675 gconf_init (int argc, char **argv, GError** err)
2676 {
2677 
2678   return TRUE;
2679 }
2680 
2681 gboolean
gconf_is_initialized(void)2682 gconf_is_initialized (void)
2683 {
2684   return TRUE;
2685 }
2686 
2687 /*
2688  * Ampersand and <> are not allowed due to the XML backend; shell
2689  * special characters aren't allowed; others are just in case we need
2690  * some magic characters someday.  hyphen, underscore, period, colon
2691  * are allowed as separators. % disallowed to avoid printf confusion.
2692  */
2693 
2694 /* Key/dir validity is exactly the same, except that '/' must be a dir,
2695    but we are sort of ignoring that for now. */
2696 
2697 /* Also, keys can contain only ASCII */
2698 
2699 static const gchar invalid_chars[] = " \t\r\n\"$&<>,+=#!()'|{}[]?~`;%\\";
2700 
2701 gboolean
gconf_valid_key(const gchar * key,gchar ** why_invalid)2702 gconf_valid_key      (const gchar* key, gchar** why_invalid)
2703 {
2704   const gchar* s = key;
2705   gboolean just_saw_slash = FALSE;
2706 
2707   /* Key must start with the root */
2708   if (*key != '/')
2709     {
2710       if (why_invalid != NULL)
2711         *why_invalid = g_strdup(_("Must begin with a slash '/'"));
2712       return FALSE;
2713     }
2714 
2715   /* Root key is a valid dir */
2716   if (*key == '/' && key[1] == '\0')
2717     return TRUE;
2718 
2719   while (*s)
2720     {
2721       if (just_saw_slash)
2722         {
2723           /* Can't have two slashes in a row, since it would mean
2724            * an empty spot.
2725            * Can't have a period right after a slash,
2726            * because it would be a pain for filesystem-based backends.
2727            */
2728           if (*s == '/' || *s == '.')
2729             {
2730               if (why_invalid != NULL)
2731                 {
2732                   if (*s == '/')
2733                     *why_invalid = g_strdup(_("Can't have two slashes '/' in a row"));
2734                   else
2735                     *why_invalid = g_strdup(_("Can't have a period '.' right after a slash '/'"));
2736                 }
2737               return FALSE;
2738             }
2739         }
2740 
2741       if (*s == '/')
2742         {
2743           just_saw_slash = TRUE;
2744         }
2745       else
2746         {
2747           const gchar* inv = invalid_chars;
2748           guchar c = (unsigned char) *s;
2749 
2750           just_saw_slash = FALSE;
2751 
2752           if (c > 127)
2753             {
2754               if (why_invalid != NULL)
2755                 *why_invalid = g_strdup_printf (_("'\\%o' is not an ASCII character and thus isn't allowed in key names"),
2756                                                 (guint) c);
2757               return FALSE;
2758             }
2759 
2760           while (*inv)
2761             {
2762               if (*inv == *s)
2763                 {
2764                   if (why_invalid != NULL)
2765                     *why_invalid = g_strdup_printf(_("`%c' is an invalid character in key/directory names"), *s);
2766                   return FALSE;
2767                 }
2768               ++inv;
2769             }
2770         }
2771 
2772       ++s;
2773     }
2774 
2775   /* Can't end with slash */
2776   if (just_saw_slash)
2777     {
2778       if (why_invalid != NULL)
2779         *why_invalid = g_strdup(_("Key/directory may not end with a slash '/'"));
2780       return FALSE;
2781     }
2782   else
2783     return TRUE;
2784 }
2785 
2786 /**
2787  * gconf_escape_key:
2788  * @arbitrary_text: some text in any encoding or format
2789  * @len: length of @arbitrary_text in bytes, or -1 if @arbitrary_text is nul-terminated
2790  *
2791  * Escape @arbitrary_text such that it's a valid key element (i.e. one
2792  * part of the key path). The escaped key won't pass gconf_valid_key()
2793  * because it isn't a whole key (i.e. it doesn't have a preceding
2794  * slash), but prepending a slash to the escaped text should always
2795  * result in a valid key.
2796  *
2797  * Return value: a nul-terminated valid GConf key
2798  **/
2799 char*
gconf_escape_key(const char * arbitrary_text,int len)2800 gconf_escape_key (const char *arbitrary_text,
2801                   int         len)
2802 {
2803   const char *p;
2804   const char *end;
2805   GString *retval;
2806 
2807   g_return_val_if_fail (arbitrary_text != NULL, NULL);
2808 
2809   /* Nearly all characters we would normally use for escaping aren't allowed in key
2810    * names, so we use @ for that.
2811    *
2812    * Invalid chars and @ itself are escaped as @xxx@ where xxx is the
2813    * Latin-1 value in decimal
2814    */
2815 
2816   if (len < 0)
2817     len = strlen (arbitrary_text);
2818 
2819   retval = g_string_sized_new (len);
2820 
2821   p = arbitrary_text;
2822   end = arbitrary_text + len;
2823   while (p != end)
2824     {
2825       if (*p == '/' || *p == '.' || *p == '@' || ((guchar) *p) > 127 ||
2826           strchr (invalid_chars, *p))
2827         {
2828           g_string_append_printf (retval, "@%u@", (guchar) *p);
2829         }
2830       else
2831         g_string_append_c (retval, *p);
2832 
2833       ++p;
2834     }
2835 
2836   return g_string_free (retval, FALSE);
2837 }
2838 
2839 /**
2840  * gconf_unescape_key:
2841  * @escaped_key: a key created with gconf_escape_key()
2842  * @len: length of @escaped_key in bytes, or -1 if @escaped_key is nul-terminated
2843  *
2844  * Converts a string escaped with gconf_escape_key() back into its original
2845  * form.
2846  *
2847  * Return value: the original string that was escaped to create @escaped_key
2848  **/
2849 char*
gconf_unescape_key(const char * escaped_key,int len)2850 gconf_unescape_key (const char *escaped_key,
2851                     int         len)
2852 {
2853   const char *p;
2854   const char *end;
2855   const char *start_seq;
2856   GString *retval;
2857 
2858   g_return_val_if_fail (escaped_key != NULL, NULL);
2859 
2860   if (len < 0)
2861     len = strlen (escaped_key);
2862 
2863   retval = g_string_new (NULL);
2864 
2865   p = escaped_key;
2866   end = escaped_key + len;
2867   start_seq = NULL;
2868   while (p != end)
2869     {
2870       if (start_seq)
2871         {
2872           if (*p == '@')
2873             {
2874               /* *p is the @ that ends a seq */
2875               char *end_seq;
2876               guchar val;
2877 
2878               val = strtoul (start_seq, &end_seq, 10);
2879               if (start_seq != end_seq)
2880                 g_string_append_c (retval, val);
2881 
2882               start_seq = NULL;
2883             }
2884         }
2885       else
2886         {
2887           if (*p == '@')
2888             start_seq = p + 1;
2889           else
2890             g_string_append_c (retval, *p);
2891         }
2892 
2893       ++p;
2894     }
2895 
2896   return g_string_free (retval, FALSE);
2897 }
2898 
2899 
2900 gboolean
gconf_key_is_below(const gchar * above,const gchar * below)2901 gconf_key_is_below   (const gchar* above, const gchar* below)
2902 {
2903   int len;
2904 
2905   if (above[0] == '/' && above[1] == '\0')
2906     return TRUE;
2907 
2908   len = strlen (above);
2909   if (strncmp (below, above, len) == 0)
2910     {
2911       /* only if this is a complete key component,
2912        * so that /foo is not above /foofoo/bar */
2913       if (below[len] == '\0' || below[len] == '/')
2914         return TRUE;
2915       else
2916 	return FALSE;
2917     }
2918   else
2919     return FALSE;
2920 }
2921 
2922 gchar*
gconf_unique_key(void)2923 gconf_unique_key (void)
2924 {
2925   /* This function is hardly cryptographically random but should be
2926      "good enough" */
2927 
2928   static guint serial = 0;
2929   gchar* key;
2930   guint t, ut, p, u, r;
2931   GTimeVal tv;
2932 
2933   g_get_current_time(&tv);
2934 
2935   t = tv.tv_sec;
2936   ut = tv.tv_usec;
2937 
2938   p = getpid();
2939 
2940 #ifdef HAVE_GETUID
2941   u = getuid();
2942 #else
2943   u = 0;
2944 #endif
2945 
2946   /* don't bother to seed; if it's based on the time or any other
2947      changing info we can get, we may as well just use that changing
2948      info. since we don't seed we'll at least get a different number
2949      on every call to this function in the same executable. */
2950   r = rand();
2951 
2952   /* The letters may increase uniqueness by preventing "melds"
2953      i.e. 01t01k01 and 0101t0k1 are not the same */
2954   key = g_strdup_printf("%ut%uut%uu%up%ur%uk%u",
2955                         /* Duplicate keys must be generated
2956                            by two different program instances */
2957                         serial,
2958                         /* Duplicate keys must be generated
2959                            in the same microsecond */
2960                         t,
2961                         ut,
2962                         /* Duplicate keys must be generated by
2963                            the same user */
2964                         u,
2965                         /* Duplicate keys must be generated by
2966                            two programs that got the same PID */
2967                         p,
2968                         /* Duplicate keys must be generated with the
2969                            same random seed and the same index into
2970                            the series of pseudorandom values */
2971                         r,
2972                         /* Duplicate keys must result from running
2973                            this function at the same stack location */
2974                         GPOINTER_TO_UINT(&key));
2975 
2976   ++serial;
2977 
2978   return key;
2979 }
2980 
2981 #ifdef HAVE_CORBA
2982 /*
2983  * Table of connections
2984  */
2985 
2986 static gint
corba_unsigned_long_equal(gconstpointer v1,gconstpointer v2)2987 corba_unsigned_long_equal (gconstpointer v1,
2988                            gconstpointer v2)
2989 {
2990   return *((const CORBA_unsigned_long*) v1) == *((const CORBA_unsigned_long*) v2);
2991 }
2992 
2993 static guint
corba_unsigned_long_hash(gconstpointer v)2994 corba_unsigned_long_hash (gconstpointer v)
2995 {
2996   /* for our purposes we can just assume 32 bits are significant */
2997   return (guint)(*(const CORBA_unsigned_long*) v);
2998 }
2999 
3000 static CnxnTable*
ctable_new(void)3001 ctable_new(void)
3002 {
3003   CnxnTable* ct;
3004 
3005   ct = g_new(CnxnTable, 1);
3006 
3007   ct->server_ids = g_hash_table_new (corba_unsigned_long_hash,
3008                                      corba_unsigned_long_equal);
3009   ct->client_ids = g_hash_table_new (g_int_hash, g_int_equal);
3010 
3011   return ct;
3012 }
3013 
3014 static void
ctable_destroy(CnxnTable * ct)3015 ctable_destroy(CnxnTable* ct)
3016 {
3017   g_hash_table_destroy (ct->server_ids);
3018   g_hash_table_destroy (ct->client_ids);
3019   g_free(ct);
3020 }
3021 
3022 static void
ctable_insert(CnxnTable * ct,GConfCnxn * cnxn)3023 ctable_insert(CnxnTable* ct, GConfCnxn* cnxn)
3024 {
3025   g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
3026   g_hash_table_insert (ct->client_ids, &cnxn->client_id, cnxn);
3027 }
3028 
3029 static void
ctable_remove(CnxnTable * ct,GConfCnxn * cnxn)3030 ctable_remove(CnxnTable* ct, GConfCnxn* cnxn)
3031 {
3032   g_hash_table_remove (ct->server_ids, &cnxn->server_id);
3033   g_hash_table_remove (ct->client_ids, &cnxn->client_id);
3034 }
3035 
3036 struct RemoveData {
3037   GSList* removed;
3038   GConfEngine* conf;
3039   gboolean save_removed;
3040 };
3041 
3042 static gboolean
remove_by_conf(gpointer key,gpointer value,gpointer user_data)3043 remove_by_conf(gpointer key, gpointer value, gpointer user_data)
3044 {
3045   struct RemoveData* rd = user_data;
3046   GConfCnxn* cnxn = value;
3047 
3048   if (cnxn->conf == rd->conf)
3049     {
3050       if (rd->save_removed)
3051         rd->removed = g_slist_prepend(rd->removed, cnxn);
3052 
3053       return TRUE;  /* remove this one */
3054     }
3055   else
3056     return FALSE; /* or not */
3057 }
3058 
3059 /* FIXME this no longer makes any sense, because a CnxnTable
3060    belongs to a GConfEngine and all entries have the same
3061    GConfEngine.
3062 */
3063 
3064 /* We return a list of the removed GConfCnxn */
3065 static GSList*
ctable_remove_by_conf(CnxnTable * ct,GConfEngine * conf)3066 ctable_remove_by_conf(CnxnTable* ct, GConfEngine* conf)
3067 {
3068   guint client_ids_removed;
3069   guint server_ids_removed;
3070   struct RemoveData rd;
3071 
3072   rd.removed = NULL;
3073   rd.conf = conf;
3074   rd.save_removed = TRUE;
3075 
3076   client_ids_removed = g_hash_table_foreach_remove (ct->server_ids,
3077                                                     remove_by_conf,
3078                                                     &rd);
3079 
3080   rd.save_removed = FALSE;
3081 
3082   server_ids_removed = g_hash_table_foreach_remove(ct->client_ids,
3083                                                    remove_by_conf,
3084                                                    &rd);
3085 
3086   g_assert(client_ids_removed == server_ids_removed);
3087   g_assert(client_ids_removed == g_slist_length(rd.removed));
3088 
3089   return rd.removed;
3090 }
3091 
3092 static GConfCnxn*
ctable_lookup_by_client_id(CnxnTable * ct,guint client_id)3093 ctable_lookup_by_client_id(CnxnTable* ct, guint client_id)
3094 {
3095   return g_hash_table_lookup(ct->client_ids, &client_id);
3096 }
3097 
3098 static GConfCnxn*
ctable_lookup_by_server_id(CnxnTable * ct,CORBA_unsigned_long server_id)3099 ctable_lookup_by_server_id(CnxnTable* ct, CORBA_unsigned_long server_id)
3100 {
3101   return g_hash_table_lookup (ct->server_ids, &server_id);
3102 }
3103 
3104 static void
ctable_reinstall(CnxnTable * ct,GConfCnxn * cnxn,guint old_server_id,guint new_server_id)3105 ctable_reinstall (CnxnTable* ct,
3106                   GConfCnxn *cnxn,
3107                   guint old_server_id,
3108                   guint new_server_id)
3109 {
3110   g_return_if_fail (cnxn->server_id == old_server_id);
3111 
3112   g_hash_table_remove (ct->server_ids, &old_server_id);
3113 
3114   cnxn->server_id = new_server_id;
3115 
3116   g_hash_table_insert (ct->server_ids, &cnxn->server_id, cnxn);
3117 }
3118 
3119 /*
3120  * Daemon control
3121  */
3122 
3123 void
gconf_shutdown_daemon(GError ** err)3124 gconf_shutdown_daemon (GError** err)
3125 {
3126   CORBA_Environment ev;
3127   ConfigServer cs;
3128 
3129   cs = gconf_get_config_server (FALSE, err); /* Don't want to spawn it if it's already down */
3130 
3131   if (err && *err && (*err)->code == GCONF_ERROR_NO_SERVER)
3132     {
3133       /* No server is hardly an error here */
3134       g_error_free (*err);
3135       *err = NULL;
3136     }
3137 
3138   if (cs == CORBA_OBJECT_NIL)
3139     {
3140 
3141       return;
3142     }
3143 
3144   CORBA_exception_init (&ev);
3145 
3146   ConfigServer_shutdown (cs, &ev);
3147 
3148   if (ev._major != CORBA_NO_EXCEPTION)
3149     {
3150       if (err)
3151         *err = gconf_error_new (GCONF_ERROR_FAILED, _("Failure shutting down configuration server: %s"),
3152                                 CORBA_exception_id (&ev));
3153 
3154       CORBA_exception_free(&ev);
3155     }
3156 }
3157 
3158 gboolean
gconf_ping_daemon(void)3159 gconf_ping_daemon(void)
3160 {
3161   ConfigServer cs;
3162 
3163   cs = gconf_get_config_server(FALSE, NULL); /* ignore error, since whole point is to see if server is reachable */
3164 
3165   if (cs == CORBA_OBJECT_NIL)
3166     return FALSE;
3167   else
3168     return TRUE;
3169 }
3170 
3171 gboolean
gconf_spawn_daemon(GError ** err)3172 gconf_spawn_daemon(GError** err)
3173 {
3174   ConfigServer cs;
3175 
3176   cs = gconf_get_config_server(TRUE, err);
3177 
3178   if (cs == CORBA_OBJECT_NIL)
3179     {
3180       g_return_val_if_fail(err == NULL || *err != NULL, FALSE);
3181       return FALSE; /* Failed to spawn, error should be set */
3182     }
3183   else
3184     return TRUE;
3185 }
3186 #endif /* HAVE_CORBA */
3187 
3188 /*
3189  * Sugar functions
3190  */
3191 
3192 gdouble
gconf_engine_get_float(GConfEngine * conf,const gchar * key,GError ** err)3193 gconf_engine_get_float (GConfEngine* conf, const gchar* key,
3194                  GError** err)
3195 {
3196   GConfValue* val;
3197   static const gdouble deflt = 0.0;
3198 
3199   g_return_val_if_fail(conf != NULL, 0.0);
3200   g_return_val_if_fail(key != NULL, 0.0);
3201 
3202   val = gconf_engine_get (conf, key, err);
3203 
3204   if (val == NULL)
3205     return deflt;
3206   else
3207     {
3208       gdouble retval;
3209 
3210       if (val->type != GCONF_VALUE_FLOAT)
3211         {
3212           if (err)
3213             *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected float, got %s"),
3214                                     gconf_value_type_to_string(val->type));
3215           gconf_value_free(val);
3216           return deflt;
3217         }
3218 
3219       retval = gconf_value_get_float(val);
3220 
3221       gconf_value_free(val);
3222 
3223       return retval;
3224     }
3225 }
3226 
3227 gint
gconf_engine_get_int(GConfEngine * conf,const gchar * key,GError ** err)3228 gconf_engine_get_int   (GConfEngine* conf, const gchar* key,
3229                  GError** err)
3230 {
3231   GConfValue* val;
3232   static const gint deflt = 0;
3233 
3234   g_return_val_if_fail(conf != NULL, 0);
3235   g_return_val_if_fail(key != NULL, 0);
3236 
3237   val = gconf_engine_get (conf, key, err);
3238 
3239   if (val == NULL)
3240     return deflt;
3241   else
3242     {
3243       gint retval;
3244 
3245       if (val->type != GCONF_VALUE_INT)
3246         {
3247           if (err)
3248             *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected int, got %s"),
3249                                     gconf_value_type_to_string(val->type));
3250           gconf_value_free(val);
3251           return deflt;
3252         }
3253 
3254       retval = gconf_value_get_int(val);
3255 
3256       gconf_value_free(val);
3257 
3258       return retval;
3259     }
3260 }
3261 
3262 gchar*
gconf_engine_get_string(GConfEngine * conf,const gchar * key,GError ** err)3263 gconf_engine_get_string(GConfEngine* conf, const gchar* key,
3264                  GError** err)
3265 {
3266   GConfValue* val;
3267   static const gchar* deflt = NULL;
3268 
3269   g_return_val_if_fail(conf != NULL, NULL);
3270   g_return_val_if_fail(key != NULL, NULL);
3271 
3272   val = gconf_engine_get (conf, key, err);
3273 
3274   if (val == NULL)
3275     return g_strdup(deflt);
3276   else
3277     {
3278       gchar* retval;
3279 
3280       if (val->type != GCONF_VALUE_STRING)
3281         {
3282           if (err)
3283             *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected string, got %s"),
3284                                     gconf_value_type_to_string(val->type));
3285           gconf_value_free(val);
3286           return g_strdup(deflt);
3287         }
3288 
3289       retval = gconf_value_steal_string (val);
3290       gconf_value_free (val);
3291 
3292       return retval;
3293     }
3294 }
3295 
3296 gboolean
gconf_engine_get_bool(GConfEngine * conf,const gchar * key,GError ** err)3297 gconf_engine_get_bool  (GConfEngine* conf, const gchar* key,
3298                         GError** err)
3299 {
3300   GConfValue* val;
3301   static const gboolean deflt = FALSE;
3302 
3303   g_return_val_if_fail(conf != NULL, FALSE);
3304   g_return_val_if_fail(key != NULL, FALSE);
3305 
3306   val = gconf_engine_get (conf, key, err);
3307 
3308   if (val == NULL)
3309     return deflt;
3310   else
3311     {
3312       gboolean retval;
3313 
3314       if (val->type != GCONF_VALUE_BOOL)
3315         {
3316           if (err)
3317             *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected bool, got %s"),
3318                                     gconf_value_type_to_string(val->type));
3319           gconf_value_free(val);
3320           return deflt;
3321         }
3322 
3323       retval = gconf_value_get_bool(val);
3324 
3325       gconf_value_free(val);
3326 
3327       return retval;
3328     }
3329 }
3330 
3331 /**
3332  * gconf_engine_get_schema: (skip)
3333  * @conf: a #GConfEngine.
3334  * @key: key you want the value of.
3335  * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
3336  * @Returns: the value of @key as an allocated #GConfSchema, or <symbol>NULL</symbol> if no value was obtained.
3337  *
3338  * Requests the schema (%GCONF_VALUE_SCHEMA) stored at @key.
3339  * Automatically performs type-checking, so if a non-schema is stored at
3340  * @key, an error is returned. If no value is set or an error occurs,
3341  * <symbol>NULL</symbol> is returned.
3342  *
3343  * Return value: (transfer full): the value of @key as an allocated #GConfSchema, or <symbol>NULL</symbol> if no value was obtained.
3344  */
3345 GConfSchema*
gconf_engine_get_schema(GConfEngine * conf,const gchar * key,GError ** err)3346 gconf_engine_get_schema  (GConfEngine* conf, const gchar* key, GError** err)
3347 {
3348   GConfValue* val;
3349 
3350   g_return_val_if_fail(conf != NULL, NULL);
3351   g_return_val_if_fail(key != NULL, NULL);
3352 
3353   val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
3354 
3355   if (val == NULL)
3356     return NULL;
3357   else
3358     {
3359       GConfSchema* retval;
3360 
3361       if (val->type != GCONF_VALUE_SCHEMA)
3362         {
3363           if (err)
3364             *err = gconf_error_new(GCONF_ERROR_TYPE_MISMATCH, _("Expected schema, got %s"),
3365                                     gconf_value_type_to_string(val->type));
3366           gconf_value_free(val);
3367           return NULL;
3368         }
3369 
3370       retval = gconf_value_steal_schema (val);
3371       gconf_value_free (val);
3372 
3373       return retval;
3374     }
3375 }
3376 
3377 /**
3378  * gconf_engine_get_list: (skip)
3379  * @conf: a #GConfEngine.
3380  * @key: key you want the value of.
3381  * @list_type: type of each list element.
3382  * @err: the return location for an allocated #GError, or <symbol>NULL</symbol> to ignore errors.
3383  *
3384  * Requests the list (%GCONF_VALUE_LIST) stored at @key.  Automatically
3385  * performs type-checking, so if a non-list is stored at @key, or the
3386  * list does not contain elements of type @list_type, an error is
3387  * returned. If no value is set or an error occurs, <symbol>NULL</symbol>
3388  * is returned. Note that <symbol>NULL</symbol> is also the empty list,
3389  * so if you need to distinguish the empty list from an unset value, you
3390  * must use gconf_engine_get () to obtain a raw #GConfValue.
3391  *
3392  * <emphasis>Remember that GConf lists can only store primitive types:
3393  * %GCONF_VALUE_FLOAT, %GCONF_VALUE_INT, %GCONF_VALUE_BOOL,
3394  * %GCONF_VALUE_STRING, %GCONF_VALUE_SCHEMA.</emphasis> Also remember
3395  * that lists must be uniform, you may not mix types in the same list.
3396  *
3397  * The type of the list elements depends on @list_type. A #GConfValue
3398  * with type %GCONF_VALUE_LIST normally stores a list of more #GConfValue
3399  * objects. gconf_engine_get_list() automatically converts to primitive C
3400  * types. Thus, the list-&gt;data fields in the returned list
3401  * contain:
3402  *
3403  * <informaltable pgwide="1" frame="none">
3404  * <tgroup cols="2"><colspec colwidth="2*"/><colspec colwidth="8*"/>
3405  * <tbody>
3406  *
3407  * <row>
3408  * <entry>%GCONF_VALUE_INT</entry>
3409  * <entry>The integer itself, converted with GINT_TO_POINTER()</entry>
3410  * </row>
3411  *
3412  * <row>
3413  * <entry>%GCONF_VALUE_BOOL</entry>
3414  * <entry>The bool itself, converted with GINT_TO_POINTER()</entry>
3415  * </row>
3416  *
3417  * <row>
3418  * <entry>%GCONF_VALUE_FLOAT</entry>
3419  * <entry>A pointer to #gdouble, which should be freed with g_free()</entry>
3420  * </row>
3421  *
3422  * <row>
3423  * <entry>%GCONF_VALUE_STRING</entry>
3424  * <entry>A pointer to #gchar, which should be freed with g_free()</entry>
3425  * </row>
3426  *
3427  * <row>
3428  * <entry>%GCONF_VALUE_SCHEMA</entry>
3429  * <entry>A pointer to #GConfSchema, which should be freed with gconf_schema_free()</entry>
3430  * </row>
3431  *
3432  * </tbody></tgroup></informaltable>
3433  *
3434  * In the %GCONF_VALUE_FLOAT and %GCONF_VALUE_STRING cases, you must
3435  * g_free() each list element. In the %GCONF_VALUE_SCHEMA case you must
3436  * gconf_schema_free() each element. In all cases you must free the
3437  * list itself with g_slist_free().
3438  *
3439  * Return value: an allocated list, with elements as described above.
3440  */
3441 GSList*
gconf_engine_get_list(GConfEngine * conf,const gchar * key,GConfValueType list_type,GError ** err)3442 gconf_engine_get_list    (GConfEngine* conf, const gchar* key,
3443                           GConfValueType list_type, GError** err)
3444 {
3445   GConfValue* val;
3446 
3447   g_return_val_if_fail(conf != NULL, NULL);
3448   g_return_val_if_fail(key != NULL, NULL);
3449   g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, NULL);
3450   g_return_val_if_fail(list_type != GCONF_VALUE_LIST, NULL);
3451   g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, NULL);
3452   g_return_val_if_fail(err == NULL || *err == NULL, NULL);
3453 
3454   val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), err);
3455 
3456   if (val == NULL)
3457     return NULL;
3458   else
3459     {
3460       /* This type-checks the value */
3461       return gconf_value_list_to_primitive_list_destructive(val, list_type, err);
3462     }
3463 }
3464 
3465 gboolean
gconf_engine_get_pair(GConfEngine * conf,const gchar * key,GConfValueType car_type,GConfValueType cdr_type,gpointer car_retloc,gpointer cdr_retloc,GError ** err)3466 gconf_engine_get_pair    (GConfEngine* conf, const gchar* key,
3467                    GConfValueType car_type, GConfValueType cdr_type,
3468                    gpointer car_retloc, gpointer cdr_retloc,
3469                    GError** err)
3470 {
3471   GConfValue* val;
3472   GError* error = NULL;
3473 
3474   g_return_val_if_fail(conf != NULL, FALSE);
3475   g_return_val_if_fail(key != NULL, FALSE);
3476   g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
3477   g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
3478   g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
3479   g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
3480   g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
3481   g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
3482   g_return_val_if_fail(car_retloc != NULL, FALSE);
3483   g_return_val_if_fail(cdr_retloc != NULL, FALSE);
3484   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3485 
3486   val = gconf_engine_get_with_locale(conf, key, gconf_current_locale(), &error);
3487 
3488   if (error != NULL)
3489     {
3490       g_assert(val == NULL);
3491 
3492       if (err)
3493         *err = error;
3494       else
3495         g_error_free(error);
3496 
3497       return FALSE;
3498     }
3499 
3500   if (val == NULL)
3501     {
3502       return TRUE;
3503     }
3504   else
3505     {
3506       /* Destroys val */
3507       return gconf_value_pair_to_primitive_pair_destructive(val,
3508                                                             car_type, cdr_type,
3509                                                             car_retloc, cdr_retloc,
3510                                                             err);
3511     }
3512 }
3513 
3514 /*
3515  * Setters
3516  */
3517 
3518 static gboolean
error_checked_set(GConfEngine * conf,const gchar * key,GConfValue * gval,GError ** err)3519 error_checked_set(GConfEngine* conf, const gchar* key,
3520                   GConfValue* gval, GError** err)
3521 {
3522   GError* my_err = NULL;
3523 
3524   gconf_engine_set (conf, key, gval, &my_err);
3525 
3526   gconf_value_free(gval);
3527 
3528   if (my_err != NULL)
3529     {
3530       if (err)
3531         *err = my_err;
3532       else
3533         g_error_free(my_err);
3534       return FALSE;
3535     }
3536   else
3537     return TRUE;
3538 }
3539 
3540 gboolean
gconf_engine_set_float(GConfEngine * conf,const gchar * key,gdouble val,GError ** err)3541 gconf_engine_set_float   (GConfEngine* conf, const gchar* key,
3542                           gdouble val, GError** err)
3543 {
3544   GConfValue* gval;
3545 
3546   g_return_val_if_fail(conf != NULL, FALSE);
3547   g_return_val_if_fail(key != NULL, FALSE);
3548   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3549 
3550   gval = gconf_value_new(GCONF_VALUE_FLOAT);
3551 
3552   gconf_value_set_float(gval, val);
3553 
3554   return error_checked_set(conf, key, gval, err);
3555 }
3556 
3557 gboolean
gconf_engine_set_int(GConfEngine * conf,const gchar * key,gint val,GError ** err)3558 gconf_engine_set_int     (GConfEngine* conf, const gchar* key,
3559                           gint val, GError** err)
3560 {
3561   GConfValue* gval;
3562 
3563   g_return_val_if_fail(conf != NULL, FALSE);
3564   g_return_val_if_fail(key != NULL, FALSE);
3565   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3566 
3567   gval = gconf_value_new(GCONF_VALUE_INT);
3568 
3569   gconf_value_set_int(gval, val);
3570 
3571   return error_checked_set(conf, key, gval, err);
3572 }
3573 
3574 gboolean
gconf_engine_set_string(GConfEngine * conf,const gchar * key,const gchar * val,GError ** err)3575 gconf_engine_set_string  (GConfEngine* conf, const gchar* key,
3576                           const gchar* val, GError** err)
3577 {
3578   GConfValue* gval;
3579 
3580   g_return_val_if_fail (val != NULL, FALSE);
3581   g_return_val_if_fail (conf != NULL, FALSE);
3582   g_return_val_if_fail (key != NULL, FALSE);
3583   g_return_val_if_fail (err == NULL || *err == NULL, FALSE);
3584 
3585   g_return_val_if_fail (g_utf8_validate (val, -1, NULL), FALSE);
3586 
3587   gval = gconf_value_new(GCONF_VALUE_STRING);
3588 
3589   gconf_value_set_string(gval, val);
3590 
3591   return error_checked_set(conf, key, gval, err);
3592 }
3593 
3594 gboolean
gconf_engine_set_bool(GConfEngine * conf,const gchar * key,gboolean val,GError ** err)3595 gconf_engine_set_bool    (GConfEngine* conf, const gchar* key,
3596                           gboolean val, GError** err)
3597 {
3598   GConfValue* gval;
3599 
3600   g_return_val_if_fail(conf != NULL, FALSE);
3601   g_return_val_if_fail(key != NULL, FALSE);
3602   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3603 
3604   gval = gconf_value_new(GCONF_VALUE_BOOL);
3605 
3606   gconf_value_set_bool(gval, !!val); /* canonicalize the bool */
3607 
3608   return error_checked_set(conf, key, gval, err);
3609 }
3610 
3611 gboolean
gconf_engine_set_schema(GConfEngine * conf,const gchar * key,const GConfSchema * val,GError ** err)3612 gconf_engine_set_schema  (GConfEngine* conf, const gchar* key,
3613                           const GConfSchema* val, GError** err)
3614 {
3615   GConfValue* gval;
3616 
3617   g_return_val_if_fail(conf != NULL, FALSE);
3618   g_return_val_if_fail(key != NULL, FALSE);
3619   g_return_val_if_fail(val != NULL, FALSE);
3620   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3621 
3622   gval = gconf_value_new(GCONF_VALUE_SCHEMA);
3623 
3624   gconf_value_set_schema(gval, val);
3625 
3626   return error_checked_set(conf, key, gval, err);
3627 }
3628 
3629 gboolean
gconf_engine_set_list(GConfEngine * conf,const gchar * key,GConfValueType list_type,GSList * list,GError ** err)3630 gconf_engine_set_list    (GConfEngine* conf, const gchar* key,
3631                           GConfValueType list_type,
3632                           GSList* list,
3633                           GError** err)
3634 {
3635   GConfValue* value_list;
3636   GError *tmp_err = NULL;
3637 
3638   g_return_val_if_fail(conf != NULL, FALSE);
3639   g_return_val_if_fail(key != NULL, FALSE);
3640   g_return_val_if_fail(list_type != GCONF_VALUE_INVALID, FALSE);
3641   g_return_val_if_fail(list_type != GCONF_VALUE_LIST, FALSE);
3642   g_return_val_if_fail(list_type != GCONF_VALUE_PAIR, FALSE);
3643   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3644 
3645   value_list = gconf_value_list_from_primitive_list(list_type, list, &tmp_err);
3646 
3647   if (tmp_err)
3648     {
3649       g_propagate_error (err, tmp_err);
3650       return FALSE;
3651     }
3652 
3653   /* destroys the value_list */
3654 
3655   return error_checked_set(conf, key, value_list, err);
3656 }
3657 
3658 gboolean
gconf_engine_set_pair(GConfEngine * conf,const gchar * key,GConfValueType car_type,GConfValueType cdr_type,gconstpointer address_of_car,gconstpointer address_of_cdr,GError ** err)3659 gconf_engine_set_pair    (GConfEngine* conf, const gchar* key,
3660                           GConfValueType car_type, GConfValueType cdr_type,
3661                           gconstpointer address_of_car,
3662                           gconstpointer address_of_cdr,
3663                           GError** err)
3664 {
3665   GConfValue* pair;
3666   GError *tmp_err = NULL;
3667 
3668   g_return_val_if_fail(conf != NULL, FALSE);
3669   g_return_val_if_fail(key != NULL, FALSE);
3670   g_return_val_if_fail(car_type != GCONF_VALUE_INVALID, FALSE);
3671   g_return_val_if_fail(car_type != GCONF_VALUE_LIST, FALSE);
3672   g_return_val_if_fail(car_type != GCONF_VALUE_PAIR, FALSE);
3673   g_return_val_if_fail(cdr_type != GCONF_VALUE_INVALID, FALSE);
3674   g_return_val_if_fail(cdr_type != GCONF_VALUE_LIST, FALSE);
3675   g_return_val_if_fail(cdr_type != GCONF_VALUE_PAIR, FALSE);
3676   g_return_val_if_fail(address_of_car != NULL, FALSE);
3677   g_return_val_if_fail(address_of_cdr != NULL, FALSE);
3678   g_return_val_if_fail(err == NULL || *err == NULL, FALSE);
3679 
3680 
3681   pair = gconf_value_pair_from_primitive_pair(car_type, cdr_type,
3682                                               address_of_car, address_of_cdr,
3683                                               &tmp_err);
3684 
3685   if (tmp_err)
3686     {
3687       g_propagate_error (err, tmp_err);
3688       return FALSE;
3689     }
3690 
3691   return error_checked_set(conf, key, pair, err);
3692 }
3693 
3694 #ifdef HAVE_CORBA
3695 /* CORBA Util */
3696 
3697 /* Set GConfError from an exception, free exception, etc. */
3698 
3699 static GConfError
corba_errno_to_gconf_errno(ConfigErrorType corba_err)3700 corba_errno_to_gconf_errno(ConfigErrorType corba_err)
3701 {
3702   switch (corba_err)
3703     {
3704     case ConfigFailed:
3705       return GCONF_ERROR_FAILED;
3706     case ConfigNoPermission:
3707       return GCONF_ERROR_NO_PERMISSION;
3708     case ConfigBadAddress:
3709       return GCONF_ERROR_BAD_ADDRESS;
3710     case ConfigBadKey:
3711       return GCONF_ERROR_BAD_KEY;
3712     case ConfigParseError:
3713       return GCONF_ERROR_PARSE_ERROR;
3714     case ConfigCorrupt:
3715       return GCONF_ERROR_CORRUPT;
3716     case ConfigTypeMismatch:
3717       return GCONF_ERROR_TYPE_MISMATCH;
3718     case ConfigIsDir:
3719       return GCONF_ERROR_IS_DIR;
3720     case ConfigIsKey:
3721       return GCONF_ERROR_IS_KEY;
3722     case ConfigOverridden:
3723       return GCONF_ERROR_OVERRIDDEN;
3724     case ConfigLockFailed:
3725       return GCONF_ERROR_LOCK_FAILED;
3726     case ConfigNoWritableDatabase:
3727       return GCONF_ERROR_NO_WRITABLE_DATABASE;
3728     case ConfigInShutdown:
3729       return GCONF_ERROR_IN_SHUTDOWN;
3730     default:
3731       g_assert_not_reached();
3732       return GCONF_ERROR_SUCCESS; /* warnings */
3733     }
3734 }
3735 
3736 static gboolean
gconf_server_broken(CORBA_Environment * ev)3737 gconf_server_broken(CORBA_Environment* ev)
3738 {
3739   switch (ev->_major)
3740     {
3741     case CORBA_SYSTEM_EXCEPTION:
3742       return TRUE;
3743 
3744     case CORBA_USER_EXCEPTION:
3745       {
3746         ConfigException* ce;
3747 
3748         ce = CORBA_exception_value(ev);
3749 
3750         return ce->err_no == ConfigInShutdown;
3751       }
3752 
3753     default:
3754       return FALSE;
3755     }
3756 }
3757 
3758 static gboolean
gconf_handle_corba_exception(CORBA_Environment * ev,GError ** err)3759 gconf_handle_corba_exception(CORBA_Environment* ev, GError** err)
3760 {
3761   switch (ev->_major)
3762     {
3763     case CORBA_NO_EXCEPTION:
3764       CORBA_exception_free (ev);
3765       return FALSE;
3766     case CORBA_SYSTEM_EXCEPTION:
3767       if (err)
3768         *err = gconf_error_new (GCONF_ERROR_NO_SERVER, _("CORBA error: %s"),
3769                                 CORBA_exception_id (ev));
3770       CORBA_exception_free (ev);
3771       return TRUE;
3772     case CORBA_USER_EXCEPTION:
3773       {
3774         ConfigException* ce;
3775 
3776         ce = CORBA_exception_value (ev);
3777 
3778         if (err)
3779           *err = gconf_error_new (corba_errno_to_gconf_errno (ce->err_no),
3780                                   "%s", ce->message);
3781         CORBA_exception_free (ev);
3782         return TRUE;
3783       }
3784     default:
3785       g_assert_not_reached();
3786       return TRUE;
3787     }
3788 }
3789 #endif
3790 
3791 /*
3792  * Enumeration conversions
3793  */
3794 
3795 gboolean
gconf_string_to_enum(GConfEnumStringPair lookup_table[],const gchar * str,gint * enum_value_retloc)3796 gconf_string_to_enum (GConfEnumStringPair lookup_table[],
3797                       const gchar* str,
3798                       gint* enum_value_retloc)
3799 {
3800   int i = 0;
3801 
3802   while (lookup_table[i].str != NULL)
3803     {
3804       if (g_ascii_strcasecmp (lookup_table[i].str, str) == 0)
3805         {
3806           *enum_value_retloc = lookup_table[i].enum_value;
3807           return TRUE;
3808         }
3809 
3810       ++i;
3811     }
3812 
3813   return FALSE;
3814 }
3815 
3816 const gchar*
gconf_enum_to_string(GConfEnumStringPair lookup_table[],gint enum_value)3817 gconf_enum_to_string (GConfEnumStringPair lookup_table[],
3818                       gint enum_value)
3819 {
3820   int i = 0;
3821 
3822   while (lookup_table[i].str != NULL)
3823     {
3824       if (lookup_table[i].enum_value == enum_value)
3825         return lookup_table[i].str;
3826 
3827       ++i;
3828     }
3829 
3830   return NULL;
3831 }
3832