root/include/crm/common/xml.h

/* [previous][next][first][last][top][bottom][index][help] */

INCLUDED FROM


DEFINITIONS

This source file includes following definitions.
  1. crm_xml_add_boolean
  2. crm_element_name
  3. crm_copy_xml_element
  4. __xml_first_child
  5. __xml_next
  6. __xml_first_child_element
  7. __xml_next_element
  8. numXpathResults

   1 /*
   2  * Copyright (C) 2004 Andrew Beekhof <andrew@beekhof.net>
   3  *
   4  * This program is free software; you can redistribute it and/or
   5  * modify it under the terms of the GNU Lesser General Public
   6  * License as published by the Free Software Foundation; either
   7  * version 2 of the License, or (at your option) any later version.
   8  *
   9  * This software is distributed in the hope that it will be useful,
  10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  12  * General Public License for more details.
  13  *
  14  * You should have received a copy of the GNU Lesser General Public
  15  * License along with this library; if not, write to the Free Software
  16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
  17  */
  18 #ifndef CRM_COMMON_XML__H
  19 #  define CRM_COMMON_XML__H
  20 
  21 /**
  22  * \file
  23  * \brief Wrappers for and extensions to libxml2
  24  * \ingroup core
  25  */
  26 
  27 #  include <stdio.h>
  28 #  include <sys/types.h>
  29 #  include <unistd.h>
  30 
  31 #  include <stdlib.h>
  32 #  include <errno.h>
  33 #  include <fcntl.h>
  34 
  35 #  include <crm/crm.h>
  36 
  37 #  include <libxml/tree.h>
  38 #  include <libxml/xpath.h>
  39 
  40 /* Define compression parameters for IPC messages
  41  *
  42  * Compression costs a LOT, so we don't want to do it unless we're hitting
  43  * message limits. Currently, we use 128KB as the threshold, because higher
  44  * values don't play well with the heartbeat stack. With an earlier limit of
  45  * 10KB, compressing 184 of 1071 messages accounted for 23% of the total CPU
  46  * used by the cib.
  47  */
  48 #  define CRM_BZ2_BLOCKS                4
  49 #  define CRM_BZ2_WORK          20
  50 #  define CRM_BZ2_THRESHOLD     128 * 1024
  51 
  52 #  define XML_PARANOIA_CHECKS 0
  53 
  54 gboolean add_message_xml(xmlNode * msg, const char *field, xmlNode * xml);
  55 xmlNode *get_message_xml(xmlNode * msg, const char *field);
  56 GHashTable *xml2list(xmlNode * parent);
  57 
  58 xmlNode *crm_create_nvpair_xml(xmlNode *parent, const char *id,
  59                                const char *name, const char *value);
  60 
  61 void hash2nvpair(gpointer key, gpointer value, gpointer user_data);
  62 void hash2field(gpointer key, gpointer value, gpointer user_data);
  63 void hash2metafield(gpointer key, gpointer value, gpointer user_data);
  64 void hash2smartfield(gpointer key, gpointer value, gpointer user_data);
  65 
  66 xmlDoc *getDocPtr(xmlNode * node);
  67 
  68 /*
  69  * Replacement function for xmlCopyPropList which at the very least,
  70  * doesn't work the way *I* would expect it to.
  71  *
  72  * Copy all the attributes/properties from src into target.
  73  *
  74  * Not recursive, does not return anything.
  75  *
  76  */
  77 void copy_in_properties(xmlNode * target, xmlNode * src);
  78 void expand_plus_plus(xmlNode * target, const char *name, const char *value);
  79 void fix_plus_plus_recursive(xmlNode * target);
  80 
  81 /*
  82  * Create a node named "name" as a child of "parent"
  83  * If parent is NULL, creates an unconnected node.
  84  *
  85  * Returns the created node
  86  *
  87  */
  88 xmlNode *create_xml_node(xmlNode * parent, const char *name);
  89 
  90 /*
  91  * Make a copy of name and value and use the copied memory to create
  92  * an attribute for node.
  93  *
  94  * If node, name or value are NULL, nothing is done.
  95  *
  96  * If name or value are an empty string, nothing is done.
  97  *
  98  * Returns FALSE on failure and TRUE on success.
  99  *
 100  */
 101 const char *crm_xml_add(xmlNode * node, const char *name, const char *value);
 102 
 103 const char *crm_xml_replace(xmlNode * node, const char *name, const char *value);
 104 
 105 const char *crm_xml_add_int(xmlNode * node, const char *name, int value);
 106 
 107 /*!
 108  * \brief Add a boolean attribute to an XML object
 109  *
 110  * Add an attribute with the value XML_BOOLEAN_TRUE or XML_BOOLEAN_FALSE
 111  * as appropriate to an XML object.
 112  *
 113  * \param[in,out] node   XML object to add attribute to
 114  * \param[in]     name   Name of attribute to add
 115  * \param[in]     value  Boolean whose value will be tested
 116  *
 117  * \return Pointer to newly created XML attribute's content, or NULL on error
 118  */
 119 static inline const char *
 120 crm_xml_add_boolean(xmlNode *node, const char *name, gboolean value)
     /* [previous][next][first][last][top][bottom][index][help] */
 121 {
 122     return crm_xml_add(node, name, (value? "true" : "false"));
 123 }
 124 
 125 /*
 126  * Unlink the node and set its doc pointer to NULL so free_xml()
 127  * will act appropriately
 128  */
 129 void unlink_xml_node(xmlNode * node);
 130 
 131 /*
 132  *
 133  */
 134 void purge_diff_markers(xmlNode * a_node);
 135 
 136 /*
 137  * Returns a deep copy of src_node
 138  *
 139  */
 140 xmlNode *copy_xml(xmlNode * src_node);
 141 
 142 /*
 143  * Add a copy of xml_node to new_parent
 144  */
 145 xmlNode *add_node_copy(xmlNode * new_parent, xmlNode * xml_node);
 146 
 147 int add_node_nocopy(xmlNode * parent, const char *name, xmlNode * child);
 148 
 149 /*
 150  * XML I/O Functions
 151  *
 152  * Whitespace between tags is discarded.
 153  */
 154 xmlNode *filename2xml(const char *filename);
 155 
 156 xmlNode *stdin2xml(void);
 157 
 158 xmlNode *string2xml(const char *input);
 159 
 160 int write_xml_fd(xmlNode * xml_node, const char *filename, int fd, gboolean compress);
 161 int write_xml_file(xmlNode * xml_node, const char *filename, gboolean compress);
 162 
 163 char *dump_xml_formatted(xmlNode * msg);
 164 /* Also dump the text node with xml_log_option_text enabled */ 
 165 char *dump_xml_formatted_with_text(xmlNode * msg);
 166 
 167 char *dump_xml_unformatted(xmlNode * msg);
 168 
 169 /*
 170  * Diff related Functions
 171  */
 172 xmlNode *diff_xml_object(xmlNode * left, xmlNode * right, gboolean suppress);
 173 
 174 xmlNode *subtract_xml_object(xmlNode * parent, xmlNode * left, xmlNode * right,
 175                              gboolean full, gboolean * changed, const char *marker);
 176 
 177 gboolean can_prune_leaf(xmlNode * xml_node);
 178 
 179 void print_xml_diff(FILE * where, xmlNode * diff);
 180 
 181 gboolean apply_xml_diff(xmlNode * old, xmlNode * diff, xmlNode ** new);
 182 
 183 /*
 184  * Searching & Modifying
 185  */
 186 xmlNode *find_xml_node(xmlNode * cib, const char *node_path, gboolean must_find);
 187 
 188 xmlNode *find_entity(xmlNode * parent, const char *node_name, const char *id);
 189 
 190 void xml_remove_prop(xmlNode * obj, const char *name);
 191 
 192 gboolean replace_xml_child(xmlNode * parent, xmlNode * child, xmlNode * update,
 193                            gboolean delete_only);
 194 
 195 gboolean update_xml_child(xmlNode * child, xmlNode * to_update);
 196 
 197 int find_xml_children(xmlNode ** children, xmlNode * root,
 198                       const char *tag, const char *field, const char *value,
 199                       gboolean search_matches);
 200 
 201 int crm_element_value_int(xmlNode * data, const char *name, int *dest);
 202 char *crm_element_value_copy(xmlNode * data, const char *name);
 203 int crm_element_value_const_int(const xmlNode * data, const char *name, int *dest);
 204 const char *crm_element_value_const(const xmlNode * data, const char *name);
 205 xmlNode *get_xpath_object(const char *xpath, xmlNode * xml_obj, int error_level);
 206 xmlNode *get_xpath_object_relative(const char *xpath, xmlNode * xml_obj, int error_level);
 207 
 208 static inline const char *
 209 crm_element_name(xmlNode *xml)
     /* [previous][next][first][last][top][bottom][index][help] */
 210 {
 211     return xml? (const char *)(xml->name) : NULL;
 212 }
 213 
 214 const char *crm_element_value(xmlNode * data, const char *name);
 215 
 216 /*!
 217  * \brief Copy an element from one XML object to another
 218  *
 219  * \param[in]     obj1     Source XML
 220  * \param[in,out] obj2     Destination XML
 221  * \param[in]     element  Name of element to copy
 222  *
 223  * \return Pointer to copied value (from source)
 224  */
 225 static inline const char *
 226 crm_copy_xml_element(xmlNode *obj1, xmlNode *obj2, const char *element)
     /* [previous][next][first][last][top][bottom][index][help] */
 227 {
 228     const char *value = crm_element_value(obj1, element);
 229 
 230     crm_xml_add(obj2, element, value);
 231     return value;
 232 }
 233 
 234 void xml_validate(const xmlNode * root);
 235 
 236 gboolean xml_has_children(const xmlNode * root);
 237 
 238 char *calculate_on_disk_digest(xmlNode * local_cib);
 239 char *calculate_operation_digest(xmlNode * local_cib, const char *version);
 240 char *calculate_xml_versioned_digest(xmlNode * input, gboolean sort, gboolean do_filter,
 241                                      const char *version);
 242 
 243 /* schema-related functions (from schemas.c) */
 244 gboolean validate_xml(xmlNode * xml_blob, const char *validation, gboolean to_logs);
 245 gboolean validate_xml_verbose(xmlNode * xml_blob);
 246 
 247 /*!
 248  * \brief Update CIB XML to most recent schema version
 249  *
 250  * "Update" means either actively employ XSLT-based transformation(s)
 251  * (if intermediate product to transform valid per its declared schema version,
 252  * transformation available, proceeded successfully with a result valid per
 253  * expectated newer schema version), or just try to bump the marked validating
 254  * schema until all gradually rising schema versions attested or the first
 255  * such attempt subsequently fails to validate.   Which of the two styles will
 256  * be used depends on \p transform parameter (positive/negative, respectively).
 257  *
 258  * \param[in,out] xml_blob   XML tree representing CIB, may be swapped with
 259  *                           an "updated" one
 260  * \param[out]    best       The highest configuration version (per its index
 261  *                           in the global schemas table) it was possible to
 262  *                           reach during the update steps while ensuring
 263  *                           the validity of the result; if no validation
 264  *                           success was observed against possibly multiple
 265  *                           schemas, the value is less or equal the result
 266  *                           of <tt>get_schema_version</tt> applied on the
 267  *                           input \p xml_blob value (unless that function
 268  *                           maps it to -1, then 0 would be used instead)
 269  * \param[in]     max        When \p transform is positive, this allows to
 270  *                           set upper boundary schema (per its index in the
 271  *                           global schemas table) beyond which its forbidden
 272  *                           to update by the means of XSLT transformation
 273  * \param[in]     transform  Whether to employ XSLT-based transformation so
 274  *                           as allow overcoming possible incompatibilities
 275  *                           between major schema versions (see above)
 276  * \param[in]     to_logs    If true, output notable progress info to
 277  *                           internal log streams; if false, to stderr
 278  *
 279  * \return <tt>pcmk_ok</tt> if no non-recoverable error encountered (up to
 280  *         caller to evaluate if the update satisfies the requirements
 281  *         per returned \p best value), negative value carrying the reason
 282  *         otherwise
 283  */
 284 int update_validation(xmlNode **xml_blob, int *best, int max,
 285                       gboolean transform, gboolean to_logs);
 286 
 287 int get_schema_version(const char *name);
 288 const char *get_schema_name(int version);
 289 const char *xml_latest_schema(void);
 290 gboolean cli_config_update(xmlNode ** xml, int *best_version, gboolean to_logs);
 291 
 292 void crm_xml_init(void);
 293 void crm_xml_cleanup(void);
 294 
 295 static inline xmlNode *
 296 __xml_first_child(xmlNode * parent)
     /* [previous][next][first][last][top][bottom][index][help] */
 297 {
 298     xmlNode *child = NULL;
 299 
 300     if (parent) {
 301         child = parent->children;
 302         while (child && child->type == XML_TEXT_NODE) {
 303             child = child->next;
 304         }
 305     }
 306     return child;
 307 }
 308 
 309 static inline xmlNode *
 310 __xml_next(xmlNode * child)
     /* [previous][next][first][last][top][bottom][index][help] */
 311 {
 312     if (child) {
 313         child = child->next;
 314         while (child && child->type == XML_TEXT_NODE) {
 315             child = child->next;
 316         }
 317     }
 318     return child;
 319 }
 320 
 321 static inline xmlNode *
 322 __xml_first_child_element(xmlNode * parent)
     /* [previous][next][first][last][top][bottom][index][help] */
 323 {
 324     xmlNode *child = NULL;
 325 
 326     if (parent) {
 327         child = parent->children;
 328     }
 329 
 330     while (child) {
 331         if(child->type == XML_ELEMENT_NODE) {
 332             return child;
 333         }
 334         child = child->next;
 335     }
 336     return NULL;
 337 }
 338 
 339 static inline xmlNode *
 340 __xml_next_element(xmlNode * child)
     /* [previous][next][first][last][top][bottom][index][help] */
 341 {
 342     while (child) {
 343         child = child->next;
 344         if(child && child->type == XML_ELEMENT_NODE) {
 345             return child;
 346         }
 347     }
 348     return NULL;
 349 }
 350 
 351 void free_xml(xmlNode * child);
 352 
 353 xmlNode *first_named_child(xmlNode * parent, const char *name);
 354 xmlNode *crm_next_same_xml(xmlNode *sibling);
 355 
 356 xmlNode *sorted_xml(xmlNode * input, xmlNode * parent, gboolean recursive);
 357 xmlXPathObjectPtr xpath_search(xmlNode * xml_top, const char *path);
 358 void crm_foreach_xpath_result(xmlNode *xml, const char *xpath,
 359                               void (*helper)(xmlNode*, void*), void *user_data);
 360 xmlNode *expand_idref(xmlNode * input, xmlNode * top);
 361 
 362 void freeXpathObject(xmlXPathObjectPtr xpathObj);
 363 xmlNode *getXpathResult(xmlXPathObjectPtr xpathObj, int index);
 364 void dedupXpathResults(xmlXPathObjectPtr xpathObj);
 365 
 366 static inline int numXpathResults(xmlXPathObjectPtr xpathObj)
     /* [previous][next][first][last][top][bottom][index][help] */
 367 {
 368     if(xpathObj == NULL || xpathObj->nodesetval == NULL) {
 369         return 0;
 370     }
 371     return xpathObj->nodesetval->nodeNr;
 372 }
 373 
 374 bool xml_acl_enabled(xmlNode *xml);
 375 void xml_acl_disable(xmlNode *xml);
 376 bool xml_acl_denied(xmlNode *xml); /* Part or all of a change was rejected */
 377 bool xml_acl_filtered_copy(const char *user, xmlNode* acl_source, xmlNode *xml, xmlNode ** result);
 378 
 379 bool xml_tracking_changes(xmlNode * xml);
 380 bool xml_document_dirty(xmlNode *xml);
 381 void xml_track_changes(xmlNode * xml, const char *user, xmlNode *acl_source, bool enforce_acls);
 382 void xml_calculate_changes(xmlNode * old, xmlNode * new); /* For comparing two documents after the fact */
 383 void xml_accept_changes(xmlNode * xml);
 384 void xml_log_changes(uint8_t level, const char *function, xmlNode *xml);
 385 void xml_log_patchset(uint8_t level, const char *function, xmlNode *xml);
 386 bool xml_patch_versions(xmlNode *patchset, int add[3], int del[3]);
 387 
 388 xmlNode *xml_create_patchset(
 389     int format, xmlNode *source, xmlNode *target, bool *config, bool manage_version);
 390 int xml_apply_patchset(xmlNode *xml, xmlNode *patchset, bool check_version);
 391 
 392 void patchset_process_digest(xmlNode *patch, xmlNode *source, xmlNode *target, bool with_digest);
 393 
 394 void save_xml_to_file(xmlNode * xml, const char *desc, const char *filename);
 395 char *xml_get_path(xmlNode *xml);
 396 
 397 char * crm_xml_escape(const char *text);
 398 void crm_xml_sanitize_id(char *id);
 399 void crm_xml_set_id(xmlNode *xml, const char *format, ...)
 400     __attribute__ ((__format__ (__printf__, 2, 3)));
 401 
 402 /*!
 403  * \brief xmlNode destructor which can be used in glib collections
 404  */
 405 void crm_destroy_xml(gpointer data);
 406 
 407 #endif

/* [previous][next][first][last][top][bottom][index][help] */