summaryrefslogtreecommitdiffstats
path: root/lib/common/schemas.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/common/schemas.c')
-rw-r--r--lib/common/schemas.c149
1 files changed, 43 insertions, 106 deletions
diff --git a/lib/common/schemas.c b/lib/common/schemas.c
index 88a3051..b3c09eb 100644
--- a/lib/common/schemas.c
+++ b/lib/common/schemas.c
@@ -1,5 +1,5 @@
/*
- * Copyright 2004-2022 the Pacemaker project contributors
+ * Copyright 2004-2023 the Pacemaker project contributors
*
* The version control history for this file may have further details.
*
@@ -432,34 +432,8 @@ crm_schema_init(void)
NULL, NULL, FALSE, -1);
}
-#if 0
-static void
-relaxng_invalid_stderr(void *userData, xmlErrorPtr error)
-{
- /*
- Structure xmlError
- struct _xmlError {
- int domain : What part of the library raised this er
- int code : The error code, e.g. an xmlParserError
- char * message : human-readable informative error messag
- xmlErrorLevel level : how consequent is the error
- char * file : the filename
- int line : the line number if available
- char * str1 : extra string information
- char * str2 : extra string information
- char * str3 : extra string information
- int int1 : extra number information
- int int2 : column number of the error or 0 if N/A
- void * ctxt : the parser context if available
- void * node : the node in the tree
- }
- */
- crm_err("Structured error: line=%d, level=%d %s", error->line, error->level, error->message);
-}
-#endif
-
static gboolean
-validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file,
+validate_with_relaxng(xmlDocPtr doc, xmlRelaxNGValidityErrorFunc error_handler, void *error_handler_context, const char *relaxng_file,
relaxng_ctx_cache_t **cached_ctx)
{
int rc = 0;
@@ -476,15 +450,14 @@ validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file,
crm_debug("Creating RNG parser context");
ctx = calloc(1, sizeof(relaxng_ctx_cache_t));
- xmlLoadExtDtdDefaultValue = 1;
ctx->parser = xmlRelaxNGNewParserCtxt(relaxng_file);
CRM_CHECK(ctx->parser != NULL, goto cleanup);
- if (to_logs) {
+ if (error_handler) {
xmlRelaxNGSetParserErrors(ctx->parser,
- (xmlRelaxNGValidityErrorFunc) xml_log,
- (xmlRelaxNGValidityWarningFunc) xml_log,
- GUINT_TO_POINTER(LOG_ERR));
+ (xmlRelaxNGValidityErrorFunc) error_handler,
+ (xmlRelaxNGValidityWarningFunc) error_handler,
+ error_handler_context);
} else {
xmlRelaxNGSetParserErrors(ctx->parser,
(xmlRelaxNGValidityErrorFunc) fprintf,
@@ -500,11 +473,11 @@ validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file,
ctx->valid = xmlRelaxNGNewValidCtxt(ctx->rng);
CRM_CHECK(ctx->valid != NULL, goto cleanup);
- if (to_logs) {
+ if (error_handler) {
xmlRelaxNGSetValidErrors(ctx->valid,
- (xmlRelaxNGValidityErrorFunc) xml_log,
- (xmlRelaxNGValidityWarningFunc) xml_log,
- GUINT_TO_POINTER(LOG_ERR));
+ (xmlRelaxNGValidityErrorFunc) error_handler,
+ (xmlRelaxNGValidityWarningFunc) error_handler,
+ error_handler_context);
} else {
xmlRelaxNGSetValidErrors(ctx->valid,
(xmlRelaxNGValidityErrorFunc) fprintf,
@@ -513,10 +486,6 @@ validate_with_relaxng(xmlDocPtr doc, gboolean to_logs, const char *relaxng_file,
}
}
- /* xmlRelaxNGSetValidStructuredErrors( */
- /* valid, relaxng_invalid_stderr, valid); */
-
- xmlLineNumbersDefault(1);
rc = xmlRelaxNGValidateDoc(ctx->valid, doc);
if (rc > 0) {
valid = FALSE;
@@ -590,39 +559,36 @@ crm_schema_cleanup(void)
}
static gboolean
-validate_with(xmlNode *xml, int method, gboolean to_logs)
+validate_with(xmlNode *xml, int method, xmlRelaxNGValidityErrorFunc error_handler, void* error_handler_context)
{
- xmlDocPtr doc = NULL;
gboolean valid = FALSE;
char *file = NULL;
+ struct schema_s *schema = NULL;
+ relaxng_ctx_cache_t **cache = NULL;
if (method < 0) {
return FALSE;
}
- if (known_schemas[method].validator == schema_validator_none) {
+ schema = &(known_schemas[method]);
+ if (schema->validator == schema_validator_none) {
return TRUE;
}
- CRM_CHECK(xml != NULL, return FALSE);
-
- if (pcmk__str_eq(known_schemas[method].name, "pacemaker-next",
- pcmk__str_none)) {
+ if (pcmk__str_eq(schema->name, "pacemaker-next", pcmk__str_none)) {
crm_warn("The pacemaker-next schema is deprecated and will be removed "
"in a future release.");
}
- doc = getDocPtr(xml);
file = pcmk__xml_artefact_path(pcmk__xml_artefact_ns_legacy_rng,
- known_schemas[method].name);
+ schema->name);
crm_trace("Validating with %s (type=%d)",
- pcmk__s(file, "missing schema"), known_schemas[method].validator);
- switch (known_schemas[method].validator) {
+ pcmk__s(file, "missing schema"), schema->validator);
+ switch (schema->validator) {
case schema_validator_rng:
- valid =
- validate_with_relaxng(doc, to_logs, file,
- (relaxng_ctx_cache_t **) & (known_schemas[method].cache));
+ cache = (relaxng_ctx_cache_t **) &(schema->cache);
+ valid = validate_with_relaxng(xml->doc, error_handler, error_handler_context, file, cache);
break;
default:
crm_err("Unknown validator type: %d",
@@ -639,7 +605,7 @@ validate_with_silent(xmlNode *xml, int method)
{
bool rc, sl_backup = silent_logging;
silent_logging = TRUE;
- rc = validate_with(xml, method, TRUE);
+ rc = validate_with(xml, method, (xmlRelaxNGValidityErrorFunc) xml_log, GUINT_TO_POINTER(LOG_ERR));
silent_logging = sl_backup;
return rc;
}
@@ -676,7 +642,7 @@ dump_file(const char *filename)
}
gboolean
-validate_xml_verbose(xmlNode *xml_blob)
+validate_xml_verbose(const xmlNode *xml_blob)
{
int fd = 0;
xmlDoc *doc = NULL;
@@ -692,7 +658,7 @@ validate_xml_verbose(xmlNode *xml_blob)
dump_file(filename);
- doc = xmlParseFile(filename);
+ doc = xmlReadFile(filename, NULL, 0);
xml = xmlDocGetRootElement(doc);
rc = validate_xml(xml, NULL, FALSE);
free_xml(xml);
@@ -706,8 +672,16 @@ validate_xml_verbose(xmlNode *xml_blob)
gboolean
validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
{
+ return pcmk__validate_xml(xml_blob, validation, to_logs ? (xmlRelaxNGValidityErrorFunc) xml_log : NULL, GUINT_TO_POINTER(LOG_ERR));
+}
+
+gboolean
+pcmk__validate_xml(xmlNode *xml_blob, const char *validation, xmlRelaxNGValidityErrorFunc error_handler, void* error_handler_context)
+{
int version = 0;
+ CRM_CHECK((xml_blob != NULL) && (xml_blob->doc != NULL), return FALSE);
+
if (validation == NULL) {
validation = crm_element_value(xml_blob, XML_ATTR_VALIDATION);
}
@@ -717,7 +691,7 @@ validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
bool valid = FALSE;
for (lpc = 0; lpc < xml_schema_max; lpc++) {
- if (validate_with(xml_blob, lpc, FALSE)) {
+ if (validate_with(xml_blob, lpc, NULL, NULL)) {
valid = TRUE;
crm_xml_add(xml_blob, XML_ATTR_VALIDATION,
known_schemas[lpc].name);
@@ -735,7 +709,7 @@ validate_xml(xmlNode *xml_blob, const char *validation, gboolean to_logs)
if (strcmp(validation, PCMK__VALUE_NONE) == 0) {
return TRUE;
} else if (version < xml_schema_max) {
- return validate_with(xml_blob, version, to_logs);
+ return validate_with(xml_blob, version, error_handler, error_handler_context);
}
crm_err("Unknown validator: %s", validation);
@@ -884,47 +858,17 @@ cib_upgrade_err(void *ctx, const char *fmt, ...)
va_end(ap);
}
-
-/* Denotes temporary emergency fix for "xmldiff'ing not text-node-ready";
- proper fix is most likely to teach __xml_diff_object and friends to
- deal with XML_TEXT_NODE (and more?), i.e., those nodes currently
- missing "_private" field (implicitly as NULL) which clashes with
- unchecked accesses (e.g. in __xml_offset) -- the outcome may be that
- those unexpected XML nodes will simply be ignored for the purpose of
- diff'ing, or it may be made more robust, or per the user's preference
- (which then may be exposed as crm_diff switch).
-
- Said XML_TEXT_NODE may appear unexpectedly due to how upgrade-2.10.xsl
- is arranged.
-
- The emergency fix is simple: reparse XSLT output with blank-ignoring
- parser. */
-#ifndef PCMK_SCHEMAS_EMERGENCY_XSLT
-#define PCMK_SCHEMAS_EMERGENCY_XSLT 1
-#endif
-
static xmlNode *
apply_transformation(xmlNode *xml, const char *transform, gboolean to_logs)
{
char *xform = NULL;
xmlNode *out = NULL;
xmlDocPtr res = NULL;
- xmlDocPtr doc = NULL;
xsltStylesheet *xslt = NULL;
-#if PCMK_SCHEMAS_EMERGENCY_XSLT != 0
- xmlChar *emergency_result;
- int emergency_txt_len;
- int emergency_res;
-#endif
-
- CRM_CHECK(xml != NULL, return FALSE);
- doc = getDocPtr(xml);
+
xform = pcmk__xml_artefact_path(pcmk__xml_artefact_ns_legacy_xslt,
transform);
- xmlLoadExtDtdDefaultValue = 1;
- xmlSubstituteEntitiesDefault(1);
-
/* for capturing, e.g., what's emitted via <xsl:message> */
if (to_logs) {
xsltSetGenericErrorFunc(NULL, cib_upgrade_err);
@@ -935,22 +879,12 @@ apply_transformation(xmlNode *xml, const char *transform, gboolean to_logs)
xslt = xsltParseStylesheetFile((pcmkXmlStr) xform);
CRM_CHECK(xslt != NULL, goto cleanup);
- res = xsltApplyStylesheet(xslt, doc, NULL);
+ res = xsltApplyStylesheet(xslt, xml->doc, NULL);
CRM_CHECK(res != NULL, goto cleanup);
xsltSetGenericErrorFunc(NULL, NULL); /* restore default one */
-
-#if PCMK_SCHEMAS_EMERGENCY_XSLT != 0
- emergency_res = xsltSaveResultToString(&emergency_result,
- &emergency_txt_len, res, xslt);
- xmlFreeDoc(res);
- CRM_CHECK(emergency_res == 0, goto cleanup);
- out = string2xml((const char *) emergency_result);
- free(emergency_result);
-#else
out = xmlDocGetRootElement(res);
-#endif
cleanup:
if (xslt) {
@@ -1055,12 +989,15 @@ update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform,
int max_stable_schemas = xml_latest_schema_index();
int lpc = 0, match = -1, rc = pcmk_ok;
int next = -1; /* -1 denotes "inactive" value */
+ xmlRelaxNGValidityErrorFunc error_handler =
+ to_logs ? (xmlRelaxNGValidityErrorFunc) xml_log : NULL;
CRM_CHECK(best != NULL, return -EINVAL);
*best = 0;
- CRM_CHECK(xml_blob != NULL, return -EINVAL);
- CRM_CHECK(*xml_blob != NULL, return -EINVAL);
+ CRM_CHECK((xml_blob != NULL) && (*xml_blob != NULL)
+ && ((*xml_blob)->doc != NULL),
+ return -EINVAL);
xml = *xml_blob;
value = crm_element_value_copy(xml, XML_ATTR_VALIDATION);
@@ -1090,7 +1027,7 @@ update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform,
known_schemas[lpc].name ? known_schemas[lpc].name : "<unset>",
lpc, max_stable_schemas);
- if (validate_with(xml, lpc, to_logs) == FALSE) {
+ if (validate_with(xml, lpc, error_handler, GUINT_TO_POINTER(LOG_ERR)) == FALSE) {
if (next != -1) {
crm_info("Configuration not valid for schema: %s",
known_schemas[lpc].name);
@@ -1155,7 +1092,7 @@ update_validation(xmlNode **xml_blob, int *best, int max, gboolean transform,
known_schemas[lpc].transform);
rc = -pcmk_err_transform_failed;
- } else if (validate_with(upgrade, next, to_logs)) {
+ } else if (validate_with(upgrade, next, error_handler, GUINT_TO_POINTER(LOG_ERR))) {
crm_info("Transformation %s.xsl successful",
known_schemas[lpc].transform);
lpc = next;