Huw Davies : inetcomm: Parse headers into a list.
Alexandre Julliard
julliard at winehq.org
Tue Nov 27 09:54:26 CST 2007
Module: wine
Branch: master
Commit: 31297b6a3b20a73be36978b6036846a035b3fd07
URL: http://source.winehq.org/git/wine.git/?a=commit;h=31297b6a3b20a73be36978b6036846a035b3fd07
Author: Huw Davies <huw at codeweavers.com>
Date: Mon Nov 26 12:01:52 2007 +0000
inetcomm: Parse headers into a list.
---
dlls/inetcomm/mimeole.c | 173 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 172 insertions(+), 1 deletions(-)
diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c
index 28460ba..5d33537 100644
--- a/dlls/inetcomm/mimeole.c
+++ b/dlls/inetcomm/mimeole.c
@@ -31,18 +31,68 @@
#include "ole2.h"
#include "mimeole.h"
+#include "wine/list.h"
#include "wine/debug.h"
#include "inetcomm_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(inetcomm);
+typedef struct
+{
+ LPCSTR name;
+ DWORD id;
+ DWORD flags; /* MIMEPROPFLAGS */
+ VARTYPE default_vt;
+} property_t;
+
+typedef struct
+{
+ struct list entry;
+ property_t prop;
+} property_list_entry_t;
+
+static const property_t default_props[] =
+{
+ {"References", PID_HDR_REFS, 0, VT_LPSTR},
+ {"Subject", PID_HDR_SUBJECT, 0, VT_LPSTR},
+ {"From", PID_HDR_FROM, MPF_ADDRESS, VT_LPSTR},
+ {"Message-ID", PID_HDR_MESSAGEID, 0, VT_LPSTR},
+ {"Return-Path", PID_HDR_RETURNPATH, MPF_ADDRESS, VT_LPSTR},
+ {"Date", PID_HDR_DATE, 0, VT_LPSTR},
+ {"Received", PID_HDR_RECEIVED, 0, VT_LPSTR},
+ {"Reply-To", PID_HDR_REPLYTO, MPF_ADDRESS, VT_LPSTR},
+ {"X-Mailer", PID_HDR_XMAILER, 0, VT_LPSTR},
+ {"Bcc", PID_HDR_BCC, MPF_ADDRESS, VT_LPSTR},
+ {"MIME-Version", PID_HDR_MIMEVER, MPF_MIME, VT_LPSTR},
+ {"Content-Type", PID_HDR_CNTTYPE, MPF_MIME | MPF_HASPARAMS, VT_LPSTR},
+ {"Content-Transfer-Encoding", PID_HDR_CNTXFER, MPF_MIME, VT_LPSTR},
+ {"Content-ID", PID_HDR_CNTID, MPF_MIME, VT_LPSTR},
+ {"Content-Disposition", PID_HDR_CNTDISP, MPF_MIME, VT_LPSTR},
+ {"To", PID_HDR_TO, MPF_ADDRESS, VT_LPSTR},
+ {"Cc", PID_HDR_CC, MPF_ADDRESS, VT_LPSTR},
+ {"Sender", PID_HDR_SENDER, MPF_ADDRESS, VT_LPSTR},
+ {"In-Reply-To", PID_HDR_INREPLYTO, 0, VT_LPSTR},
+ {NULL, 0, 0, 0}
+};
+
+typedef struct
+{
+ struct list entry;
+ const property_t *prop;
+ PROPVARIANT value;
+} header_t;
+
typedef struct MimeBody
{
const IMimeBodyVtbl *lpVtbl;
LONG refs;
HBODY handle;
+
+ struct list headers;
+ struct list new_props; /* FIXME: This should be in a PropertySchema */
+ DWORD next_prop_id;
} MimeBody;
static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface )
@@ -50,6 +100,15 @@ static inline MimeBody *impl_from_IMimeBody( IMimeBody *iface )
return (MimeBody *)((char*)iface - FIELD_OFFSET(MimeBody, lpVtbl));
}
+static LPSTR strdupA(LPCSTR str)
+{
+ char *ret;
+ int len = strlen(str);
+ ret = HeapAlloc(GetProcessHeap(), 0, len + 1);
+ memcpy(ret, str, len + 1);
+ return ret;
+}
+
#define PARSER_BUF_SIZE 1024
/*****************************************************
@@ -117,18 +176,122 @@ fail:
return hr;
}
+static header_t *read_prop(MimeBody *body, char **ptr)
+{
+ char *colon = strchr(*ptr, ':');
+ const property_t *prop;
+ header_t *ret;
+
+ if(!colon) return NULL;
+
+ *colon = '\0';
+
+ for(prop = default_props; prop->name; prop++)
+ {
+ if(!strcasecmp(*ptr, prop->name))
+ {
+ TRACE("%s: found match with default property id %d\n", *ptr, prop->id);
+ break;
+ }
+ }
+
+ if(!prop->name)
+ {
+ property_list_entry_t *prop_entry;
+ LIST_FOR_EACH_ENTRY(prop_entry, &body->new_props, property_list_entry_t, entry)
+ {
+ if(!strcasecmp(*ptr, prop_entry->prop.name))
+ {
+ TRACE("%s: found match with already added new property id %d\n", *ptr, prop_entry->prop.id);
+ prop = &prop_entry->prop;
+ break;
+ }
+ }
+ if(!prop->name)
+ {
+ prop_entry = HeapAlloc(GetProcessHeap(), 0, sizeof(*prop_entry));
+ prop_entry->prop.name = strdupA(*ptr);
+ prop_entry->prop.id = body->next_prop_id++;
+ prop_entry->prop.flags = 0;
+ prop_entry->prop.default_vt = VT_LPSTR;
+ list_add_tail(&body->new_props, &prop_entry->entry);
+ prop = &prop_entry->prop;
+ TRACE("%s: allocating new prop id %d\n", *ptr, prop_entry->prop.id);
+ }
+ }
+
+ ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret));
+ ret->prop = prop;
+ PropVariantInit(&ret->value);
+ *ptr = colon + 1;
+
+ return ret;
+}
+
+static void read_value(header_t *header, char **cur)
+{
+ char *end = *cur, *value;
+ DWORD len;
+
+ do {
+ end = strstr(end, "\r\n");
+ end += 2;
+ } while(*end == ' ' || *end == '\t');
+
+ len = end - *cur;
+ value = HeapAlloc(GetProcessHeap(), 0, len + 1);
+ memcpy(value, *cur, len);
+ value[len] = '\0';
+
+ header->value.vt = VT_LPSTR;
+ header->value.pszVal = value;
+
+ *cur = end;
+}
+
static HRESULT parse_headers(MimeBody *body, IStream *stm)
{
- char *header_buf;
+ char *header_buf, *cur_header_ptr;
HRESULT hr;
+ header_t *header;
hr = copy_headers_to_buf(stm, &header_buf);
if(FAILED(hr)) return hr;
+ cur_header_ptr = header_buf;
+ while((header = read_prop(body, &cur_header_ptr)))
+ {
+ read_value(header, &cur_header_ptr);
+ list_add_tail(&body->headers, &header->entry);
+ }
+
HeapFree(GetProcessHeap(), 0, header_buf);
return hr;
}
+static void empty_header_list(struct list *list)
+{
+ header_t *header, *cursor2;
+
+ LIST_FOR_EACH_ENTRY_SAFE(header, cursor2, list, header_t, entry)
+ {
+ list_remove(&header->entry);
+ PropVariantClear(&header->value);
+ HeapFree(GetProcessHeap(), 0, header);
+ }
+}
+
+static void empty_new_prop_list(struct list *list)
+{
+ property_list_entry_t *prop, *cursor2;
+
+ LIST_FOR_EACH_ENTRY_SAFE(prop, cursor2, list, property_list_entry_t, entry)
+ {
+ list_remove(&prop->entry);
+ HeapFree(GetProcessHeap(), 0, (char *)prop->prop.name);
+ HeapFree(GetProcessHeap(), 0, prop);
+ }
+}
static HRESULT WINAPI MimeBody_QueryInterface(IMimeBody* iface,
REFIID riid,
@@ -174,6 +337,9 @@ static ULONG WINAPI MimeBody_Release(IMimeBody* iface)
refs = InterlockedDecrement(&This->refs);
if (!refs)
{
+ empty_header_list(&This->headers);
+ empty_new_prop_list(&This->new_props);
+
HeapFree(GetProcessHeap(), 0, This);
}
@@ -582,6 +748,8 @@ static IMimeBodyVtbl body_vtbl =
MimeBody_GetHandle
};
+#define FIRST_CUSTOM_PROP_ID 0x100
+
HRESULT MimeBody_create(IUnknown *outer, void **obj)
{
MimeBody *This;
@@ -596,6 +764,9 @@ HRESULT MimeBody_create(IUnknown *outer, void **obj)
This->lpVtbl = &body_vtbl;
This->refs = 1;
This->handle = NULL;
+ list_init(&This->headers);
+ list_init(&This->new_props);
+ This->next_prop_id = FIRST_CUSTOM_PROP_ID;
*obj = (IMimeBody *)&This->lpVtbl;
return S_OK;
More information about the wine-cvs
mailing list