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