libpurple/xmlnode.c

changeset 41647
63c65c9fbb34
parent 40756
3a58ef28ee44
child 41685
ca22b00972d4
equal deleted inserted replaced
41646:df5560078186 41647:63c65c9fbb34
139 sibling->next = attr_node->next; 139 sibling->next = attr_node->next;
140 sibling = attr_node->next; 140 sibling = attr_node->next;
141 purple_xmlnode_free(attr_node); 141 purple_xmlnode_free(attr_node);
142 attr_node = sibling; 142 attr_node = sibling;
143 } 143 }
144 } 144 } else {
145 else
146 {
147 attr_node = attr_node->next; 145 attr_node = attr_node->next;
148 } 146 }
149 sibling = attr_node; 147 sibling = attr_node;
150 } 148 }
151 } 149 }
156 PurpleXmlNode *attr_node, *sibling = NULL; 154 PurpleXmlNode *attr_node, *sibling = NULL;
157 155
158 g_return_if_fail(node != NULL); 156 g_return_if_fail(node != NULL);
159 g_return_if_fail(attr != NULL); 157 g_return_if_fail(attr != NULL);
160 158
161 for(attr_node = node->child; attr_node; attr_node = attr_node->next) 159 for(attr_node = node->child; attr_node; attr_node = attr_node->next) {
162 {
163 if(attr_node->type == PURPLE_XMLNODE_TYPE_ATTRIB && 160 if(attr_node->type == PURPLE_XMLNODE_TYPE_ATTRIB &&
164 purple_strequal(attr, attr_node->name) && 161 purple_strequal(attr, attr_node->name) &&
165 purple_strequal(xmlns, attr_node->xmlns)) 162 purple_strequal(xmlns, attr_node->xmlns))
166 { 163 {
167 if(sibling == NULL) { 164 if(sibling == NULL) {
280 */ 277 */
281 if (!current_node->prefix && current_node->xmlns) { 278 if (!current_node->prefix && current_node->xmlns) {
282 return current_node->xmlns; 279 return current_node->xmlns;
283 } else if (current_node->namespace_map) { 280 } else if (current_node->namespace_map) {
284 ns = g_hash_table_lookup(current_node->namespace_map, ""); 281 ns = g_hash_table_lookup(current_node->namespace_map, "");
285 if (ns && *ns) 282 if (ns && *ns) {
286 return ns; 283 return ns;
284 }
287 } 285 }
288 286
289 current_node = current_node->parent; 287 current_node = current_node->parent;
290 } 288 }
291 289
337 const char *prefix; 335 const char *prefix;
338 336
339 g_return_if_fail(node != NULL); 337 g_return_if_fail(node != NULL);
340 338
341 for (child = node->child; child; child = child->next) { 339 for (child = node->child; child; child = child->next) {
342 if (child->type == PURPLE_XMLNODE_TYPE_TAG) 340 if (child->type == PURPLE_XMLNODE_TYPE_TAG) {
343 purple_xmlnode_strip_prefixes(child); 341 purple_xmlnode_strip_prefixes(child);
342 }
344 } 343 }
345 344
346 prefix = purple_xmlnode_get_prefix(node); 345 prefix = purple_xmlnode_get_prefix(node);
347 if (prefix) { 346 if (prefix) {
348 const char *ns = purple_xmlnode_get_prefix_namespace(node, prefix); 347 const char *ns = purple_xmlnode_get_prefix_namespace(node, prefix);
368 367
369 /* if we're part of a tree, remove ourselves from the tree first */ 368 /* if we're part of a tree, remove ourselves from the tree first */
370 if(NULL != node->parent) { 369 if(NULL != node->parent) {
371 if(node->parent->child == node) { 370 if(node->parent->child == node) {
372 node->parent->child = node->next; 371 node->parent->child = node->next;
373 if (node->parent->lastchild == node) 372 if (node->parent->lastchild == node) {
374 node->parent->lastchild = node->next; 373 node->parent->lastchild = node->next;
374 }
375 } else { 375 } else {
376 PurpleXmlNode *prev = node->parent->child; 376 PurpleXmlNode *prev = node->parent->child;
377 while(prev && prev->next != node) { 377 while(prev && prev->next != node) {
378 prev = prev->next; 378 prev = prev->next;
379 } 379 }
380 if(prev) { 380 if(prev) {
381 prev->next = node->next; 381 prev->next = node->next;
382 if (node->parent->lastchild == node) 382 if (node->parent->lastchild == node) {
383 node->parent->lastchild = prev; 383 node->parent->lastchild = prev;
384 }
384 } 385 }
385 } 386 }
386 } 387 }
387 388
388 /* now free our children */ 389 /* now free our children */
397 g_free(node->name); 398 g_free(node->name);
398 g_free(node->data); 399 g_free(node->data);
399 g_free(node->xmlns); 400 g_free(node->xmlns);
400 g_free(node->prefix); 401 g_free(node->prefix);
401 402
402 if(node->namespace_map) 403 g_clear_pointer(&node->namespace_map, g_hash_table_destroy);
403 g_hash_table_destroy(node->namespace_map);
404 404
405 g_free(node); 405 g_free(node);
406 } 406 }
407 407
408 PurpleXmlNode* 408 PurpleXmlNode*
426 child_name = names[1]; 426 child_name = names[1];
427 427
428 for(x = parent->child; x; x = x->next) { 428 for(x = parent->child; x; x = x->next) {
429 /* XXX: Is it correct to ignore the namespace for the match if none was specified? */ 429 /* XXX: Is it correct to ignore the namespace for the match if none was specified? */
430 const char *xmlns = NULL; 430 const char *xmlns = NULL;
431 if(ns) 431 if(ns) {
432 xmlns = purple_xmlnode_get_namespace(x); 432 xmlns = purple_xmlnode_get_namespace(x);
433 }
433 434
434 if(x->type == PURPLE_XMLNODE_TYPE_TAG && purple_strequal(parent_name, x->name) 435 if(x->type == PURPLE_XMLNODE_TYPE_TAG && purple_strequal(parent_name, x->name)
435 && purple_strequal(ns, xmlns)) { 436 && purple_strequal(ns, xmlns)) {
436 ret = x; 437 ret = x;
437 break; 438 break;
438 } 439 }
439 } 440 }
440 441
441 if(child_name && ret) 442 if(child_name && ret) {
442 ret = purple_xmlnode_get_child(ret, child_name); 443 ret = purple_xmlnode_get_child(ret, child_name);
444 }
443 445
444 g_strfreev(names); 446 g_strfreev(names);
445 return ret; 447 return ret;
446 } 448 }
447 449
453 455
454 g_return_val_if_fail(node != NULL, NULL); 456 g_return_val_if_fail(node != NULL, NULL);
455 457
456 for(c = node->child; c; c = c->next) { 458 for(c = node->child; c; c = c->next) {
457 if(c->type == PURPLE_XMLNODE_TYPE_DATA) { 459 if(c->type == PURPLE_XMLNODE_TYPE_DATA) {
458 if(!str) 460 if(!str) {
459 str = g_string_new_len(c->data, c->data_sz); 461 str = g_string_new_len(c->data, c->data_sz);
460 else 462 } else {
461 str = g_string_append_len(str, c->data, c->data_sz); 463 str = g_string_append_len(str, c->data, c->data_sz);
462 } 464 }
463 } 465 }
464 466 }
465 if (str == NULL) 467
468 if (str == NULL) {
466 return NULL; 469 return NULL;
470 }
467 471
468 return g_string_free(str, FALSE); 472 return g_string_free(str, FALSE);
469 } 473 }
470 474
471 char * 475 char *
523 (GHFunc)purple_xmlnode_to_str_foreach_append_ns, text); 527 (GHFunc)purple_xmlnode_to_str_foreach_append_ns, text);
524 } else { 528 } else {
525 /* Figure out if this node has a different default namespace from parent */ 529 /* Figure out if this node has a different default namespace from parent */
526 const char *xmlns = NULL; 530 const char *xmlns = NULL;
527 const char *parent_xmlns = NULL; 531 const char *parent_xmlns = NULL;
528 if (!prefix) 532 if (!prefix) {
529 xmlns = node->xmlns; 533 xmlns = node->xmlns;
530 534 }
531 if (!xmlns) 535
536 if (!xmlns) {
532 xmlns = purple_xmlnode_get_default_namespace(node); 537 xmlns = purple_xmlnode_get_default_namespace(node);
533 if (node->parent) 538 }
539 if (node->parent) {
534 parent_xmlns = purple_xmlnode_get_default_namespace(node->parent); 540 parent_xmlns = purple_xmlnode_get_default_namespace(node->parent);
535 if (!purple_strequal(xmlns, parent_xmlns)) 541 }
536 { 542 if (!purple_strequal(xmlns, parent_xmlns)) {
537 char *escaped_xmlns = g_markup_escape_text(xmlns, -1); 543 char *escaped_xmlns = g_markup_escape_text(xmlns, -1);
538 g_string_append_printf(text, " xmlns='%s'", escaped_xmlns); 544 g_string_append_printf(text, " xmlns='%s'", escaped_xmlns);
539 g_free(escaped_xmlns); 545 g_free(escaped_xmlns);
540 } 546 }
541 } 547 }
542 for(c = node->child; c; c = c->next) 548 for(c = node->child; c; c = c->next) {
543 {
544 if(c->type == PURPLE_XMLNODE_TYPE_ATTRIB) { 549 if(c->type == PURPLE_XMLNODE_TYPE_ATTRIB) {
545 const char *aprefix = purple_xmlnode_get_prefix(c); 550 const char *aprefix = purple_xmlnode_get_prefix(c);
546 esc = g_markup_escape_text(c->name, -1); 551 esc = g_markup_escape_text(c->name, -1);
547 esc2 = g_markup_escape_text(c->data, -1); 552 esc2 = g_markup_escape_text(c->data, -1);
548 if (aprefix) { 553 if (aprefix) {
551 g_string_append_printf(text, " %s='%s'", esc, esc2); 556 g_string_append_printf(text, " %s='%s'", esc, esc2);
552 } 557 }
553 g_free(esc); 558 g_free(esc);
554 g_free(esc2); 559 g_free(esc2);
555 } else if(c->type == PURPLE_XMLNODE_TYPE_TAG || c->type == PURPLE_XMLNODE_TYPE_DATA) { 560 } else if(c->type == PURPLE_XMLNODE_TYPE_TAG || c->type == PURPLE_XMLNODE_TYPE_DATA) {
556 if(c->type == PURPLE_XMLNODE_TYPE_DATA) 561 if(c->type == PURPLE_XMLNODE_TYPE_DATA) {
557 pretty = FALSE; 562 pretty = FALSE;
563 }
558 need_end = TRUE; 564 need_end = TRUE;
559 } 565 }
560 } 566 }
561 567
562 if(need_end) { 568 if(need_end) {
563 g_string_append_printf(text, ">%s", pretty ? NEWLINE_S : ""); 569 g_string_append_printf(text, ">%s", pretty ? NEWLINE_S : "");
564 570
565 for(c = node->child; c; c = c->next) 571 for(c = node->child; c; c = c->next) {
566 {
567 if(c->type == PURPLE_XMLNODE_TYPE_TAG) { 572 if(c->type == PURPLE_XMLNODE_TYPE_TAG) {
568 int esc_len; 573 int esc_len;
569 esc = purple_xmlnode_to_str_helper(c, &esc_len, pretty, depth+1); 574 esc = purple_xmlnode_to_str_helper(c, &esc_len, pretty, depth+1);
570 text = g_string_append_len(text, esc, esc_len); 575 text = g_string_append_len(text, esc, esc_len);
571 g_free(esc); 576 g_free(esc);
574 text = g_string_append(text, esc); 579 text = g_string_append(text, esc);
575 g_free(esc); 580 g_free(esc);
576 } 581 }
577 } 582 }
578 583
579 if(tab && pretty) 584 if(tab && pretty) {
580 text = g_string_append(text, tab); 585 text = g_string_append(text, tab);
586 }
581 if (prefix) { 587 if (prefix) {
582 g_string_append_printf(text, "</%s:%s>%s", prefix, node_name, formatting ? NEWLINE_S : ""); 588 g_string_append_printf(text, "</%s:%s>%s", prefix, node_name, formatting ? NEWLINE_S : "");
583 } else { 589 } else {
584 g_string_append_printf(text, "</%s>%s", node_name, formatting ? NEWLINE_S : ""); 590 g_string_append_printf(text, "</%s>%s", node_name, formatting ? NEWLINE_S : "");
585 } 591 }
589 595
590 g_free(node_name); 596 g_free(node_name);
591 597
592 g_free(tab); 598 g_free(tab);
593 599
594 if(len) 600 if(len) {
595 *len = text->len; 601 *len = text->len;
602 }
596 603
597 return g_string_free(text, FALSE); 604 return g_string_free(text, FALSE);
598 } 605 }
599 606
600 char * 607 char *
613 xml = purple_xmlnode_to_str_helper(node, len, TRUE, 0); 620 xml = purple_xmlnode_to_str_helper(node, len, TRUE, 0);
614 xml_with_declaration = 621 xml_with_declaration =
615 g_strdup_printf("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S "%s", xml); 622 g_strdup_printf("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S "%s", xml);
616 g_free(xml); 623 g_free(xml);
617 624
618 if (len) 625 if (len) {
619 *len += sizeof("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S) - 1; 626 *len += sizeof("<?xml version='1.0' encoding='UTF-8' ?>" NEWLINE_S NEWLINE_S) - 1;
627 }
620 628
621 return xml_with_declaration; 629 return xml_with_declaration;
622 } 630 }
623 631
624 struct _xmlnode_parser_data { 632 struct _xmlnode_parser_data {
637 int i, j; 645 int i, j;
638 646
639 if(!element_name || xpd->error) { 647 if(!element_name || xpd->error) {
640 return; 648 return;
641 } else { 649 } else {
642 if(xpd->current) 650 if(xpd->current) {
643 node = purple_xmlnode_new_child(xpd->current, (const char*) element_name); 651 node = purple_xmlnode_new_child(xpd->current, (const char*) element_name);
644 else 652 } else {
645 node = purple_xmlnode_new((const char *) element_name); 653 node = purple_xmlnode_new((const char *) element_name);
654 }
646 655
647 purple_xmlnode_set_namespace(node, (const char *) xmlns); 656 purple_xmlnode_set_namespace(node, (const char *) xmlns);
648 purple_xmlnode_set_prefix(node, (const char *)prefix); 657 purple_xmlnode_set_prefix(node, (const char *)prefix);
649 658
650 if (nb_namespaces != 0) { 659 if (nb_namespaces != 0) {
680 purple_xmlnode_parser_element_end_libxml(void *user_data, const xmlChar *element_name, 689 purple_xmlnode_parser_element_end_libxml(void *user_data, const xmlChar *element_name,
681 const xmlChar *prefix, const xmlChar *xmlns) 690 const xmlChar *prefix, const xmlChar *xmlns)
682 { 691 {
683 struct _xmlnode_parser_data *xpd = user_data; 692 struct _xmlnode_parser_data *xpd = user_data;
684 693
685 if(!element_name || !xpd->current || xpd->error) 694 if(!element_name || !xpd->current || xpd->error) {
686 return; 695 return;
696 }
687 697
688 if(xpd->current->parent) { 698 if(xpd->current->parent) {
689 if(!xmlStrcmp((xmlChar*) xpd->current->name, element_name)) 699 if(!xmlStrcmp((xmlChar*) xpd->current->name, element_name)) {
690 xpd->current = xpd->current->parent; 700 xpd->current = xpd->current->parent;
701 }
691 } 702 }
692 } 703 }
693 704
694 static void 705 static void
695 purple_xmlnode_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len) 706 purple_xmlnode_parser_element_text_libxml(void *user_data, const xmlChar *text, int text_len)
696 { 707 {
697 struct _xmlnode_parser_data *xpd = user_data; 708 struct _xmlnode_parser_data *xpd = user_data;
698 709
699 if(!xpd->current || xpd->error) 710 if(!xpd->current || xpd->error) {
700 return; 711 return;
701 712 }
702 if(!text || !text_len) 713
714 if(!text || !text_len) {
703 return; 715 return;
716 }
704 717
705 purple_xmlnode_insert_data(xpd->current, (const char*) text, text_len); 718 purple_xmlnode_insert_data(xpd->current, (const char*) text, text_len);
706 } 719 }
707 720
708 static void 721 static void
730 error->level == XML_ERR_FATAL)) { 743 error->level == XML_ERR_FATAL)) {
731 xpd->error = TRUE; 744 xpd->error = TRUE;
732 purple_debug_error("xmlnode", "XML parser error for PurpleXmlNode %p: " 745 purple_debug_error("xmlnode", "XML parser error for PurpleXmlNode %p: "
733 "Domain %i, code %i, level %i: %s", 746 "Domain %i, code %i, level %i: %s",
734 user_data, error->domain, error->code, error->level, 747 user_data, error->domain, error->code, error->level,
735 error->message ? error->message : "(null)\n"); 748 error->message ? error->message : "(null)");
736 } else if (error) 749 } else if (error) {
737 purple_debug_warning("xmlnode", "XML parser error for PurpleXmlNode %p: " 750 purple_debug_warning("xmlnode", "XML parser error for PurpleXmlNode %p: "
738 "Domain %i, code %i, level %i: %s", 751 "Domain %i, code %i, level %i: %s",
739 user_data, error->domain, error->code, error->level, 752 user_data, error->domain, error->code, error->level,
740 error->message ? error->message : "(null)\n"); 753 error->message ? error->message : "(null)");
741 else 754 } else {
742 purple_debug_warning("xmlnode", "XML parser error for PurpleXmlNode %p\n", 755 purple_debug_warning("xmlnode", "XML parser error for PurpleXmlNode %p",
743 user_data); 756 user_data);
757 }
744 } 758 }
745 759
746 static xmlSAXHandler purple_xmlnode_parser_libxml = { 760 static xmlSAXHandler purple_xmlnode_parser_libxml = {
747 NULL, /* internalSubset */ 761 NULL, /* internalSubset */
748 NULL, /* isStandalone */ 762 NULL, /* isStandalone */
789 803
790 real_size = size < 0 ? strlen(str) : (gsize)size; 804 real_size = size < 0 ? strlen(str) : (gsize)size;
791 xpd = g_new0(struct _xmlnode_parser_data, 1); 805 xpd = g_new0(struct _xmlnode_parser_data, 1);
792 806
793 if (xmlSAXUserParseMemory(&purple_xmlnode_parser_libxml, xpd, str, real_size) < 0) { 807 if (xmlSAXUserParseMemory(&purple_xmlnode_parser_libxml, xpd, str, real_size) < 0) {
794 while(xpd->current && xpd->current->parent) 808 while(xpd->current && xpd->current->parent) {
795 xpd->current = xpd->current->parent; 809 xpd->current = xpd->current->parent;
796 if(xpd->current) 810 }
797 purple_xmlnode_free(xpd->current); 811 g_clear_pointer(&xpd->current, purple_xmlnode_free);
798 xpd->current = NULL;
799 } 812 }
800 ret = xpd->current; 813 ret = xpd->current;
801 if (xpd->error) { 814 if (xpd->error) {
802 ret = NULL; 815 ret = NULL;
803 if (xpd->current) 816 g_clear_pointer(&xpd->current, purple_xmlnode_free);
804 purple_xmlnode_free(xpd->current);
805 } 817 }
806 818
807 g_free(xpd); 819 g_free(xpd);
808 return ret; 820 return ret;
809 } 821 }
817 gsize length; 829 gsize length;
818 PurpleXmlNode *node = NULL; 830 PurpleXmlNode *node = NULL;
819 831
820 g_return_val_if_fail(dir != NULL, NULL); 832 g_return_val_if_fail(dir != NULL, NULL);
821 833
822 purple_debug_misc(process, "Reading file %s from directory %s\n", 834 purple_debug_misc(process, "Reading file %s from directory %s",
823 filename, dir); 835 filename, dir);
824 836
825 filename_full = g_build_filename(dir, filename, NULL); 837 filename_full = g_build_filename(dir, filename, NULL);
826 838
827 if (!g_file_test(filename_full, G_FILE_TEST_EXISTS)) 839 if (!g_file_test(filename_full, G_FILE_TEST_EXISTS)) {
828 {
829 purple_debug_info(process, "File %s does not exist (this is not " 840 purple_debug_info(process, "File %s does not exist (this is not "
830 "necessarily an error)\n", filename_full); 841 "necessarily an error)", filename_full);
831 g_free(filename_full); 842 g_free(filename_full);
832 return NULL; 843 return NULL;
833 } 844 }
834 845
835 if (!g_file_get_contents(filename_full, &contents, &length, &error)) 846 if (!g_file_get_contents(filename_full, &contents, &length, &error)) {
836 { 847 purple_debug_error(process, "Error reading file %s: %s",
837 purple_debug_error(process, "Error reading file %s: %s\n",
838 filename_full, error->message); 848 filename_full, error->message);
839 g_error_free(error); 849 g_error_free(error);
840 } 850 }
841 851
842 if ((contents != NULL) && (length > 0)) 852 if ((contents != NULL) && (length > 0)) {
843 {
844 node = purple_xmlnode_from_str(contents, length); 853 node = purple_xmlnode_from_str(contents, length);
845 854
846 /* If we were unable to parse the file then save its contents to a backup file */ 855 /* If we were unable to parse the file then save its contents to a backup file */
847 if (node == NULL) 856 if (node == NULL) {
848 {
849 gchar *filename_temp, *filename_temp_full; 857 gchar *filename_temp, *filename_temp_full;
850 858
851 filename_temp = g_strdup_printf("%s~", filename); 859 filename_temp = g_strdup_printf("%s~", filename);
852 filename_temp_full = g_build_filename(dir, filename_temp, NULL); 860 filename_temp_full = g_build_filename(dir, filename_temp, NULL);
853 861
854 purple_debug_error("util", "Error parsing file %s. Renaming old " 862 purple_debug_error("util", "Error parsing file %s. Renaming old "
855 "file to %s\n", filename_full, filename_temp); 863 "file to %s", filename_full, filename_temp);
856 g_file_set_contents(filename_temp_full, contents, length, NULL); 864 g_file_set_contents(filename_temp_full, contents, length, NULL);
857 865
858 g_free(filename_temp_full); 866 g_free(filename_temp_full);
859 g_free(filename_temp); 867 g_free(filename_temp);
860 } 868 }
861 869
862 g_free(contents); 870 g_free(contents);
863 } 871 }
864 872
865 /* If we could not parse the file then show the user an error message */ 873 /* If we could not parse the file then show the user an error message */
866 if (node == NULL) 874 if (node == NULL) {
867 {
868 gchar *title, *msg; 875 gchar *title, *msg;
869 title = g_strdup_printf(_("Error Reading %s"), filename); 876 title = g_strdup_printf(_("Error Reading %s"), filename);
870 msg = g_strdup_printf(_("An error was encountered reading your " 877 msg = g_strdup_printf(_("An error was encountered reading your "
871 "%s. The file has not been loaded, and the old file " 878 "%s. The file has not been loaded, and the old file "
872 "has been renamed to %s~."), description, filename_full); 879 "has been renamed to %s~."), description, filename_full);
938 g_return_val_if_fail(node->type == PURPLE_XMLNODE_TYPE_TAG, NULL); 945 g_return_val_if_fail(node->type == PURPLE_XMLNODE_TYPE_TAG, NULL);
939 946
940 for(sibling = node->next; sibling; sibling = sibling->next) { 947 for(sibling = node->next; sibling; sibling = sibling->next) {
941 /* XXX: Is it correct to ignore the namespace for the match if none was specified? */ 948 /* XXX: Is it correct to ignore the namespace for the match if none was specified? */
942 const char *xmlns = NULL; 949 const char *xmlns = NULL;
943 if(ns) 950 if(ns) {
944 xmlns = purple_xmlnode_get_namespace(sibling); 951 xmlns = purple_xmlnode_get_namespace(sibling);
952 }
945 953
946 if(sibling->type == PURPLE_XMLNODE_TYPE_TAG && purple_strequal(node->name, sibling->name) && 954 if(sibling->type == PURPLE_XMLNODE_TYPE_TAG && purple_strequal(node->name, sibling->name) &&
947 purple_strequal(ns, xmlns)) 955 purple_strequal(ns, xmlns)) {
948 return sibling; 956 return sibling;
957 }
949 } 958 }
950 959
951 return NULL; 960 return NULL;
952 } 961 }
953 962

mercurial