From 31297b6a3b20a73be36978b6036846a035b3fd07 Mon Sep 17 00:00:00 2001 From: Huw Davies Date: Mon, 26 Nov 2007 12:01:52 +0000 Subject: [PATCH] inetcomm: Parse headers into a list. --- dlls/inetcomm/mimeole.c | 173 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 172 insertions(+), 1 deletion(-) diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c index 28460baaa47..5d335374556 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;