Module: wine Branch: master Commit: 915acd68de3531348d36bd31a02413b122554221 URL: http://source.winehq.org/git/wine.git/?a=commit;h=915acd68de3531348d36bd31a0...
Author: Jacek Caban jacek@codeweavers.com Date: Fri Jan 27 16:01:07 2017 +0100
inetcomm: Added support for decoding base64 in IMimeBody::GetData.
Signed-off-by: Jacek Caban jacek@codeweavers.com Signed-off-by: Alexandre Julliard julliard@winehq.org
---
dlls/inetcomm/mimeole.c | 95 ++++++++++++++++++++++++++++++++++++++++++- dlls/inetcomm/tests/mimeole.c | 22 ++++++++++ 2 files changed, 116 insertions(+), 1 deletion(-)
diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index 0f0da61..90a5dd4 100644 --- a/dlls/inetcomm/mimeole.c +++ b/dlls/inetcomm/mimeole.c @@ -1515,6 +1515,88 @@ static HRESULT WINAPI MimeBody_GetDataHere( return E_NOTIMPL; }
+static const signed char base64_decode_table[] = +{ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x00 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, /* 0x10 */ + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, /* 0x20 */ + 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, /* 0x30 */ + -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40 */ + 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, /* 0x50 */ + -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60 */ + 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1 /* 0x70 */ +}; + +static HRESULT decode_base64(IStream *input, IStream **ret_stream) +{ + const unsigned char *ptr, *end; + unsigned char buf[1024]; + LARGE_INTEGER pos; + unsigned char *ret; + unsigned char in[4]; + IStream *output; + DWORD size; + int n = 0; + HRESULT hres; + + pos.QuadPart = 0; + hres = IStream_Seek(input, pos, STREAM_SEEK_SET, NULL); + if(FAILED(hres)) + return hres; + + hres = CreateStreamOnHGlobal(NULL, TRUE, &output); + if(FAILED(hres)) + return hres; + + while(1) { + hres = IStream_Read(input, buf, sizeof(buf), &size); + if(FAILED(hres) || !size) + break; + + ptr = ret = buf; + end = buf + size; + + while(1) { + /* skip invalid chars */ + while(ptr < end && + (*ptr >= sizeof(base64_decode_table)/sizeof(*base64_decode_table) + || base64_decode_table[*ptr] == -1)) + ptr++; + if(ptr == end) + break; + + in[n++] = base64_decode_table[*ptr++]; + switch(n) { + case 2: + *ret++ = in[0] << 2 | in[1] >> 4; + continue; + case 3: + *ret++ = in[1] << 4 | in[2] >> 2; + continue; + case 4: + *ret++ = ((in[2] << 6) & 0xc0) | in[3]; + n = 0; + } + } + + if(ret > buf) { + hres = IStream_Write(output, buf, ret - buf, NULL); + if(FAILED(hres)) + break; + } + } + + if(SUCCEEDED(hres)) + hres = IStream_Seek(output, pos, STREAM_SEEK_SET, NULL); + if(FAILED(hres)) { + IStream_Release(output); + return hres; + } + + *ret_stream = output; + return S_OK; +} + static HRESULT WINAPI MimeBody_GetData( IMimeBody* iface, ENCODINGTYPE ietEncoding, @@ -1524,7 +1606,18 @@ static HRESULT WINAPI MimeBody_GetData( ULARGE_INTEGER start, size; HRESULT hres;
- FIXME("(%p)->(%d, %p). Ignoring encoding type.\n", This, ietEncoding, ppStream); + TRACE("(%p)->(%d %p)\n", This, ietEncoding, ppStream); + + if(This->encoding != ietEncoding) { + switch(This->encoding) { + case IET_BASE64: + if(ietEncoding != IET_BINARY) + FIXME("Encofing %d is not supported.\n", ietEncoding); + return decode_base64(This->data, ppStream); + default: + FIXME("Decoding %d is not supported.\n", This->encoding); + } + }
start.QuadPart = 0; hres = get_stream_size(This->data, &size); diff --git a/dlls/inetcomm/tests/mimeole.c b/dlls/inetcomm/tests/mimeole.c index 5d7bb9a..0765396 100644 --- a/dlls/inetcomm/tests/mimeole.c +++ b/dlls/inetcomm/tests/mimeole.c @@ -494,6 +494,28 @@ static void test_SetData(void) IStream_Release(stream); IStream_Release(stream2); IStream_Release(&test_stream->IStream_iface); + + stream = create_stream_from_string(" \t\r\n|}~YWJj ZGV|}~mZw== \t"); /* "abcdefg" in base64 obscured by invalid chars */ + hr = IMimeBody_SetData(body, IET_BASE64, "text", "plain", &IID_IStream, stream); + IStream_Release(stream); + ok(hr == S_OK, "SetData failed: %08x\n", hr); + + test_current_encoding(body, IET_BASE64); + + hr = IMimeBody_GetData(body, IET_BINARY, &stream); + ok(hr == S_OK, "GetData failed %08x\n", hr); + + test_stream_read(stream, S_OK, "abc", 3); + test_stream_read(stream, S_OK, "defg", -1); + + IStream_Release(stream); + + hr = IMimeBody_GetData(body, IET_BASE64, &stream); + ok(hr == S_OK, "GetData failed %08x\n", hr); + + test_stream_read(stream, S_OK, " \t\r", 3); + IStream_Release(stream); + IMimeBody_Release(body); }