webservices: Add support for writing WS_BYTES values.

Signed-off-by: Hans Leidekker <hans@codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
Hans Leidekker 2016-10-04 13:28:36 +02:00 committed by Alexandre Julliard
parent 8ce55bc98f
commit c8a90e5de9
2 changed files with 128 additions and 49 deletions

View File

@ -574,6 +574,17 @@ static void test_WsWriteType(void)
WsFreeWriter( writer );
}
static void prepare_basic_type_test( WS_XML_WRITER *writer )
{
WS_XML_STRING localname = {1, (BYTE *)"t"}, ns = {0, NULL};
HRESULT hr;
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
}
static void test_basic_type(void)
{
static WCHAR testW[] = {'t','e','s','t',0};
@ -583,6 +594,7 @@ static void test_basic_type(void)
GUID guid;
WCHAR *str;
WS_STRING string;
WS_BYTES bytes;
ULONG i;
static const struct
{
@ -615,12 +627,7 @@ static void test_basic_type(void)
/* element content type mapping */
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@ -635,12 +642,7 @@ static void test_basic_type(void)
{
const INT64 *ptr = &tests[i].val;
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr );
@ -653,12 +655,7 @@ static void test_basic_type(void)
/* attribute type mapping */
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@ -674,68 +671,81 @@ static void test_basic_type(void)
check_output( writer, tests[i].result2, __LINE__ );
}
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
memset( &guid, 0, sizeof(guid) );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&guid, sizeof(guid), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
string.chars = testW;
string.length = 4;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&string, sizeof(string), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ );
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
str = testW;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
&str, sizeof(str), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ );
hr = set_output( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
prepare_basic_type_test( writer );
xmlstr.bytes = (BYTE *)"test";
xmlstr.length = 4;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&xmlstr, sizeof(xmlstr), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ );
prepare_basic_type_test( writer );
bytes.bytes = (BYTE *)"test";
bytes.length = 4;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&bytes, sizeof(bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>dGVzdA==</t>", __LINE__ );
prepare_basic_type_test( writer );
bytes.length = 0;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&bytes, sizeof(bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t/>", __LINE__ );
prepare_basic_type_test( writer );
bytes.bytes = NULL;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&bytes, sizeof(bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t/>", __LINE__ );
prepare_basic_type_test( writer );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL, WS_WRITE_NILLABLE_VALUE,
&bytes, sizeof(bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t a:nil=\"true\" xmlns:a=\"http://www.w3.org/2001/XMLSchema-instance\"/>",
__LINE__ );
WsFreeWriter( writer );
}

View File

@ -1265,6 +1265,38 @@ static ULONG format_urn( const GUID *ptr, unsigned char *buf )
ptr->Data4[4], ptr->Data4[5], ptr->Data4[6], ptr->Data4[7] );
}
static ULONG encode_base64( const unsigned char *bin, ULONG len, unsigned char *buf )
{
static const char base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
ULONG i = 0, x;
while (len > 0)
{
buf[i++] = base64[(bin[0] & 0xfc) >> 2];
x = (bin[0] & 3) << 4;
if (len == 1)
{
buf[i++] = base64[x];
buf[i++] = '=';
buf[i++] = '=';
break;
}
buf[i++] = base64[x | ((bin[1] & 0xf0) >> 4)];
x = (bin[1] & 0x0f) << 2;
if (len == 2)
{
buf[i++] = base64[x];
buf[i++] = '=';
break;
}
buf[i++] = base64[x | ((bin[2] & 0xc0) >> 6)];
buf[i++] = base64[bin[2] & 0x3f];
bin += 3;
len -= 3;
}
return i;
}
static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
{
switch (text->textType)
@ -1287,6 +1319,14 @@ static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret
WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
return S_OK;
}
case WS_XML_TEXT_TYPE_BASE64:
{
const WS_XML_BASE64_TEXT *base64 = (const WS_XML_BASE64_TEXT *)text;
ULONG len = ((4 * base64->length / 3) + 3) & ~3;
if (!(*ret = alloc_utf8_text( NULL, len ))) return E_OUTOFMEMORY;
(*ret)->value.length = encode_base64( base64->bytes, base64->length, (*ret)->value.bytes );
return S_OK;
}
case WS_XML_TEXT_TYPE_BOOL:
{
const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text;
@ -1837,6 +1877,32 @@ static HRESULT write_type_wsz( struct writer *writer, WS_TYPE_MAPPING mapping,
return write_type_text( writer, mapping, &utf16.text );
}
static HRESULT write_type_bytes( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_BYTES_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
{
WS_XML_BASE64_TEXT base64;
const WS_BYTES *ptr;
HRESULT hr;
if (desc)
{
FIXME( "description not supported\n" );
return E_NOTIMPL;
}
if (!option) return E_INVALIDARG;
if ((hr = get_value_ptr( option, value, size, sizeof(WS_BYTES), (const void **)&ptr )) != S_OK) return hr;
if ((option == WS_WRITE_NILLABLE_VALUE && is_nil_value( value, size )) ||
(option == WS_WRITE_NILLABLE_POINTER && !ptr)) return write_add_nil_attribute( writer );
if (!ptr->length) return S_OK;
base64.text.textType = WS_XML_TEXT_TYPE_BASE64;
base64.bytes = ptr->bytes;
base64.length = ptr->length;
return write_type_text( writer, mapping, &base64.text );
}
static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size )
@ -1996,9 +2062,6 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
{
switch (type)
{
case WS_STRUCT_TYPE:
return write_type_struct( writer, mapping, desc, option, value, size );
case WS_BOOL_TYPE:
return write_type_bool( writer, mapping, desc, option, value, size );
@ -2038,9 +2101,15 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
case WS_WSZ_TYPE:
return write_type_wsz( writer, mapping, desc, option, value, size );
case WS_BYTES_TYPE:
return write_type_bytes( writer, mapping, desc, option, value, size );
case WS_XML_STRING_TYPE:
return write_type_xml_string( writer, mapping, desc, option, value, size );
case WS_STRUCT_TYPE:
return write_type_struct( writer, mapping, desc, option, value, size );
default:
FIXME( "type %u not supported\n", type );
return E_NOTIMPL;