Module: wine Branch: master Commit: 98dfca50bbc4109a921c4fcf5aa7d7376abcb4b6 URL: http://source.winehq.org/git/wine.git/?a=commit;h=98dfca50bbc4109a921c4fcf5a...
Author: Huw Davies huw@codeweavers.com Date: Mon Nov 26 12:01:12 2007 +0000
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 56ee5d9..28460ba 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 156884e..0683356 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 huw@codeweavers.com\r\n" + "From: Me xxx@codeweavers.com\r\n" + "To: wine-patches wine-patches@winehq.org\r\n" + "Cc: Huw Davies huw@codeweavers.com,\r\n" + " "Fred Bloggs" fred@bloggs.com\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); }