| 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 { |
| 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 |