inetcomm: Copy RFC822 headers into a memory block for later parsing.

This commit is contained in:
Huw Davies 2007-11-26 12:01:12 +00:00 committed by Alexandre Julliard
parent c2f0697763
commit 98dfca50bb
2 changed files with 131 additions and 4 deletions

View File

@ -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(

View File

@ -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);
}