comparison libpurple/xmlnode.c @ 32037:114a98da1a5f

xmlnode: Fix some brokeness in xmlnode serialization with prefixed elements. Basically we were treating node->xmlns as the default namespace, but that isn't the case with prefexed elements. In our serialization, I believe we were adding an extraneous xmlns='' to a prefixed element, which changes the (default) namespace for its children. (It's been a bit too long with this in my tree, so I've forgotten the exact details)
author Paul Aurich <paul@darkrain42.org>
date Sun, 04 Sep 2011 18:52:18 +0000
parents 67addaf8677f
children 8d3b5853b017
comparison
equal deleted inserted replaced
32036:a9f13cb4e945 32037:114a98da1a5f
76 g_return_val_if_fail(name != NULL && *name != '\0', NULL); 76 g_return_val_if_fail(name != NULL && *name != '\0', NULL);
77 77
78 node = new_node(name, XMLNODE_TYPE_TAG); 78 node = new_node(name, XMLNODE_TYPE_TAG);
79 79
80 xmlnode_insert_child(parent, node); 80 xmlnode_insert_child(parent, node);
81 #if 0
82 /* This would give xmlnodes more appropriate namespacing
83 * when creating them. Otherwise, unless an explicit namespace
84 * is set, xmlnode_get_namespace() will return NULL, when
85 * there may be a default namespace.
86 *
87 * I'm unconvinced that it's useful, and concerned it may break things.
88 *
89 * _insert_child would need the same thing, probably (assuming
90 * xmlns->node == NULL)
91 */
92 xmlnode_set_namespace(node, xmlnode_get_default_namespace(node))
93 #endif
81 94
82 return node; 95 return node;
83 } 96 }
84 97
85 void 98 void
253 266
254 g_free(node->xmlns); 267 g_free(node->xmlns);
255 node->xmlns = g_strdup(xmlns); 268 node->xmlns = g_strdup(xmlns);
256 } 269 }
257 270
258 const char *xmlnode_get_namespace(xmlnode *node) 271 const char *xmlnode_get_namespace(const xmlnode *node)
259 { 272 {
260 g_return_val_if_fail(node != NULL, NULL); 273 g_return_val_if_fail(node != NULL, NULL);
261 274
262 return node->xmlns; 275 return node->xmlns;
276 }
277
278 const char *xmlnode_get_default_namespace(const xmlnode *node)
279 {
280 const char *ns = NULL;
281 g_return_val_if_fail(node != NULL, NULL);
282
283 /* If this node does *not* have a prefix, node->xmlns is the default
284 * namespace. Otherwise, it's the prefix namespace.
285 */
286 if (!node->prefix && node->xmlns) {
287 return node->xmlns;
288 } else if (node->namespace_map) {
289 ns = g_hash_table_lookup(node->namespace_map, "");
290 }
291
292 /* No default ns found? Walk up the tree looking for one */
293 if (!(ns && *ns) && node->parent)
294 ns = xmlnode_get_default_namespace(node->parent);
295
296 return ns;
263 } 297 }
264 298
265 void xmlnode_set_prefix(xmlnode *node, const char *prefix) 299 void xmlnode_set_prefix(xmlnode *node, const char *prefix)
266 { 300 {
267 g_return_if_fail(node != NULL); 301 g_return_if_fail(node != NULL);
441 } 475 }
442 476
443 if (node->namespace_map) { 477 if (node->namespace_map) {
444 g_hash_table_foreach(node->namespace_map, 478 g_hash_table_foreach(node->namespace_map,
445 (GHFunc)xmlnode_to_str_foreach_append_ns, text); 479 (GHFunc)xmlnode_to_str_foreach_append_ns, text);
446 } else if (node->xmlns) { 480 } else {
447 if(!node->parent || !purple_strequal(node->xmlns, node->parent->xmlns)) 481 /* Figure out if this node has a different default namespace from parent */
482 const char *xmlns = NULL;
483 const char *parent_xmlns = NULL;
484 if (!prefix)
485 xmlns = node->xmlns;
486
487 if (!xmlns)
488 xmlns = xmlnode_get_default_namespace(node);
489 if (node->parent)
490 parent_xmlns = xmlnode_get_default_namespace(node->parent);
491 if (!purple_strequal(xmlns, parent_xmlns))
448 { 492 {
449 char *xmlns = g_markup_escape_text(node->xmlns, -1); 493 char *escaped_xmlns = g_markup_escape_text(xmlns, -1);
450 g_string_append_printf(text, " xmlns='%s'", xmlns); 494 g_string_append_printf(text, " xmlns='%s'", escaped_xmlns);
451 g_free(xmlns); 495 g_free(escaped_xmlns);
452 } 496 }
453 } 497 }
454 for(c = node->child; c; c = c->next) 498 for(c = node->child; c; c = c->next)
455 { 499 {
456 if(c->type == XMLNODE_TYPE_ATTRIB) { 500 if(c->type == XMLNODE_TYPE_ATTRIB) {