Jacek Caban : mshtml: Properly handle upload streams containing headers.

Alexandre Julliard julliard at winehq.org
Tue Apr 5 11:23:32 CDT 2011


Module: wine
Branch: master
Commit: 589c213890f2ae749359ab5d7016d9c579ea1445
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=589c213890f2ae749359ab5d7016d9c579ea1445

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Tue Apr  5 15:23:25 2011 +0200

mshtml: Properly handle upload streams containing headers.

---

 dlls/mshtml/mshtml_private.h |    3 +-
 dlls/mshtml/navigate.c       |  125 +++++++++++++++++++++++++++++------------
 dlls/mshtml/nsio.c           |    5 +-
 3 files changed, 94 insertions(+), 39 deletions(-)

diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h
index a449b18..44b6b1d 100644
--- a/dlls/mshtml/mshtml_private.h
+++ b/dlls/mshtml/mshtml_private.h
@@ -500,6 +500,7 @@ typedef struct {
 
     nsWineURI *uri;
     nsIInputStream *post_data_stream;
+    BOOL post_data_contains_headers;
     nsILoadGroup *load_group;
     nsIInterfaceRequestor *notif_callback;
     nsISupports *owner;
@@ -687,7 +688,7 @@ HRESULT nsuri_to_url(LPCWSTR,BOOL,BSTR*);
 HRESULT create_doc_uri(HTMLWindow*,WCHAR*,nsWineURI**);
 HRESULT load_nsuri(HTMLWindow*,nsWineURI*,nsChannelBSC*,DWORD);
 
-HRESULT hlink_frame_navigate(HTMLDocument*,LPCWSTR,nsIInputStream*,DWORD,BOOL*);
+HRESULT hlink_frame_navigate(HTMLDocument*,LPCWSTR,nsChannel*,DWORD,BOOL*);
 HRESULT navigate_url(HTMLWindow*,const WCHAR*,const WCHAR*);
 HRESULT set_frame_doc(HTMLFrameBase*,nsIDOMDocument*);
 HRESULT set_moniker(HTMLDocument*,IMoniker*,IBindCtx*,nsChannelBSC*,BOOL);
diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c
index db624d8..446b57b 100644
--- a/dlls/mshtml/navigate.c
+++ b/dlls/mshtml/navigate.c
@@ -684,33 +684,6 @@ static HRESULT parse_headers(const WCHAR *headers, struct list *headers_list)
     return S_OK;
 }
 
-static HRESULT read_post_data_stream(nsIInputStream *stream, HGLOBAL *post_data,
-        ULONG *post_data_len)
-{
-    PRUint32 data_len = 0, available = 0;
-    char *data;
-    nsresult nsres;
-
-    nsres =  nsIInputStream_Available(stream, &available);
-    if(NS_FAILED(nsres))
-        return E_FAIL;
-
-    data = GlobalAlloc(0, available+1);
-    if(!data)
-        return E_OUTOFMEMORY;
-
-    nsres = nsIInputStream_Read(stream, data, available, &data_len);
-    if(NS_FAILED(nsres)) {
-        GlobalFree(data);
-        return E_FAIL;
-    }
-
-    data[data_len] = 0;
-    *post_data = data;
-    *post_data_len = data_len;
-    return S_OK;
-}
-
 HRESULT start_binding(HTMLWindow *window, HTMLDocumentNode *doc, BSCallback *bscallback, IBindCtx *bctx)
 {
     IStream *str = NULL;
@@ -899,6 +872,90 @@ struct nsChannelBSC {
     nsProtocolStream *nsstream;
 };
 
+static HRESULT read_post_data_stream(nsChannelBSC *This, nsChannel *nschannel)
+{
+    PRUint32 data_len = 0, available = 0;
+    char *data, *post_data;
+    nsresult nsres;
+    HRESULT hres = S_OK;
+
+    if(!nschannel->post_data_stream)
+        return S_OK;
+
+    nsres =  nsIInputStream_Available(nschannel->post_data_stream, &available);
+    if(NS_FAILED(nsres))
+        return E_FAIL;
+
+    post_data = data = GlobalAlloc(0, available+1);
+    if(!data)
+        return E_OUTOFMEMORY;
+
+    nsres = nsIInputStream_Read(nschannel->post_data_stream, data, available, &data_len);
+    if(NS_FAILED(nsres)) {
+        GlobalFree(data);
+        return E_FAIL;
+    }
+
+    data[data_len++] = 0;
+
+    if(nschannel->post_data_contains_headers) {
+        if(data[0] == '\r' && data[1] == '\n') {
+            post_data = data+2;
+            data_len -= 2;
+        }else {
+            WCHAR *headers;
+            DWORD size;
+
+            post_data = strstr(data, "\r\n\r\n");
+            if(post_data)
+                post_data += 4;
+            else
+                post_data = data+data_len;
+
+            data_len -= post_data-data;
+
+            size = MultiByteToWideChar(CP_ACP, 0, data, post_data-data, NULL, 0);
+            headers = heap_alloc((size+1)*sizeof(WCHAR));
+            if(headers) {
+                MultiByteToWideChar(CP_ACP, 0, data, post_data-data, headers, size);
+                headers[size] = 0;
+                hres = parse_headers(headers , &nschannel->request_headers);
+                if(SUCCEEDED(hres))
+                    This->bsc.headers = headers;
+                else
+                    heap_free(headers);
+            }else {
+                hres = E_OUTOFMEMORY;
+            }
+        }
+    }
+
+    if(FAILED(hres)) {
+        GlobalFree(data);
+        return hres;
+    }
+
+    if(!data_len) {
+        GlobalFree(data);
+        post_data = NULL;
+    }else if(post_data != data) {
+        char *new_data;
+
+        new_data = GlobalAlloc(0, data_len);
+        if(new_data)
+            memcpy(new_data, post_data, data_len);
+        GlobalFree(data);
+        if(!new_data)
+            return E_OUTOFMEMORY;
+        post_data = new_data;
+    }
+
+    This->bsc.post_data = post_data;
+    This->bsc.post_data_len = data_len;
+    TRACE("post_data = %s\n", debugstr_a(This->bsc.post_data));
+    return S_OK;
+}
+
 static HRESULT on_start_nsrequest(nsChannelBSC *This)
 {
     nsresult nsres;
@@ -1068,12 +1125,9 @@ static HRESULT nsChannelBSC_init_bindinfo(BSCallback *bsc)
     HRESULT hres;
 
     if(This->nschannel && This->nschannel->post_data_stream) {
-        hres = read_post_data_stream(This->nschannel->post_data_stream,
-                &This->bsc.post_data, &This->bsc.post_data_len);
+        hres = read_post_data_stream(This, This->nschannel);
         if(FAILED(hres))
             return hres;
-
-        TRACE("post_data = %s\n", debugstr_an(This->bsc.post_data, This->bsc.post_data_len));
     }
 
     return S_OK;
@@ -1512,8 +1566,7 @@ void channelbsc_set_channel(nsChannelBSC *This, nsChannel *channel, nsIStreamLis
     }
 }
 
-HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url,
-        nsIInputStream *post_data_stream, DWORD hlnf, BOOL *cancel)
+HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url, nsChannel *nschannel, DWORD hlnf, BOOL *cancel)
 {
     IHlinkFrame *hlink_frame;
     nsChannelBSC *callback;
@@ -1542,10 +1595,8 @@ HRESULT hlink_frame_navigate(HTMLDocument *doc, LPCWSTR url,
         return hres;
     }
 
-    if(post_data_stream) {
-        read_post_data_stream(post_data_stream, &callback->bsc.post_data, &callback->bsc.post_data_len);
-        TRACE("post_data = %s\n", debugstr_an(callback->bsc.post_data, callback->bsc.post_data_len));
-    }
+    if(nschannel)
+        read_post_data_stream(callback, nschannel);
 
     hres = CreateAsyncBindCtx(0, &callback->bsc.IBindStatusCallback_iface, NULL, &bindctx);
     if(SUCCEEDED(hres))
diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c
index b2dab98..b25aae0 100644
--- a/dlls/mshtml/nsio.c
+++ b/dlls/mshtml/nsio.c
@@ -149,7 +149,7 @@ static BOOL before_async_open(nsChannel *channel, NSContainer *container)
     if(!hlnf && !exec_shldocvw_67(doc, channel->uri->wine_url))
         return FALSE;
 
-    hres = hlink_frame_navigate(&doc->basedoc, channel->uri->wine_url, channel->post_data_stream, hlnf, &cancel);
+    hres = hlink_frame_navigate(&doc->basedoc, channel->uri->wine_url, channel, hlnf, &cancel);
     return FAILED(hres) || cancel;
 }
 
@@ -1304,6 +1304,8 @@ static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
 
     TRACE("(%p)->(%p %s %d)\n", This, aStream, debugstr_nsacstr(aContentType), aContentLength);
 
+    This->post_data_contains_headers = TRUE;
+
     if(aContentType) {
         nsACString_GetData(aContentType, &content_type);
         if(*content_type) {
@@ -1316,6 +1318,7 @@ static nsresult NSAPI nsUploadChannel_SetUploadStream(nsIUploadChannel *iface,
             set_http_header(&This->request_headers, content_typeW,
                     sizeof(content_typeW)/sizeof(WCHAR), ct, strlenW(ct));
             heap_free(ct);
+            This->post_data_contains_headers = FALSE;
         }
     }
 




More information about the wine-cvs mailing list