Module: wine Branch: master Commit: cf2a3af6f0e9f0d7a7d2eee903f58d78eacb7c4e URL: http://source.winehq.org/git/wine.git/?a=commit;h=cf2a3af6f0e9f0d7a7d2eee903...
Author: Andrew Eikum aeikum@codeweavers.com Date: Fri Apr 2 17:31:45 2010 -0500
mshtml: Implement HTTPChannel::GetResponseHeader.
---
dlls/mshtml/mshtml_private.h | 7 ++++ dlls/mshtml/navigate.c | 70 +++++++++++++++++++++++++++++++++++++++-- dlls/mshtml/nsio.c | 39 ++++++++++++++++++++++- 3 files changed, 110 insertions(+), 6 deletions(-)
diff --git a/dlls/mshtml/mshtml_private.h b/dlls/mshtml/mshtml_private.h index b19dbfa..e378f26 100644 --- a/dlls/mshtml/mshtml_private.h +++ b/dlls/mshtml/mshtml_private.h @@ -463,9 +463,16 @@ typedef struct { char *content_type; char *charset; PRUint32 response_status; + struct list response_headers; UINT url_scheme; } nsChannel;
+struct ResponseHeader { + struct list entry; + WCHAR *header; + WCHAR *data; +}; + typedef struct { HRESULT (*qi)(HTMLDOMNode*,REFIID,void**); void (*destructor)(HTMLDOMNode*); diff --git a/dlls/mshtml/navigate.c b/dlls/mshtml/navigate.c index cc2aeb3..7a77795 100644 --- a/dlls/mshtml/navigate.c +++ b/dlls/mshtml/navigate.c @@ -62,7 +62,7 @@ typedef struct { HRESULT (*stop_binding)(BSCallback*,HRESULT); HRESULT (*read_data)(BSCallback*,IStream*); HRESULT (*on_progress)(BSCallback*,ULONG,LPCWSTR); - HRESULT (*on_response)(BSCallback*,DWORD); + HRESULT (*on_response)(BSCallback*,DWORD,LPCWSTR); } BSCallbackVtbl;
struct BSCallback { @@ -493,7 +493,7 @@ static HRESULT WINAPI HttpNegotiate_OnResponse(IHttpNegotiate2 *iface, DWORD dwR TRACE("(%p)->(%d %s %s %p)\n", This, dwResponseCode, debugstr_w(szResponseHeaders), debugstr_w(szRequestHeaders), pszAdditionalRequestHeaders);
- return This->vtbl->on_response(This, dwResponseCode); + return This->vtbl->on_response(This, dwResponseCode, szResponseHeaders); }
static HRESULT WINAPI HttpNegotiate_GetRootSecurityId(IHttpNegotiate2 *iface, @@ -825,7 +825,8 @@ static HRESULT BufferBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCWSTR return S_OK; }
-static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code) +static HRESULT BufferBSC_on_response(BSCallback *bsc, DWORD response_code, + LPCWSTR response_headers) { return S_OK; } @@ -1099,11 +1100,72 @@ static HRESULT nsChannelBSC_on_progress(BSCallback *bsc, ULONG status_code, LPCW return S_OK; }
-static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code) +static HRESULT nsChannelBSC_on_response(BSCallback *bsc, DWORD response_code, + LPCWSTR response_headers) { nsChannelBSC *This = NSCHANNELBSC_THIS(bsc);
This->nschannel->response_status = response_code; + + if(response_headers) { + const WCHAR *hdr_start, *hdr_end; + + hdr_start = strchrW(response_headers, '\r'); + while(hdr_start) { + const WCHAR *colon; + struct ResponseHeader *new_header; + int len; + + hdr_start += 2; + hdr_end = strchrW(hdr_start, '\r'); + if(!hdr_end) { + WARN("Header doesn't end with CRLF: %s\n", wine_dbgstr_w(hdr_start)); + break; + } + if(hdr_end == hdr_start) + break; + + for(colon = hdr_start; *colon != ':' && colon != hdr_end; ++colon); + if(*colon != ':') { + WARN("Header missing colon: %s\n", wine_dbgstr_w(hdr_start)); + hdr_start = strchrW(hdr_start, '\r'); + continue; + } + + new_header = heap_alloc(sizeof(struct ResponseHeader)); + if(!new_header) + return E_OUTOFMEMORY; + + len = colon - hdr_start; + new_header->header = heap_alloc((len + 1) * sizeof(WCHAR)); + if(!new_header->header) { + heap_free(new_header); + return E_OUTOFMEMORY; + } + memcpy(new_header->header, hdr_start, len * sizeof(WCHAR)); + new_header->header[len] = 0; + + colon++; + while(*colon == ' ') + colon++; + + len = hdr_end - colon; + new_header->data = heap_alloc((len + 1) * sizeof(WCHAR)); + if(!new_header->data) { + heap_free(new_header->header); + heap_free(new_header); + return E_OUTOFMEMORY; + } + memcpy(new_header->data, colon, len * sizeof(WCHAR)); + new_header->data[len] = 0; + + list_add_head(&This->nschannel->response_headers, &new_header->entry); + TRACE("Adding header to list: (%s):(%s)\n", wine_dbgstr_w(new_header->header), wine_dbgstr_w(new_header->data)); + + hdr_start = strchrW(hdr_start, '\r'); + } + } + return S_OK; }
diff --git a/dlls/mshtml/nsio.c b/dlls/mshtml/nsio.c index 8967fa1..dc4f538 100644 --- a/dlls/mshtml/nsio.c +++ b/dlls/mshtml/nsio.c @@ -363,6 +363,8 @@ static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface) LONG ref = InterlockedDecrement(&This->ref);
if(!ref) { + struct ResponseHeader *header, *next_hdr; + nsIURI_Release(NSURI(This->uri)); if(This->owner) nsISupports_Release(This->owner); @@ -376,6 +378,14 @@ static nsrefcnt NSAPI nsChannel_Release(nsIHttpChannel *iface) nsIURI_Release(This->original_uri); heap_free(This->content_type); heap_free(This->charset); + + LIST_FOR_EACH_ENTRY_SAFE(header, next_hdr, &This->response_headers, struct ResponseHeader, entry) { + list_remove(&header->entry); + heap_free(header->header); + heap_free(header->data); + heap_free(header); + } + heap_free(This); }
@@ -1066,10 +1076,34 @@ static nsresult NSAPI nsChannel_GetResponseHeader(nsIHttpChannel *iface, const nsACString *header, nsACString *_retval) { nsChannel *This = NSCHANNEL_THIS(iface); + const char *header_str; + WCHAR *header_wstr; + struct ResponseHeader *this_header;
- FIXME("(%p)->(%p %p)\n", This, header, _retval); + nsACString_GetData(header, &header_str); + TRACE("(%p)->(%p(%s) %p)\n", This, header, header_str, _retval);
- return NS_ERROR_NOT_IMPLEMENTED; + header_wstr = heap_strdupAtoW(header_str); + if(!header_wstr) + return NS_ERROR_UNEXPECTED; + + LIST_FOR_EACH_ENTRY(this_header, &This->response_headers, struct ResponseHeader, entry) { + if(!strcmpW(this_header->header, header_wstr)) { + char *data = heap_strdupWtoA(this_header->data); + if(!data) { + heap_free(header_wstr); + return NS_ERROR_UNEXPECTED; + } + nsACString_SetData(_retval, data); + heap_free(data); + heap_free(header_wstr); + return NS_OK; + } + } + + heap_free(header_wstr); + + return NS_ERROR_NOT_AVAILABLE; }
static nsresult NSAPI nsChannel_SetResponseHeader(nsIHttpChannel *iface, @@ -2521,6 +2555,7 @@ static nsresult NSAPI nsIOService_NewChannelFromURI(nsIIOService *iface, nsIURI ret->lpIHttpChannelInternalVtbl = &nsHttpChannelInternalVtbl; ret->ref = 1; ret->uri = wine_uri; + list_init(&ret->response_headers);
nsIURI_AddRef(aURI); ret->original_uri = aURI;