mirror of
https://github.com/reactos/wine.git
synced 2025-02-24 15:01:41 +00:00
msxml3: Implement response headers access methods.
This commit is contained in:
parent
e736c3e983
commit
02414775e9
@ -56,7 +56,7 @@ static const WCHAR crlfW[] = {'\r','\n',0};
|
||||
|
||||
typedef struct BindStatusCallback BindStatusCallback;
|
||||
|
||||
struct reqheader
|
||||
struct httpheader
|
||||
{
|
||||
struct list entry;
|
||||
BSTR header;
|
||||
@ -80,6 +80,9 @@ typedef struct
|
||||
struct list reqheaders;
|
||||
/* cached resulting custom request headers string length in WCHARs */
|
||||
LONG reqheader_size;
|
||||
/* response headers */
|
||||
struct list respheaders;
|
||||
BSTR raw_respheaders;
|
||||
|
||||
/* credentials */
|
||||
BSTR user;
|
||||
@ -126,6 +129,22 @@ static void httprequest_setreadystate(httprequest *This, READYSTATE state)
|
||||
}
|
||||
}
|
||||
|
||||
static void free_response_headers(httprequest *This)
|
||||
{
|
||||
struct httpheader *header, *header2;
|
||||
|
||||
LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->respheaders, struct httpheader, entry)
|
||||
{
|
||||
list_remove(&header->entry);
|
||||
SysFreeString(header->header);
|
||||
SysFreeString(header->value);
|
||||
heap_free(header);
|
||||
}
|
||||
|
||||
SysFreeString(This->raw_respheaders);
|
||||
This->raw_respheaders = NULL;
|
||||
}
|
||||
|
||||
struct BindStatusCallback
|
||||
{
|
||||
IBindStatusCallback IBindStatusCallback_iface;
|
||||
@ -386,7 +405,7 @@ static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *ifac
|
||||
LPCWSTR url, LPCWSTR headers, DWORD reserved, LPWSTR *add_headers)
|
||||
{
|
||||
BindStatusCallback *This = impl_from_IHttpNegotiate(iface);
|
||||
const struct reqheader *entry;
|
||||
const struct httpheader *entry;
|
||||
WCHAR *buff, *ptr;
|
||||
|
||||
TRACE("(%p)->(%s %s %d %p)\n", This, debugstr_w(url), debugstr_w(headers), reserved, add_headers);
|
||||
@ -399,7 +418,7 @@ static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *ifac
|
||||
if (!buff) return E_OUTOFMEMORY;
|
||||
|
||||
ptr = buff;
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct reqheader, entry)
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->request->reqheaders, struct httpheader, entry)
|
||||
{
|
||||
lstrcpyW(ptr, entry->header);
|
||||
ptr += SysStringLen(entry->header);
|
||||
@ -419,6 +438,37 @@ static HRESULT WINAPI BSCHttpNegotiate_BeginningTransaction(IHttpNegotiate *ifac
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static void add_response_header(httprequest *This, const WCHAR *data, int len)
|
||||
{
|
||||
struct httpheader *entry;
|
||||
const WCHAR *ptr = data;
|
||||
BSTR header, value;
|
||||
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == ':')
|
||||
{
|
||||
header = SysAllocStringLen(data, ptr-data);
|
||||
/* skip leading spaces for a value */
|
||||
while (*++ptr == ' ')
|
||||
;
|
||||
value = SysAllocStringLen(ptr, len-(ptr-data));
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
if (!*ptr) return;
|
||||
|
||||
/* new header */
|
||||
TRACE("got header %s:%s\n", debugstr_w(header), debugstr_w(value));
|
||||
|
||||
entry = heap_alloc(sizeof(*header));
|
||||
entry->header = header;
|
||||
entry->value = value;
|
||||
list_add_head(&This->respheaders, &entry->entry);
|
||||
}
|
||||
|
||||
static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD code,
|
||||
LPCWSTR resp_headers, LPCWSTR req_headers, LPWSTR *add_reqheaders)
|
||||
{
|
||||
@ -428,6 +478,28 @@ static HRESULT WINAPI BSCHttpNegotiate_OnResponse(IHttpNegotiate *iface, DWORD c
|
||||
debugstr_w(req_headers), add_reqheaders);
|
||||
|
||||
This->request->status = code;
|
||||
/* store headers */
|
||||
free_response_headers(This->request);
|
||||
if (resp_headers)
|
||||
{
|
||||
const WCHAR *ptr, *line;
|
||||
|
||||
ptr = line = resp_headers;
|
||||
|
||||
/* skip status line */
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == '\r' && *(ptr+1) == '\n')
|
||||
{
|
||||
line = ++ptr+1;
|
||||
break;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
|
||||
/* store as unparsed string for now */
|
||||
This->request->raw_respheaders = SysAllocString(line);
|
||||
}
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
@ -563,7 +635,7 @@ static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
|
||||
|
||||
if ( ref == 0 )
|
||||
{
|
||||
struct reqheader *header, *header2;
|
||||
struct httpheader *header, *header2;
|
||||
|
||||
if (This->site)
|
||||
IUnknown_Release( This->site );
|
||||
@ -573,13 +645,15 @@ static ULONG WINAPI httprequest_Release(IXMLHTTPRequest *iface)
|
||||
SysFreeString(This->password);
|
||||
|
||||
/* request headers */
|
||||
LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct reqheader, entry)
|
||||
LIST_FOR_EACH_ENTRY_SAFE(header, header2, &This->reqheaders, struct httpheader, entry)
|
||||
{
|
||||
list_remove(&header->entry);
|
||||
SysFreeString(header->header);
|
||||
SysFreeString(header->value);
|
||||
heap_free(header);
|
||||
}
|
||||
/* response headers */
|
||||
free_response_headers(This);
|
||||
|
||||
/* detach callback object */
|
||||
BindStatusCallback_Detach(This->bsc);
|
||||
@ -719,7 +793,7 @@ static HRESULT WINAPI httprequest_open(IXMLHTTPRequest *iface, BSTR method, BSTR
|
||||
static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR header, BSTR value)
|
||||
{
|
||||
httprequest *This = impl_from_IXMLHTTPRequest( iface );
|
||||
struct reqheader *entry;
|
||||
struct httpheader *entry;
|
||||
|
||||
TRACE("(%p)->(%s %s)\n", This, debugstr_w(header), debugstr_w(value));
|
||||
|
||||
@ -728,7 +802,7 @@ static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR
|
||||
if (!value) return E_INVALIDARG;
|
||||
|
||||
/* replace existing header value if already added */
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct reqheader, entry)
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->reqheaders, struct httpheader, entry)
|
||||
{
|
||||
if (lstrcmpW(entry->header, header) == 0)
|
||||
{
|
||||
@ -760,22 +834,56 @@ static HRESULT WINAPI httprequest_setRequestHeader(IXMLHTTPRequest *iface, BSTR
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR bstrHeader, BSTR *pbstrValue)
|
||||
static HRESULT WINAPI httprequest_getResponseHeader(IXMLHTTPRequest *iface, BSTR header, BSTR *value)
|
||||
{
|
||||
httprequest *This = impl_from_IXMLHTTPRequest( iface );
|
||||
struct httpheader *entry;
|
||||
|
||||
FIXME("stub (%p) %s %p\n", This, debugstr_w(bstrHeader), pbstrValue);
|
||||
TRACE("(%p)->(%s %p)\n", This, debugstr_w(header), value);
|
||||
|
||||
return E_NOTIMPL;
|
||||
if (!header || !value) return E_INVALIDARG;
|
||||
|
||||
if (This->raw_respheaders && list_empty(&This->respheaders))
|
||||
{
|
||||
WCHAR *ptr, *line;
|
||||
|
||||
ptr = line = This->raw_respheaders;
|
||||
while (*ptr)
|
||||
{
|
||||
if (*ptr == '\r' && *(ptr+1) == '\n')
|
||||
{
|
||||
add_response_header(This, line, ptr-line);
|
||||
ptr++; line = ++ptr;
|
||||
continue;
|
||||
}
|
||||
ptr++;
|
||||
}
|
||||
}
|
||||
|
||||
LIST_FOR_EACH_ENTRY(entry, &This->respheaders, struct httpheader, entry)
|
||||
{
|
||||
if (!strcmpiW(entry->header, header))
|
||||
{
|
||||
*value = SysAllocString(entry->value);
|
||||
TRACE("header value %s\n", debugstr_w(*value));
|
||||
return S_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return S_FALSE;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *pbstrHeaders)
|
||||
static HRESULT WINAPI httprequest_getAllResponseHeaders(IXMLHTTPRequest *iface, BSTR *respheaders)
|
||||
{
|
||||
httprequest *This = impl_from_IXMLHTTPRequest( iface );
|
||||
|
||||
FIXME("stub (%p) %p\n", This, pbstrHeaders);
|
||||
TRACE("(%p)->(%p)\n", This, respheaders);
|
||||
|
||||
return E_NOTIMPL;
|
||||
if (!respheaders) return E_INVALIDARG;
|
||||
|
||||
*respheaders = SysAllocString(This->raw_respheaders);
|
||||
|
||||
return S_OK;
|
||||
}
|
||||
|
||||
static HRESULT WINAPI httprequest_send(IXMLHTTPRequest *iface, VARIANT body)
|
||||
@ -1189,6 +1297,9 @@ HRESULT XMLHTTPRequest_create(IUnknown *pUnkOuter, void **ppObj)
|
||||
req->status = 0;
|
||||
req->reqheader_size = 0;
|
||||
list_init(&req->reqheaders);
|
||||
list_init(&req->respheaders);
|
||||
req->raw_respheaders = NULL;
|
||||
|
||||
req->site = NULL;
|
||||
req->safeopt = 0;
|
||||
|
||||
|
@ -4690,7 +4690,7 @@ static void test_XMLHTTP(void)
|
||||
IXMLHttpRequest *xhr;
|
||||
IObjectSafety *safety;
|
||||
IObjectWithSite *obj_site, *obj_site2;
|
||||
BSTR bstrResponse, url;
|
||||
BSTR bstrResponse, url, str, str1;
|
||||
VARIANT dummy;
|
||||
VARIANT async;
|
||||
VARIANT varbody;
|
||||
@ -4840,6 +4840,29 @@ static void test_XMLHTTP(void)
|
||||
}
|
||||
EXPECT_HR(hr, S_OK);
|
||||
|
||||
/* response headers */
|
||||
hr = IXMLHttpRequest_getAllResponseHeaders(xhr, NULL);
|
||||
EXPECT_HR(hr, E_INVALIDARG);
|
||||
hr = IXMLHttpRequest_getAllResponseHeaders(xhr, &str);
|
||||
EXPECT_HR(hr, S_OK);
|
||||
/* status line is stripped already */
|
||||
ok(memcmp(str, _bstr_("HTTP"), 4*sizeof(WCHAR)), "got response headers %s\n", wine_dbgstr_w(str));
|
||||
ok(*str, "got empty headers\n");
|
||||
hr = IXMLHttpRequest_getAllResponseHeaders(xhr, &str1);
|
||||
EXPECT_HR(hr, S_OK);
|
||||
ok(str1 != str, "got %p\n", str1);
|
||||
SysFreeString(str1);
|
||||
SysFreeString(str);
|
||||
|
||||
hr = IXMLHttpRequest_getResponseHeader(xhr, NULL, NULL);
|
||||
EXPECT_HR(hr, E_INVALIDARG);
|
||||
hr = IXMLHttpRequest_getResponseHeader(xhr, _bstr_("Date"), NULL);
|
||||
EXPECT_HR(hr, E_INVALIDARG);
|
||||
hr = IXMLHttpRequest_getResponseHeader(xhr, _bstr_("Date"), &str);
|
||||
EXPECT_HR(hr, S_OK);
|
||||
ok(*str != ' ', "got leading space in header %s\n", wine_dbgstr_w(str));
|
||||
SysFreeString(str);
|
||||
|
||||
/* status code after ::send() */
|
||||
status = 0xdeadbeef;
|
||||
hr = IXMLHttpRequest_get_status(xhr, &status);
|
||||
|
Loading…
x
Reference in New Issue
Block a user