Piotr Caban : wininet: Create raw HTTP headers dynamically.
Alexandre Julliard
julliard at winehq.org
Tue Apr 30 12:51:28 CDT 2013
Module: wine
Branch: master
Commit: e092233396bceb950c64394b386fb3acad505935
URL: http://source.winehq.org/git/wine.git/?a=commit;h=e092233396bceb950c64394b386fb3acad505935
Author: Piotr Caban <piotr at codeweavers.com>
Date: Tue Apr 30 16:58:00 2013 +0200
wininet: Create raw HTTP headers dynamically.
---
dlls/wininet/http.c | 149 ++++++++++++++++++++++++++------------------------
1 files changed, 77 insertions(+), 72 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index 73aa3f7..682ed36 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -585,61 +585,9 @@ static DWORD init_gzip_stream(http_request_t *req)
#endif
/***********************************************************************
- * 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;
-
- if (string)
- {
- /* 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)))
- {
- DWORD 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 = heap_alloc((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] = heap_alloc((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.
+ * Frees table of pointers.
*/
static void HTTP_FreeTokens(LPWSTR * token_array)
{
@@ -742,6 +690,59 @@ static LPWSTR HTTP_BuildHeaderRequestString( http_request_t *request, LPCWSTR ve
return requestString;
}
+static WCHAR* build_response_header(http_request_t *request, BOOL use_cr)
+{
+ static const WCHAR colonW[] = { ':',' ',0 };
+ static const WCHAR crW[] = { '\r',0 };
+ static const WCHAR lfW[] = { '\n',0 };
+ static const WCHAR status_fmt[] = { ' ','%','u',' ',0 };
+
+ const WCHAR **req;
+ WCHAR *ret, buf[14];
+ DWORD i, n = 0;
+
+ req = heap_alloc((request->nCustHeaders*5+8)*sizeof(WCHAR*));
+ if(!req)
+ return NULL;
+
+ if(request->rawHeaders)
+ {
+ req[n++] = request->version;
+ sprintfW(buf, status_fmt, request->status_code);
+ req[n++] = buf;
+ req[n++] = request->statusText;
+ if (use_cr)
+ req[n++] = crW;
+ req[n++] = lfW;
+ }
+
+ for(i = 0; i < request->nCustHeaders; i++)
+ {
+ if(!(request->custHeaders[i].wFlags & HDR_ISREQUEST)
+ && strcmpW(request->custHeaders[i].lpszField, szStatus))
+ {
+ req[n++] = request->custHeaders[i].lpszField;
+ req[n++] = colonW;
+ req[n++] = request->custHeaders[i].lpszValue;
+ if(use_cr)
+ req[n++] = crW;
+ req[n++] = lfW;
+
+ TRACE("Adding custom header %s (%s)\n",
+ debugstr_w(request->custHeaders[i].lpszField),
+ debugstr_w(request->custHeaders[i].lpszValue));
+ }
+ }
+ if(use_cr)
+ req[n++] = crW;
+ req[n++] = lfW;
+ req[n] = NULL;
+
+ ret = HTTP_build_req(req, 0);
+ heap_free(req);
+ return ret;
+}
+
static void HTTP_ProcessCookies( http_request_t *request )
{
int HeaderIndex;
@@ -3422,7 +3423,7 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
if (request_only)
headers = HTTP_BuildHeaderRequestString(request, request->verb, request->path, request->version);
else
- headers = request->rawHeaders;
+ headers = build_response_header(request, TRUE);
if (headers)
len = strlenW(headers) * sizeof(WCHAR);
@@ -3446,38 +3447,42 @@ static DWORD HTTP_HttpQueryInfoW(http_request_t *request, DWORD dwInfoLevel,
}
*lpdwBufferLength = len;
- if (request_only) heap_free(headers);
+ heap_free(headers);
return res;
}
case HTTP_QUERY_RAW_HEADERS:
{
- LPWSTR * ppszRawHeaderLines = HTTP_Tokenize(request->rawHeaders, szCrLf);
- DWORD i, size = 0;
- LPWSTR pszString = lpBuffer;
+ LPWSTR headers;
+ DWORD len;
- for (i = 0; ppszRawHeaderLines[i]; i++)
- size += strlenW(ppszRawHeaderLines[i]) + 1;
+ headers = build_response_header(request, FALSE);
+ if (!headers)
+ return ERROR_OUTOFMEMORY;
- if (size + 1 > *lpdwBufferLength/sizeof(WCHAR))
+ len = strlenW(headers) * sizeof(WCHAR);
+ if (len > *lpdwBufferLength)
{
- HTTP_FreeTokens(ppszRawHeaderLines);
- *lpdwBufferLength = (size + 1) * sizeof(WCHAR);
+ *lpdwBufferLength = len;
+ heap_free(headers);
return ERROR_INSUFFICIENT_BUFFER;
}
- if (pszString)
+
+ if (lpBuffer)
{
- for (i = 0; ppszRawHeaderLines[i]; i++)
+ DWORD i;
+
+ TRACE("returning data: %s\n", debugstr_wn(headers, len / sizeof(WCHAR)));
+
+ for (i=0; i<len; i++)
{
- DWORD len = strlenW(ppszRawHeaderLines[i]);
- memcpy(pszString, ppszRawHeaderLines[i], (len+1)*sizeof(WCHAR));
- pszString += len+1;
+ if (headers[i] == '\n')
+ headers[i] = 0;
}
- *pszString = '\0';
- TRACE("returning data: %s\n", debugstr_wn(lpBuffer, size));
+ memcpy(lpBuffer, headers, len + sizeof(WCHAR));
}
- *lpdwBufferLength = size * sizeof(WCHAR);
- HTTP_FreeTokens(ppszRawHeaderLines);
+ *lpdwBufferLength = len - sizeof(WCHAR);
+ heap_free(headers);
return ERROR_SUCCESS;
}
case HTTP_QUERY_STATUS_TEXT:
More information about the wine-cvs
mailing list