Module: wine Branch: master Commit: 3c9d356bc44c208264c07e7d123a62dfdc068255 URL: http://source.winehq.org/git/wine.git/?a=commit;h=3c9d356bc44c208264c07e7d12...
Author: Hans Leidekker hans@codeweavers.com Date: Thu Nov 10 11:37:31 2011 +0100
winhttp: Convert string data to UTF-8 and add a corresponding content type header.
---
dlls/winhttp/request.c | 62 ++++++++++++++++++++++++++++++++++------- dlls/winhttp/tests/winhttp.c | 21 +++++++++++++- 2 files changed, 71 insertions(+), 12 deletions(-)
diff --git a/dlls/winhttp/request.c b/dlls/winhttp/request.c index 51c433e..e0c68e6 100644 --- a/dlls/winhttp/request.c +++ b/dlls/winhttp/request.c @@ -2217,6 +2217,7 @@ static void free_request( struct winhttp_request *request ) heap_free( (WCHAR *)request->proxy.lpszProxyBypass ); heap_free( request->buffer ); heap_free( request->verb ); + VariantClear( &request->data ); }
static ULONG WINAPI winhttp_request_Release( @@ -2860,6 +2861,20 @@ static DWORD request_set_parameters( struct winhttp_request *request ) return ERROR_SUCCESS; }
+static void request_set_utf8_content_type( struct winhttp_request *request ) +{ + static const WCHAR fmtW[] = {'%','s',':',' ','%','s',0}; + static const WCHAR text_plainW[] = {'t','e','x','t','/','p','l','a','i','n',0}; + static const WCHAR charset_utf8W[] = {'c','h','a','r','s','e','t','=','u','t','f','-','8',0}; + WCHAR headerW[64]; + int len; + + len = sprintfW( headerW, fmtW, attr_content_type, text_plainW ); + WinHttpAddRequestHeaders( request->hrequest, headerW, len, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ); + len = sprintfW( headerW, fmtW, attr_content_type, charset_utf8W ); + WinHttpAddRequestHeaders( request->hrequest, headerW, len, WINHTTP_ADDREQ_FLAG_COALESCE_WITH_SEMICOLON ); +} + static HRESULT request_send( struct winhttp_request *request ) { SAFEARRAY *sa = NULL; @@ -2871,24 +2886,47 @@ static HRESULT request_send( struct winhttp_request *request ) DWORD err;
if ((err = request_set_parameters( request ))) return HRESULT_FROM_WIN32( err ); - VariantInit( &data ); - if (strcmpW( request->verb, getW ) && VariantChangeType( &data, &request->data, 0, VT_ARRAY|VT_UI1 ) == S_OK) + if (strcmpW( request->verb, getW )) { - SAFEARRAY *sa = V_ARRAY( &data ); - if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) return hr; - if ((hr = SafeArrayGetUBound( sa, 1, &size ) != S_OK)) + VariantInit( &data ); + if (V_VT( &request->data ) == VT_BSTR) { - SafeArrayUnaccessData( sa ); - return hr; + UINT i, cp = CP_ACP; + const WCHAR *str = V_BSTR( &request->data ); + int len = strlenW( str ); + + for (i = 0; i < len; i++) + { + if (str[i] > 127) + { + cp = CP_UTF8; + break; + } + } + size = WideCharToMultiByte( cp, 0, str, len, NULL, 0, NULL, NULL ); + if (!(ptr = heap_alloc( size ))) return E_OUTOFMEMORY; + WideCharToMultiByte( cp, 0, str, len, ptr, size, NULL, NULL ); + if (cp == CP_UTF8) request_set_utf8_content_type( request ); + } + else if (VariantChangeType( &data, &request->data, 0, VT_ARRAY|VT_UI1 ) == S_OK) + { + sa = V_ARRAY( &data ); + if ((hr = SafeArrayAccessData( sa, (void **)&ptr )) != S_OK) return hr; + if ((hr = SafeArrayGetUBound( sa, 1, &size ) != S_OK)) + { + SafeArrayUnaccessData( sa ); + return hr; + } + size++; } - size++; } wait_set_status_callback( request, WINHTTP_CALLBACK_STATUS_REQUEST_SENT ); if (!(ret = WinHttpSendRequest( request->hrequest, NULL, 0, ptr, size, size, 0 ))) { err = get_last_error(); } - if (sa && (hr = SafeArrayUnaccessData( sa )) != S_OK) return hr; + if (!sa) heap_free( ptr ); + else if ((hr = SafeArrayUnaccessData( sa )) != S_OK) return hr; if (!ret) return HRESULT_FROM_WIN32( err ); if ((err = wait_for_completion( request ))) return HRESULT_FROM_WIN32( err );
@@ -2914,7 +2952,7 @@ static HRESULT WINAPI winhttp_request_Send( VARIANT body ) { struct winhttp_request *request = impl_from_IWinHttpRequest( iface ); - HRESULT hr = S_OK; + HRESULT hr;
TRACE("%p, %s\n", request, debugstr_variant(&body));
@@ -2929,7 +2967,9 @@ static HRESULT WINAPI winhttp_request_Send( LeaveCriticalSection( &request->cs ); return S_OK; } - request->data = body; + VariantClear( &request->data ); + if ((hr = VariantCopyInd( &request->data, &body )) != S_OK) return hr; + if (request->wait) /* async request */ { if (!(request->thread = CreateThread( NULL, 0, send_and_receive_proc, request, 0, NULL ))) diff --git a/dlls/winhttp/tests/winhttp.c b/dlls/winhttp/tests/winhttp.c index 01b74e3..acf88dc 100644 --- a/dlls/winhttp/tests/winhttp.c +++ b/dlls/winhttp/tests/winhttp.c @@ -2111,17 +2111,22 @@ static void test_IWinHttpRequest(void) static const WCHAR passwordW[] = {'p','a','s','s','w','o','r','d',0}; static const WCHAR url1W[] = {'h','t','t','p',':','/','/','w','i','n','e','h','q','.','o','r','g',0}; static const WCHAR url2W[] = {'w','i','n','e','h','q','.','o','r','g',0}; + static const WCHAR url3W[] = {'h','t','t','p',':','/','/','c','r','o','s','s','o','v','e','r','.', + 'c','o','d','e','w','e','a','v','e','r','s','.','c','o','m','/', + 'p','o','s','t','t','e','s','t','.','p','h','p',0}; static const WCHAR method1W[] = {'G','E','T',0}; static const WCHAR method2W[] = {'I','N','V','A','L','I','D',0}; + static const WCHAR method3W[] = {'P','O','S','T',0}; static const WCHAR proxy_serverW[] = {'p','r','o','x','y','s','e','r','v','e','r',0}; static const WCHAR bypas_listW[] = {'b','y','p','a','s','s','l','i','s','t',0}; static const WCHAR connectionW[] = {'C','o','n','n','e','c','t','i','o','n',0}; static const WCHAR dateW[] = {'D','a','t','e',0}; + static const WCHAR test_dataW[] = {'t','e','s','t','d','a','t','a',128,0}; HRESULT hr; IWinHttpRequest *req; BSTR method, url, username, password, response = NULL, status_text = NULL, headers = NULL; BSTR date, today, connection, value = NULL; - VARIANT async, empty, timeout, body, proxy_server, bypass_list; + VARIANT async, empty, timeout, body, proxy_server, bypass_list, data; VARIANT_BOOL succeeded; LONG status; WCHAR todayW[WINHTTP_TIME_FORMAT_BUFSIZE]; @@ -2140,6 +2145,20 @@ static void test_IWinHttpRequest(void) V_VT( &async ) = VT_BOOL; V_BOOL( &async ) = VARIANT_FALSE;
+ method = SysAllocString( method3W ); + url = SysAllocString( url3W ); + hr = IWinHttpRequest_Open( req, method, url, async ); + ok( hr == S_OK, "got %08x\n", hr ); + SysFreeString( method ); + SysFreeString( url ); + + V_VT( &data ) = VT_BSTR; + V_BSTR( &data ) = SysAllocString( test_dataW ); + hr = IWinHttpRequest_Send( req, data ); + ok( hr == S_OK || broken(hr == HRESULT_FROM_WIN32(ERROR_WINHTTP_INVALID_SERVER_RESPONSE)), + "got %08x\n", hr ); + SysFreeString( V_BSTR( &data ) ); + hr = IWinHttpRequest_Open( req, NULL, NULL, empty ); ok( hr == E_INVALIDARG, "got %08x\n", hr );