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:
parent
620cfe7e79
commit
cceb19d0b2
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
||||
|
|
|
@ -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 );
|
||||
|
|
Loading…
Reference in New Issue