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 ); 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 void test_basic_type(void)
{ {
static WCHAR testW[] = {'t','e','s','t',0}; static WCHAR testW[] = {'t','e','s','t',0};
@ -583,6 +594,7 @@ static void test_basic_type(void)
GUID guid; GUID guid;
WCHAR *str; WCHAR *str;
WS_STRING string; WS_STRING string;
WS_BYTES bytes;
ULONG i; ULONG i;
static const struct static const struct
{ {
@ -615,12 +627,7 @@ static void test_basic_type(void)
/* element content type mapping */ /* element content type mapping */
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{ {
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL, hr = WsWriteType( writer, WS_ELEMENT_CONTENT_TYPE_MAPPING, tests[i].type, NULL,
WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL ); WS_WRITE_REQUIRED_VALUE, &tests[i].val, tests[i].size, NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr ); 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; const INT64 *ptr = &tests[i].val;
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL, hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, tests[i].type, NULL,
WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL ); WS_WRITE_REQUIRED_POINTER, &ptr, sizeof(ptr), NULL );
ok( hr == S_OK, "%u: got %08x\n", i, hr ); ok( hr == S_OK, "%u: got %08x\n", i, hr );
@ -653,12 +655,7 @@ static void test_basic_type(void)
/* attribute type mapping */ /* attribute type mapping */
for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++) for (i = 0; i < sizeof(tests)/sizeof(tests[0]); i++)
{ {
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL ); hr = WsWriteStartAttribute( writer, NULL, &localname, &ns, FALSE, NULL );
ok( hr == S_OK, "got %08x\n", hr ); 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__ ); check_output( writer, tests[i].result2, __LINE__ );
} }
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
memset( &guid, 0, sizeof(guid) ); memset( &guid, 0, sizeof(guid) );
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE, hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_GUID_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&guid, sizeof(guid), NULL ); &guid, sizeof(guid), NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL ); hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ ); check_output( writer, "<t>00000000-0000-0000-0000-000000000000</t>", __LINE__ );
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
string.chars = testW; string.chars = testW;
string.length = 4; string.length = 4;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE, hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&string, sizeof(string), NULL ); &string, sizeof(string), NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL ); hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ ); check_output( writer, "<t>test</t>", __LINE__ );
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
str = testW; str = testW;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER, hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_WSZ_TYPE, NULL, WS_WRITE_REQUIRED_POINTER,
&str, sizeof(str), NULL ); &str, sizeof(str), NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL ); hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ ); check_output( writer, "<t>test</t>", __LINE__ );
hr = set_output( writer ); prepare_basic_type_test( writer );
ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteStartElement( writer, NULL, &localname, &ns, NULL );
ok( hr == S_OK, "got %08x\n", hr );
xmlstr.bytes = (BYTE *)"test"; xmlstr.bytes = (BYTE *)"test";
xmlstr.length = 4; xmlstr.length = 4;
hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE, hr = WsWriteType( writer, WS_ELEMENT_TYPE_MAPPING, WS_XML_STRING_TYPE, NULL, WS_WRITE_REQUIRED_VALUE,
&xmlstr, sizeof(xmlstr), NULL ); &xmlstr, sizeof(xmlstr), NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
hr = WsWriteEndElement( writer, NULL ); hr = WsWriteEndElement( writer, NULL );
ok( hr == S_OK, "got %08x\n", hr ); ok( hr == S_OK, "got %08x\n", hr );
check_output( writer, "<t>test</t>", __LINE__ ); 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 ); 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] ); 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 ) static HRESULT text_to_utf8text( const WS_XML_TEXT *text, WS_XML_UTF8_TEXT **ret )
{ {
switch (text->textType) 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 ); WideCharToMultiByte( CP_UTF8, 0, str, len, (char *)(*ret)->value.bytes, (*ret)->value.length, NULL, NULL );
return S_OK; 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: case WS_XML_TEXT_TYPE_BOOL:
{ {
const WS_XML_BOOL_TEXT *bool_text = (const WS_XML_BOOL_TEXT *)text; 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 ); 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, static HRESULT write_type_xml_string( struct writer *writer, WS_TYPE_MAPPING mapping,
const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option, const WS_XML_STRING_DESCRIPTION *desc, WS_WRITE_OPTION option,
const void *value, ULONG size ) const void *value, ULONG size )
@ -1996,9 +2062,6 @@ static HRESULT write_type( struct writer *writer, WS_TYPE_MAPPING mapping, WS_TY
{ {
switch (type) switch (type)
{ {
case WS_STRUCT_TYPE:
return write_type_struct( writer, mapping, desc, option, value, size );
case WS_BOOL_TYPE: case WS_BOOL_TYPE:
return write_type_bool( writer, mapping, desc, option, value, size ); 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: case WS_WSZ_TYPE:
return write_type_wsz( writer, mapping, desc, option, value, size ); 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: case WS_XML_STRING_TYPE:
return write_type_xml_string( writer, mapping, desc, option, value, size ); 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: default:
FIXME( "type %u not supported\n", type ); FIXME( "type %u not supported\n", type );
return E_NOTIMPL; return E_NOTIMPL;