webservices: Keep track of prefix bindings.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2016-03-09 14:16:32 +01:00 committed by Alexandre Julliard
parent 620cfe7e79
commit cceb19d0b2
3 changed files with 257 additions and 15 deletions

View File

@ -396,6 +396,12 @@ enum reader_state
READER_STATE_EOF
};
struct prefix
{
WS_XML_STRING str;
WS_XML_STRING ns;
};
struct reader
{
ULONG read_size;
@ -405,6 +411,9 @@ struct reader
struct node *root;
struct node *current;
ULONG current_attr;
struct prefix *prefixes;
ULONG nb_prefixes;
ULONG nb_prefixes_allocated;
WS_XML_READER_INPUT_TYPE input_type;
const unsigned char *input_data;
ULONG input_size;
@ -422,6 +431,13 @@ static struct reader *alloc_reader(void)
for (i = 0; i < count; i++) size += reader_props[i].size;
if (!(ret = heap_alloc_zero( size ))) return NULL;
if (!(ret->prefixes = heap_alloc_zero( sizeof(*ret->prefixes) )))
{
heap_free( ret );
return NULL;
}
ret->nb_prefixes = ret->nb_prefixes_allocated = 1;
ptr = (char *)&ret->prop[count];
for (i = 0; i < count; i++)
{
@ -433,6 +449,74 @@ static struct reader *alloc_reader(void)
return ret;
}
static void clear_prefixes( struct prefix *prefixes, ULONG count )
{
ULONG i;
for (i = 0; i < count; i++)
{
heap_free( prefixes[i].str.bytes );
prefixes[i].str.bytes = NULL;
prefixes[i].str.length = 0;
heap_free( prefixes[i].ns.bytes );
prefixes[i].ns.bytes = NULL;
prefixes[i].ns.length = 0;
}
}
static HRESULT set_prefix( struct prefix *prefix, const WS_XML_STRING *str, const WS_XML_STRING *ns )
{
if (str)
{
heap_free( prefix->str.bytes );
if (!(prefix->str.bytes = heap_alloc( str->length ))) return E_OUTOFMEMORY;
memcpy( prefix->str.bytes, str->bytes, str->length );
prefix->str.length = str->length;
}
heap_free( prefix->ns.bytes );
if (!(prefix->ns.bytes = heap_alloc( ns->length ))) return E_OUTOFMEMORY;
memcpy( prefix->ns.bytes, ns->bytes, ns->length );
prefix->ns.length = ns->length;
return S_OK;
}
static HRESULT bind_prefix( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING *ns )
{
ULONG i;
HRESULT hr;
for (i = 0; i < reader->nb_prefixes; i++)
{
if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
return set_prefix( &reader->prefixes[i], NULL, ns );
}
if (i >= reader->nb_prefixes_allocated)
{
ULONG new_size = reader->nb_prefixes_allocated * sizeof(*reader->prefixes) * 2;
struct prefix *tmp = heap_realloc_zero( reader->prefixes, new_size );
if (!tmp) return E_OUTOFMEMORY;
reader->prefixes = tmp;
reader->nb_prefixes_allocated *= 2;
}
if ((hr = set_prefix( &reader->prefixes[i], prefix, ns )) != S_OK) return hr;
reader->nb_prefixes++;
return S_OK;
}
static const WS_XML_STRING *get_namespace( struct reader *reader, const WS_XML_STRING *prefix )
{
ULONG i;
for (i = 0; i < reader->nb_prefixes; i++)
{
if (WsXmlStringEquals( prefix, &reader->prefixes[i].str, NULL ) == S_OK)
return &reader->prefixes[i].ns;
}
return NULL;
}
static HRESULT set_reader_prop( struct reader *reader, WS_XML_READER_PROPERTY_ID id, const void *value, ULONG size )
{
if (id >= reader->prop_count || size != reader_props[id].size || reader_props[id].readonly)
@ -487,6 +571,8 @@ static HRESULT read_init_state( struct reader *reader )
destroy_nodes( reader->root );
reader->root = NULL;
clear_prefixes( reader->prefixes, reader->nb_prefixes );
reader->nb_prefixes = 1;
if (!(node = alloc_node( WS_XML_NODE_TYPE_EOF ))) return E_OUTOFMEMORY;
read_insert_eof( reader, node );
reader->state = READER_STATE_INITIAL;
@ -548,6 +634,8 @@ void WINAPI WsFreeReader( WS_XML_READER *handle )
if (!reader) return;
destroy_nodes( reader->root );
clear_prefixes( reader->prefixes, reader->nb_prefixes );
heap_free( reader->prefixes );
heap_free( reader );
}
@ -947,8 +1035,19 @@ static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
hr = E_OUTOFMEMORY;
if (WsXmlStringEquals( prefix, &xmlns, NULL ) == S_OK)
{
heap_free( prefix );
attr->isXmlNs = 1;
if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length ))) goto error;
if (!(attr->prefix = alloc_xml_string( localname->bytes, localname->length )))
{
heap_free( localname );
goto error;
}
attr->localName = localname;
}
else if (!prefix->length && WsXmlStringEquals( localname, &xmlns, NULL ) == S_OK)
{
attr->isXmlNs = 1;
attr->prefix = prefix;
attr->localName = localname;
}
else
@ -982,15 +1081,12 @@ static HRESULT read_attribute( struct reader *reader, WS_XML_ATTRIBUTE **ret )
if (attr->isXmlNs)
{
if (!(attr->ns = alloc_xml_string( start, len ))) goto error;
if ((hr = bind_prefix( reader, attr->prefix, attr->ns )) != S_OK) goto error;
if (!(text = alloc_utf8_text( NULL, 0 ))) goto error;
attr->value = &text->text;
}
else
{
if (!(attr->ns = alloc_xml_string( NULL, 0 ))) goto error;
if (!(text = alloc_utf8_text( start, len ))) goto error;
attr->value = &text->text;
}
else if (!(text = alloc_utf8_text( start, len ))) goto error;
attr->value = &text->text;
attr->singleQuote = (quote == '\'');
*ret = attr;
@ -1037,13 +1133,33 @@ static struct node *read_find_parent( struct reader *reader, const WS_XML_STRING
return NULL;
}
static HRESULT set_namespaces( struct reader *reader, WS_XML_ELEMENT_NODE *elem )
{
static const WS_XML_STRING xml = {3, (BYTE *)"xml"};
const WS_XML_STRING *ns;
ULONG i;
if (!(ns = get_namespace( reader, elem->prefix ))) return WS_E_INVALID_FORMAT;
if (!(elem->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
if (!elem->ns->length) elem->ns->bytes = (BYTE *)(elem->ns + 1); /* quirk */
for (i = 0; i < elem->attributeCount; i++)
{
WS_XML_ATTRIBUTE *attr = elem->attributes[i];
if (attr->isXmlNs || WsXmlStringEquals( attr->prefix, &xml, NULL ) == S_OK) continue;
if (!(ns = get_namespace( reader, attr->prefix ))) return WS_E_INVALID_FORMAT;
if (!(attr->ns = alloc_xml_string( ns->bytes, ns->length ))) return E_OUTOFMEMORY;
}
return S_OK;
}
static HRESULT read_element( struct reader *reader )
{
unsigned int len = 0, ch, skip;
const unsigned char *start;
struct node *node = NULL, *parent;
WS_XML_ELEMENT_NODE *elem;
WS_XML_ATTRIBUTE *attr;
WS_XML_ATTRIBUTE *attr = NULL;
HRESULT hr = WS_E_INVALID_FORMAT;
if (read_end_of_data( reader ))
@ -1072,11 +1188,7 @@ static HRESULT read_element( struct reader *reader )
hr = E_OUTOFMEMORY;
if (!(node = alloc_node( WS_XML_NODE_TYPE_ELEMENT ))) goto error;
elem = (WS_XML_ELEMENT_NODE *)node;
if ((hr = parse_name( start, len, &elem->prefix, &elem->localName )) != S_OK) goto error;
hr = E_OUTOFMEMORY;
if (!(elem->ns = alloc_xml_string( NULL, 0 ))) goto error;
elem->ns->bytes = (BYTE *)(elem->ns + 1);
reader->current_attr = 0;
for (;;)
@ -1091,6 +1203,7 @@ static HRESULT read_element( struct reader *reader )
}
reader->current_attr++;
}
if ((hr = set_namespaces( reader, elem )) != S_OK) goto error;
read_insert_node( reader, parent, node );
reader->state = READER_STATE_STARTELEMENT;

View File

@ -2220,7 +2220,7 @@ static void test_WsGetNamespaceFromPrefix(void)
ok( !memcmp( ns->bytes, "ns", 2 ), "wrong data\n" );
}
prepare_namespace_test( reader, "<t xmlns:prefix='ns'>>/t>" );
prepare_namespace_test( reader, "<t xmlns:prefix='ns'></t>" );
ns = NULL;
hr = WsGetNamespaceFromPrefix( reader, &prefix, TRUE, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@ -2244,6 +2244,12 @@ static void test_WsGetNamespaceFromPrefix(void)
WS_XML_UTF8_TEXT *text;
ok( elem->node.nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", elem->node.nodeType );
ok( elem->prefix != NULL, "prefix not set\n" );
ok( !elem->prefix->length, "got %u\n", elem->prefix->length );
ok( elem->prefix->bytes == NULL, "bytes not set\n" );
ok( elem->ns != NULL, "ns not set\n" );
ok( !elem->ns->length, "got %u\n", elem->ns->length );
ok( elem->ns->bytes != NULL, "bytes not set\n" );
ok( elem->attributeCount == 1, "got %u\n", elem->attributeCount );
ok( elem->attributes != NULL, "attributes not set\n" );
@ -2259,7 +2265,7 @@ static void test_WsGetNamespaceFromPrefix(void)
ok( !memcmp( attr->localName->bytes, "prefix", 6 ), "wrong data\n" );
ok( attr->ns != NULL, "ns not set\n" );
ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
ok( attr->ns->bytes != NULL, "bytes set\n" );
ok( attr->ns->bytes != NULL, "bytes not set\n" );
ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong data\n" );
ok( attr->value != NULL, "value not set\n" );
@ -2319,6 +2325,124 @@ static void test_WsGetNamespaceFromPrefix(void)
ok( hr == S_FALSE, "got %08x\n", hr );
ok( ns == NULL, "ns not set\n" );
hr = set_input( reader, "<t prefix:attr='' xmlns:prefix='ns'></t>", sizeof("<t prefix:attr='' xmlns:prefix='ns'></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node)
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
WS_XML_ATTRIBUTE *attr;
ok( elem->node.nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", elem->node.nodeType );
ok( elem->attributeCount == 2, "got %u\n", elem->attributeCount );
ok( elem->attributes != NULL, "attributes not set\n" );
attr = elem->attributes[0];
ok( attr->singleQuote, "singleQuote not set\n" );
ok( !attr->isXmlNs, "isXmlNs is set\n" );
ok( attr->prefix != NULL, "prefix not set\n" );
ok( attr->prefix->length == 6, "got %u\n", attr->prefix->length );
ok( attr->prefix->bytes != NULL, "bytes not set\n" );
ok( !memcmp( attr->prefix->bytes, "prefix", 6 ), "wrong data\n" );
ok( attr->localName != NULL, "localName not set\n" );
ok( attr->localName->length == 4, "got %u\n", attr->localName->length );
ok( !memcmp( attr->localName->bytes, "attr", 4 ), "wrong data\n" );
ok( attr->ns != NULL, "ns not set\n" );
ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
ok( attr->ns->bytes != NULL, "bytes not set\n" );
ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong data\n" );
}
hr = set_input( reader, "<t xmlns:p='ns'><u xmlns:p='ns2'/></t>", sizeof("<t xmlns:p='ns'><u xmlns:p='ns2'/></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadStartElement( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = set_input( reader, "<t xmlns:p='ns'><p:u p:a=''/></t>", sizeof("<t xmlns:p='ns'><p:u p:a=''/></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadStartElement( reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node)
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
WS_XML_ATTRIBUTE *attr;
ok( elem->node.nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", elem->node.nodeType );
ok( elem->attributeCount == 1, "got %u\n", elem->attributeCount );
ok( elem->attributes != NULL, "attributes not set\n" );
attr = elem->attributes[0];
ok( attr->prefix != NULL, "prefix not set\n" );
ok( attr->prefix->length == 1, "got %u\n", attr->prefix->length );
ok( attr->prefix->bytes != NULL, "bytes set\n" );
ok( !memcmp( attr->prefix->bytes, "p", 1 ), "wrong data\n" );
ok( attr->localName != NULL, "localName not set\n" );
ok( attr->localName->length == 1, "got %u\n", attr->localName->length );
ok( !memcmp( attr->localName->bytes, "a", 1 ), "wrong data\n" );
ok( attr->ns != NULL, "ns not set\n" );
ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
ok( attr->ns->bytes != NULL, "bytes not set\n" );
ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong data\n" );
}
hr = set_input( reader, "<t xmlns='ns'></t>", sizeof("<t xmlns='ns'></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsGetReaderNode( reader, &node, NULL );
ok( hr == S_OK, "got %08x\n", hr );
if (node)
{
WS_XML_ELEMENT_NODE *elem = (WS_XML_ELEMENT_NODE *)node;
WS_XML_ATTRIBUTE *attr;
ok( elem->node.nodeType == WS_XML_NODE_TYPE_ELEMENT, "got %u\n", elem->node.nodeType );
ok( elem->prefix != NULL, "prefix not set\n" );
ok( !elem->prefix->length, "got %u\n", elem->prefix->length );
ok( elem->prefix->bytes == NULL, "bytes not set\n" );
ok( elem->ns != NULL, "ns not set\n" );
ok( elem->ns->length == 2, "got %u\n", elem->ns->length );
ok( elem->ns->bytes != NULL, "bytes not set\n" );
ok( !memcmp( elem->ns->bytes, "ns", 2 ), "wrong data\n" );
attr = elem->attributes[0];
ok( attr->isXmlNs, "isXmlNs is not set\n" );
ok( attr->prefix != NULL, "prefix not set\n" );
ok( !attr->prefix->length, "got %u\n", attr->prefix->length );
ok( attr->prefix->bytes == NULL, "bytes set\n" );
ok( attr->localName != NULL, "localName not set\n" );
ok( attr->localName->length == 5, "got %u\n", attr->localName->length );
ok( !memcmp( attr->localName->bytes, "xmlns", 5 ), "wrong data\n" );
ok( attr->ns != NULL, "ns not set\n" );
ok( attr->ns->length == 2, "got %u\n", attr->ns->length );
ok( attr->ns->bytes != NULL, "bytes not set\n" );
ok( !memcmp( attr->ns->bytes, "ns", 2 ), "wrong data\n" );
}
hr = set_input( reader, "<t xmlns:p='ns' xmlns:p='ns2'></t>", sizeof("<t xmlns:p='ns' xmlns:p='ns2'></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
hr = set_input( reader, "<t xmlns:p='ns' xmlns:p='ns'></t>", sizeof("<t xmlns:p='ns' xmlns:p='ns'></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
todo_wine ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
hr = set_input( reader, "<t xmlns:p='ns' xmlns:P='ns2'></t>", sizeof("<t xmlns:p='ns' xmlns:P='ns2'></t>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadToStartElement( reader, NULL, NULL, NULL, NULL );
ok( hr == S_OK, "got %08x\n", hr );
WsFreeReader( reader );
}

View File

@ -60,6 +60,11 @@ static inline void *heap_realloc( void *mem, SIZE_T size )
return HeapReAlloc( GetProcessHeap(), 0, mem, size );
}
static inline void *heap_realloc_zero( void *mem, SIZE_T size )
{
return HeapReAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, mem, size );
}
static inline BOOL heap_free( void *mem )
{
return HeapFree( GetProcessHeap(), 0, mem );