This source file includes following definitions.
- pcmk__log_xmllib_err
- show_xml_comment
- show_xml_element
- show_xml_node
- pcmk__xml_show
- show_xml_changes_recursive
- pcmk__xml_show_changes
1
2
3
4
5
6
7
8
9
10 #include <crm_internal.h>
11
12 #include <libxml/tree.h>
13
14 #include <crm/crm.h>
15 #include <crm/common/xml.h>
16 #include <crm/common/xml_internal.h>
17 #include "crmcommon_private.h"
18
19 static int show_xml_node(pcmk__output_t *out, GString *buffer,
20 const char *prefix, const xmlNode *data, int depth,
21 uint32_t options);
22
23
24 void
25 pcmk__log_xmllib_err(void *ctx, const char *fmt, ...)
26 {
27 va_list ap;
28
29 va_start(ap, fmt);
30 pcmk__if_tracing(
31 {
32 PCMK__XML_LOG_BASE(LOG_ERR, TRUE,
33 crm_abort(__FILE__, __PRETTY_FUNCTION__,
34 __LINE__, "xml library error", TRUE,
35 TRUE),
36 "XML Error: ", fmt, ap);
37 },
38 {
39 PCMK__XML_LOG_BASE(LOG_ERR, TRUE, 0, "XML Error: ", fmt, ap);
40 }
41 );
42 va_end(ap);
43 }
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58 static int
59 show_xml_comment(pcmk__output_t *out, const xmlNode *data, int depth,
60 uint32_t options)
61 {
62 if (pcmk_is_set(options, pcmk__xml_fmt_open)) {
63 int width = pcmk_is_set(options, pcmk__xml_fmt_pretty)? (2 * depth) : 0;
64
65 return out->info(out, "%*s<!--%s-->",
66 width, "", (const char *) data->content);
67 }
68 return pcmk_rc_no_output;
69 }
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90 static int
91 show_xml_element(pcmk__output_t *out, GString *buffer, const char *prefix,
92 const xmlNode *data, int depth, uint32_t options)
93 {
94 int spaces = pcmk_is_set(options, pcmk__xml_fmt_pretty)? (2 * depth) : 0;
95 int rc = pcmk_rc_no_output;
96
97 if (pcmk_is_set(options, pcmk__xml_fmt_open)) {
98 const char *hidden = crm_element_value(data, PCMK__XA_HIDDEN);
99
100 g_string_truncate(buffer, 0);
101
102 for (int lpc = 0; lpc < spaces; lpc++) {
103 g_string_append_c(buffer, ' ');
104 }
105 pcmk__g_strcat(buffer, "<", data->name, NULL);
106
107 for (const xmlAttr *attr = pcmk__xe_first_attr(data); attr != NULL;
108 attr = attr->next) {
109 xml_node_private_t *nodepriv = attr->_private;
110 const char *p_name = (const char *) attr->name;
111 const char *p_value = pcmk__xml_attr_value(attr);
112 gchar *p_copy = NULL;
113
114 if (pcmk_is_set(nodepriv->flags, pcmk__xf_deleted)) {
115 continue;
116 }
117
118 if ((hidden != NULL) && (p_name[0] != '\0')
119 && (strstr(hidden, p_name) != NULL)) {
120
121 p_value = "*****";
122
123 } else {
124 p_copy = pcmk__xml_escape(p_value, true);
125 p_value = p_copy;
126 }
127
128 pcmk__g_strcat(buffer, " ", p_name, "=\"",
129 pcmk__s(p_value, "<null>"), "\"", NULL);
130 g_free(p_copy);
131 }
132
133 if ((data->children != NULL)
134 && pcmk_is_set(options, pcmk__xml_fmt_children)) {
135 g_string_append_c(buffer, '>');
136
137 } else {
138 g_string_append(buffer, "/>");
139 }
140
141 rc = out->info(out, "%s%s%s",
142 pcmk__s(prefix, ""), pcmk__str_empty(prefix)? "" : " ",
143 buffer->str);
144 }
145
146 if (data->children == NULL) {
147 return rc;
148 }
149
150 if (pcmk_is_set(options, pcmk__xml_fmt_children)) {
151 for (const xmlNode *child = pcmk__xml_first_child(data); child != NULL;
152 child = pcmk__xml_next(child)) {
153
154 int temp_rc = show_xml_node(out, buffer, prefix, child, depth + 1,
155 options
156 |pcmk__xml_fmt_open
157 |pcmk__xml_fmt_close);
158 rc = pcmk__output_select_rc(rc, temp_rc);
159 }
160 }
161
162 if (pcmk_is_set(options, pcmk__xml_fmt_close)) {
163 int temp_rc = out->info(out, "%s%s%*s</%s>",
164 pcmk__s(prefix, ""),
165 pcmk__str_empty(prefix)? "" : " ",
166 spaces, "", data->name);
167 rc = pcmk__output_select_rc(rc, temp_rc);
168 }
169
170 return rc;
171 }
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192 static int
193 show_xml_node(pcmk__output_t *out, GString *buffer, const char *prefix,
194 const xmlNode *data, int depth, uint32_t options)
195 {
196 switch (data->type) {
197 case XML_COMMENT_NODE:
198 return show_xml_comment(out, data, depth, options);
199 case XML_ELEMENT_NODE:
200 return show_xml_element(out, buffer, prefix, data, depth, options);
201 default:
202 return pcmk_rc_no_output;
203 }
204 }
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220 int
221 pcmk__xml_show(pcmk__output_t *out, const char *prefix, const xmlNode *data,
222 int depth, uint32_t options)
223 {
224 int rc = pcmk_rc_no_output;
225 GString *buffer = NULL;
226
227 pcmk__assert(out != NULL);
228 CRM_CHECK(depth >= 0, depth = 0);
229
230 if (data == NULL) {
231 return rc;
232 }
233
234
235
236
237 buffer = g_string_sized_new(1024);
238 rc = show_xml_node(out, buffer, prefix, data, depth, options);
239 g_string_free(buffer, TRUE);
240
241 return rc;
242 }
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257 static int
258 show_xml_changes_recursive(pcmk__output_t *out, const xmlNode *data, int depth,
259 uint32_t options)
260 {
261
262
263
264 xml_node_private_t *nodepriv = (xml_node_private_t *) data->_private;
265 int rc = pcmk_rc_no_output;
266 int temp_rc = pcmk_rc_no_output;
267
268 if (pcmk_all_flags_set(nodepriv->flags, pcmk__xf_dirty|pcmk__xf_created)) {
269
270 return pcmk__xml_show(out, PCMK__XML_PREFIX_CREATED, data, depth,
271 options
272 |pcmk__xml_fmt_open
273 |pcmk__xml_fmt_children
274 |pcmk__xml_fmt_close);
275 }
276
277 if (pcmk_is_set(nodepriv->flags, pcmk__xf_dirty)) {
278
279 bool pretty = pcmk_is_set(options, pcmk__xml_fmt_pretty);
280 int spaces = pretty? (2 * depth) : 0;
281 const char *prefix = PCMK__XML_PREFIX_MODIFIED;
282
283 if (pcmk_is_set(nodepriv->flags, pcmk__xf_moved)) {
284 prefix = PCMK__XML_PREFIX_MOVED;
285 }
286
287
288 rc = pcmk__xml_show(out, prefix, data, depth,
289 options|pcmk__xml_fmt_open);
290
291
292 for (const xmlAttr *attr = pcmk__xe_first_attr(data); attr != NULL;
293 attr = attr->next) {
294 const char *name = (const char *) attr->name;
295
296 nodepriv = attr->_private;
297
298 if (pcmk_is_set(nodepriv->flags, pcmk__xf_deleted)) {
299 const char *value = pcmk__xml_attr_value(attr);
300
301 temp_rc = out->info(out, "%s %*s @%s=%s",
302 PCMK__XML_PREFIX_DELETED, spaces, "", name,
303 value);
304
305 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_dirty)) {
306 const char *value = pcmk__xml_attr_value(attr);
307
308 if (pcmk_is_set(nodepriv->flags, pcmk__xf_created)) {
309 prefix = PCMK__XML_PREFIX_CREATED;
310
311 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_modified)) {
312 prefix = PCMK__XML_PREFIX_MODIFIED;
313
314 } else if (pcmk_is_set(nodepriv->flags, pcmk__xf_moved)) {
315 prefix = PCMK__XML_PREFIX_MOVED;
316
317 } else {
318 prefix = PCMK__XML_PREFIX_MODIFIED;
319 }
320
321 temp_rc = out->info(out, "%s %*s @%s=%s",
322 prefix, spaces, "", name, value);
323 }
324 rc = pcmk__output_select_rc(rc, temp_rc);
325 }
326
327
328 for (const xmlNode *child = pcmk__xml_first_child(data); child != NULL;
329 child = pcmk__xml_next(child)) {
330 temp_rc = show_xml_changes_recursive(out, child, depth + 1,
331 options);
332 rc = pcmk__output_select_rc(rc, temp_rc);
333 }
334
335
336 temp_rc = pcmk__xml_show(out, PCMK__XML_PREFIX_MODIFIED, data, depth,
337 options|pcmk__xml_fmt_close);
338 return pcmk__output_select_rc(rc, temp_rc);
339 }
340
341
342 for (const xmlNode *child = pcmk__xml_first_child(data); child != NULL;
343 child = pcmk__xml_next(child)) {
344 temp_rc = show_xml_changes_recursive(out, child, depth + 1, options);
345 rc = pcmk__output_select_rc(rc, temp_rc);
346 }
347 return rc;
348 }
349
350
351
352
353
354
355
356
357
358
359
360
361 int
362 pcmk__xml_show_changes(pcmk__output_t *out, const xmlNode *xml)
363 {
364 xml_doc_private_t *docpriv = NULL;
365 int rc = pcmk_rc_no_output;
366 int temp_rc = pcmk_rc_no_output;
367
368 pcmk__assert((out != NULL) && (xml != NULL) && (xml->doc != NULL));
369
370 docpriv = xml->doc->_private;
371 if (!pcmk_is_set(docpriv->flags, pcmk__xf_dirty)) {
372 return rc;
373 }
374
375 for (const GList *iter = docpriv->deleted_objs; iter != NULL;
376 iter = iter->next) {
377 const pcmk__deleted_xml_t *deleted_obj = iter->data;
378
379 if (deleted_obj->position >= 0) {
380 temp_rc = out->info(out, PCMK__XML_PREFIX_DELETED " %s (%d)",
381 deleted_obj->path, deleted_obj->position);
382 } else {
383 temp_rc = out->info(out, PCMK__XML_PREFIX_DELETED " %s",
384 deleted_obj->path);
385 }
386 rc = pcmk__output_select_rc(rc, temp_rc);
387 }
388
389 temp_rc = show_xml_changes_recursive(out, xml, 0, pcmk__xml_fmt_pretty);
390 return pcmk__output_select_rc(rc, temp_rc);
391 }