From 98dfca50bbc4109a921c4fcf5aa7d7376abcb4b6 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Mon, 26 Nov 2007 12:01:12 +0000 Subject: [PATCH] inetcomm: Copy RFC822 headers into a memory block for later parsing. --- dlls/inetcomm/mimeole.c | 90 +++++++++++++++++++++++++++++++++++++++++-- dlls/inetcomm/tests/mimeole.c | 45 ++++++++++++++++++++++ 2 files changed, 131 insertions(+), 4 deletions(-) diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index 56ee5d95748..28460baaa47 100644 --- a/dlls/inetcomm/mimeole.c +++ b/dlls/inetcomm/mimeole.c @@ -2,6 +2,7 @@ * MIME OLE Interfaces * * Copyright 2006 Robert Shearman for CodeWeavers + * Copyright 2007 Huw Davies for CodeWeavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -49,6 +50,86 @@ static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface ) return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl)); } +#define PARSER_BUF_SIZE 1024 + +/***************************************************** + * copy_headers_to_buf [internal] + * + * Copies the headers into a '\0' terminated memory block and leave + * the stream's current position set to after the blank line. + */ +static HRESULT copy_headers_to_buf(IStream *stm, char **ptr) +{ + char *buf = NULL; + DWORD size = PARSER_BUF_SIZE, offset = 0, last_end = 0; + HRESULT hr; + int done = 0; + + *ptr = NULL; + + do + { + char *end; + DWORD read; + + if(!buf) + buf = HeapAlloc(GetProcessHeap(), 0, size + 1); + else + { + size *= 2; + buf = HeapReAlloc(GetProcessHeap(), 0, buf, size + 1); + } + if(!buf) + { + hr = E_OUTOFMEMORY; + goto fail; + } + + hr = IStream_Read(stm, buf + offset, size - offset, &read); + if(FAILED(hr)) goto fail; + + offset += read; + buf[offset] = '\0'; + + if(read == 0) done = 1; + + while(!done && (end = strstr(buf + last_end, "\r\n"))) + { + DWORD new_end = end - buf + 2; + if(new_end - last_end == 2) + { + LARGE_INTEGER off; + off.QuadPart = new_end; + IStream_Seek(stm, off, STREAM_SEEK_SET, NULL); + buf[new_end] = '\0'; + done = 1; + } + else + last_end = new_end; + } + } while(!done); + + *ptr = buf; + return S_OK; + +fail: + HeapFree(GetProcessHeap(), 0, buf); + return hr; +} + +static HRESULT parse_headers(MimeBody *body, IStream *stm) +{ + char *header_buf; + HRESULT hr; + + hr = copy_headers_to_buf(stm, &header_buf); + if(FAILED(hr)) return hr; + + HeapFree(GetProcessHeap(), 0, header_buf); + return hr; +} + + static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface, REFIID riid, void** ppvObject) @@ -119,8 +200,9 @@ static HRESULT WINAPI MimeBody_Load( IMimeBody* iface, LPSTREAM pStm) { - FIXME("(%p)->(%p): stub\n", iface, pStm); - return E_NOTIMPL; + MimeBody *This = impl_from_IMimeBody(iface); + TRACE("(%p)->(%p)\n", iface, pStm); + return parse_headers(This, pStm); } static HRESULT WINAPI MimeBody_Save( @@ -143,8 +225,8 @@ static HRESULT WINAPI MimeBody_GetSizeMax( static HRESULT WINAPI MimeBody_InitNew( IMimeBody* iface) { - FIXME("stub\n"); - return E_NOTIMPL; + TRACE("%p->()\n", iface); + return S_OK; } static HRESULT WINAPI MimeBody_GetPropInfo( diff --git a/dlls/inetcomm/tests/mimeole.c b/dlls/inetcomm/tests/mimeole.c index 156884efcb8..0683356b666 100644 --- a/dlls/inetcomm/tests/mimeole.c +++ b/dlls/inetcomm/tests/mimeole.c @@ -32,6 +32,32 @@ #include "wine/test.h" +static char msg1[] = + "MIME-Version: 1.0\r\n" + "Content-Type: multipart/mixed;\r\n" + " boundary=\"------------1.5.0.6\";\r\n" + " stuff=\"du;nno\"\r\n" + "foo: bar\r\n" + "From: Huw Davies \r\n" + "From: Me \r\n" + "To: wine-patches \r\n" + "Cc: Huw Davies ,\r\n" + " \"Fred Bloggs\" \r\n" + "foo: baz\r\n" + "bar: fum\r\n" + "\r\n" + "This is a multi-part message in MIME format.\r\n" + "--------------1.5.0.6\r\n" + "Content-Type: text/plain; format=fixed; charset=UTF-8\r\n" + "Content-Transfer-Encoding: 8bit\r\n" + "\r\n" + "Stuff\r\n" + "--------------1.5.0.6\r\n" + "Content-Type: text/plain; charset=\"us-ascii\"\r\n" + "Content-Transfer-Encoding: 7bit\r\n" + "\r\n" + "More stuff\r\n" + "--------------1.5.0.6--\r\n"; static void test_CreateVirtualStream(void) { @@ -60,6 +86,9 @@ static void test_CreateBody(void) HRESULT hr; IMimeBody *body; HBODY handle = (void *)0xdeadbeef; + IStream *in; + LARGE_INTEGER off; + ULARGE_INTEGER pos; hr = CoCreateInstance(&CLSID_IMimeBody, NULL, CLSCTX_INPROC_SERVER, &IID_IMimeBody, (void**)&body); ok(hr == S_OK, "ret %08x\n", hr); @@ -68,6 +97,22 @@ static void test_CreateBody(void) ok(hr == MIME_E_NO_DATA, "ret %08x\n", hr); ok(handle == NULL, "handle %p\n", handle); + hr = CreateStreamOnHGlobal(NULL, TRUE, &in); + ok(hr == S_OK, "ret %08x\n", hr); + IStream_Write(in, msg1, sizeof(msg1) - 1, NULL); + off.QuadPart = 0; + IStream_Seek(in, off, STREAM_SEEK_SET, NULL); + + /* Need to call InitNew before Load otherwise Load crashes with native inetcomm */ + hr = IMimeBody_InitNew(body); + ok(hr == S_OK, "ret %08x\n", hr); + + hr = IMimeBody_Load(body, in); + ok(hr == S_OK, "ret %08x\n", hr); + off.QuadPart = 0; + IStream_Seek(in, off, STREAM_SEEK_CUR, &pos); + ok(pos.LowPart == 328, "pos %u\n", pos.LowPart); + IMimeBody_Release(body); } -- 2.11.4.GIT