Mercurial > pidgin
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) { |
