/* +----------------------------------------------------------------------+ | Xdebug | +----------------------------------------------------------------------+ | Copyright (c) 2002-2020 Derick Rethans | +----------------------------------------------------------------------+ | This source file is subject to version 1.01 of the Xdebug license, | | that is bundled with this package in the file LICENSE, and is | | available at through the world-wide-web at | | https://xdebug.org/license.php | | If you did not receive a copy of the Xdebug license and are unable | | to obtain it through the world-wide-web, please send a note to | | derick@xdebug.org so we can mail you a copy immediately. | +----------------------------------------------------------------------+ */ #include <stdlib.h> #include <stdio.h> #include "mm.h" #include "str.h" #include "var.h" #include "xml.h" #include "compat.h" static void xdebug_xml_return_attribute(xdebug_xml_attribute* attr, xdebug_str* output) { char *tmp; size_t newlen; xdebug_str_addc(output, ' '); /* attribute name */ tmp = xdebug_xmlize(attr->name, attr->name_len, &newlen); xdebug_str_addl(output, tmp, newlen, 0); efree(tmp); /* attribute value */ xdebug_str_add_literal(output, "=\""); if (attr->value) { tmp = xdebug_xmlize(attr->value->d, attr->value->l, &newlen); xdebug_str_add(output, tmp, 0); efree(tmp); } xdebug_str_addc(output, '\"'); if (attr->next) { xdebug_xml_return_attribute(attr->next, output); } } static void xdebug_xml_return_text_node(xdebug_xml_text_node* node, xdebug_str* output) { xdebug_str_add_literal(output, "<![CDATA["); if (node->encode) { /* if cdata tags are in the text, then we must base64 encode */ size_t new_len = 0; unsigned char *encoded_text; encoded_text = xdebug_base64_encode((unsigned char*) node->text, node->text_len, &new_len); xdebug_str_add(output, (char*) encoded_text, 0); xdfree(encoded_text); } else { xdebug_str_add(output, node->text, 0); } xdebug_str_add_literal(output, "]]>"); } void xdebug_xml_return_node(xdebug_xml_node* node, struct xdebug_str *output) { xdebug_str_addc(output, '<'); xdebug_str_add(output, node->tag, 0); if (node->text && node->text->encode) { xdebug_xml_add_attribute_ex(node, "encoding", "base64", 0, 0); } if (node->attribute) { xdebug_xml_return_attribute(node->attribute, output); } xdebug_str_addc(output, '>'); if (node->child) { xdebug_xml_return_node(node->child, output); } if (node->text) { xdebug_xml_return_text_node(node->text, output); } xdebug_str_add_literal(output, "</"); xdebug_str_add(output, node->tag, 0); xdebug_str_addc(output, '>'); if (node->next) { xdebug_xml_return_node(node->next, output); } } xdebug_xml_node *xdebug_xml_node_init_ex(const char *tag, int free_tag) { xdebug_xml_node *xml = xdmalloc(sizeof (xdebug_xml_node)); xml->tag = (char*) tag; xml->text = NULL; xml->child = NULL; xml->attribute = NULL; xml->next = NULL; xml->free_tag = free_tag; return xml; } void xdebug_xml_add_attribute_exl(xdebug_xml_node* xml, const char *attribute, size_t attribute_len, const char *value, size_t value_len, int free_name, int free_value) { xdebug_xml_attribute *attr = xdmalloc(sizeof (xdebug_xml_attribute)); xdebug_xml_attribute **ptr; /* Init structure */ attr->name = (char*) attribute; attr->name_len = attribute_len; attr->value = xdebug_str_create(value, value_len); attr->next = NULL; attr->free_name = free_name; if (free_value) { xdfree((char*) value); /* This is ugly, but it's to preserve BC */ } /* Find last attribute in node */ ptr = &xml->attribute; while (*ptr != NULL) { ptr = &(*ptr)->next; } *ptr = attr; } xdebug_str *xdebug_xml_get_attribute_value(xdebug_xml_node *xml, const char *attribute) { xdebug_xml_attribute **ptr = &xml->attribute; while (*ptr != NULL) { if (strcmp((*ptr)->name, attribute) == 0) { return (*ptr)->value; } ptr = &(*ptr)->next; } return NULL; } void xdebug_xml_add_child(xdebug_xml_node *xml, xdebug_xml_node *child) { xdebug_xml_node **ptr; ptr = &xml->child; while (*ptr != NULL) { ptr = &((*ptr)->next); } *ptr = child; } static void xdebug_xml_text_node_dtor(xdebug_xml_text_node* node) { if (node->free_value && node->text) { xdfree(node->text); } xdfree(node); } void xdebug_xml_add_text(xdebug_xml_node *xml, char *text) { xdebug_xml_add_text_ex(xml, text, strlen(text), 1, 0); } void xdebug_xml_add_text_encode(xdebug_xml_node *xml, char *text) { xdebug_xml_add_text_ex(xml, text, strlen(text), 1, 1); } void xdebug_xml_add_text_ex(xdebug_xml_node *xml, char *text, int length, int free_text, int encode) { xdebug_xml_text_node *node = xdmalloc(sizeof (xdebug_xml_text_node)); node->free_value = free_text; node->encode = encode; if (xml->text) { xdebug_xml_text_node_dtor(xml->text); } node->text = text; node->text_len = length; xml->text = node; if (!encode && strstr(node->text, "]]>")) { node->encode = 1; } } static void xdebug_xml_attribute_dtor(xdebug_xml_attribute *attr) { if (attr->next) { xdebug_xml_attribute_dtor(attr->next); } if (attr->free_name) { xdfree(attr->name); } xdebug_str_free(attr->value); xdfree(attr); } void xdebug_xml_node_dtor(xdebug_xml_node* xml) { if (xml->next) { xdebug_xml_node_dtor(xml->next); } if (xml->child) { xdebug_xml_node_dtor(xml->child); } if (xml->attribute) { xdebug_xml_attribute_dtor(xml->attribute); } if (xml->free_tag) { xdfree(xml->tag); } if (xml->text) { xdebug_xml_text_node_dtor(xml->text); } xdfree(xml); }