webservices: Add support for reading 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:35 +02:00 committed by Alexandre Julliard
parent 503d152bfb
commit 8ce55bc98f
3 changed files with 184 additions and 16 deletions

View file

@ -2468,6 +2468,78 @@ static HRESULT str_to_guid( const unsigned char *str, ULONG len, GUID *ret )
return S_OK;
}
static inline unsigned char decode_char( unsigned char c )
{
if (c >= 'A' && c <= 'Z') return c - 'A';
if (c >= 'a' && c <= 'z') return c - 'a' + 26;
if (c >= '0' && c <= '9') return c - '0' + 52;
if (c == '+') return 62;
if (c == '/') return 63;
return 64;
}
static ULONG decode_base64( const unsigned char *base64, ULONG len, unsigned char *buf )
{
ULONG i = 0;
unsigned char c0, c1, c2, c3;
const unsigned char *p = base64;
while (len > 4)
{
if ((c0 = decode_char( p[0] )) > 63) return 0;
if ((c1 = decode_char( p[1] )) > 63) return 0;
if ((c2 = decode_char( p[2] )) > 63) return 0;
if ((c3 = decode_char( p[3] )) > 63) return 0;
buf[i + 0] = (c0 << 2) | (c1 >> 4);
buf[i + 1] = (c1 << 4) | (c2 >> 2);
buf[i + 2] = (c2 << 6) | c3;
len -= 4;
i += 3;
p += 4;
}
if (p[2] == '=')
{
if ((c0 = decode_char( p[0] )) > 63) return 0;
if ((c1 = decode_char( p[1] )) > 63) return 0;
buf[i] = (c0 << 2) | (c1 >> 4);
i++;
}
else if (p[3] == '=')
{
if ((c0 = decode_char( p[0] )) > 63) return 0;
if ((c1 = decode_char( p[1] )) > 63) return 0;
if ((c2 = decode_char( p[2] )) > 63) return 0;
buf[i + 0] = (c0 << 2) | (c1 >> 4);
buf[i + 1] = (c1 << 4) | (c2 >> 2);
i += 2;
}
else
{
if ((c0 = decode_char( p[0] )) > 63) return 0;
if ((c1 = decode_char( p[1] )) > 63) return 0;
if ((c2 = decode_char( p[2] )) > 63) return 0;
if ((c3 = decode_char( p[3] )) > 63) return 0;
buf[i + 0] = (c0 << 2) | (c1 >> 4);
buf[i + 1] = (c1 << 4) | (c2 >> 2);
buf[i + 2] = (c2 << 6) | c3;
i += 3;
}
return i;
}
static HRESULT str_to_bytes( const unsigned char *str, ULONG len, WS_HEAP *heap, WS_BYTES *ret )
{
const unsigned char *p = str;
while (len && read_isspace( *p )) { p++; len--; }
while (len && read_isspace( p[len - 1] )) { len--; }
if (len % 4) return WS_E_INVALID_FORMAT;
if (!(ret->bytes = ws_alloc( heap, len * 3 / 4 ))) return WS_E_QUOTA_EXCEEDED;
ret->length = decode_base64( p, len, ret->bytes );
return S_OK;
}
static const int month_offsets[2][12] =
{
{0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334},
@ -3515,6 +3587,58 @@ static HRESULT read_type_guid( struct reader *reader, WS_TYPE_MAPPING mapping,
return S_OK;
}
static HRESULT read_type_bytes( struct reader *reader, WS_TYPE_MAPPING mapping,
const WS_XML_STRING *localname, const WS_XML_STRING *ns,
const WS_BYTES_DESCRIPTION *desc, WS_READ_OPTION option,
WS_HEAP *heap, void *ret, ULONG size )
{
WS_XML_UTF8_TEXT *utf8;
WS_BYTES val = {0};
HRESULT hr;
BOOL found;
if (desc) FIXME( "ignoring description\n" );
if ((hr = read_get_text( reader, mapping, localname, ns, &utf8, &found )) != S_OK) return hr;
if (found && (hr = str_to_bytes( utf8->value.bytes, utf8->value.length, heap, &val )) != S_OK)
return hr;
switch (option)
{
case WS_READ_REQUIRED_VALUE:
if (!found) return WS_E_INVALID_FORMAT;
/* fall through */
case WS_READ_NILLABLE_VALUE:
if (size != sizeof(WS_BYTES)) return E_INVALIDARG;
*(WS_BYTES *)ret = val;
break;
case WS_READ_REQUIRED_POINTER:
if (!found) return WS_E_INVALID_FORMAT;
/* fall through */
case WS_READ_OPTIONAL_POINTER:
case WS_READ_NILLABLE_POINTER:
{
WS_BYTES *heap_val = NULL;
if (size != sizeof(heap_val)) return E_INVALIDARG;
if (found)
{
if (!(heap_val = ws_alloc( heap, sizeof(*heap_val) ))) return WS_E_QUOTA_EXCEEDED;
*heap_val = val;
}
*(WS_BYTES **)ret = heap_val;
break;
}
default:
FIXME( "read option %u not supported\n", option );
return E_NOTIMPL;
}
return S_OK;
}
static BOOL is_empty_text_node( const struct node *node )
{
const WS_XML_TEXT_NODE *text = (const WS_XML_TEXT_NODE *)node;
@ -3629,6 +3753,9 @@ ULONG get_type_size( WS_TYPE type, const WS_STRUCT_DESCRIPTION *desc )
case WS_WSZ_TYPE:
return sizeof(WCHAR *);
case WS_BYTES_TYPE:
return sizeof(WS_BYTES);
case WS_STRUCT_TYPE:
return desc->size;
@ -3659,10 +3786,11 @@ static WS_READ_OPTION get_field_read_option( WS_TYPE type, ULONG options )
case WS_UINT32_TYPE:
case WS_UINT64_TYPE:
case WS_DOUBLE_TYPE:
case WS_ENUM_TYPE:
case WS_DATETIME_TYPE:
case WS_GUID_TYPE:
case WS_BYTES_TYPE:
case WS_STRUCT_TYPE:
case WS_ENUM_TYPE:
if (options & (WS_FIELD_OPTIONAL|WS_FIELD_NILLABLE)) return WS_READ_NILLABLE_VALUE;
return WS_READ_REQUIRED_VALUE;
@ -3924,11 +4052,6 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
switch (type)
{
case WS_STRUCT_TYPE:
if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_BOOL_TYPE:
if ((hr = read_type_bool( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
@ -3979,16 +4102,6 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
return hr;
break;
case WS_WSZ_TYPE:
if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_ENUM_TYPE:
if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_DATETIME_TYPE:
if ((hr = read_type_datetime( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
@ -3999,6 +4112,26 @@ static HRESULT read_type( struct reader *reader, WS_TYPE_MAPPING mapping, WS_TYP
return hr;
break;
case WS_WSZ_TYPE:
if ((hr = read_type_wsz( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_BYTES_TYPE:
if ((hr = read_type_bytes( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_STRUCT_TYPE:
if ((hr = read_type_struct( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
case WS_ENUM_TYPE:
if ((hr = read_type_enum( reader, mapping, localname, ns, desc, option, heap, value, size )) != S_OK)
return hr;
break;
default:
FIXME( "type %u not supported\n", type );
return E_NOTIMPL;

View file

@ -1339,6 +1339,7 @@ static void test_WsReadType(void)
UINT32 val_uint32;
UINT64 val_uint64;
GUID val_guid;
WS_BYTES val_bytes;
hr = WsCreateHeap( 1 << 16, 0, NULL, 0, &heap, NULL );
ok( hr == S_OK, "got %08x\n", hr );
@ -1608,6 +1609,27 @@ static void test_WsReadType(void)
ok( hr == S_OK, "got %08x\n", hr );
ok( IsEqualGUID( &val_guid, &guid2 ), "wrong guid\n" );
memset( &val_bytes, 0, sizeof(val_bytes) );
prepare_type_test( reader, "<t>dGVzdA==</t>", sizeof("<t>dGVzdA==</t>") - 1 );
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL,
WS_READ_REQUIRED_VALUE, heap, &val_bytes, sizeof(val_bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( val_bytes.length == 4, "got %u\n", val_bytes.length );
ok( !memcmp( val_bytes.bytes, "test", 4 ), "wrong data\n" );
memset( &val_bytes, 0, sizeof(val_bytes) );
prepare_type_test( reader, "<t> dGVzdA== </t>", sizeof("<t> dGVzdA== </t>") - 1 );
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL,
WS_READ_REQUIRED_VALUE, heap, &val_bytes, sizeof(val_bytes), NULL );
ok( hr == S_OK, "got %08x\n", hr );
ok( val_bytes.length == 4, "got %u\n", val_bytes.length );
ok( !memcmp( val_bytes.bytes, "test", 4 ), "wrong data\n" );
prepare_type_test( reader, "<t>dGVzdA===</t>", sizeof("<t>dGVzdA===</t>") - 1 );
hr = WsReadType( reader, WS_ELEMENT_CONTENT_TYPE_MAPPING, WS_BYTES_TYPE, NULL,
WS_READ_REQUIRED_VALUE, heap, &val_bytes, sizeof(val_bytes), NULL );
ok( hr == WS_E_INVALID_FORMAT, "got %08x\n", hr );
WsFreeReader( reader );
WsFreeHeap( heap );
}

View file

@ -59,9 +59,11 @@ typedef struct _WS_CALL_PROPERTY WS_CALL_PROPERTY;
typedef struct _WS_DOUBLE_DESCRIPTION WS_DOUBLE_DESCRIPTION;
typedef struct _WS_DATETIME WS_DATETIME;
typedef struct _WS_XML_DATETIME_TEXT WS_XML_DATETIME_TEXT;
typedef struct _WS_XML_BASE64_TEXT WS_XML_BASE64_TEXT;
typedef struct _WS_DATETIME_DESCRIPTION WS_DATETIME_DESCRIPTION;
typedef struct _WS_GUID_DESCRIPTION WS_GUID_DESCRIPTION;
typedef struct _WS_UNIQUE_ID_DESCRIPTION WS_UNIQUE_ID_DESCRIPTION;
typedef struct _WS_BYTES_DESCRIPTION WS_BYTES_DESCRIPTION;
typedef struct _WS_URL WS_URL;
typedef struct _WS_HTTP_URL WS_HTTP_URL;
typedef struct _WS_HTTPS_URL WS_HTTPS_URL;
@ -426,6 +428,11 @@ struct _WS_UNIQUE_ID_DESCRIPTION {
ULONG maxCharCount;
};
struct _WS_BYTES_DESCRIPTION {
ULONG minByteCount;
ULONG maxByteCount;
};
typedef enum {
WS_TYPE_ATTRIBUTE_FIELD_MAPPING,
WS_ATTRIBUTE_FIELD_MAPPING,
@ -1112,6 +1119,12 @@ struct _WS_XML_DATETIME_TEXT {
WS_DATETIME value;
};
struct _WS_XML_BASE64_TEXT {
WS_XML_TEXT text;
BYTE *bytes;
ULONG length;
};
typedef enum {
WS_URL_HTTP_SCHEME_TYPE,
WS_URL_HTTPS_SCHEME_TYPE,