Huw Davies : inetcomm: Copy RFC822 headers into a memory block for later parsing.
Alexandre Julliard
julliard at winehq.org
Tue Nov 27 09:54:26 CST 2007
Module: wine
Branch: master
Commit: 98dfca50bbc4109a921c4fcf5aa7d7376abcb4b6
URL: http://source.winehq.org/git/wine.git/?a=commit;h=98dfca50bbc4109a921c4fcf5aa7d7376abcb4b6
Author: Huw Davies <huw at 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 at codeweavers.com>\r\n"
+ "From: Me <xxx at codeweavers.com>\r\n"
+ "To: wine-patches <wine-patches at winehq.org>\r\n"
+ "Cc: Huw Davies <huw at codeweavers.com>,\r\n"
+ " \"Fred Bloggs\" <fred at 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);
}
More information about the wine-cvs
mailing list