Fix HttpQueryInfo(HTTP_QUERY_RAW_HEADERS*) so that it returns the

actual headers received, not just reconstituting them from processed
data.
This commit is contained in:
Robert Shearman 2004-07-19 20:09:20 +00:00 committed by Alexandre Julliard
parent 95f067d3cd
commit dee8751ca8
2 changed files with 140 additions and 138 deletions

View File

@ -96,6 +96,66 @@ BOOL HTTP_InsertCustomHeader(LPWININETHTTPREQW lpwhr, LPHTTPHEADERW lpHdr);
INT HTTP_GetCustomHeaderIndex(LPWININETHTTPREQW lpwhr, LPCWSTR lpszField);
BOOL HTTP_DeleteCustomHeader(LPWININETHTTPREQW lpwhr, INT index);
/***********************************************************************
* HTTP_Tokenize (internal)
*
* Tokenize a string, allocating memory for the tokens.
*/
static LPWSTR * HTTP_Tokenize(LPCWSTR string, LPCWSTR token_string)
{
LPWSTR * token_array;
int tokens = 0;
int i;
LPCWSTR next_token;
/* empty string has no tokens */
if (*string)
tokens++;
/* count tokens */
for (i = 0; string[i]; i++)
if (!strncmpW(string+i, token_string, strlenW(token_string)))
{
int j;
tokens++;
/* we want to skip over separators, but not the null terminator */
for (j = 0; j < strlenW(token_string) - 1; j++)
if (!string[i+j])
break;
i += j;
}
/* add 1 for terminating NULL */
token_array = HeapAlloc(GetProcessHeap(), 0, (tokens+1) * sizeof(*token_array));
token_array[tokens] = NULL;
if (!tokens)
return token_array;
for (i = 0; i < tokens; i++)
{
int len;
next_token = strstrW(string, token_string);
if (!next_token) next_token = string+strlenW(string);
len = next_token - string;
token_array[i] = HeapAlloc(GetProcessHeap(), 0, (len+1)*sizeof(WCHAR));
memcpy(token_array[i], string, len*sizeof(WCHAR));
token_array[i][len] = '\0';
string = next_token+strlenW(token_string);
}
return token_array;
}
/***********************************************************************
* HTTP_FreeTokens (internal)
*
* Frees memory returned from HTTP_Tokenize.
*/
static void HTTP_FreeTokens(LPWSTR * token_array)
{
int i;
for (i = 0; token_array[i]; i++)
HeapFree(GetProcessHeap(), 0, token_array[i]);
HeapFree(GetProcessHeap(), 0, token_array);
}
/***********************************************************************
* HTTP_HttpAddRequestHeadersW (internal)
*/
@ -788,141 +848,6 @@ HINTERNET WINAPI HTTP_HttpOpenRequestW(HINTERNET hHttpSession,
return handle;
}
/***********************************************************************
* HTTP_build_resp_header (internal)
*
* This function reconstructs the response header. It takes an array
* of strings in the response buffer, and the count of those strings.
* A null pointer in the array represents a separator.
*
* RETURNS:
* a buffer allocated and initialized with the reconstructed response
* *pSize is set to the number of wide characters in the returned buffer
*/
static LPWSTR HTTP_build_resp_header(
LPCWSTR *str, DWORD count, BOOL bUseCrlf, DWORD *pSize )
{
static const WCHAR szcrlf[] = { '\r','\n',0 };
DWORD len, i;
LPWSTR ret;
/* calculate the length of the response buffer */
len = 0;
for( i=0; i<count; i++ )
{
if( str[i] )
len += strlenW( str[i] );
else if( bUseCrlf )
len += 2;
else
len ++;
}
len++;
/* fill the buffer in */
ret = HeapAlloc( GetProcessHeap(), 0, len*sizeof(WCHAR) );
len = 0;
for( i=0; i<count; i++ )
{
if( str[i] )
{
strcpyW( &ret[len], str[i] );
len += strlenW( str[i] );
}
else if( bUseCrlf )
{
strcpyW( &ret[len], szcrlf );
len += 2;
}
else
ret[len++] = 0;
}
ret[len++] = 0;
*pSize = len;
return ret;
}
/***********************************************************************
* HTTP_query_raw_headers (internal)
*
* Reconstruct the raw HTTP header and copy it into the buffer provided
*/
static BOOL HTTP_query_raw_headers( LPWININETHTTPREQW lpwhr, BOOL bUseCrlf,
LPVOID lpBuffer, LPDWORD lpdwBufferLength )
{
static const WCHAR szColonSpace[] = { ':',' ',0 };
static const WCHAR szSpace[] = { ' ',0 };
BOOL bSuccess = FALSE;
LPCWSTR *str;
DWORD i, n, size = 0;
LPWSTR hdr;
n = 7 + ( HTTP_QUERY_MAX + 1 + lpwhr->nCustHeaders )*4 ;
str = HeapAlloc( GetProcessHeap(), 0, sizeof(LPCWSTR)*n );
n = 0;
/* reconstruct the status line */
str[n++] = lpwhr->StdHeaders[HTTP_QUERY_VERSION].lpszValue;
str[n++] = szSpace;
str[n++] = lpwhr->StdHeaders[HTTP_QUERY_STATUS_CODE].lpszValue;
str[n++] = szSpace;
str[n++] = lpwhr->StdHeaders[HTTP_QUERY_STATUS_TEXT].lpszValue;
str[n++] = NULL;
/* Append standard request heades */
for (i = 0; i <= HTTP_QUERY_MAX; i++)
{
if( lpwhr->StdHeaders[i].wFlags & HDR_ISREQUEST )
continue;
if( !lpwhr->StdHeaders[i].lpszField )
continue;
if( !lpwhr->StdHeaders[i].lpszValue )
continue;
/* ignore the stuff that's in the status line */
if( ( i == HTTP_QUERY_VERSION ) ||
( i == HTTP_QUERY_STATUS_CODE ) ||
( i == HTTP_QUERY_STATUS_TEXT ) )
continue;
str[n++] = lpwhr->StdHeaders[i].lpszField;
str[n++] = szColonSpace;
str[n++] = lpwhr->StdHeaders[i].lpszValue,
str[n++] = NULL;
}
/* Append custom request heades */
for (i = 0; i < lpwhr->nCustHeaders; i++)
{
if( lpwhr->pCustHeaders[i].wFlags & HDR_ISREQUEST)
continue;
if( !lpwhr->pCustHeaders[i].lpszField )
continue;
if( !lpwhr->pCustHeaders[i].lpszValue )
continue;
str[n++] = lpwhr->pCustHeaders[i].lpszField;
str[n++] = szColonSpace;
str[n++] = lpwhr->pCustHeaders[i].lpszValue;
str[n++] = NULL;
}
str[n++] = NULL;
/* concatenate all the strings together */
hdr = HTTP_build_resp_header( str, n, bUseCrlf, &size );
HeapFree( GetProcessHeap(), 0, str );
/* check that the target buffer is big enough */
if ( size > (*lpdwBufferLength/sizeof(WCHAR)) )
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
else
{
memcpy( lpBuffer, hdr, size*sizeof(WCHAR) );
bSuccess = TRUE;
}
HeapFree( GetProcessHeap(), 0, hdr );
*lpdwBufferLength = size*sizeof(WCHAR);
return bSuccess;
}
/***********************************************************************
* HTTP_HttpQueryInfoW (internal)
*/
@ -947,9 +872,52 @@ BOOL WINAPI HTTP_HttpQueryInfoW( LPWININETHTTPREQW lpwhr, DWORD dwInfoLevel,
INT index = dwInfoLevel & ~HTTP_QUERY_MODIFIER_FLAGS_MASK;
if (index == HTTP_QUERY_RAW_HEADERS_CRLF)
return HTTP_query_raw_headers(lpwhr, TRUE, lpBuffer, lpdwBufferLength );
if (index == HTTP_QUERY_RAW_HEADERS)
return HTTP_query_raw_headers(lpwhr, FALSE, lpBuffer, lpdwBufferLength );
{
int len = strlenW(lpwhr->lpszRawHeaders);
if (len + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
memcpy(lpBuffer, lpwhr->lpszRawHeaders, (len+1)*sizeof(WCHAR));
*lpdwBufferLength = (len + 1) * sizeof(WCHAR);
return TRUE;
}
else if (index == HTTP_QUERY_RAW_HEADERS)
{
static const WCHAR szCrLf[] = {'\r','\n',0};
LPWSTR * ppszRawHeaderLines = HTTP_Tokenize(lpwhr->lpszRawHeaders, szCrLf);
int size = 0;
int i;
LPWSTR pszString = (WCHAR*)lpBuffer;
for (i = 0; ppszRawHeaderLines[i]; i++)
size += strlenW(ppszRawHeaderLines[i]) + 1;
if (size + 1 > *lpdwBufferLength/sizeof(WCHAR))
{
HTTP_FreeTokens(ppszRawHeaderLines);
*lpdwBufferLength = (size + 1) * sizeof(WCHAR);
INTERNET_SetLastError(ERROR_INSUFFICIENT_BUFFER);
return FALSE;
}
for (i = 0; ppszRawHeaderLines[i]; i++)
{
int len = strlenW(ppszRawHeaderLines[i]);
memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
pszString += len+1;
}
*pszString = '\0';
TRACE("returning data: %s\n", debugstr_wn((WCHAR*)lpBuffer, size));
*lpdwBufferLength = (size + 1) * sizeof(WCHAR);
HTTP_FreeTokens(ppszRawHeaderLines);
return TRUE;
}
else if (index >= 0 && index <= HTTP_QUERY_MAX && lpwhr->StdHeaders[index].lpszValue)
{
lphttpHdr = &lpwhr->StdHeaders[index];
@ -2011,8 +1979,12 @@ BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
INT rc = 0;
WCHAR value[MAX_FIELD_VALUE_LEN], field[MAX_FIELD_LEN];
static const WCHAR szHttp[] = { 'H','T','T','P',0 };
static const WCHAR szCrLf[] = {'\r','\n',0};
char bufferA[MAX_REPLY_LEN];
LPWSTR status_code, status_text;
int cchMaxRawHeaders = 1024;
LPWSTR lpszRawHeaders = HeapAlloc(GetProcessHeap(), 0, (cchMaxRawHeaders+1)*sizeof(WCHAR));
int cchRawHeaders = 0;
TRACE("-->\n");
@ -2039,6 +2011,18 @@ BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
if (strncmpW(buffer, szHttp, 4) != 0)
goto lend;
/* regenerate raw headers */
while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
{
cchMaxRawHeaders *= 2;
lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
}
memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
cchRawHeaders += (buflen-1);
memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
lpszRawHeaders[cchRawHeaders] = '\0';
/* split the version from the status code */
status_code = strchrW( buffer, ' ' );
if( !status_code )
@ -2065,6 +2049,18 @@ BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
{
TRACE("got line %s, now interpretting\n", debugstr_a(bufferA));
MultiByteToWideChar( CP_ACP, 0, bufferA, buflen, buffer, MAX_REPLY_LEN );
while (cchRawHeaders + buflen + strlenW(szCrLf) > cchMaxRawHeaders)
{
cchMaxRawHeaders *= 2;
lpszRawHeaders = HeapReAlloc(GetProcessHeap(), 0, lpszRawHeaders, (cchMaxRawHeaders+1)*sizeof(WCHAR));
}
memcpy(lpszRawHeaders+cchRawHeaders, buffer, (buflen-1)*sizeof(WCHAR));
cchRawHeaders += (buflen-1);
memcpy(lpszRawHeaders+cchRawHeaders, szCrLf, sizeof(szCrLf));
cchRawHeaders += sizeof(szCrLf)/sizeof(szCrLf[0])-1;
lpszRawHeaders[cchRawHeaders] = '\0';
if (!HTTP_InterpretHttpHeader(buffer, field, MAX_FIELD_LEN, value, MAX_FIELD_VALUE_LEN))
break;
@ -2078,6 +2074,9 @@ BOOL HTTP_GetResponseHeaders(LPWININETHTTPREQW lpwhr)
}
}while(1);
if (lpwhr->lpszRawHeaders) HeapFree(GetProcessHeap(), 0, lpszRawHeaders);
lpwhr->lpszRawHeaders = lpszRawHeaders;
TRACE("raw headers: %s\n", debugstr_w(lpszRawHeaders));
bSuccess = TRUE;
lend:
@ -2468,6 +2467,8 @@ void HTTP_CloseHTTPRequestHandle(LPWININETHTTPREQW lpwhr)
HeapFree(GetProcessHeap(), 0, lpwhr->lpszVerb);
if (lpwhr->lpszHostName)
HeapFree(GetProcessHeap(), 0, lpwhr->lpszHostName);
if (lpwhr->lpszRawHeaders)
HeapFree(GetProcessHeap(), 0, lpwhr->lpszRawHeaders);
for (i = 0; i <= HTTP_QUERY_MAX; i++)
{

View File

@ -173,6 +173,7 @@ typedef struct
LPWSTR lpszPath;
LPWSTR lpszVerb;
LPWSTR lpszHostName;
LPWSTR lpszRawHeaders;
WININET_NETCONNECTION netConnection;
HTTPHEADERW StdHeaders[HTTP_QUERY_MAX+1];
HTTPHEADERW *pCustHeaders;