Andrew Eikum : mshtml: Implement HTTPChannel::GetResponseHeader.

Alexandre Julliard julliard at winehq.org
Mon Apr 5 11:22:59 CDT 2010


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

Author: Andrew Eikum <aeikum at 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;




More information about the wine-cvs mailing list