static void compare_lists(GConfValueType type, GSList* first, GSList* second) { GSList* l1; GSList* l2; l1 = first; l2 = second; while (l1 != NULL) { check(l2 != NULL, "second list too short"); switch (type) { case GCONF_VALUE_INT: check(GPOINTER_TO_INT(l1->data) == GPOINTER_TO_INT(l2->data), "integer values %d and %d are not equal", GPOINTER_TO_INT(l1->data), GPOINTER_TO_INT(l2->data)); break; case GCONF_VALUE_BOOL: check(GPOINTER_TO_INT(l1->data) == GPOINTER_TO_INT(l2->data), "boolean values %d and %d are not equal", GPOINTER_TO_INT(l1->data), GPOINTER_TO_INT(l2->data)); break; case GCONF_VALUE_FLOAT: { gdouble d1 = *((gdouble*)l1->data); gdouble d2 = *((gdouble*)l2->data); check(fabs(d2 - d1) < 1e-5, "float values %g and %g are not equal (epsilon %g)", d1, d2, d2 - d1); } break; case GCONF_VALUE_STRING: check(strcmp(l1->data, l2->data) == 0, "string values `%s' and `%s' are not equal", l1->data, l2->data); break; default: g_assert_not_reached(); break; } l1 = g_slist_next(l1); l2 = g_slist_next(l2); } check(l2 == NULL, "second list too long with list type %s", gconf_value_type_to_string(type)); }
static gboolean check_type (const gchar* key, GConfValue* val, GConfValueType t, GError** err) { if (val->type != t) { /* gconf_set_error(err, GCONF_ERROR_TYPE_MISMATCH, _("Expected `%s' got `%s' for key %s"), gconf_value_type_to_string(t), gconf_value_type_to_string(val->type), key); */ g_set_error (err, GCONF_ERROR, GCONF_ERROR_TYPE_MISMATCH, _("Expected `%s' got `%s' for key %s"), gconf_value_type_to_string(t), gconf_value_type_to_string(val->type), key); return FALSE; } else return TRUE; }
static gboolean handle_file (const gchar *filename) { GKeyFile *keyfile; GConfClient *client; GConfValue *value; gint i, j; gchar *gconf_key; gchar **groups; gchar **keys; GVariantBuilder *builder; GVariant *v; const gchar *s; gchar *str; gint ii; GSList *list, *l; GSettingsSchemaSource *source; GSettingsSchema *schema; GSettings *settings; GError *error; keyfile = g_key_file_new (); error = NULL; if (!g_key_file_load_from_file (keyfile, filename, 0, &error)) { if (verbose) g_printerr ("%s: %s\n", filename, error->message); g_error_free (error); g_key_file_free (keyfile); return FALSE; } client = get_writable_client (); source = g_settings_schema_source_get_default (); groups = g_key_file_get_groups (keyfile, NULL); for (i = 0; groups[i]; i++) { gchar **schema_path; schema_path = g_strsplit (groups[i], ":", 2); schema = g_settings_schema_source_lookup (source, schema_path[0], TRUE); if (schema == NULL) { if (verbose) { g_print ("Schema '%s' not found, skipping\n", schema_path[0]); } g_strfreev (schema_path); continue; } g_settings_schema_unref (schema); if (verbose) { g_print ("Collecting settings for schema '%s'\n", schema_path[0]); if (schema_path[1]) g_print ("for storage at '%s'\n", schema_path[1]); } if (schema_path[1] != NULL) settings = g_settings_new_with_path (schema_path[0], schema_path[1]); else settings = g_settings_new (schema_path[0]); g_settings_delay (settings); error = NULL; if ((keys = g_key_file_get_keys (keyfile, groups[i], NULL, &error)) == NULL) { g_printerr ("%s", error->message); g_error_free (error); continue; } for (j = 0; keys[j]; j++) { if (strchr (keys[j], '/') != 0) { g_printerr ("Key '%s' contains a '/'\n", keys[j]); continue; } error = NULL; if ((gconf_key = g_key_file_get_string (keyfile, groups[i], keys[j], &error)) == NULL) { g_printerr ("%s", error->message); g_error_free (error); continue; } error = NULL; if ((value = gconf_client_get_without_default (client, gconf_key, &error)) == NULL) { if (error) { g_printerr ("Failed to get GConf key '%s': %s\n", gconf_key, error->message); g_error_free (error); } else { if (verbose) g_print ("Skipping GConf key '%s', no user value\n", gconf_key); } g_free (gconf_key); continue; } switch (value->type) { case GCONF_VALUE_STRING: if (dry_run) g_print ("Set key '%s' to string '%s'\n", keys[j], gconf_value_get_string (value)); else g_settings_set (settings, keys[j], "s", gconf_value_get_string (value)); break; case GCONF_VALUE_INT: if (dry_run) g_print ("Set key '%s' to integer '%d'\n", keys[j], gconf_value_get_int (value)); else { GVariant *range; gchar *type; range = g_settings_get_range (settings, keys[j]); g_variant_get (range, "(&sv)", &type, NULL); if (strcmp (type, "enum") == 0) g_settings_set_enum (settings, keys[j], gconf_value_get_int (value)); else if (strcmp (type, "flags") == 0) g_settings_set_flags (settings, keys[j], gconf_value_get_int (value)); else if (type_uint32 (settings, keys[j])) g_settings_set (settings, keys[j], "u", gconf_value_get_int (value)); else g_settings_set (settings, keys[j], "i", gconf_value_get_int (value)); g_variant_unref (range); } break; case GCONF_VALUE_BOOL: if (dry_run) g_print ("Set key '%s' to boolean '%d'\n", keys[j], gconf_value_get_bool (value)); else g_settings_set (settings, keys[j], "b", gconf_value_get_bool (value)); break; case GCONF_VALUE_FLOAT: if (dry_run) g_print ("Set key '%s' to double '%g'\n", keys[j], gconf_value_get_float (value)); else g_settings_set (settings, keys[j], "d", gconf_value_get_float (value)); break; case GCONF_VALUE_LIST: switch (gconf_value_get_list_type (value)) { case GCONF_VALUE_STRING: builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); list = gconf_value_get_list (value); if (list != NULL) { for (l = list; l; l = l->next) { GConfValue *lv = l->data; s = gconf_value_get_string (lv); g_variant_builder_add (builder, "s", s); } v = g_variant_new ("as", builder); } else v = g_variant_new_array (G_VARIANT_TYPE_STRING, NULL, 0); g_variant_ref_sink (v); if (dry_run) { str = g_variant_print (v, FALSE); g_print ("Set key '%s' to a list of strings: %s\n", keys[j], str); g_free (str); } else g_settings_set_value (settings, keys[j], v); g_variant_unref (v); g_variant_builder_unref (builder); break; case GCONF_VALUE_INT: builder = g_variant_builder_new (G_VARIANT_TYPE_ARRAY); list = gconf_value_get_list (value); if (list != NULL) { for (l = list; l; l = l->next) { GConfValue *lv = l->data; ii = gconf_value_get_int (lv); g_variant_builder_add (builder, "i", ii); } v = g_variant_new ("ai", builder); } else v = g_variant_new_array (G_VARIANT_TYPE_INT32, NULL, 0); g_variant_ref_sink (v); if (dry_run) { str = g_variant_print (v, FALSE); g_print ("Set key '%s' to a list of integers: %s\n", keys[j], str); g_free (str); } else g_settings_set_value (settings, keys[j], v); g_variant_unref (v); g_variant_builder_unref (builder); break; default: g_printerr ("Keys of type 'list of %s' not handled yet\n", gconf_value_type_to_string (gconf_value_get_list_type (value))); break; } break; default: g_printerr ("Keys of type %s not handled yet\n", gconf_value_type_to_string (value->type)); break; } gconf_value_free (value); g_free (gconf_key); } g_strfreev (keys); if (!dry_run) g_settings_apply (settings); g_object_unref (settings); g_strfreev (schema_path); } g_strfreev (groups); g_object_unref (client); return TRUE; }
/* this actually works on any node, not just <entry>, such as the <car> and <cdr> nodes and the <li> nodes and the <default> node */ static GConfValue* node_extract_value(xmlNodePtr node, const gchar** locales, GError** err) { GConfValue* value = NULL; gchar* type_str; GConfValueType type = GCONF_VALUE_INVALID; const gchar* default_locales[] = { "C", NULL }; if (locales == NULL) locales = default_locales; type_str = my_xmlGetProp(node, "type"); if (type_str == NULL) { gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("No \"type\" attribute for <%s> node"), (node->name ? (char*)node->name : "(nil)")); return NULL; } type = gconf_value_type_from_string(type_str); xmlFree(type_str); switch (type) { case GCONF_VALUE_INVALID: { gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("A node has unknown \"type\" attribute `%s', ignoring"), type_str); return NULL; } break; case GCONF_VALUE_INT: case GCONF_VALUE_BOOL: case GCONF_VALUE_FLOAT: { gchar* value_str; value_str = my_xmlGetProp(node, "value"); if (value_str == NULL) { gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("No \"value\" attribute for node")); return NULL; } value = gconf_value_new_from_string(type, value_str, err); xmlFree(value_str); g_return_val_if_fail( (value != NULL) || (err == NULL) || (*err != NULL), NULL ); return value; } break; case GCONF_VALUE_STRING: { xmlNodePtr iter; iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { GConfValue* v = NULL; if (strcmp((char *)iter->name, "stringvalue") == 0) { gchar* s; s = (gchar *)xmlNodeGetContent(iter); v = gconf_value_new(GCONF_VALUE_STRING); /* strdup() caused purely by g_free()/free() difference */ gconf_value_set_string(v, s ? s : ""); if (s) xmlFree(s); return v; } else { /* What the hell is this? */ gconf_log(GCL_WARNING, _("Didn't understand XML node <%s> inside an XML list node"), iter->name ? iter->name : (guchar*)"???"); } } iter = iter->next; } return NULL; } break; case GCONF_VALUE_SCHEMA: return schema_node_extract_value(node, locales); break; case GCONF_VALUE_LIST: { xmlNodePtr iter; GSList* values = NULL; GConfValueType list_type = GCONF_VALUE_INVALID; { gchar* s; s = my_xmlGetProp(node, "ltype"); if (s != NULL) { list_type = gconf_value_type_from_string(s); xmlFree(s); } } switch (list_type) { case GCONF_VALUE_INVALID: case GCONF_VALUE_LIST: case GCONF_VALUE_PAIR: gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("Invalid type (list, pair, or unknown) in a list node")); return NULL; default: break; } iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { GConfValue* v = NULL; if (strcmp((char*)iter->name, "li") == 0) { v = node_extract_value(iter, locales, err); if (v == NULL) { if (err && *err) { gconf_log(GCL_WARNING, _("Bad XML node: %s"), (*err)->message); /* avoid pile-ups */ g_clear_error(err); } } else if (v->type != list_type) { gconf_log(GCL_WARNING, _("List contains a badly-typed node (%s, should be %s)"), gconf_value_type_to_string(v->type), gconf_value_type_to_string(list_type)); gconf_value_free(v); v = NULL; } } else { /* What the hell is this? */ gconf_log(GCL_WARNING, _("Didn't understand XML node <%s> inside an XML list node"), iter->name ? iter->name : (guchar*)"???"); } if (v != NULL) values = g_slist_prepend(values, v); } iter = iter->next; } /* put them in order, set the value */ values = g_slist_reverse(values); value = gconf_value_new(GCONF_VALUE_LIST); gconf_value_set_list_type(value, list_type); gconf_value_set_list_nocopy(value, values); return value; } break; case GCONF_VALUE_PAIR: { GConfValue* car = NULL; GConfValue* cdr = NULL; xmlNodePtr iter; iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (car == NULL && strcmp((char *)iter->name, "car") == 0) { car = node_extract_value(iter, locales, err); if (car == NULL) { if (err && *err) { gconf_log(GCL_WARNING, _("Ignoring bad car from XML pair: %s"), (*err)->message); /* prevent pile-ups */ g_clear_error(err); } } else if (car->type == GCONF_VALUE_LIST || car->type == GCONF_VALUE_PAIR) { gconf_log(GCL_WARNING, _("parsing XML file: lists and pairs may not be placed inside a pair")); gconf_value_free(car); car = NULL; } } else if (cdr == NULL && strcmp((char *)iter->name, "cdr") == 0) { cdr = node_extract_value(iter, locales, err); if (cdr == NULL) { if (err && *err) { gconf_log(GCL_WARNING, _("Ignoring bad cdr from XML pair: %s"), (*err)->message); /* avoid pile-ups */ g_clear_error(err); } } else if (cdr->type == GCONF_VALUE_LIST || cdr->type == GCONF_VALUE_PAIR) { gconf_log(GCL_WARNING, _("parsing XML file: lists and pairs may not be placed inside a pair")); gconf_value_free(cdr); cdr = NULL; } } else { /* What the hell is this? */ gconf_log(GCL_WARNING, _("Didn't understand XML node <%s> inside an XML pair node"), iter->name ? (gchar*)iter->name : "???"); } } iter = iter->next; } /* Return the pair if we got both halves */ if (car && cdr) { value = gconf_value_new(GCONF_VALUE_PAIR); gconf_value_set_car_nocopy(value, car); gconf_value_set_cdr_nocopy(value, cdr); return value; } else { gconf_log(GCL_WARNING, _("Didn't find car and cdr for XML pair node")); if (car) { g_assert(cdr == NULL); gconf_value_free(car); gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("Missing cdr from pair of values in XML file")); } else if (cdr) { g_assert(car == NULL); gconf_value_free(cdr); gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("Missing car from pair of values in XML file")); } else { gconf_set_error(err, GCONF_ERROR_PARSE_ERROR, _("Missing both car and cdr values from pair in XML file")); } return NULL; } } break; default: g_assert_not_reached(); return NULL; break; } }
static void node_set_value(xmlNodePtr node, GConfValue* value) { const gchar* type; gchar* value_str; g_return_if_fail(node != NULL); g_return_if_fail(value != NULL); g_return_if_fail(value->type != GCONF_VALUE_INVALID); type = gconf_value_type_to_string(value->type); g_assert(type != NULL); my_xmlSetProp(node, "type", type); switch (value->type) { case GCONF_VALUE_INT: case GCONF_VALUE_FLOAT: case GCONF_VALUE_BOOL: free_childs(node); value_str = gconf_value_to_string(value); my_xmlSetProp(node, "value", value_str); g_free(value_str); break; case GCONF_VALUE_STRING: { xmlChar* encoded; free_childs(node); encoded = xmlEncodeEntitiesReentrant(node->doc, (xmlChar *)gconf_value_get_string(value)); xmlNewChild(node, NULL, (xmlChar *)"stringvalue", encoded); xmlFree(encoded); } break; case GCONF_VALUE_SCHEMA: { node_set_schema_value(node, value); } break; case GCONF_VALUE_LIST: { GSList* list; free_childs(node); my_xmlSetProp(node, "ltype", gconf_value_type_to_string(gconf_value_get_list_type(value))); /* Add a new child for each node */ list = gconf_value_get_list(value); while (list != NULL) { xmlNodePtr child; /* this is O(1) because libxml saves the list tail */ child = xmlNewChild(node, NULL, (xmlChar *)"li", NULL); g_return_if_fail(list->data != NULL); node_set_value(child, (GConfValue*)list->data); list = g_slist_next(list); } } break; case GCONF_VALUE_PAIR: { xmlNodePtr car, cdr; free_childs(node); car = xmlNewChild(node, NULL, (xmlChar *)"car", NULL); cdr = xmlNewChild(node, NULL, (xmlChar *)"cdr", NULL); g_return_if_fail(gconf_value_get_car(value) != NULL); g_return_if_fail(gconf_value_get_cdr(value) != NULL); node_set_value(car, gconf_value_get_car(value)); node_set_value(cdr, gconf_value_get_cdr(value)); } break; default: g_assert_not_reached(); break; } }
static void node_set_schema_value(xmlNodePtr node, GConfValue* value) { GConfSchema* sc; const gchar* locale; const gchar* type; xmlNodePtr found = NULL; sc = gconf_value_get_schema (value); /* Set the types */ if (gconf_schema_get_list_type (sc) != GCONF_VALUE_INVALID) { type = gconf_value_type_to_string(gconf_schema_get_list_type (sc)); g_assert(type != NULL); my_xmlSetProp(node, "list_type", type); } if (gconf_schema_get_car_type (sc) != GCONF_VALUE_INVALID) { type = gconf_value_type_to_string(gconf_schema_get_car_type (sc)); g_assert(type != NULL); my_xmlSetProp(node, "car_type", type); } if (gconf_schema_get_cdr_type (sc) != GCONF_VALUE_INVALID) { type = gconf_value_type_to_string(gconf_schema_get_cdr_type (sc)); g_assert(type != NULL); my_xmlSetProp(node, "cdr_type", type); } /* unset this in case the node was previously a different type */ my_xmlSetProp(node, "value", NULL); /* set the cross-locale attributes */ my_xmlSetProp(node, "stype", gconf_value_type_to_string(gconf_schema_get_type (sc))); my_xmlSetProp(node, "owner", gconf_schema_get_owner (sc)); locale = gconf_schema_get_locale(sc); gconf_log(GCL_DEBUG, "Setting XML node to schema with locale `%s'", locale); /* Find the node for this locale */ found = find_schema_subnode_by_locale(node, locale); if (found == NULL) found = xmlNewChild(node, NULL, (xmlChar *)"local_schema", NULL); /* OK if these are set to NULL, since that unsets the property */ my_xmlSetProp(found, "locale", gconf_schema_get_locale (sc)); my_xmlSetProp(found, "short_desc", gconf_schema_get_short_desc (sc)); free_childs(found); if (gconf_schema_get_default_value (sc) != NULL) { xmlNodePtr default_value_node; default_value_node = xmlNewChild(found, NULL, (xmlChar *)"default", NULL); node_set_value(default_value_node, gconf_schema_get_default_value (sc)); } if (gconf_schema_get_long_desc (sc)) { xmlNewChild(found, NULL, (xmlChar *)"longdesc", (xmlChar *)gconf_schema_get_long_desc (sc)); } }