Module: wine Branch: master Commit: 589c213890f2ae749359ab5d7016d9c579ea1445 URL: http://source.winehq.org/git/wine.git/?a=commit;h=589c213890f2ae749359ab5d70...
Author: Jacek Caban jacek@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; } }