From 0672bfa216a48ca0394ea7294212e36681a18280 Mon Sep 17 00:00:00 2001 From: Jacek Caban Date: Wed, 1 Feb 2017 11:23:39 +0100 Subject: [PATCH] inetcomm: Added support for decoding quoted-printable data. Signed-off-by: Jacek Caban Signed-off-by: Alexandre Julliard --- dlls/inetcomm/mimeole.c | 97 +++++++++++++++++++++++++++++++++-- dlls/inetcomm/tests/mimeole.c | 14 +++++ 2 files changed, 108 insertions(+), 3 deletions(-) diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index c55be72faa5..0ed7cef26d1 100644 --- a/dlls/inetcomm/mimeole.c +++ b/dlls/inetcomm/mimeole.c @@ -1614,6 +1614,90 @@ static HRESULT decode_base64(IStream *input, IStream **ret_stream) return S_OK; } +static int hex_digit(char c) +{ + if('0' <= c && c <= '9') + return c - '0'; + if('A' <= c && c <= 'F') + return c - 'A' + 10; + if('a' <= c && c <= 'f') + return c - 'a' + 10; + return -1; +} + +static HRESULT decode_qp(IStream *input, IStream **ret_stream) +{ + const unsigned char *ptr, *end; + unsigned char *ret, prev = 0; + unsigned char buf[1024]; + LARGE_INTEGER pos; + IStream *output; + DWORD size; + int n = -1; + 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(ptr < end) { + unsigned char byte = *ptr++; + + switch(n) { + case -1: + if(byte == '=') + n = 0; + else + *ret++ = byte; + continue; + case 0: + prev = byte; + n = 1; + continue; + case 1: + if(prev != '\r' || byte != '\n') { + int h1 = hex_digit(prev), h2 = hex_digit(byte); + if(h1 != -1 && h2 != -1) + *ret++ = (h1 << 4) | h2; + else + *ret++ = '='; + } + n = -1; + continue; + } + } + + 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, @@ -1628,12 +1712,19 @@ static HRESULT WINAPI MimeBody_GetData( 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); + hres = decode_base64(This->data, ppStream); + break; + case IET_QP: + hres = decode_qp(This->data, ppStream); + break; default: FIXME("Decoding %d is not supported.\n", This->encoding); + hres = S_FALSE; } + if(ietEncoding != IET_BINARY) + FIXME("Encoding %d is not supported.\n", ietEncoding); + if(hres != S_FALSE) + return hres; } start.QuadPart = 0; diff --git a/dlls/inetcomm/tests/mimeole.c b/dlls/inetcomm/tests/mimeole.c index c680938da4a..fbee6e12f0c 100644 --- a/dlls/inetcomm/tests/mimeole.c +++ b/dlls/inetcomm/tests/mimeole.c @@ -556,6 +556,20 @@ static void test_SetData(void) test_stream_read(stream, S_OK, " \t\r", 3); IStream_Release(stream); + stream = create_stream_from_string(" =3d=3D\"one\" \t=\r\ntw= o=\nx3\n=34\r\n5"); + hr = IMimeBody_SetData(body, IET_QP, "text", "plain", &IID_IStream, stream); + IStream_Release(stream); + ok(hr == S_OK, "SetData failed: %08x\n", hr); + + test_current_encoding(body, IET_QP); + + hr = IMimeBody_GetData(body, IET_BINARY, &stream); + ok(hr == S_OK, "GetData failed %08x\n", hr); + + test_stream_read(stream, S_OK, " ==\"one\" \ttw=o=3\n4\r\n5", -1); + + IStream_Release(stream); + IMimeBody_Release(body); }