Line data Source code
1 : /* 2 : * Copyright 2004-2024 the Pacemaker project contributors 3 : * 4 : * The version control history for this file may have further details. 5 : * 6 : * This source code is licensed under the GNU Lesser General Public License 7 : * version 2.1 or later (LGPLv2.1+) WITHOUT ANY WARRANTY. 8 : */ 9 : 10 : #include <crm_internal.h> 11 : 12 : #include <stdio.h> 13 : #include <sys/types.h> 14 : #include <unistd.h> 15 : #include <time.h> 16 : #include <string.h> 17 : #include <stdlib.h> 18 : #include <stdarg.h> 19 : #include <bzlib.h> 20 : 21 : #include <libxml/parser.h> 22 : #include <libxml/tree.h> 23 : #include <libxml/xmlIO.h> /* xmlAllocOutputBuffer */ 24 : 25 : #include <crm/crm.h> 26 : #include <crm/common/xml.h> 27 : #include <crm/common/xml_internal.h> // PCMK__XML_LOG_BASE, etc. 28 : #include "crmcommon_private.h" 29 : 30 : void 31 0 : pcmk__mark_xml_attr_dirty(xmlAttr *a) 32 : { 33 0 : xmlNode *parent = a->parent; 34 0 : xml_node_private_t *nodepriv = a->_private; 35 : 36 0 : pcmk__set_xml_flags(nodepriv, pcmk__xf_dirty|pcmk__xf_modified); 37 0 : pcmk__clear_xml_flags(nodepriv, pcmk__xf_deleted); 38 0 : pcmk__mark_xml_node_dirty(parent); 39 0 : } 40 : 41 : // This also clears attribute's flags if not marked as deleted 42 : bool 43 0 : pcmk__marked_as_deleted(xmlAttrPtr a, void *user_data) 44 : { 45 0 : xml_node_private_t *nodepriv = a->_private; 46 : 47 0 : if (pcmk_is_set(nodepriv->flags, pcmk__xf_deleted)) { 48 0 : return true; 49 : } 50 0 : nodepriv->flags = pcmk__xf_none; 51 0 : return false; 52 : } 53 : 54 : /*! 55 : * \internal 56 : * \brief Append an XML attribute to a buffer 57 : * 58 : * \param[in] attr Attribute to append 59 : * \param[in,out] buffer Where to append the content (must not be \p NULL) 60 : */ 61 : void 62 0 : pcmk__dump_xml_attr(const xmlAttr *attr, GString *buffer) 63 : { 64 0 : const char *name = NULL; 65 0 : const char *value = NULL; 66 0 : gchar *value_esc = NULL; 67 0 : xml_node_private_t *nodepriv = NULL; 68 : 69 0 : if (attr == NULL || attr->children == NULL) { 70 0 : return; 71 : } 72 : 73 0 : nodepriv = attr->_private; 74 0 : if (nodepriv && pcmk_is_set(nodepriv->flags, pcmk__xf_deleted)) { 75 0 : return; 76 : } 77 : 78 0 : name = (const char *) attr->name; 79 0 : value = (const char *) attr->children->content; 80 0 : if (value == NULL) { 81 : /* Don't print anything for unset attribute. Any null-indicator value, 82 : * including the empty string, could also be a real value that needs to 83 : * be treated differently from "unset". 84 : */ 85 0 : return; 86 : } 87 : 88 0 : if (pcmk__xml_needs_escape(value, pcmk__xml_escape_attr)) { 89 0 : value_esc = pcmk__xml_escape(value, pcmk__xml_escape_attr); 90 0 : value = value_esc; 91 : } 92 : 93 0 : pcmk__g_strcat(buffer, " ", name, "=\"", value, "\"", NULL); 94 0 : g_free(value_esc); 95 : }