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, &param_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