static xmlNodePtr find_schema_subnode_by_locale(xmlNodePtr node, const gchar* locale) { xmlNodePtr iter; xmlNodePtr found = NULL; iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE && strcmp((char *)iter->name, "local_schema") == 0) { char* this_locale = my_xmlGetProp(iter, "locale"); if (locale && this_locale && strcmp(locale, this_locale) == 0) { found = iter; xmlFree(this_locale); break; } else if (this_locale == NULL && locale == NULL) { found = iter; break; } else if (this_locale != NULL) xmlFree(this_locale); } iter = iter->next; } return found; }
static void dir_fill_cache_from_doc(Dir* d) { xmlNodePtr node; if (d->doc == NULL || d->doc->xmlRootNode == NULL || d->doc->xmlRootNode->xmlChildrenNode == NULL) { /* Empty document - just return. */ return; } node = d->doc->xmlRootNode->xmlChildrenNode; while (node != NULL) { if (node->type == XML_ELEMENT_NODE && (strcmp((xmlChar *)node->name, "entry") == 0)) { gchar* attr = my_xmlGetProp(node, "name"); if (attr != NULL) { if (g_hash_table_lookup(d->entry_cache, attr) != NULL) { gconf_log(GCL_WARNING, _("Duplicate entry `%s' in `%s', ignoring"), attr, d->xml_filename); } else { Entry* e; e = entry_new(attr); entry_set_node(e, node); entry_fill_from_node(e); safe_g_hash_table_insert(d->entry_cache, (gchar*)entry_get_name(e), e); } free(attr); } else { gconf_log(GCL_WARNING, _("Entry with no name in XML file `%s', ignoring"), d->xml_filename); } } else { if (node->type == XML_ELEMENT_NODE) gconf_log(GCL_WARNING, _("A toplevel node in XML file `%s' is <%s> rather than <entry>, ignoring"), d->xml_filename, node->name ? (char*) node->name : "unknown"); } node = node->next; } }
/* 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 GConfValue* schema_node_extract_value(xmlNodePtr node, const gchar** locales) { GConfValue* value = NULL; gchar* owner_str; gchar* stype_str; gchar* list_type_str; gchar* car_type_str; gchar* cdr_type_str; GConfSchema* sc; xmlNodePtr iter; guint i; xmlNodePtr* localized_nodes; xmlNodePtr best = NULL; /* owner, type are for all locales; default value, descriptions are per-locale */ owner_str = my_xmlGetProp(node, "owner"); stype_str = my_xmlGetProp(node, "stype"); list_type_str = my_xmlGetProp(node, "list_type"); car_type_str = my_xmlGetProp(node, "car_type"); cdr_type_str = my_xmlGetProp(node, "cdr_type"); sc = gconf_schema_new(); if (owner_str) { gconf_schema_set_owner(sc, owner_str); xmlFree(owner_str); } if (stype_str) { GConfValueType stype; stype = gconf_value_type_from_string(stype_str); gconf_schema_set_type(sc, stype); xmlFree(stype_str); } if (list_type_str) { GConfValueType type; type = gconf_value_type_from_string(list_type_str); gconf_schema_set_list_type(sc, type); xmlFree(list_type_str); } if (car_type_str) { GConfValueType type; type = gconf_value_type_from_string(car_type_str); gconf_schema_set_car_type(sc, type); xmlFree(car_type_str); } if (cdr_type_str) { GConfValueType type; type = gconf_value_type_from_string(cdr_type_str); gconf_schema_set_cdr_type(sc, type); xmlFree(cdr_type_str); } if (locales != NULL && locales[0]) { /* count the number of possible locales */ int n_locales; n_locales = 0; while (locales[n_locales]) ++n_locales; localized_nodes = g_new0(xmlNodePtr, n_locales); /* Find the node for each possible locale */ iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE && strcmp((char *)iter->name, "local_schema") == 0) { char* locale_name; locale_name = my_xmlGetProp(iter, "locale"); if (locale_name != NULL) { i = 0; while (locales[i]) { if (strcmp(locales[i], locale_name) == 0) { localized_nodes[i] = iter; break; } ++i; } xmlFree(locale_name); /* Quit as soon as we have the best possible locale */ if (localized_nodes[0] != NULL) break; } } iter = iter->next; } /* See which is the best locale we managed to load, they are in order of preference. */ i = 0; best = localized_nodes[i]; while (best == NULL && i < n_locales) { best = localized_nodes[i]; ++i; } g_free(localized_nodes); } /* If no locale matched, try picking the the null localization, * and then try picking the first node */ if (best == NULL) best = find_schema_subnode_by_locale (node, NULL); if (best == NULL) { best = node->xmlChildrenNode; while (best && best->type != XML_ELEMENT_NODE) best = best->next; } /* Extract info from the best locale node */ if (best != NULL) schema_subnode_extract_data(best, sc); /* Create a GConfValue with this schema and return it */ value = gconf_value_new(GCONF_VALUE_SCHEMA); gconf_value_set_schema_nocopy(value, sc); return value; }
static void schema_subnode_extract_data(xmlNodePtr node, GConfSchema* sc) { gchar* sd_str; gchar* locale_str; GError* error = NULL; sd_str = my_xmlGetProp(node, "short_desc"); locale_str = my_xmlGetProp(node, "locale"); if (sd_str) { gconf_schema_set_short_desc(sc, sd_str); xmlFree(sd_str); } if (locale_str) { gconf_log(GCL_DEBUG, "found locale `%s'", locale_str); gconf_schema_set_locale(sc, locale_str); xmlFree(locale_str); } else { gconf_log(GCL_DEBUG, "found <%s> with no locale setting", node->name ? node->name : (unsigned char*) "null"); } if (node->xmlChildrenNode != NULL) { GConfValue* default_value = NULL; xmlChar* ld_str = NULL; GSList* bad_nodes = NULL; xmlNodePtr iter = node->xmlChildrenNode; while (iter != NULL) { if (iter->type == XML_ELEMENT_NODE) { if (default_value == NULL && strcmp((char *)iter->name, "default") == 0) { default_value = node_extract_value(iter, NULL, &error); if (error != NULL) { g_assert(default_value == NULL); gconf_log(GCL_WARNING, _("Failed reading default value for schema: %s"), error->message); g_error_free(error); error = NULL; bad_nodes = g_slist_prepend(bad_nodes, iter); } } else if (ld_str == NULL && strcmp((char *)iter->name, "longdesc") == 0) { ld_str = xmlNodeGetContent(iter); } else { bad_nodes = g_slist_prepend(bad_nodes, iter); } } else bad_nodes = g_slist_prepend(bad_nodes, iter); /* what is this node? */ iter = iter->next; } /* Remove the bad nodes from the parse tree */ if (bad_nodes != NULL) { GSList* tmp = bad_nodes; while (tmp != NULL) { xmlUnlinkNode(tmp->data); xmlFreeNode(tmp->data); tmp = g_slist_next(tmp); } g_slist_free(bad_nodes); } if (default_value != NULL) gconf_schema_set_default_value_nocopy(sc, default_value); if (ld_str) { gconf_schema_set_long_desc(sc, (char *)ld_str); xmlFree(ld_str); } } }
void entry_fill_from_node(Entry* e) { gchar* tmp; GError* error = NULL; g_return_if_fail(e->node != NULL); tmp = my_xmlGetProp(e->node, "schema"); if (tmp != NULL) { /* Filter any crap schemas that appear, some speed cost */ gchar* why_bad = NULL; if (gconf_valid_key(tmp, &why_bad)) { g_assert(why_bad == NULL); e->schema_name = g_strdup(tmp); } else { e->schema_name = NULL; gconf_log(GCL_WARNING, _("Ignoring schema name `%s', invalid: %s"), tmp, why_bad); g_free(why_bad); } xmlFree(tmp); } tmp = my_xmlGetProp(e->node, "mtime"); if (tmp != NULL) { e->mod_time = gconf_string_to_gulong(tmp); xmlFree(tmp); } else e->mod_time = 0; tmp = my_xmlGetProp(e->node, "muser"); if (tmp != NULL) { e->mod_user = g_strdup(tmp); xmlFree(tmp); } else e->mod_user = NULL; entry_sync_if_needed(e); if (e->cached_value != NULL) gconf_value_free(e->cached_value); e->cached_value = node_extract_value(e->node, NULL, /* FIXME current locale as a guess */ &error); if (e->cached_value) { g_return_if_fail(error == NULL); return; } else if (error != NULL) { /* Ignore errors from node_extract_value() if we got a schema name, * since the node's only purpose may be to store the schema name. */ if (e->schema_name == NULL) gconf_log (GCL_WARNING, _("Ignoring XML node `%s': %s"), e->name, error->message); g_error_free(error); } }