webservices: Implement WsReadQualifiedName.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2017-04-28 12:12:48 +02:00 committed by Alexandre Julliard
parent 992da70339
commit e61291479f
4 changed files with 262 additions and 12 deletions

View File

@ -966,27 +966,45 @@ HRESULT append_attribute( WS_XML_ELEMENT_NODE *elem, WS_XML_ATTRIBUTE *attr )
return S_OK;
}
static HRESULT parse_name( const unsigned char *str, unsigned int len,
WS_XML_STRING **prefix, WS_XML_STRING **localname )
static HRESULT split_name( const unsigned char *str, ULONG len, const unsigned char **prefix,
ULONG *prefix_len, const unsigned char **localname, ULONG *localname_len )
{
const unsigned char *name_ptr = str, *prefix_ptr = NULL;
unsigned int i, name_len = len, prefix_len = 0;
const unsigned char *ptr = str;
for (i = 0; i < len; i++)
*prefix = NULL;
*prefix_len = 0;
*localname = str;
*localname_len = len;
while (len--)
{
if (str[i] == ':')
if (*ptr == ':')
{
prefix_ptr = str;
prefix_len = i;
name_ptr = &str[i + 1];
name_len -= i + 1;
if (ptr == str) return WS_E_INVALID_FORMAT;
*prefix = str;
*prefix_len = ptr - str;
*localname = ptr + 1;
*localname_len = len;
break;
}
ptr++;
}
return S_OK;
}
static HRESULT parse_name( const unsigned char *str, ULONG len, WS_XML_STRING **prefix, WS_XML_STRING **localname )
{
const unsigned char *localname_ptr, *prefix_ptr;
ULONG localname_len, prefix_len;
HRESULT hr;
if ((hr = split_name( str, len, &prefix_ptr, &prefix_len, &localname_ptr, &localname_len )) != S_OK) return hr;
if (!(*prefix = alloc_xml_string( prefix_ptr, prefix_len ))) return E_OUTOFMEMORY;
if (!(*localname = alloc_xml_string( name_ptr, name_len )))
if (!(*localname = alloc_xml_string( localname_ptr, localname_len )))
{
heap_free( *prefix );
*prefix = NULL;
return E_OUTOFMEMORY;
}
return S_OK;
@ -2116,6 +2134,124 @@ HRESULT WINAPI WsReadEndAttribute( WS_XML_READER *handle, WS_ERROR *error )
return S_OK;
}
static HRESULT find_namespace( struct reader *reader, const WS_XML_STRING *prefix, const WS_XML_STRING **ns )
{
const struct node *node;
for (node = reader->current->parent; node_type( node ) == WS_XML_NODE_TYPE_ELEMENT; node = node->parent)
{
const WS_XML_ELEMENT_NODE *elem = &node->hdr;
ULONG i;
for (i = 0; i < elem->attributeCount; i++)
{
if (!elem->attributes[i]->isXmlNs) continue;
if (WsXmlStringEquals( elem->attributes[i]->prefix, prefix, NULL ) != S_OK) continue;
*ns = elem->attributes[i]->ns;
return S_OK;
}
}
return WS_E_INVALID_FORMAT;
}
static HRESULT read_qualified_name( struct reader *reader, WS_HEAP *heap, WS_XML_STRING *prefix_ret,
WS_XML_STRING *localname_ret, WS_XML_STRING *ns_ret )
{
const WS_XML_TEXT_NODE *node = (const WS_XML_TEXT_NODE *)reader->current;
const WS_XML_UTF8_TEXT *utf8 = (const WS_XML_UTF8_TEXT *)node->text;
unsigned char *prefix_bytes, *localname_bytes, *ns_bytes;
const unsigned char *ptr = utf8->value.bytes;
WS_XML_STRING prefix, localname, empty = {0, NULL};
const WS_XML_STRING *ns = &empty;
ULONG len = utf8->value.length;
HRESULT hr;
while (len && read_isspace( *ptr )) { ptr++; len--; }
while (len && read_isspace( ptr[len - 1] )) { len--; }
if (!len) return WS_E_INVALID_FORMAT;
if ((hr = split_name( ptr, len, (const unsigned char **)&prefix.bytes, &prefix.length,
(const unsigned char **)&localname.bytes, &localname.length )) != S_OK) return hr;
if (!localname.length) return WS_E_INVALID_FORMAT;
if (prefix.length && (hr = find_namespace( reader, &prefix, &ns )) != S_OK) return hr;
if (!(prefix_bytes = ws_alloc( heap, prefix.length ))) return WS_E_QUOTA_EXCEEDED;
memcpy( prefix_bytes, prefix.bytes, prefix.length );
if (!(localname_bytes = ws_alloc( heap, localname.length )))
{
ws_free( heap, prefix_bytes, prefix.length );
return WS_E_QUOTA_EXCEEDED;
}
memcpy( localname_bytes, localname.bytes, localname.length );
if (!(ns_bytes = ws_alloc( heap, ns->length )))
{
ws_free( heap, prefix_bytes, prefix.length );
ws_free( heap, localname_bytes, localname.length );
return WS_E_QUOTA_EXCEEDED;
}
memcpy( ns_bytes, ns->bytes, ns->length );
prefix_ret->bytes = prefix_bytes;
prefix_ret->length = prefix.length;
localname_ret->bytes = localname_bytes;
localname_ret->length = localname.length;
ns_ret->bytes = ns_bytes;
ns_ret->length = ns->length;
return S_OK;
}
/**************************************************************************
* WsReadQualifiedName [webservices.@]
*/
HRESULT WINAPI WsReadQualifiedName( WS_XML_READER *handle, WS_HEAP *heap, WS_XML_STRING *prefix,
WS_XML_STRING *localname, WS_XML_STRING *ns,
WS_ERROR *error )
{
struct reader *reader = (struct reader *)handle;
HRESULT hr;
TRACE( "%p %p %s %s %s %p\n", handle, heap, debugstr_xmlstr(prefix), debugstr_xmlstr(localname),
debugstr_xmlstr(ns), error );
if (error) FIXME( "ignoring error parameter\n" );
if (!reader || !heap) return E_INVALIDARG;
EnterCriticalSection( &reader->cs );
if (reader->magic != READER_MAGIC)
{
LeaveCriticalSection( &reader->cs );
return E_INVALIDARG;
}
if (!reader->input_type)
{
LeaveCriticalSection( &reader->cs );
return WS_E_INVALID_OPERATION;
}
if (!localname)
{
LeaveCriticalSection( &reader->cs );
return E_INVALIDARG;
}
if (reader->state != READER_STATE_TEXT)
{
LeaveCriticalSection( &reader->cs );
return WS_E_INVALID_FORMAT;
}
hr = read_qualified_name( reader, heap, prefix, localname, ns );
LeaveCriticalSection( &reader->cs );
return hr;
}
static WCHAR *xmltext_to_widechar( WS_HEAP *heap, const WS_XML_TEXT *text )
{
WCHAR *ret;

View File

@ -4240,6 +4240,117 @@ static void test_WsReadCharsUtf8(void)
WsFreeReader( reader );
}
static void test_WsReadQualifiedName(void)
{
static const char utf8[] = {'<','a','>',0xc3,0xab,'<','/','a','>',0};
static const char localname_utf8[] = {0xc3,0xab,0};
WS_XML_STRING prefix, localname, ns;
WS_XML_READER *reader;
WS_HEAP *heap;
HRESULT hr;
BOOL found;
ULONG i;
static const struct
{
const char *str;
HRESULT hr;
const char *prefix;
const char *localname;
const char *ns;
} tests[] =
{
{ "<a></a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a> </a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a>:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a>t</a>", S_OK, "", "t", "" },
{ "<a>p:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a>p:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a>:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">p:t</a>", S_OK, "p", "t", "ns" },
{ "<a xmlns:p=\"ns\">p:t:</a>", S_OK, "p", "t:", "ns" },
{ "<a xmlns:p=\"ns\">p:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">:t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">:</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">t</a>", S_OK, "", "t", "" },
{ "<a xmlns:p=\"ns\"> </a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\"></a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">p:t u</a>", S_OK, "p", "t u", "ns" },
{ utf8, S_OK, "", localname_utf8, "" },
{ "<a> t </a>", S_OK, "", "t", "" },
{ "<a xmlns:p=\"ns\"> p:t</a>", S_OK, "p", "t", "ns" },
{ "<a xmlns:p=\"ns\">p :t</a>", WS_E_INVALID_FORMAT, NULL, NULL, NULL },
{ "<a xmlns:p=\"ns\">p: t</a>", S_OK, "p", " t", "ns" },
};
hr = WsReadQualifiedName( NULL, NULL, NULL, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
hr = WsCreateReader( NULL, 0, &reader, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadQualifiedName( reader, NULL, NULL, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadQualifiedName( reader, heap, NULL, NULL, NULL, NULL );
ok( hr == WS_E_INVALID_OPERATION, "got %08x\n", hr );
hr = set_input( reader, "<t/>", sizeof("<t/>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadQualifiedName( reader, heap, NULL, NULL, NULL, NULL );
ok( hr == E_INVALIDARG, "got %08x\n", hr );
hr = set_input( reader, "<t/>", sizeof("<t/>") - 1 );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsReadQualifiedName( reader, heap, NULL, &localname, NULL, NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
hr = set_input( reader, tests[i].str, strlen(tests[i].str) );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
hr = WsReadToStartElement( reader, NULL, NULL, &found, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
hr = WsReadStartElement( reader, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
prefix.length = localname.length = ns.length = 0xdeadbeef;
prefix.bytes = localname.bytes = ns.bytes = (BYTE *)0xdeadbeef;
hr = WsReadQualifiedName( reader, heap, &prefix, &localname, &ns, NULL );
ok( hr == tests[i].hr, "%u: got %08x\n", i, hr );
if (tests[i].hr == S_OK && hr == S_OK)
{
ok( prefix.length == strlen( tests[i].prefix ), "%u: got %u\n", i, prefix.length );
ok( !memcmp( prefix.bytes, tests[i].prefix, prefix.length ), "%u: wrong data\n", i );
ok( localname.length == strlen( tests[i].localname ), "%u: got %u\n", i, localname.length );
ok( !memcmp( localname.bytes, tests[i].localname, localname.length ), "%u: wrong data\n", i );
ok( ns.length == strlen( tests[i].ns ), "%u: got %u\n", i, ns.length );
ok( !memcmp( ns.bytes, tests[i].ns, ns.length ), "%u: wrong data\n", i );
}
else if (tests[i].hr != S_OK)
{
ok( prefix.length == 0xdeadbeef, "got %u\n", prefix.length );
ok( prefix.bytes == (BYTE *)0xdeadbeef, "got %p\n", prefix.bytes );
ok( localname.length == 0xdeadbeef, "got %u\n", localname.length );
ok( localname.bytes == (BYTE *)0xdeadbeef, "got %p\n", localname.bytes );
ok( ns.length == 0xdeadbeef, "got %u\n", ns.length );
ok( ns.bytes == (BYTE *)0xdeadbeef, "got %p\n", ns.bytes );
}
}
WsFreeHeap( heap );
WsFreeReader( reader );
}
START_TEST(reader)
{
test_WsCreateError();
@ -4279,4 +4390,5 @@ START_TEST(reader)
test_WsReadBytes();
test_WsReadChars();
test_WsReadCharsUtf8();
test_WsReadQualifiedName();
}

View File

@ -117,7 +117,7 @@
@ stdcall WsReadMessageStart(ptr ptr ptr ptr)
@ stub WsReadMetadata
@ stdcall WsReadNode(ptr ptr)
@ stub WsReadQualifiedName
@ stdcall WsReadQualifiedName(ptr ptr ptr ptr ptr ptr)
@ stdcall WsReadStartAttribute(ptr long ptr)
@ stdcall WsReadStartElement(ptr ptr)
@ stdcall WsReadToStartElement(ptr ptr ptr ptr ptr)

View File

@ -1610,6 +1610,8 @@ HRESULT WINAPI WsReadEnvelopeStart(WS_MESSAGE*, WS_XML_READER*, WS_MESSAGE_DONE_
HRESULT WINAPI WsReadMessageEnd(WS_CHANNEL*, WS_MESSAGE*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
HRESULT WINAPI WsReadMessageStart(WS_CHANNEL*, WS_MESSAGE*, const WS_ASYNC_CONTEXT*, WS_ERROR*);
HRESULT WINAPI WsReadNode(WS_XML_READER*, WS_ERROR*);
HRESULT WINAPI WsReadQualifiedName(WS_XML_READER*, WS_HEAP*, WS_XML_STRING*, WS_XML_STRING*,
WS_XML_STRING*, WS_ERROR*);
HRESULT WINAPI WsReadStartAttribute(WS_XML_READER*, ULONG, WS_ERROR*);
HRESULT WINAPI WsReadStartElement(WS_XML_READER*, WS_ERROR*);
HRESULT WINAPI WsReadToStartElement(WS_XML_READER*, const WS_XML_STRING*, const WS_XML_STRING*,