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:
parent
503d152bfb
commit
8ce55bc98f
|
@ -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;
|
||||
|
|
|
@ -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 );
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
|
|
Loading…
Reference in New Issue