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:
parent
2663c5df95
commit
8e98e432ff
|
@ -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 {
|
||||
|
|
116
lasso/xml/xml.c
116
lasso/xml/xml.c
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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),
|
||||
|
|
Loading…
Reference in New Issue