Mercurial > pidgin
comparison libgaim/xmlnode.c @ 14436:289490ee84d1
[gaim-migrate @ 17150]
libxml2 is now required for XML parsing
committer: Tailor Script <tailor@pidgin.im>
| author | Mark Doliner <mark@kingant.net> |
|---|---|
| date | Mon, 04 Sep 2006 03:55:12 +0000 |
| parents | 2d7086454b08 |
| children | 58202142e9ad |
comparison
equal
deleted
inserted
replaced
| 14435:9c6533500fff | 14436:289490ee84d1 |
|---|---|
| 27 * write my own stuff. Also, re-writing this lets me be as lightweight | 27 * write my own stuff. Also, re-writing this lets me be as lightweight |
| 28 * as I want to be. Thank you libxode for giving me a good starting point */ | 28 * as I want to be. Thank you libxode for giving me a good starting point */ |
| 29 | 29 |
| 30 #include "internal.h" | 30 #include "internal.h" |
| 31 | 31 |
| 32 #ifdef HAVE_LIBXML | |
| 33 #include <libxml/parser.h> | 32 #include <libxml/parser.h> |
| 34 #endif | |
| 35 #include <string.h> | 33 #include <string.h> |
| 36 #include <glib.h> | 34 #include <glib.h> |
| 37 | 35 |
| 38 #include "dbus-maybe.h" | 36 #include "dbus-maybe.h" |
| 39 #include "util.h" | 37 #include "util.h" |
| 179 } | 177 } |
| 180 | 178 |
| 181 | 179 |
| 182 void xmlnode_set_namespace(xmlnode *node, const char *xmlns) | 180 void xmlnode_set_namespace(xmlnode *node, const char *xmlns) |
| 183 { | 181 { |
| 184 #ifdef HAVE_LIBXML | |
| 185 g_return_if_fail(node != NULL); | 182 g_return_if_fail(node != NULL); |
| 186 | 183 |
| 187 g_free(node->namespace); | 184 g_free(node->namespace); |
| 188 node->namespace = g_strdup(xmlns); | 185 node->namespace = g_strdup(xmlns); |
| 189 #else | |
| 190 xmlnode_set_attrib(node, "xmlns", xmlns); | |
| 191 #endif | |
| 192 } | 186 } |
| 193 | 187 |
| 194 const char *xmlnode_get_namespace(xmlnode *node) | 188 const char *xmlnode_get_namespace(xmlnode *node) |
| 195 { | 189 { |
| 196 #ifdef HAVE_LIBXML | |
| 197 g_return_val_if_fail(node != NULL, NULL); | 190 g_return_val_if_fail(node != NULL, NULL); |
| 198 | 191 |
| 199 return node->namespace; | 192 return node->namespace; |
| 200 #else | |
| 201 return xmlnode_get_attrib(node, "xmlns"); | |
| 202 #endif | |
| 203 } | 193 } |
| 204 | 194 |
| 205 void | 195 void |
| 206 xmlnode_free(xmlnode *node) | 196 xmlnode_free(xmlnode *node) |
| 207 { | 197 { |
| 216 x = y; | 206 x = y; |
| 217 } | 207 } |
| 218 | 208 |
| 219 g_free(node->name); | 209 g_free(node->name); |
| 220 g_free(node->data); | 210 g_free(node->data); |
| 221 #ifdef HAVE_LIBXML | |
| 222 g_free(node->namespace); | 211 g_free(node->namespace); |
| 223 #endif | |
| 224 | 212 |
| 225 GAIM_DBUS_UNREGISTER_POINTER(node); | 213 GAIM_DBUS_UNREGISTER_POINTER(node); |
| 226 g_free(node); | 214 g_free(node); |
| 227 } | 215 } |
| 228 | 216 |
| 303 } | 291 } |
| 304 | 292 |
| 305 node_name = g_markup_escape_text(node->name, -1); | 293 node_name = g_markup_escape_text(node->name, -1); |
| 306 g_string_append_printf(text, "<%s", node_name); | 294 g_string_append_printf(text, "<%s", node_name); |
| 307 | 295 |
| 308 #ifdef HAVE_LIBXML | |
| 309 if (node->namespace) { | 296 if (node->namespace) { |
| 310 char *namespace = g_markup_escape_text(node->namespace, -1); | 297 char *namespace = g_markup_escape_text(node->namespace, -1); |
| 311 g_string_append_printf(text, " xmlns='%s'", namespace); | 298 g_string_append_printf(text, " xmlns='%s'", namespace); |
| 312 g_free(namespace); | 299 g_free(namespace); |
| 313 } | 300 } |
| 314 #endif | |
| 315 for(c = node->child; c; c = c->next) | 301 for(c = node->child; c; c = c->next) |
| 316 { | 302 { |
| 317 if(c->type == XMLNODE_TYPE_ATTRIB) { | 303 if(c->type == XMLNODE_TYPE_ATTRIB) { |
| 318 esc = g_markup_escape_text(c->name, -1); | 304 esc = g_markup_escape_text(c->name, -1); |
| 319 esc2 = g_markup_escape_text(c->data, -1); | 305 esc2 = g_markup_escape_text(c->data, -1); |
| 384 | 370 |
| 385 struct _xmlnode_parser_data { | 371 struct _xmlnode_parser_data { |
| 386 xmlnode *current; | 372 xmlnode *current; |
| 387 }; | 373 }; |
| 388 | 374 |
| 389 #ifdef HAVE_LIBXML | |
| 390 static void | 375 static void |
| 391 xmlnode_parser_element_start_libxml(void *user_data, | 376 xmlnode_parser_element_start_libxml(void *user_data, |
| 392 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace, | 377 const xmlChar *element_name, const xmlChar *prefix, const xmlChar *namespace, |
| 393 int nb_namespaces, const xmlChar **namespaces, | 378 int nb_namespaces, const xmlChar **namespaces, |
| 394 int nb_attributes, int nb_defaulted, const xmlChar **attributes) | 379 int nb_attributes, int nb_defaulted, const xmlChar **attributes) |
| 406 node = xmlnode_new(element_name); | 391 node = xmlnode_new(element_name); |
| 407 | 392 |
| 408 xmlnode_set_namespace(node, namespace); | 393 xmlnode_set_namespace(node, namespace); |
| 409 | 394 |
| 410 for(i=0; i < nb_attributes * 5; i+=5) { | 395 for(i=0; i < nb_attributes * 5; i+=5) { |
| 411 #ifdef HAVE_LIBXML | |
| 412 char *txt; | 396 char *txt; |
| 413 #endif | |
| 414 int attrib_len = attributes[i+4] - attributes[i+3]; | 397 int attrib_len = attributes[i+4] - attributes[i+3]; |
| 415 char *attrib = g_malloc(attrib_len + 1); | 398 char *attrib = g_malloc(attrib_len + 1); |
| 416 memcpy(attrib, attributes[i+3], attrib_len); | 399 memcpy(attrib, attributes[i+3], attrib_len); |
| 417 attrib[attrib_len] = '\0'; | 400 attrib[attrib_len] = '\0'; |
| 418 #ifdef HAVE_LIBXML | |
| 419 txt = attrib; | 401 txt = attrib; |
| 420 attrib = gaim_unescape_html(txt); | 402 attrib = gaim_unescape_html(txt); |
| 421 g_free(txt); | 403 g_free(txt); |
| 422 #endif | |
| 423 xmlnode_set_attrib(node, attributes[i], attrib); | 404 xmlnode_set_attrib(node, attributes[i], attrib); |
| 424 g_free(attrib); | 405 g_free(attrib); |
| 425 } | 406 } |
| 426 | 407 |
| 427 xpd->current = node; | 408 xpd->current = node; |
| 455 return; | 436 return; |
| 456 | 437 |
| 457 xmlnode_insert_data(xpd->current, text, text_len); | 438 xmlnode_insert_data(xpd->current, text, text_len); |
| 458 } | 439 } |
| 459 | 440 |
| 460 #else | |
| 461 | |
| 462 static void | |
| 463 xmlnode_parser_element_start(GMarkupParseContext *context, | |
| 464 const char *element_name, const char **attrib_names, | |
| 465 const char **attrib_values, gpointer user_data, GError **error) | |
| 466 { | |
| 467 struct _xmlnode_parser_data *xpd = user_data; | |
| 468 xmlnode *node; | |
| 469 int i; | |
| 470 | |
| 471 if(!element_name) { | |
| 472 return; | |
| 473 } else { | |
| 474 if(xpd->current) | |
| 475 node = xmlnode_new_child(xpd->current, element_name); | |
| 476 else | |
| 477 node = xmlnode_new(element_name); | |
| 478 | |
| 479 for(i=0; attrib_names[i]; i++) | |
| 480 xmlnode_set_attrib(node, attrib_names[i], attrib_values[i]); | |
| 481 | |
| 482 xpd->current = node; | |
| 483 } | |
| 484 } | |
| 485 | |
| 486 static void | |
| 487 xmlnode_parser_element_end(GMarkupParseContext *context, | |
| 488 const char *element_name, gpointer user_data, GError **error) | |
| 489 { | |
| 490 struct _xmlnode_parser_data *xpd = user_data; | |
| 491 | |
| 492 if(!element_name || !xpd->current) | |
| 493 return; | |
| 494 | |
| 495 if(xpd->current->parent) { | |
| 496 if(!strcmp(xpd->current->name, element_name)) | |
| 497 xpd->current = xpd->current->parent; | |
| 498 } | |
| 499 } | |
| 500 | |
| 501 static void | |
| 502 xmlnode_parser_element_text(GMarkupParseContext *context, const char *text, | |
| 503 gsize text_len, gpointer user_data, GError **error) | |
| 504 { | |
| 505 struct _xmlnode_parser_data *xpd = user_data; | |
| 506 | |
| 507 if(!xpd->current) | |
| 508 return; | |
| 509 | |
| 510 if(!text || !text_len) | |
| 511 return; | |
| 512 | |
| 513 xmlnode_insert_data(xpd->current, text, text_len); | |
| 514 } | |
| 515 #endif | |
| 516 | |
| 517 #ifdef HAVE_LIBXML | |
| 518 static xmlSAXHandler xmlnode_parser_libxml = { | 441 static xmlSAXHandler xmlnode_parser_libxml = { |
| 519 .internalSubset = NULL, | 442 .internalSubset = NULL, |
| 520 .isStandalone = NULL, | 443 .isStandalone = NULL, |
| 521 .hasInternalSubset = NULL, | 444 .hasInternalSubset = NULL, |
| 522 .hasExternalSubset = NULL, | 445 .hasExternalSubset = NULL, |
| 547 ._private = NULL, | 470 ._private = NULL, |
| 548 .startElementNs = xmlnode_parser_element_start_libxml, | 471 .startElementNs = xmlnode_parser_element_start_libxml, |
| 549 .endElementNs = xmlnode_parser_element_end_libxml, | 472 .endElementNs = xmlnode_parser_element_end_libxml, |
| 550 .serror = NULL | 473 .serror = NULL |
| 551 }; | 474 }; |
| 552 #else | |
| 553 static GMarkupParser xmlnode_parser = { | |
| 554 xmlnode_parser_element_start, | |
| 555 xmlnode_parser_element_end, | |
| 556 xmlnode_parser_element_text, | |
| 557 NULL, | |
| 558 NULL | |
| 559 }; | |
| 560 #endif | |
| 561 | 475 |
| 562 xmlnode * | 476 xmlnode * |
| 563 xmlnode_from_str(const char *str, gssize size) | 477 xmlnode_from_str(const char *str, gssize size) |
| 564 { | 478 { |
| 565 struct _xmlnode_parser_data *xpd; | 479 struct _xmlnode_parser_data *xpd; |
| 566 xmlnode *ret; | 480 xmlnode *ret; |
| 567 #ifndef HAVE_LIBXML | |
| 568 GMarkupParseContext *context; | |
| 569 #endif | |
| 570 gsize real_size; | 481 gsize real_size; |
| 571 | 482 |
| 572 g_return_val_if_fail(str != NULL, NULL); | 483 g_return_val_if_fail(str != NULL, NULL); |
| 573 | 484 |
| 574 real_size = size < 0 ? strlen(str) : size; | 485 real_size = size < 0 ? strlen(str) : size; |
| 575 xpd = g_new0(struct _xmlnode_parser_data, 1); | 486 xpd = g_new0(struct _xmlnode_parser_data, 1); |
| 576 | 487 |
| 577 #ifdef HAVE_LIBXML | |
| 578 if (xmlSAXUserParseMemory(&xmlnode_parser_libxml, xpd, str, real_size) < 0) { | 488 if (xmlSAXUserParseMemory(&xmlnode_parser_libxml, xpd, str, real_size) < 0) { |
| 579 while(xpd->current && xpd->current->parent) | 489 while(xpd->current && xpd->current->parent) |
| 580 xpd->current = xpd->current->parent; | 490 xpd->current = xpd->current->parent; |
| 581 if(xpd->current) | 491 if(xpd->current) |
| 582 xmlnode_free(xpd->current); | 492 xmlnode_free(xpd->current); |
| 583 xpd->current = NULL; | 493 xpd->current = NULL; |
| 584 } | 494 } |
| 585 #else | |
| 586 context = g_markup_parse_context_new(&xmlnode_parser, 0, xpd, NULL); | |
| 587 | |
| 588 if(!g_markup_parse_context_parse(context, str, real_size, NULL)) { | |
| 589 while(xpd->current && xpd->current->parent) | |
| 590 xpd->current = xpd->current->parent; | |
| 591 if(xpd->current) | |
| 592 xmlnode_free(xpd->current); | |
| 593 xpd->current = NULL; | |
| 594 } | |
| 595 g_markup_parse_context_free(context); | |
| 596 #endif | |
| 597 ret = xpd->current; | 495 ret = xpd->current; |
| 598 g_free(xpd); | 496 g_free(xpd); |
| 599 return ret; | 497 return ret; |
| 600 } | 498 } |
| 601 | 499 |
