xml: really enforce elements cardinality when parsing messages

- add a new SNIPPET_MANDATORY:
	 we could only indicate 0-1 and 0-* cardinalities, now we can also
	 indicate 1-1 and 1-* cardinalities.
 - repect cadinalities when parsing an xmlNode tree into a LassoNode
	 tree.
This commit is contained in:
Benjamin Dauvergne 2012-10-08 19:28:57 +02:00
parent 2663c5df95
commit 8e98e432ff
3 changed files with 97 additions and 38 deletions

View File

@ -62,6 +62,7 @@ typedef enum {
SNIPPET_ALLOW_TEXT = 1 << 26, /* allow text childs in list of nodes */
SNIPPET_KEEP_XMLNODE = 1 << 27, /* force keep xmlNode */
SNIPPET_PRIVATE = 1 << 28, /* means that the offset is relative to a private extension */
SNIPPET_MANDATORY = 1 << 29, /* means that the element cardinality is at least 1 */
} SnippetType;
typedef enum {

View File

@ -1365,15 +1365,43 @@ is_snippet_type(struct XmlSnippet *snippet, SnippetType simple_type) {
return (snippet->type & 0xff) == simple_type;
}
static inline gboolean
is_snippet_mandatory(struct XmlSnippet *snippet)
{
return snippet->type & SNIPPET_MANDATORY ? TRUE : FALSE;
}
static inline gboolean
is_snippet_multiple(struct XmlSnippet *snippet)
{
switch (snippet->type & 0xff) {
case SNIPPET_LIST_XMLNODES:
case SNIPPET_LIST_CONTENT:
case SNIPPET_LIST_NODES:
case SNIPPET_EXTENSION:
return TRUE;
default:
return FALSE;
}
}
static inline gboolean
node_match_snippet(xmlNode *parent, xmlNode *node, struct XmlSnippet *snippet)
{
gboolean rc = TRUE;
/* special case of ArtifactResponse */
if (snippet->type & SNIPPET_ANY)
if (snippet->type & SNIPPET_ANY) {
return TRUE;
return (lasso_strisequal(snippet->name, (char*)node->name)
&& ((!snippet->ns_uri && lasso_equal_namespace(parent->ns, node->ns)) ||
(node->ns && lasso_strisequal((char*)node->ns->href, snippet->ns_uri))));
} else {
rc = rc && lasso_strisequal(snippet->name, (char*)node->name);
rc = rc &&
((!snippet->ns_uri &&
lasso_equal_namespace(parent->ns, node->ns)) ||
(node->ns &&
lasso_strisequal((char*)node->ns->href, snippet->ns_uri)));
return rc;
}
}
/** FIXME: return a real error code */
@ -1564,28 +1592,54 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
xmlNode *first_child = NULL;
GList **list = NULL;
xmlChar *content = NULL;
gboolean match = FALSE;
struct XmlSnippet *matched_snippet = NULL;
/* Find a matching snippet */
while (class_iter && ! node_match_snippet(xmlnode, t, snippet)) {
snippet++;
#define ADVANCE \
snippet++; \
next_node_snippet(&class_iter, &snippet);
}
if (! class_iter) {
/* If we cannot find one, terminate here. */
break;
}
class = class_iter->data;
g_type = G_TYPE_FROM_CLASS(class);
value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
list = value;
#define ERROR \
error("Element %s:%s cannot be parsed", \
t->ns != NULL ? (char*)t->ns->prefix : "<noprefix>", \
t->name); \
rc = 1; \
goto cleanup;
/* Find a matching snippet */
while (class_iter && snippet) {
gboolean mandatory = is_snippet_mandatory(snippet);
gboolean multiple = is_snippet_multiple(snippet);
if (snippet->offset || (snippet->type & SNIPPET_PRIVATE)) {
switch (snippet->type & 0xff) {
if ((match = node_match_snippet(xmlnode, t, snippet))) {
matched_snippet = snippet;
class = class_iter->data;
g_type = G_TYPE_FROM_CLASS(class);
value = SNIPPET_STRUCT_MEMBER_P(node, g_type, snippet);
list = value;
if (! multiple) {
ADVANCE;
}
break;
} else {
if (mandatory) {
break;
} else {
ADVANCE;
}
}
}
if (! match) {
ERROR;
}
#undef ADVANCE
#undef ERROR
if (matched_snippet->offset || (matched_snippet->type & SNIPPET_PRIVATE)) {
switch (matched_snippet->type & 0xff) {
case SNIPPET_LIST_NODES:
case SNIPPET_NODE:
subnode = lasso_node_new_from_xmlNode_with_type(t,
snippet->class_name);
if (is_snippet_type(snippet, SNIPPET_NODE)) {
matched_snippet->class_name);
if (is_snippet_type(matched_snippet, SNIPPET_NODE)) {
lasso_assign_new_gobject(*(LassoNode**)value, subnode);
} else {
lasso_list_add_new_gobject(*list, subnode);
@ -1595,7 +1649,7 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
first_child = xmlSecGetNextElementNode(t->children);
if (first_child) {
subnode = lasso_node_new_from_xmlNode_with_type(first_child,
snippet->class_name);
matched_snippet->class_name);
lasso_assign_new_gobject(*(LassoNode**)value, subnode);
}
break;
@ -1609,8 +1663,8 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
case SNIPPET_CONTENT:
case SNIPPET_LIST_CONTENT:
content = xmlNodeGetContent(t);
if (is_snippet_type(snippet, SNIPPET_CONTENT)) {
snippet_set_value(node, class, snippet, content);
if (is_snippet_type(matched_snippet, SNIPPET_CONTENT)) {
snippet_set_value(node, class, matched_snippet, content);
} else { /* only list of string-like xsd:type supported */
lasso_list_add_string(*list, (char*)content);
}
@ -1626,22 +1680,9 @@ lasso_node_impl_init_from_xml(LassoNode *node, xmlNode *xmlnode)
}
/* When creating a new LassoNode and option KEEP_XMLNODE is present,
* we attached the xmlNode to the LassoNode */
if (subnode && (snippet->type & SNIPPET_KEEP_XMLNODE)) {
if (subnode && (matched_snippet->type & SNIPPET_KEEP_XMLNODE)) {
lasso_node_set_original_xmlnode(subnode, t);
}
switch (snippet->type & 0xff) {
case SNIPPET_NODE:
case SNIPPET_NODE_IN_CHILD:
case SNIPPET_XMLNODE:
case SNIPPET_CONTENT:
case SNIPPET_SIGNATURE:
/* Only one node to read, advance ! */
++snippet;
next_node_snippet(&class_iter, &snippet);
break;
default:
break;
}
} else {
g_assert_not_reached();
}
@ -2797,6 +2838,7 @@ lasso_node_build_xmlNode_from_snippets(LassoNode *node, LassoNodeClass *class, x
case SNIPPET_ANY:
case SNIPPET_KEEP_XMLNODE:
case SNIPPET_PRIVATE:
case SNIPPET_MANDATORY:
case SNIPPET_UNUSED1:
g_assert_not_reached();
}

View File

@ -137,6 +137,22 @@ START_TEST(test07_registry_functional_mapping)
}
END_TEST
static struct XmlSnippet schema_snippets[] = {
{NULL, 0, 0, NULL, NULL, NULL}
};
static void
class_init(LassoNodeClass *klass)
{
LassoNodeClass *nclass = LASSO_NODE_CLASS(klass);
nclass->node_data = g_new0(LassoNodeClassData, 1);
lasso_node_class_set_nodename(nclass, "Assertion");
lasso_node_class_set_ns(nclass,LASSO_SAML2_ASSERTION_HREF, LASSO_SAML2_ASSERTION_PREFIX);
lasso_node_class_add_snippets(nclass, schema_snippets);
}
START_TEST(test08_test_new_from_xmlNode)
{
static GType this_type = 0;
@ -147,7 +163,7 @@ START_TEST(test08_test_new_from_xmlNode)
sizeof (LassoNodeClass),
NULL,
NULL,
NULL,
(GClassInitFunc) class_init,
NULL,
NULL,
sizeof(LassoNode),