Huw Davies : inetcomm: Create a body tree for multipart messages.
Alexandre Julliard
julliard at winehq.org
Wed Feb 13 10:40:05 CST 2008
Module: wine
Branch: master
Commit: db4881cfb627350dad34dd0a2d2be166c5917b34
URL: http://source.winehq.org/git/wine.git/?a=commit;h=db4881cfb627350dad34dd0a2d2be166c5917b34
Author: Huw Davies <huw at codeweavers.com>
Date: Tue Feb 12 11:36:31 2008 +0000
inetcomm: Create a body tree for multipart messages.
---
dlls/inetcomm/mimeole.c | 133 ++++++++++++++++++++++++++++++++++++++++++++++-
1 files changed, 132 insertions(+), 1 deletions(-)
diff --git a/dlls/inetcomm/mimeole.c b/dlls/inetcomm/mimeole.c
index 707a1e0..bdce35b 100644
--- a/dlls/inetcomm/mimeole.c
+++ b/dlls/inetcomm/mimeole.c
@@ -1446,6 +1446,97 @@ static body_t *new_body_entry(IMimeBody *mime_body, HBODY hbody, body_t *parent)
return body;
}
+typedef struct
+{
+ struct list entry;
+ BODYOFFSETS offsets;
+} offset_entry_t;
+
+static HRESULT create_body_offset_list(IStream *stm, const char *boundary, struct list *body_offsets)
+{
+ HRESULT hr;
+ DWORD read;
+ int boundary_len = strlen(boundary);
+ char *buf, *nl_boundary, *ptr, *overlap;
+ DWORD total_read = 0;
+ DWORD start = 0, overlap_no;
+ offset_entry_t *cur_body = NULL;
+ ULARGE_INTEGER cur;
+ LARGE_INTEGER zero;
+
+ list_init(body_offsets);
+ nl_boundary = HeapAlloc(GetProcessHeap(), 0, 4 + boundary_len + 1);
+ memcpy(nl_boundary, "\r\n--", 4);
+ memcpy(nl_boundary + 4, boundary, boundary_len + 1);
+
+ overlap_no = boundary_len + 5;
+
+ overlap = buf = HeapAlloc(GetProcessHeap(), 0, overlap_no + PARSER_BUF_SIZE + 1);
+
+ zero.QuadPart = 0;
+ hr = IStream_Seek(stm, zero, STREAM_SEEK_CUR, &cur);
+ start = cur.LowPart;
+
+ do {
+ hr = IStream_Read(stm, overlap, PARSER_BUF_SIZE, &read);
+ if(FAILED(hr)) goto end;
+ if(read == 0) break;
+ total_read += read;
+ overlap[read] = '\0';
+
+ ptr = buf;
+ do {
+ ptr = strstr(ptr, nl_boundary);
+ if(ptr)
+ {
+ DWORD boundary_start = start + ptr - buf;
+ char *end = ptr + boundary_len + 4;
+
+ if(*end == '\0' || *(end + 1) == '\0')
+ break;
+
+ if(*end == '\r' && *(end + 1) == '\n')
+ {
+ if(cur_body)
+ {
+ cur_body->offsets.cbBodyEnd = boundary_start;
+ list_add_tail(body_offsets, &cur_body->entry);
+ }
+ cur_body = HeapAlloc(GetProcessHeap(), 0, sizeof(*cur_body));
+ cur_body->offsets.cbBoundaryStart = boundary_start + 2; /* doesn't including the leading \r\n */
+ cur_body->offsets.cbHeaderStart = boundary_start + boundary_len + 6;
+ }
+ else if(*end == '-' && *(end + 1) == '-')
+ {
+ if(cur_body)
+ {
+ cur_body->offsets.cbBodyEnd = boundary_start;
+ list_add_tail(body_offsets, &cur_body->entry);
+ goto end;
+ }
+ }
+ ptr = end + 2;
+ }
+ } while(ptr);
+
+ if(overlap == buf) /* 1st iteration */
+ {
+ memcpy(buf, buf + PARSER_BUF_SIZE - overlap_no, overlap_no);
+ overlap = buf + overlap_no;
+ start += read - overlap_no;
+ }
+ else
+ {
+ memcpy(buf, buf + PARSER_BUF_SIZE, overlap_no);
+ start += read;
+ }
+ } while(1);
+
+end:
+ HeapFree(GetProcessHeap(), 0, buf);
+ return hr;
+}
+
static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *offset, body_t *parent)
{
IMimeBody *mime_body;
@@ -1458,11 +1549,51 @@ static body_t *create_sub_body(MimeMessage *msg, IStream *pStm, BODYOFFSETS *off
IMimeBody_Load(mime_body, pStm);
zero.QuadPart = 0;
hr = IStream_Seek(pStm, zero, STREAM_SEEK_CUR, &cur);
- offset->cbBodyStart = cur.LowPart;
+ offset->cbBodyStart = cur.LowPart + offset->cbHeaderStart;
+ if(parent) MimeBody_set_offsets(impl_from_IMimeBody(mime_body), offset);
IMimeBody_SetData(mime_body, IET_BINARY, NULL, NULL, &IID_IStream, pStm);
body = new_body_entry(mime_body, msg->next_hbody, parent);
msg->next_hbody = (HBODY)((DWORD)msg->next_hbody + 1);
+ if(IMimeBody_IsContentType(mime_body, "multipart", NULL) == S_OK)
+ {
+ MIMEPARAMINFO *param_info;
+ ULONG count, i;
+ IMimeAllocator *alloc;
+
+ hr = IMimeBody_GetParameters(mime_body, "Content-Type", &count, ¶m_info);
+ if(hr != S_OK || count == 0) return body;
+
+ MimeOleGetAllocator(&alloc);
+
+ for(i = 0; i < count; i++)
+ {
+ if(!strcasecmp(param_info[i].pszName, "boundary"))
+ {
+ struct list offset_list;
+ offset_entry_t *cur, *cursor2;
+ hr = create_body_offset_list(pStm, param_info[i].pszData, &offset_list);
+ LIST_FOR_EACH_ENTRY_SAFE(cur, cursor2, &offset_list, offset_entry_t, entry)
+ {
+ body_t *sub_body;
+ IStream *sub_stream;
+ ULARGE_INTEGER start, length;
+
+ start.LowPart = cur->offsets.cbHeaderStart;
+ length.LowPart = cur->offsets.cbBodyEnd - cur->offsets.cbHeaderStart;
+ create_sub_stream(pStm, start, length, &sub_stream);
+ sub_body = create_sub_body(msg, sub_stream, &cur->offsets, body);
+ IStream_Release(sub_stream);
+ list_add_tail(&body->children, &sub_body->entry);
+ list_remove(&cur->entry);
+ HeapFree(GetProcessHeap(), 0, cur);
+ }
+ break;
+ }
+ }
+ IMimeAllocator_FreeParamInfoArray(alloc, count, param_info, TRUE);
+ IMimeAllocator_Release(alloc);
+ }
return body;
}
More information about the wine-cvs
mailing list