Author: cwittich Date: Sun Jun 7 16:32:05 2009 New Revision: 41333
URL: http://svn.reactos.org/svn/reactos?rev=41333&view=rev Log: sync urlmon and winhttp with wine 1.1.23
Added: trunk/reactos/dll/win32/winhttp/cookie.c (with props) trunk/reactos/dll/win32/winhttp/url.c (with props) Modified: trunk/reactos/dll/win32/urlmon/bindprot.c trunk/reactos/dll/win32/urlmon/http.c trunk/reactos/dll/win32/urlmon/urlmon_main.c trunk/reactos/dll/win32/winhttp/main.c trunk/reactos/dll/win32/winhttp/net.c trunk/reactos/dll/win32/winhttp/request.c trunk/reactos/dll/win32/winhttp/session.c trunk/reactos/dll/win32/winhttp/winhttp.rbuild trunk/reactos/dll/win32/winhttp/winhttp_private.h trunk/reactos/include/psdk/winhttp.h
Modified: trunk/reactos/dll/win32/urlmon/bindprot.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/bindprot.c... ============================================================================== --- trunk/reactos/dll/win32/urlmon/bindprot.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/urlmon/bindprot.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -608,10 +608,14 @@ static HRESULT WINAPI ProtocolHandler_Continue(IInternetProtocol *iface, PROTOCOLDATA *pProtocolData) { BindProtocol *This = PROTOCOLHANDLER_THIS(iface); + HRESULT hres;
TRACE("(%p)->(%p)\n", This, pProtocolData);
- return IInternetProtocol_Continue(This->protocol, pProtocolData); + hres = IInternetProtocol_Continue(This->protocol, pProtocolData); + + heap_free(pProtocolData); + return hres; }
static HRESULT WINAPI ProtocolHandler_Abort(IInternetProtocol *iface, HRESULT hrReason, @@ -874,14 +878,14 @@
typedef struct { task_header_t header; - PROTOCOLDATA data; + PROTOCOLDATA *data; } switch_task_t;
static void switch_proc(BindProtocol *bind, task_header_t *t) { switch_task_t *task = (switch_task_t*)t;
- IInternetProtocol_Continue(bind->protocol_handler, &task->data); + IInternetProtocol_Continue(bind->protocol_handler, task->data);
heap_free(task); } @@ -890,11 +894,17 @@ PROTOCOLDATA *pProtocolData) { BindProtocol *This = PROTSINK_THIS(iface); + PROTOCOLDATA *data;
TRACE("(%p)->(%p)\n", This, pProtocolData);
TRACE("flags %x state %x data %p cb %u\n", pProtocolData->grfFlags, pProtocolData->dwState, pProtocolData->pData, pProtocolData->cbData); + + data = heap_alloc(sizeof(PROTOCOLDATA)); + if(!data) + return E_OUTOFMEMORY; + memcpy(data, pProtocolData, sizeof(PROTOCOLDATA));
if(!do_direct_notif(This)) { switch_task_t *task; @@ -903,18 +913,18 @@ if(!task) return E_OUTOFMEMORY;
- task->data = *pProtocolData; + task->data = data;
push_task(This, &task->header, switch_proc); return S_OK; }
if(!This->protocol_sink) { - IInternetProtocol_Continue(This->protocol_handler, pProtocolData); + IInternetProtocol_Continue(This->protocol_handler, data); return S_OK; }
- return IInternetProtocolSink_Switch(This->protocol_sink, pProtocolData); + return IInternetProtocolSink_Switch(This->protocol_sink, data); }
static void report_progress(BindProtocol *This, ULONG status_code, LPCWSTR status_text)
Modified: trunk/reactos/dll/win32/urlmon/http.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/http.c?rev... ============================================================================== --- trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/urlmon/http.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -85,7 +85,7 @@ BYTE security_id[512]; DWORD len = 0; ULONG num = 0; - BOOL res; + BOOL res, b; HRESULT hres;
static const WCHAR wszBindVerb[BINDVERB_CUSTOM][5] = @@ -208,6 +208,11 @@ else optional = (LPWSTR)This->base.bind_info.stgmedData.u.hGlobal; } + + b = TRUE; + res = InternetSetOptionW(This->base.request, INTERNET_OPTION_HTTP_DECODING, &b, sizeof(b)); + if(!res) + WARN("InternetSetOption(INTERNET_OPTION_HTTP_DECODING) failed: %08x\n", GetLastError());
res = HttpSendRequestW(This->base.request, This->full_header, lstrlenW(This->full_header), optional, optional ? This->base.bind_info.cbstgmedData : 0);
Modified: trunk/reactos/dll/win32/urlmon/urlmon_main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/urlmon/urlmon_mai... ============================================================================== --- trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/urlmon/urlmon_main.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -36,7 +36,7 @@
HINSTANCE URLMON_hInstance = 0; static HMODULE hCabinet = NULL; -static DWORD urlmon_tls; +static DWORD urlmon_tls = TLS_OUT_OF_INDEXES;
static void init_session(BOOL);
@@ -56,9 +56,12 @@ { tls_data_t *data;
- if(!urlmon_tls) { + if(urlmon_tls == TLS_OUT_OF_INDEXES) { DWORD tls = TlsAlloc(); - tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, 0); + if(tls == TLS_OUT_OF_INDEXES) + return NULL; + + tls = InterlockedCompareExchange((LONG*)&urlmon_tls, tls, TLS_OUT_OF_INDEXES); if(tls != urlmon_tls) TlsFree(tls); } @@ -83,7 +86,7 @@ { tls_data_t *data;
- if(!urlmon_tls) + if(urlmon_tls == TLS_OUT_OF_INDEXES) return;
while(!list_empty(&tls_list)) { @@ -99,7 +102,7 @@ { tls_data_t *data;
- if(!urlmon_tls) + if(urlmon_tls == TLS_OUT_OF_INDEXES) return;
data = TlsGetValue(urlmon_tls);
Added: trunk/reactos/dll/win32/winhttp/cookie.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/cookie.c?... ============================================================================== --- trunk/reactos/dll/win32/winhttp/cookie.c (added) +++ trunk/reactos/dll/win32/winhttp/cookie.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -1,0 +1,281 @@ +/* + * Copyright 2008 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include <stdarg.h> + +#include "wine/debug.h" +#include "wine/list.h" + +#include "windef.h" +#include "winbase.h" +#include "winhttp.h" + +#include "winhttp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(winhttp); + +static domain_t *add_domain( session_t *session, WCHAR *name ) +{ + domain_t *domain; + + if (!(domain = heap_alloc_zero( sizeof(domain_t) ))) return NULL; + + list_init( &domain->entry ); + list_init( &domain->cookies ); + + domain->name = name; + list_add_tail( &session->cookie_cache, &domain->entry ); + + TRACE("%s\n", debugstr_w(domain->name)); + return domain; +} + +static cookie_t *find_cookie( domain_t *domain, const WCHAR *path, const WCHAR *name ) +{ + struct list *item; + cookie_t *cookie; + + LIST_FOR_EACH( item, &domain->cookies ) + { + cookie = LIST_ENTRY( item, cookie_t, entry ); + if (!strcmpW( cookie->path, path ) && !strcmpiW( cookie->name, name )) + { + TRACE("found %s=%s\n", debugstr_w(cookie->name), debugstr_w(cookie->value)); + return cookie; + } + } + return NULL; +} + +static BOOL domain_match( const WCHAR *name, domain_t *domain, BOOL partial ) +{ + TRACE("comparing %s with %s\n", debugstr_w(name), debugstr_w(domain->name)); + + if (partial && !strstrW( name, domain->name )) return FALSE; + else if (!partial && strcmpW( name, domain->name )) return FALSE; + return TRUE; +} + +static void free_cookie( cookie_t *cookie ) +{ + heap_free( cookie->name ); + heap_free( cookie->value ); + heap_free( cookie->path ); + heap_free( cookie ); +} + +static void delete_cookie( cookie_t *cookie ) +{ + list_remove( &cookie->entry ); + free_cookie( cookie ); +} + +void delete_domain( domain_t *domain ) +{ + cookie_t *cookie; + struct list *item, *next; + + LIST_FOR_EACH_SAFE( item, next, &domain->cookies ) + { + cookie = LIST_ENTRY( item, cookie_t, entry ); + delete_cookie( cookie ); + } + + list_remove( &domain->entry ); + heap_free( domain->name ); + heap_free( domain ); +} + +static BOOL add_cookie( session_t *session, cookie_t *cookie, WCHAR *domain_name, WCHAR *path ) +{ + domain_t *domain = NULL; + cookie_t *old_cookie; + struct list *item; + + LIST_FOR_EACH( item, &session->cookie_cache ) + { + domain = LIST_ENTRY( item, domain_t, entry ); + if (domain_match( domain_name, domain, FALSE )) break; + domain = NULL; + } + if (!domain) + { + if (!(domain = add_domain( session, domain_name ))) return FALSE; + } + else if ((old_cookie = find_cookie( domain, path, cookie->name ))) delete_cookie( old_cookie ); + + cookie->path = path; + list_add_tail( &domain->cookies, &cookie->entry ); + + TRACE("domain %s path %s <- %s=%s\n", debugstr_w(domain_name), debugstr_w(cookie->path), + debugstr_w(cookie->name), debugstr_w(cookie->value)); + return TRUE; +} + +static cookie_t *parse_cookie( const WCHAR *string ) +{ + cookie_t *cookie; + const WCHAR *p; + int len; + + if (!(cookie = heap_alloc_zero( sizeof(cookie_t) ))) return NULL; + + list_init( &cookie->entry ); + + if (!(p = strchrW( string, '=' ))) + { + WARN("no '=' in %s\n", debugstr_w(string)); + return NULL; + } + if (p == string) + { + WARN("empty cookie name in %s\n", debugstr_w(string)); + return NULL; + } + len = p - string; + if (!(cookie->name = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + heap_free( cookie ); + return NULL; + } + memcpy( cookie->name, string, len * sizeof(WCHAR) ); + cookie->name[len] = 0; + + p++; /* skip '=' */ + while (*p == ' ') p++; + + len = strlenW( p ); + if (!(cookie->value = heap_alloc( (len + 1) * sizeof(WCHAR) ))) + { + free_cookie( cookie ); + return NULL; + } + memcpy( cookie->value, p, len * sizeof(WCHAR) ); + cookie->value[len] = 0; + + return cookie; +} + +BOOL set_cookies( request_t *request, const WCHAR *cookies ) +{ + static const WCHAR pathW[] = {'p','a','t','h',0}; + static const WCHAR domainW[] = {'d','o','m','a','i','n',0}; + + BOOL ret = FALSE; + WCHAR *buffer, *p, *q, *r; + WCHAR *cookie_domain = NULL, *cookie_path = NULL; + session_t *session = request->connect->session; + cookie_t *cookie; + int len; + + len = strlenW( cookies ); + if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; + strcpyW( buffer, cookies ); + + p = buffer; + while (*p && *p != ';') p++; + if (*p == ';') *p++ = 0; + if (!(cookie = parse_cookie( buffer ))) + { + heap_free( buffer ); + return FALSE; + } + if ((q = strstrW( p, domainW ))) /* FIXME: do real attribute parsing */ + { + while (*q && *q != '=') q++; + if (!*q) goto end; + + r = ++q; + while (*r && *r != ';') r++; + len = r - q; + + if (!(cookie_domain = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; + memcpy( cookie_domain, q, len * sizeof(WCHAR) ); + cookie_domain[len] = 0; + + } + if ((q = strstrW( p, pathW ))) + { + while (*q && *q != '=') q++; + if (!*q) goto end; + + r = ++q; + while (*r && *r != ';') r++; + len = r - q; + + if (!(cookie_path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; + memcpy( cookie_path, q, len * sizeof(WCHAR) ); + cookie_path[len] = 0; + } + if (!cookie_domain && !(cookie_domain = strdupW( request->connect->servername ))) goto end; + if (!cookie_path && !(cookie_path = strdupW( request->path ))) goto end; + + if ((p = strrchrW( cookie_path, '/' )) && p != cookie_path) *p = 0; + ret = add_cookie( session, cookie, cookie_domain, cookie_path ); + +end: + if (!ret) + { + free_cookie( cookie ); + heap_free( cookie_domain ); + heap_free( cookie_path ); + } + heap_free( buffer ); + return ret; +} + +BOOL add_cookie_headers( request_t *request ) +{ + struct list *domain_cursor; + session_t *session = request->connect->session; + + LIST_FOR_EACH( domain_cursor, &session->cookie_cache ) + { + domain_t *domain = LIST_ENTRY( domain_cursor, domain_t, entry ); + if (domain_match( request->connect->servername, domain, TRUE )) + { + struct list *cookie_cursor; + TRACE("found domain %s\n", debugstr_w(domain->name)); + + LIST_FOR_EACH( cookie_cursor, &domain->cookies ) + { + cookie_t *cookie = LIST_ENTRY( cookie_cursor, cookie_t, entry ); + + TRACE("comparing path %s with %s\n", debugstr_w(request->path), debugstr_w(cookie->path)); + + if (strstrW( request->path, cookie->path ) == request->path) + { + const WCHAR format[] = {'C','o','o','k','i','e',':',' ','%','s','=','%','s',0}; + int len; + WCHAR *header; + + len = strlenW( cookie->name ) + strlenW( format ) + strlenW( cookie->value ); + if (!(header = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; + + sprintfW( header, format, cookie->name, cookie->value ); + + TRACE("%s\n", debugstr_w(header)); + add_request_headers( request, header, len, WINHTTP_ADDREQ_FLAG_ADD ); + heap_free( header ); + } + } + } + } + return TRUE; +}
Propchange: trunk/reactos/dll/win32/winhttp/cookie.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/win32/winhttp/main.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/main.c?re... ============================================================================== --- trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/main.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -38,8 +38,6 @@ { switch(fdwReason) { - case DLL_WINE_PREATTACH: - return FALSE; /* prefer native version */ case DLL_PROCESS_ATTACH: DisableThreadLibraryCalls(hInstDLL); break; @@ -84,41 +82,3 @@ FIXME("()\n"); return S_OK; } - -#define SCHEME_HTTP 3 -#define SCHEME_HTTPS 4 - -BOOL WINAPI InternetCrackUrlW( LPCWSTR, DWORD, DWORD, LPURL_COMPONENTSW ); -BOOL WINAPI InternetCreateUrlW( LPURL_COMPONENTS, DWORD, LPWSTR, LPDWORD ); - -/*********************************************************************** - * WinHttpCrackUrl (winhttp.@) - */ -BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW components ) -{ - BOOL ret; - - TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, components); - - if ((ret = InternetCrackUrlW( url, len, flags, components ))) - { - /* fix up an incompatibility between wininet and winhttp */ - if (components->nScheme == SCHEME_HTTP) components->nScheme = INTERNET_SCHEME_HTTP; - else if (components->nScheme == SCHEME_HTTPS) components->nScheme = INTERNET_SCHEME_HTTPS; - else - { - set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ); - return FALSE; - } - } - return ret; -} - -/*********************************************************************** - * WinHttpCreateUrl (winhttp.@) - */ -BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS comps, DWORD flags, LPWSTR url, LPDWORD len ) -{ - TRACE("%p, 0x%08x, %p, %p\n", comps, flags, url, len); - return InternetCreateUrlW( comps, flags, url, len ); -}
Modified: trunk/reactos/dll/win32/winhttp/net.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/net.c?rev... ============================================================================== --- trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/net.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -48,12 +48,13 @@ #include "windef.h" #include "winbase.h" #include "winhttp.h" +#include "wincrypt.h" + +#include "winhttp_private.h"
/* to avoid conflicts with the Unix socket headers */ #define USE_WS_PREFIX #include "winsock2.h" - -#include "winhttp_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
@@ -83,6 +84,7 @@ static void *libcrypto_handle;
static SSL_METHOD *method; +static SSL_CTX *ctx;
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
@@ -90,7 +92,6 @@ MAKE_FUNCPTR( SSL_load_error_strings ); MAKE_FUNCPTR( SSLv23_method ); MAKE_FUNCPTR( SSL_CTX_new ); -MAKE_FUNCPTR( SSL_CTX_free ); MAKE_FUNCPTR( SSL_new ); MAKE_FUNCPTR( SSL_free ); MAKE_FUNCPTR( SSL_set_fd ); @@ -107,14 +108,15 @@ MAKE_FUNCPTR( BIO_new_fp ); MAKE_FUNCPTR( ERR_get_error ); MAKE_FUNCPTR( ERR_error_string ); +MAKE_FUNCPTR( i2d_X509 ); #undef MAKE_FUNCPTR
#endif
-#if 0 /* translate a unix error code into a winsock error code */ static int sock_get_error( int err ) { +#if !defined(__MINGW32__) && !defined (_MSC_VER) switch (err) { case EINTR: return WSAEINTR; @@ -174,11 +176,9 @@ #endif default: errno = err; perror( "sock_set_error" ); return WSAEFAULT; } +#endif return err; } -#else -#define sock_get_error(x) WSAGetLastError() -#endif
BOOL netconn_init( netconn_t *conn, BOOL secure ) { @@ -210,7 +210,6 @@ LOAD_FUNCPTR( SSL_load_error_strings ); LOAD_FUNCPTR( SSLv23_method ); LOAD_FUNCPTR( SSL_CTX_new ); - LOAD_FUNCPTR( SSL_CTX_free ); LOAD_FUNCPTR( SSL_new ); LOAD_FUNCPTR( SSL_free ); LOAD_FUNCPTR( SSL_set_fd ); @@ -235,6 +234,7 @@ LOAD_FUNCPTR( BIO_new_fp ); LOAD_FUNCPTR( ERR_get_error ); LOAD_FUNCPTR( ERR_error_string ); + LOAD_FUNCPTR( i2d_X509 ); #undef LOAD_FUNCPTR
pSSL_library_init(); @@ -242,8 +242,6 @@ pBIO_new_fp( stderr, BIO_NOCLOSE );
method = pSSLv23_method(); - conn->ssl_ctx = pSSL_CTX_new( method ); - #else WARN("SSL support not compiled in.\n"); set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); @@ -314,13 +312,14 @@ X509 *cert; long res;
- if (!pSSL_CTX_set_default_verify_paths( conn->ssl_ctx )) + ctx = pSSL_CTX_new( method ); + if (!pSSL_CTX_set_default_verify_paths( ctx )) { ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_OUTOFMEMORY ); return FALSE; } - if (!(conn->ssl_conn = pSSL_new( conn->ssl_ctx ))) + if (!(conn->ssl_conn = pSSL_new( ctx ))) { ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_OUTOFMEMORY ); @@ -468,11 +467,7 @@ return TRUE; } #ifdef FIONREAD - if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) - { - TRACE("%d bytes of queued, but unread data\n", unread); - *available += unread; - } + if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available = unread; #endif return TRUE; } @@ -491,8 +486,8 @@ #ifdef SONAME_LIBSSL long timeout;
- timeout = pSSL_CTX_get_timeout( conn->ssl_ctx ); - pSSL_CTX_set_timeout( conn->ssl_ctx, DEFAULT_RECEIVE_TIMEOUT ); + timeout = pSSL_CTX_get_timeout( ctx ); + pSSL_CTX_set_timeout( ctx, DEFAULT_RECEIVE_TIMEOUT );
while (recvd < *buflen) { @@ -509,7 +504,7 @@ } if (buffer[recvd] != '\r') recvd++; } - pSSL_CTX_set_timeout( conn->ssl_ctx, timeout ); + pSSL_CTX_set_timeout( ctx, timeout ); if (ret) { buffer[recvd++] = 0; @@ -567,7 +562,7 @@ tv.tv_sec = value / 1000; tv.tv_usec = (value % 1000) * 1000;
- if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, &tv, sizeof(tv) ) == -1)) + if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1)) { WARN("setsockopt failed (%s)\n", strerror( errno )); return sock_get_error( errno ); @@ -595,7 +590,7 @@ heap_free( hostname ); if (ret != 0) { - TRACE("failed to get address of %s (%s)\n", debugstr_a(hostname), gai_strerror(ret)); + TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret)); return FALSE; } memset( sa, 0, sizeof(struct sockaddr_in) ); @@ -611,12 +606,12 @@ heap_free( hostname ); if (!he) { - TRACE("failed to get address of %s (%d)\n", debugstr_a(hostname), h_errno); + TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno); LeaveCriticalSection( &cs_gethostbyname ); return FALSE; } memset( sa, 0, sizeof(struct sockaddr_in) ); - memcpy( (char *)&sa->sin_addr, he->h_addr, he->h_length ); + memcpy( &sa->sin_addr, he->h_addr, he->h_length ); sa->sin_family = he->h_addrtype; sa->sin_port = htons( port );
@@ -624,3 +619,46 @@ #endif return TRUE; } + +const void *netconn_get_certificate( netconn_t *conn ) +{ +#ifdef SONAME_LIBSSL + X509 *cert; + unsigned char *buffer, *p; + int len; + BOOL malloc = FALSE; + const CERT_CONTEXT *ret; + + if (!conn->secure) return NULL; + + if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL; + p = NULL; + if ((len = pi2d_X509( cert, &p )) < 0) return NULL; + /* + * SSL 0.9.7 and above malloc the buffer if it is null. + * however earlier version do not and so we would need to alloc the buffer. + * + * see the i2d_X509 man page for more details. + */ + if (!p) + { + if (!(buffer = heap_alloc( len ))) return NULL; + p = buffer; + len = pi2d_X509( cert, &p ); + } + else + { + buffer = p; + malloc = TRUE; + } + + ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len ); + + if (malloc) free( buffer ); + else heap_free( buffer ); + + return ret; +#else + return NULL; +#endif +}
Modified: trunk/reactos/dll/win32/winhttp/request.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/request.c... ============================================================================== --- trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/request.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -175,6 +175,22 @@ NULL /* WINHTTP_QUERY_PASSPORT_CONFIG = 78 */ };
+static DWORD CALLBACK task_thread( LPVOID param ) +{ + task_header_t *task = param; + + task->proc( task ); + + release_object( &task->request->hdr ); + heap_free( task ); + return ERROR_SUCCESS; +} + +static BOOL queue_task( task_header_t *task ) +{ + return QueueUserWorkItem( task_thread, task, WT_EXECUTELONGFUNCTION ); +} + static void free_header( header_t *header ) { heap_free( header->field ); @@ -391,13 +407,13 @@ return TRUE; }
-static BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags ) +BOOL add_request_headers( request_t *request, LPCWSTR headers, DWORD len, DWORD flags ) { BOOL ret = FALSE; WCHAR *buffer, *p, *q; header_t *header;
- if (len == ~0UL) len = strlenW( headers ); + if (len == ~0u) len = strlenW( headers ); if (!(buffer = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; strcpyW( buffer, headers );
@@ -467,28 +483,20 @@ static const WCHAR crlf[] = {'\r','\n',0}; static const WCHAR colon[] = {':',' ',0}; static const WCHAR twocrlf[] = {'\r','\n','\r','\n',0}; - static const WCHAR get[] = {'G','E','T',0}; - static const WCHAR slash[] = {'/',0}; - static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0};
WCHAR *ret; const WCHAR **headers, **p; - const WCHAR *verb = get, *path = slash, *version = http1_1; unsigned int len, i = 0, j; - - if (request->verb && request->verb[0]) verb = request->verb; - if (request->path && request->path[0]) path = request->path; - if (request->version && request->version[0]) version = request->version;
/* allocate space for an array of all the string pointers to be added */ len = request->num_headers * 4 + 7; if (!(headers = heap_alloc( len * sizeof(LPCWSTR) ))) return NULL;
- headers[i++] = verb; + headers[i++] = request->verb; headers[i++] = space; - headers[i++] = path; + headers[i++] = request->path; headers[i++] = space; - headers[i++] = version; + headers[i++] = request->version;
for (j = 0; j < request->num_headers; j++) { @@ -561,7 +569,7 @@ } else if (buffer) { - for (p = headers, q = (WCHAR *)buffer; *p; p++, q++) + for (p = headers, q = buffer; *p; p++, q++) { if (*p != '\r') *q = *p; else @@ -571,7 +579,7 @@ } } *q = 0; - TRACE("returning data: %s\n", debugstr_wn((WCHAR *)buffer, len)); + TRACE("returning data: %s\n", debugstr_wn(buffer, len)); ret = TRUE; } *buflen = len * sizeof(WCHAR); @@ -606,7 +614,7 @@ } default: { - if (attr > sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr]) + if (attr >= sizeof(attribute_table)/sizeof(attribute_table[0]) || !attribute_table[attr]) { FIXME("attribute %u not implemented\n", attr); return FALSE; @@ -710,13 +718,16 @@ connect_t *connect; char address[32]; WCHAR *addressW; + INTERNET_PORT port;
if (netconn_connected( &request->netconn )) return TRUE; + connect = request->connect; + port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, connect->servername, strlenW(connect->servername) + 1 );
- if (!netconn_resolve( connect->servername, connect->serverport, &connect->sockaddr )) return FALSE; + if (!netconn_resolve( connect->servername, port, &connect->sockaddr )) return FALSE; inet_ntop( connect->sockaddr.sin_family, &connect->sockaddr.sin_addr, address, sizeof(address) ); addressW = strdupAW( address );
@@ -759,32 +770,35 @@ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 ); }
-static BOOL add_host_header( request_t *request, WCHAR *hostname, INTERNET_PORT port, DWORD modifier ) +static BOOL add_host_header( request_t *request, DWORD modifier ) { BOOL ret; DWORD len; WCHAR *host; static const WCHAR fmt[] = {'%','s',':','%','u',0}; + connect_t *connect = request->connect; + INTERNET_PORT port; + + port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80);
if (port == INTERNET_DEFAULT_HTTP_PORT || port == INTERNET_DEFAULT_HTTPS_PORT) { - return process_header( request, attr_host, hostname, modifier, TRUE ); - } - len = strlenW( hostname ) + 7; /* sizeof(":65335") */ + return process_header( request, attr_host, connect->hostname, modifier, TRUE ); + } + len = strlenW( connect->hostname ) + 7; /* sizeof(":65335") */ if (!(host = heap_alloc( len * sizeof(WCHAR) ))) return FALSE; - sprintfW( host, fmt, hostname, port ); + sprintfW( host, fmt, connect->hostname, port ); ret = process_header( request, attr_host, host, modifier, TRUE ); heap_free( host ); return ret; }
static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional, - DWORD optional_len, DWORD total_len, DWORD_PTR context ) + DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async ) { static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0}; static const WCHAR no_cache[] = {'n','o','-','c','a','c','h','e',0}; static const WCHAR length_fmt[] = {'%','l','d',0}; - static const WCHAR post[] = {'P','O','S','T',0};
BOOL ret = FALSE; connect_t *connect = request->connect; @@ -798,9 +812,9 @@ process_header( request, attr_user_agent, session->agent, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE );
if (connect->hostname) - add_host_header( request, connect->hostname, connect->hostport, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ); - - if (total_len || (request->verb && !strcmpW( request->verb, post ))) + add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ); + + if (total_len || (request->verb && !strcmpW( request->verb, postW ))) { WCHAR length[21]; /* decimal long int + null */ sprintfW( length, length_fmt, total_len ); @@ -820,6 +834,11 @@ TRACE("failed to add request headers\n"); return FALSE; } + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES) && !add_cookie_headers( request )) + { + WARN("failed to add cookie headers\n"); + return FALSE; + }
if (!(ret = open_connection( request ))) goto end; if (!(req = build_request_string( request ))) goto end; @@ -840,8 +859,26 @@ send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(DWORD) );
end: + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NULL, 0 ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_SEND_REQUEST; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } heap_free( req ); return ret; +} + +static void task_send_request( task_header_t *task ) +{ + send_request_t *s = (send_request_t *)task; + send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); + heap_free( s->headers ); }
/*********************************************************************** @@ -868,7 +905,25 @@ return FALSE; }
- ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context ); + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + send_request_t *s; + + if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE; + s->hdr.request = request; + s->hdr.proc = task_send_request; + s->headers = strdupW( headers ); + s->headers_len = headers_len; + s->optional = optional; + s->optional_len = optional_len; + s->total_len = total_len; + s->context = context; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)s ); + } + else + ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE );
release_object( &request->hdr ); return ret; @@ -889,9 +944,9 @@ }
#define MAX_REPLY_LEN 1460 -#define INITIAL_HEADER_BUFFER_SIZE 512 - -static BOOL receive_response( request_t *request, BOOL clear ) +#define INITIAL_HEADER_BUFFER_LEN 512 + +static BOOL read_reply( request_t *request ) { static const WCHAR crlf[] = {'\r','\n',0};
@@ -902,9 +957,6 @@ WCHAR status_codeW[4]; /* sizeof("nnn") */
if (!netconn_connected( &request->netconn )) return FALSE; - - /* clear old response headers (eg. from a redirect response) */ - if (clear) clear_response_headers( request );
send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 );
@@ -949,7 +1001,7 @@ heap_free( request->status_text ); request->status_text = status_textW;
- len = max( buflen + crlf_len, INITIAL_HEADER_BUFFER_SIZE ); + len = max( buflen + crlf_len, INITIAL_HEADER_BUFFER_LEN ); if (!(raw_headers = heap_alloc( len * sizeof(WCHAR) ))) return FALSE; MultiByteToWideChar( CP_ACP, 0, buffer, buflen, raw_headers, buflen ); memcpy( raw_headers + buflen - 1, crlf, sizeof(crlf) ); @@ -1002,6 +1054,7 @@ connect_t *connect = request->connect; INTERNET_PORT port; WCHAR *hostname = NULL, *location = NULL; + int index;
size = 0; query_headers( request, WINHTTP_QUERY_LOCATION, NULL, NULL, &size, NULL ); @@ -1012,48 +1065,73 @@
memset( &uc, 0, sizeof(uc) ); uc.dwStructSize = sizeof(uc); - uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0UL; - - if (!(ret = WinHttpCrackUrl( location, size / sizeof(WCHAR), 0, &uc ))) goto end; - - if (uc.nScheme == INTERNET_SCHEME_HTTP && request->hdr.flags & WINHTTP_FLAG_SECURE) - { - TRACE("redirect from secure page to non-secure page\n"); - request->hdr.flags &= ~WINHTTP_FLAG_SECURE; - } - else if (uc.nScheme == INTERNET_SCHEME_HTTPS && !(request->hdr.flags & WINHTTP_FLAG_SECURE)) - { - TRACE("redirect from non-secure page to secure page\n"); - request->hdr.flags |= WINHTTP_FLAG_SECURE; - } - - len = uc.dwHostNameLength; - if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - memcpy( hostname, uc.lpszHostName, len * sizeof(WCHAR) ); - hostname[len] = 0; - - port = uc.nPort ? uc.nPort : (uc.nScheme == INTERNET_SCHEME_HTTPS ? 443 : 80); - if (strcmpiW( connect->servername, hostname ) || connect->serverport != port) - { - heap_free( connect->servername ); - connect->servername = hostname; - connect->serverport = connect->hostport = port; - - netconn_close( &request->netconn ); - if (!(ret = netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE ))) goto end; - } - if (!(ret = add_host_header( request, hostname, port, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end; - if (!(ret = open_connection( request ))) goto end; - - heap_free( request->path ); - request->path = NULL; - if (uc.lpszUrlPath) - { - len = uc.dwUrlPathLength + uc.dwExtraInfoLength; - if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; - strcpyW( request->path, uc.lpszUrlPath ); - } - + uc.dwSchemeLength = uc.dwHostNameLength = uc.dwUrlPathLength = uc.dwExtraInfoLength = ~0u; + + if (!WinHttpCrackUrl( location, size / sizeof(WCHAR), 0, &uc )) /* assume relative redirect */ + { + WCHAR *path, *p; + + len = strlenW( location ) + 1; + if (location[0] != '/') len++; + if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end; + + if (location[0] != '/') *p++ = '/'; + strcpyW( p, location ); + + heap_free( request->path ); + request->path = path; + } + else + { + if (uc.nScheme == INTERNET_SCHEME_HTTP && request->hdr.flags & WINHTTP_FLAG_SECURE) + { + TRACE("redirect from secure page to non-secure page\n"); + request->hdr.flags &= ~WINHTTP_FLAG_SECURE; + } + else if (uc.nScheme == INTERNET_SCHEME_HTTPS && !(request->hdr.flags & WINHTTP_FLAG_SECURE)) + { + TRACE("redirect from non-secure page to secure page\n"); + request->hdr.flags |= WINHTTP_FLAG_SECURE; + } + + len = uc.dwHostNameLength; + if (!(hostname = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; + memcpy( hostname, uc.lpszHostName, len * sizeof(WCHAR) ); + hostname[len] = 0; + + port = uc.nPort ? uc.nPort : (uc.nScheme == INTERNET_SCHEME_HTTPS ? 443 : 80); + if (strcmpiW( connect->servername, hostname ) || connect->serverport != port) + { + heap_free( connect->hostname ); + connect->hostname = hostname; + heap_free( connect->servername ); + connect->servername = strdupW( connect->hostname ); + connect->serverport = connect->hostport = port; + + netconn_close( &request->netconn ); + if (!(ret = netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE ))) goto end; + } + if (!(ret = add_host_header( request, WINHTTP_ADDREQ_FLAG_REPLACE ))) goto end; + if (!(ret = open_connection( request ))) goto end; + + heap_free( request->path ); + request->path = NULL; + if (uc.dwUrlPathLength) + { + len = uc.dwUrlPathLength + uc.dwExtraInfoLength; + if (!(request->path = heap_alloc( (len + 1) * sizeof(WCHAR) ))) goto end; + strcpyW( request->path, uc.lpszUrlPath ); + } + else request->path = strdupW( slashW ); + } + + /* remove content-type/length headers */ + if ((index = get_header_index( request, attr_content_type, 0, TRUE )) >= 0) delete_header( request, index ); + if ((index = get_header_index( request, attr_content_length, 0, TRUE )) >= 0 ) delete_header( request, index ); + + /* redirects are always GET requests */ + heap_free( request->verb ); + request->verb = strdupW( getW ); ret = TRUE;
end: @@ -1062,7 +1140,7 @@ return ret; }
-static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) +static BOOL receive_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) { DWORD to_read; int bytes_read; @@ -1081,99 +1159,6 @@ request->content_read += bytes_read; *read = bytes_read; return TRUE; -} - -/* read any content returned by the server so that the connection can be reused */ -static void drain_content( request_t *request ) -{ - DWORD bytes_read; - char buffer[2048]; - - if (request->content_length == ~0UL) return; - for (;;) - { - if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return; - } -} - -/*********************************************************************** - * WinHttpReceiveResponse (winhttp.@) - */ -BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) -{ - BOOL ret = TRUE; - request_t *request; - DWORD size, query, status; - - TRACE("%p, %p\n", hrequest, reserved); - - if (!(request = (request_t *)grab_object( hrequest ))) - { - set_last_error( ERROR_INVALID_HANDLE ); - return FALSE; - } - if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) - { - release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); - return FALSE; - } - - for (;;) - { - if (!(ret = receive_response( request, TRUE ))) break; - - size = sizeof(DWORD); - query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; - if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break; - - size = sizeof(DWORD); - query = WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER; - if (!query_headers( request, query, NULL, &request->content_length, &size, NULL )) - request->content_length = ~0UL; - - if (status == 200) break; - if (status == 301 || status == 302) - { - if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS) break; - drain_content( request ); - if (!(ret = handle_redirect( request ))) break; - } - ret = send_request( request, NULL, 0, NULL, 0, 0, 0 ); - } - - release_object( &request->hdr ); - return ret; -} - -/*********************************************************************** - * WinHttpQueryDataAvailable (winhttp.@) - */ -BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) -{ - BOOL ret; - DWORD num_bytes; - request_t *request; - - TRACE("%p, %p\n", hrequest, available); - - if (!(request = (request_t *)grab_object( hrequest ))) - { - set_last_error( ERROR_INVALID_HANDLE ); - return FALSE; - } - if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) - { - release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); - return FALSE; - } - - ret = netconn_query_data_available( &request->netconn, &num_bytes ); - - if (ret && available) *available = num_bytes; - release_object( &request->hdr ); - return ret; }
static DWORD get_chunk_size( const char *buffer ) @@ -1191,7 +1176,7 @@ return size; }
-static BOOL read_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) +static BOOL receive_data_chunked( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) { char reply[MAX_REPLY_LEN], *p = buffer; DWORD buflen, to_read, to_write = size; @@ -1202,7 +1187,7 @@ { if (*read == size) break;
- if (request->content_length == ~0UL) /* new chunk */ + if (request->content_length == ~0u) /* new chunk */ { buflen = sizeof(reply); if (!netconn_get_next_line( &request->netconn, reply, &buflen )) break; @@ -1210,7 +1195,7 @@ if (!(request->content_length = get_chunk_size( reply ))) { /* zero sized chunk marks end of transfer; read any trailing headers and return */ - receive_response( request, FALSE ); + read_reply( request ); break; } } @@ -1236,7 +1221,7 @@ if (request->content_read == request->content_length) /* chunk complete */ { request->content_read = 0; - request->content_length = ~0UL; + request->content_length = ~0u;
buflen = sizeof(reply); if (!netconn_get_next_line( &request->netconn, reply, &buflen )) @@ -1250,17 +1235,285 @@ return TRUE; }
+static void finished_reading( request_t *request ) +{ + static const WCHAR closeW[] = {'c','l','o','s','e',0}; + + BOOL close = FALSE; + WCHAR connection[20]; + DWORD size = sizeof(connection); + + if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE; + else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) || + query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL )) + { + if (!strcmpiW( connection, closeW )) close = TRUE; + } + else if (!strcmpW( request->version, http1_0 )) close = TRUE; + + if (close) close_connection( request ); + request->content_length = ~0u; + request->content_read = 0; +} + +static BOOL read_data( request_t *request, void *buffer, DWORD to_read, DWORD *read, BOOL async ) +{ + static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0}; + + BOOL ret; + WCHAR encoding[20]; + DWORD num_bytes, buflen = sizeof(encoding); + + if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) && + !strcmpiW( encoding, chunked )) + { + ret = receive_data_chunked( request, buffer, to_read, &num_bytes, async ); + } + else + ret = receive_data( request, buffer, to_read, &num_bytes, async ); + + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, num_bytes ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_READ_DATA; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + if (ret) + { + if (read) *read = num_bytes; + if (!num_bytes) finished_reading( request ); + } + return ret; +} + +/* read any content returned by the server so that the connection can be reused */ +static void drain_content( request_t *request ) +{ + DWORD bytes_read; + char buffer[2048]; + + if (!request->content_length) return; + for (;;) + { + if (!read_data( request, buffer, sizeof(buffer), &bytes_read, FALSE ) || !bytes_read) return; + } +} + +static void record_cookies( request_t *request ) +{ + unsigned int i; + + for (i = 0; i < request->num_headers; i++) + { + header_t *set_cookie = &request->headers[i]; + if (!strcmpiW( set_cookie->field, attr_set_cookie ) && !set_cookie->is_request) + { + set_cookies( request, set_cookie->value ); + } + } +} + +static BOOL receive_response( request_t *request, BOOL async ) +{ + BOOL ret; + DWORD size, query, status; + + for (;;) + { + if (!(ret = read_reply( request ))) break; + + size = sizeof(DWORD); + query = WINHTTP_QUERY_STATUS_CODE | WINHTTP_QUERY_FLAG_NUMBER; + if (!(ret = query_headers( request, query, NULL, &status, &size, NULL ))) break; + + size = sizeof(DWORD); + query = WINHTTP_QUERY_CONTENT_LENGTH | WINHTTP_QUERY_FLAG_NUMBER; + if (!query_headers( request, query, NULL, &request->content_length, &size, NULL )) + request->content_length = ~0u; + + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES)) record_cookies( request ); + + if (status == 301 || status == 302) + { + if (request->hdr.disable_flags & WINHTTP_DISABLE_REDIRECTS) break; + + drain_content( request ); + if (!(ret = handle_redirect( request ))) break; + + clear_response_headers( request ); + ret = send_request( request, NULL, 0, NULL, 0, 0, 0, FALSE ); /* recurse synchronously */ + continue; + } + if (status == 401) FIXME("authentication not supported\n"); + break; + } + + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_HEADERS_AVAILABLE, NULL, 0 ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_RECEIVE_RESPONSE; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + return ret; +} + +static void task_receive_response( task_header_t *task ) +{ + receive_response_t *r = (receive_response_t *)task; + receive_response( r->hdr.request, TRUE ); +} + +/*********************************************************************** + * WinHttpReceiveResponse (winhttp.@) + */ +BOOL WINAPI WinHttpReceiveResponse( HINTERNET hrequest, LPVOID reserved ) +{ + BOOL ret; + request_t *request; + + TRACE("%p, %p\n", hrequest, reserved); + + if (!(request = (request_t *)grab_object( hrequest ))) + { + set_last_error( ERROR_INVALID_HANDLE ); + return FALSE; + } + if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + { + release_object( &request->hdr ); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; + } + + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + receive_response_t *r; + + if (!(r = heap_alloc( sizeof(receive_response_t) ))) return FALSE; + r->hdr.request = request; + r->hdr.proc = task_receive_response; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)r ); + } + else + ret = receive_response( request, FALSE ); + + release_object( &request->hdr ); + return ret; +} + +static BOOL query_data( request_t *request, LPDWORD available, BOOL async ) +{ + BOOL ret; + DWORD num_bytes; + + if ((ret = netconn_query_data_available( &request->netconn, &num_bytes ))) + { + if (request->content_read < request->content_length) + { + if (!num_bytes) + { + char buffer[4096]; + size_t to_read = min( sizeof(buffer), request->content_length - request->content_read ); + + ret = netconn_recv( &request->netconn, buffer, to_read, MSG_PEEK, (int *)&num_bytes ); + if (ret && !num_bytes) WARN("expected more data to be available\n"); + } + } + else if (num_bytes) + { + WARN("extra data available %u\n", num_bytes); + ret = FALSE; + } + } + TRACE("%u bytes available\n", num_bytes); + + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_DATA_AVAILABLE, &num_bytes, sizeof(DWORD) ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_QUERY_DATA_AVAILABLE; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + if (ret && available) *available = num_bytes; + return ret; +} + +static void task_query_data( task_header_t *task ) +{ + query_data_t *q = (query_data_t *)task; + query_data( q->hdr.request, q->available, TRUE ); +} + +/*********************************************************************** + * WinHttpQueryDataAvailable (winhttp.@) + */ +BOOL WINAPI WinHttpQueryDataAvailable( HINTERNET hrequest, LPDWORD available ) +{ + BOOL ret; + request_t *request; + + TRACE("%p, %p\n", hrequest, available); + + if (!(request = (request_t *)grab_object( hrequest ))) + { + set_last_error( ERROR_INVALID_HANDLE ); + return FALSE; + } + if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + { + release_object( &request->hdr ); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; + } + + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + query_data_t *q; + + if (!(q = heap_alloc( sizeof(query_data_t) ))) return FALSE; + q->hdr.request = request; + q->hdr.proc = task_query_data; + q->available = available; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)q ); + } + else + ret = query_data( request, available, FALSE ); + + release_object( &request->hdr ); + return ret; +} + +static void task_read_data( task_header_t *task ) +{ + read_data_t *r = (read_data_t *)task; + read_data( r->hdr.request, r->buffer, r->to_read, r->read, TRUE ); +} + /*********************************************************************** * WinHttpReadData (winhttp.@) */ BOOL WINAPI WinHttpReadData( HINTERNET hrequest, LPVOID buffer, DWORD to_read, LPDWORD read ) { - static const WCHAR chunked[] = {'c','h','u','n','k','e','d',0}; - BOOL ret; request_t *request; - WCHAR encoding[20]; - DWORD num_bytes, buflen = sizeof(encoding);
TRACE("%p, %p, %d, %p\n", hrequest, buffer, to_read, read);
@@ -1276,17 +1529,53 @@ return FALSE; }
- if (query_headers( request, WINHTTP_QUERY_TRANSFER_ENCODING, NULL, encoding, &buflen, NULL ) && - !strcmpiW( encoding, chunked )) - { - ret = read_data_chunked( request, buffer, to_read, &num_bytes, request->hdr.flags & WINHTTP_FLAG_ASYNC ); + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + read_data_t *r; + + if (!(r = heap_alloc( sizeof(read_data_t) ))) return FALSE; + r->hdr.request = request; + r->hdr.proc = task_read_data; + r->buffer = buffer; + r->to_read = to_read; + r->read = read; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)r ); } else - ret = read_data( request, buffer, to_read, &num_bytes, request->hdr.flags & WINHTTP_FLAG_ASYNC ); - - if (ret && read) *read = num_bytes; + ret = read_data( request, buffer, to_read, read, FALSE ); + release_object( &request->hdr ); return ret; +} + +static BOOL write_data( request_t *request, LPCVOID buffer, DWORD to_write, LPDWORD written, BOOL async ) +{ + BOOL ret; + int num_bytes; + + ret = netconn_send( &request->netconn, buffer, to_write, 0, &num_bytes ); + + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_WRITE_COMPLETE, &num_bytes, sizeof(DWORD) ); + else + { + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_WRITE_DATA; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + } + } + if (ret && written) *written = num_bytes; + return ret; +} + +static void task_write_data( task_header_t *task ) +{ + write_data_t *w = (write_data_t *)task; + write_data( w->hdr.request, w->buffer, w->to_write, w->written, TRUE ); }
/*********************************************************************** @@ -1311,7 +1600,22 @@ return FALSE; }
- ret = netconn_send( &request->netconn, buffer, to_write, 0, (int *)written ); + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + write_data_t *w; + + if (!(w = heap_alloc( sizeof(write_data_t) ))) return FALSE; + w->hdr.request = request; + w->hdr.proc = task_write_data; + w->buffer = buffer; + w->to_write = to_write; + w->written = written; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)w ); + } + else + ret = write_data( request, buffer, to_write, written, FALSE );
release_object( &request->hdr ); return ret;
Modified: trunk/reactos/dll/win32/winhttp/session.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/session.c... ============================================================================== --- trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/session.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -25,6 +25,7 @@ #include "windef.h" #include "winbase.h" #include "winhttp.h" +#include "wincrypt.h"
#include "winhttp_private.h"
@@ -36,11 +37,17 @@ SetLastError( error ); }
+DWORD get_last_error( void ) +{ + /* FIXME */ + return GetLastError(); +} + void send_callback( object_header_t *hdr, DWORD status, LPVOID info, DWORD buflen ) { TRACE("%p, 0x%08x, %p, %u\n", hdr, status, info, buflen);
- if (hdr->notify_mask & status) hdr->callback( hdr->handle, hdr->context, status, info, buflen ); + if (hdr->callback && (hdr->notify_mask & status)) hdr->callback( hdr->handle, hdr->context, status, info, buflen ); }
/*********************************************************************** @@ -58,9 +65,16 @@ static void session_destroy( object_header_t *hdr ) { session_t *session = (session_t *)hdr; + struct list *item, *next; + domain_t *domain;
TRACE("%p\n", session);
+ LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) + { + domain = LIST_ENTRY( item, domain_t, entry ); + delete_domain( domain ); + } heap_free( session->agent ); heap_free( session->proxy_server ); heap_free( session->proxy_bypass ); @@ -69,6 +83,30 @@ heap_free( session ); }
+static BOOL session_query_option( object_header_t *hdr, DWORD option, LPVOID buffer, LPDWORD buflen ) +{ + switch (option) + { + case WINHTTP_OPTION_REDIRECT_POLICY: + { + if (!buffer || *buflen < sizeof(DWORD)) + { + *buflen = sizeof(DWORD); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + *(DWORD *)buffer = hdr->redirect_policy; + *buflen = sizeof(DWORD); + return TRUE; + } + default: + FIXME("unimplemented option %u\n", option); + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } +} + static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffer, DWORD buflen ) { switch (option) @@ -82,22 +120,33 @@ } case WINHTTP_OPTION_REDIRECT_POLICY: { - DWORD policy = *(DWORD *)buffer; - + DWORD policy; + + if (buflen != sizeof(policy)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + policy = *(DWORD *)buffer; TRACE("0x%x\n", policy); hdr->redirect_policy = policy; return TRUE; } + case WINHTTP_OPTION_DISABLE_FEATURE: + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; default: FIXME("unimplemented option %u\n", option); - return TRUE; + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; } }
static const object_vtbl_t session_vtbl = { session_destroy, - NULL, + session_query_option, session_set_option };
@@ -118,6 +167,8 @@ session->hdr.flags = flags; session->hdr.refs = 1; session->access = access; + session->hdr.redirect_policy = WINHTTP_OPTION_REDIRECT_POLICY_DISALLOW_HTTPS_TO_HTTP; + list_init( &session->cookie_cache );
if (agent && !(session->agent = strdupW( agent ))) goto end; if (proxy && !(session->proxy_server = strdupW( proxy ))) goto end; @@ -202,10 +253,10 @@ list_add_head( &session->hdr.children, &connect->hdr.entry );
if (server && !(connect->hostname = strdupW( server ))) goto end; - connect->hostport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + connect->hostport = port;
if (server && !(connect->servername = strdupW( server ))) goto end; - connect->serverport = port ? port : (connect->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + connect->serverport = port;
if (!(hconnect = alloc_handle( &connect->hdr ))) goto end; connect->hdr.handle = hconnect; @@ -225,7 +276,7 @@ static void request_destroy( object_header_t *hdr ) { request_t *request = (request_t *)hdr; - int i; + DWORD i;
TRACE("%p\n", request);
@@ -251,15 +302,54 @@ { case WINHTTP_OPTION_SECURITY_FLAGS: { - DWORD flags = 0; - + DWORD flags; + + if (!buffer || *buflen < sizeof(flags)) + { + *buflen = sizeof(flags); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + flags = 0; if (hdr->flags & WINHTTP_FLAG_SECURE) flags |= SECURITY_FLAG_SECURE; *(DWORD *)buffer = flags; + *buflen = sizeof(flags); + return TRUE; + } + case WINHTTP_OPTION_SERVER_CERT_CONTEXT: + { + const CERT_CONTEXT *cert; + request_t *request = (request_t *)hdr; + + if (!buffer || *buflen < sizeof(cert)) + { + *buflen = sizeof(cert); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + if (!(cert = netconn_get_certificate( &request->netconn ))) return FALSE; + *(CERT_CONTEXT **)buffer = (CERT_CONTEXT *)cert; + *buflen = sizeof(cert); + return TRUE; + } + case WINHTTP_OPTION_SECURITY_KEY_BITNESS: + { + if (!buffer || *buflen < sizeof(DWORD)) + { + *buflen = sizeof(DWORD); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + *(DWORD *)buffer = 128; /* FIXME */ *buflen = sizeof(DWORD); return TRUE; } default: FIXME("unimplemented option %u\n", option); + set_last_error( ERROR_INVALID_PARAMETER ); return FALSE; } } @@ -277,30 +367,52 @@ } case WINHTTP_OPTION_DISABLE_FEATURE: { - DWORD disable = *(DWORD *)buffer; - + DWORD disable; + + if (buflen != sizeof(DWORD)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + disable = *(DWORD *)buffer; TRACE("0x%x\n", disable); - hdr->disable_flags &= disable; + hdr->disable_flags |= disable; return TRUE; } case WINHTTP_OPTION_AUTOLOGON_POLICY: { - DWORD policy = *(DWORD *)buffer; - + DWORD policy; + + if (buflen != sizeof(DWORD)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + policy = *(DWORD *)buffer; TRACE("0x%x\n", policy); hdr->logon_policy = policy; return TRUE; } case WINHTTP_OPTION_REDIRECT_POLICY: { - DWORD policy = *(DWORD *)buffer; - + DWORD policy; + + if (buflen != sizeof(DWORD)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + policy = *(DWORD *)buffer; TRACE("0x%x\n", policy); hdr->redirect_policy = policy; return TRUE; } default: FIXME("unimplemented option %u\n", option); + set_last_error( ERROR_INVALID_PARAMETER ); return TRUE; } } @@ -355,9 +467,26 @@
if (!netconn_init( &request->netconn, request->hdr.flags & WINHTTP_FLAG_SECURE )) goto end;
- if (verb && !(request->verb = strdupW( verb ))) goto end; - if (object && !(request->path = strdupW( object ))) goto end; - if (version && !(request->version = strdupW( version ))) goto end; + if (!verb || !verb[0]) verb = getW; + if (!(request->verb = strdupW( verb ))) goto end; + + if (object) + { + WCHAR *path, *p; + unsigned int len; + + len = strlenW( object ) + 1; + if (object[0] != '/') len++; + if (!(p = path = heap_alloc( len * sizeof(WCHAR) ))) goto end; + + if (object[0] != '/') *p++ = '/'; + strcpyW( p, object ); + request->path = path; + } + else if (!(request->path = strdupW( slashW ))) goto end; + + if (!version || !version[0]) version = http1_1; + if (!(request->version = strdupW( version ))) goto end;
if (!(hrequest = alloc_handle( &request->hdr ))) goto end; request->hdr.handle = hrequest; @@ -394,19 +523,36 @@ { BOOL ret = FALSE;
+ if (!buflen) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + switch (option) { case WINHTTP_OPTION_CONTEXT_VALUE: { + if (!buffer || *buflen < sizeof(DWORD_PTR)) + { + *buflen = sizeof(DWORD_PTR); + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + *(DWORD_PTR *)buffer = hdr->context; *buflen = sizeof(DWORD_PTR); return TRUE; } default: - { if (hdr->vtbl->query_option) ret = hdr->vtbl->query_option( hdr, option, buffer, buflen ); - else FIXME("unimplemented option %u\n", option); - } + else + { + FIXME("unimplemented option %u\n", option); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; + } + break; } return ret; } @@ -437,18 +583,34 @@ { BOOL ret = TRUE;
+ if (!buffer) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + switch (option) { case WINHTTP_OPTION_CONTEXT_VALUE: { + if (buflen != sizeof(DWORD_PTR)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + hdr->context = *(DWORD_PTR *)buffer; return TRUE; } default: - { if (hdr->vtbl->set_option) ret = hdr->vtbl->set_option( hdr, option, buffer, buflen ); - else FIXME("unimplemented option %u\n", option); - } + else + { + FIXME("unimplemented option %u\n", option); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; + } + break; } return ret; }
Added: trunk/reactos/dll/win32/winhttp/url.c URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/url.c?rev... ============================================================================== --- trunk/reactos/dll/win32/winhttp/url.c (added) +++ trunk/reactos/dll/win32/winhttp/url.c [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -1,0 +1,484 @@ +/* + * Copyright 2008 Hans Leidekker for CodeWeavers + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include "config.h" +#include <stdarg.h> + +#include "wine/debug.h" + +#include "windef.h" +#include "winbase.h" +#include "winreg.h" +#include "winhttp.h" +#include "shlwapi.h" + +#include "winhttp_private.h" + +WINE_DEFAULT_DEBUG_CHANNEL(winhttp); + +static const WCHAR scheme_http[] = {'h','t','t','p',0}; +static const WCHAR scheme_https[] = {'h','t','t','p','s',0}; + +static BOOL set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags ) +{ + if (!*str) + { + if (len && (flags & ICU_DECODE)) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + *str = value; + *str_len = len; + } + else + { + if (len > (*str_len) - 1) + { + *str_len = len + 1; + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + memcpy( *str, value, len * sizeof(WCHAR) ); + (*str)[len] = 0; + *str_len = len; + } + return TRUE; +} + +static BOOL decode_url( LPCWSTR url, LPWSTR buffer, LPDWORD buflen ) +{ + HRESULT hr = UrlCanonicalizeW( url, buffer, buflen, URL_WININET_COMPATIBILITY | URL_UNESCAPE ); + if (hr == E_POINTER) set_last_error( ERROR_INSUFFICIENT_BUFFER ); + if (hr == E_INVALIDARG) set_last_error( ERROR_INVALID_PARAMETER ); + return (SUCCEEDED(hr)) ? TRUE : FALSE; +} + +/*********************************************************************** + * WinHttpCrackUrl (winhttp.@) + */ +BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc ) +{ + BOOL ret = FALSE; + WCHAR *p, *q, *r; + WCHAR *url_decoded = NULL; + + TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, uc); + + if (flags & ICU_ESCAPE) FIXME("flag ICU_ESCAPE not supported\n"); + + if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS)) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + if (!len) len = strlenW( url ); + + if (flags & ICU_DECODE) + { + WCHAR *url_tmp; + DWORD url_len = len + 1; + + if (!(url_tmp = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) ))) + { + set_last_error( ERROR_OUTOFMEMORY ); + return FALSE; + } + memcpy( url_tmp, url, len * sizeof(WCHAR) ); + url_tmp[len] = 0; + if (!(url_decoded = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) ))) + { + HeapFree( GetProcessHeap(), 0, url_tmp ); + set_last_error( ERROR_OUTOFMEMORY ); + return FALSE; + } + if (decode_url( url_tmp, url_decoded, &url_len )) + { + len = url_len; + url = url_decoded; + } + HeapFree( GetProcessHeap(), 0, url_tmp ); + } + if (!(p = strchrW( url, ':' ))) + { + set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ); + return FALSE; + } + if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) uc->nScheme = INTERNET_SCHEME_HTTP; + else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) uc->nScheme = INTERNET_SCHEME_HTTPS; + else + { + set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME ); + goto exit; + } + if (!(set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags ))) goto exit; + + p++; /* skip ':' */ + if (!p[0] || p[0] != '/' || p[1] != '/') goto exit; + p += 2; + + if (!p[0]) goto exit; + if ((q = memchrW( p, '@', len - (p - url) ))) + { + if ((r = memchrW( p, ':', q - p ))) + { + if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags ))) goto exit; + r++; + if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags ))) goto exit; + } + else + { + if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags ))) goto exit; + if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit; + } + p = q + 1; + } + else + { + if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags ))) goto exit; + if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit; + } + if ((q = memchrW( p, '/', len - (p - url) ))) + { + if ((r = memchrW( p, ':', q - p ))) + { + if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit; + r++; + uc->nPort = atoiW( r ); + } + else + { + if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags ))) goto exit; + if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; + if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; + } + + if ((r = memchrW( q, '?', len - (q - url) ))) + { + if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags ))) goto exit; + if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags ))) goto exit; + } + else + { + if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags ))) goto exit; + if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit; + } + } + else + { + if ((r = memchrW( p, ':', len - (p - url) ))) + { + if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit; + r++; + uc->nPort = atoiW( r ); + } + else + { + if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags ))) goto exit; + if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT; + if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT; + } + if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags ))) goto exit; + if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit; + } + + ret = TRUE; + + TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", + debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ), + debugstr_wn( uc->lpszHostName, uc->dwHostNameLength ), + uc->nPort, + debugstr_wn( uc->lpszUrlPath, uc->dwUrlPathLength ), + debugstr_wn( uc->lpszExtraInfo, uc->dwExtraInfoLength )); + +exit: + HeapFree( GetProcessHeap(), 0, url_decoded ); + return ret; +} + +static INTERNET_SCHEME get_scheme( const WCHAR *scheme, DWORD len ) +{ + if (!strncmpW( scheme, scheme_http, len )) return INTERNET_SCHEME_HTTP; + if (!strncmpW( scheme, scheme_https, len )) return INTERNET_SCHEME_HTTPS; + return 0; +} + +static const WCHAR *get_scheme_string( INTERNET_SCHEME scheme ) +{ + if (scheme == INTERNET_SCHEME_HTTP) return scheme_http; + if (scheme == INTERNET_SCHEME_HTTPS) return scheme_https; + return NULL; +} + +static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port ) +{ + if ((scheme == INTERNET_SCHEME_HTTP) && (port == INTERNET_DEFAULT_HTTP_PORT)) return TRUE; + if ((scheme == INTERNET_SCHEME_HTTPS) && (port == INTERNET_DEFAULT_HTTPS_PORT)) return TRUE; + return FALSE; +} + +static BOOL need_escape( WCHAR c ) +{ + if (isalnumW( c )) return FALSE; + + if (c <= 31 || c >= 127) return TRUE; + else + { + switch (c) + { + case ' ': + case '"': + case '#': + case '%': + case '<': + case '>': + case ']': + case '\': + case '[': + case '^': + case '`': + case '{': + case '|': + case '}': + case '~': + return TRUE; + default: + return FALSE; + } + } +} + +static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD len ) +{ + static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; + DWORD ret = len; + unsigned int i; + WCHAR *p = dst; + + for (i = 0; i < len; i++, p++) + { + if (need_escape( src[i] )) + { + p[0] = '%'; + p[1] = hex[(src[i] >> 4) & 0xf]; + p[2] = hex[src[i] & 0xf]; + ret += 2; + p += 2; + } + else *p = src[i]; + } + dst[ret] = 0; + return ret; +} + +static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp ) +{ + DWORD ret; + unsigned int i; + + ret = len ? len : strlenW( comp ); + if (!(flags & ICU_ESCAPE)) return ret; + for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2; + return ret; +} + +static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len ) +{ + static const WCHAR formatW[] = {'%','d',0}; + INTERNET_SCHEME scheme; + + *len = 0; + if (uc->lpszScheme) + { + DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + *len += scheme_len; + scheme = get_scheme( uc->lpszScheme, scheme_len ); + } + else + { + scheme = uc->nScheme; + if (!scheme) scheme = INTERNET_SCHEME_HTTP; + *len += strlenW( get_scheme_string( scheme ) ); + } + *len += 1; /* ':' */ + if (uc->lpszHostName) *len += 2; /* "//" */ + + if (uc->lpszUserName) + { + *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + *len += 1; /* "@" */ + } + else + { + if (uc->lpszPassword) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + } + if (uc->lpszPassword) + { + *len += 1; /* ":" */ + *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + } + if (uc->lpszHostName) + { + *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + + if (!uses_default_port( scheme, uc->nPort )) + { + WCHAR port[sizeof("65535")]; + + sprintfW( port, formatW, uc->nPort ); + *len += strlenW( port ); + *len += 1; /* ":" */ + } + if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */ + } + if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath ); + if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo ); + return TRUE; +} + +/*********************************************************************** + * WinHttpCreateUrl (winhttp.@) + */ +BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required ) +{ + static const WCHAR formatW[] = {'%','d',0}; + static const WCHAR twoslashW[] = {'/','/'}; + + DWORD len; + INTERNET_SCHEME scheme; + + TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required); + + if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required) + { + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; + } + + if (!calc_length( uc, flags, &len )) return FALSE; + + if (!url || *required < len) + { + *required = len + 1; + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + + url[0] = 0; + *required = len; + if (uc->lpszScheme) + { + len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme ); + memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) ); + url += len; + + scheme = get_scheme( uc->lpszScheme, len ); + } + else + { + const WCHAR *schemeW; + scheme = uc->nScheme; + + if (!scheme) scheme = INTERNET_SCHEME_HTTP; + + schemeW = get_scheme_string( scheme ); + len = strlenW( schemeW ); + memcpy( url, schemeW, len * sizeof(WCHAR) ); + url += len; + } + + /* all schemes are followed by at least a colon */ + *url = ':'; + url++; + + if (uc->lpszHostName) + { + memcpy( url, twoslashW, sizeof(twoslashW) ); + url += sizeof(twoslashW) / sizeof(twoslashW[0]); + } + if (uc->lpszUserName) + { + len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName ); + memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) ); + url += len; + + if (uc->lpszPassword) + { + *url = ':'; + url++; + + len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword ); + memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) ); + url += len; + } + *url = '@'; + url++; + } + if (uc->lpszHostName) + { + len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName ); + memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) ); + url += len; + + if (!uses_default_port( scheme, uc->nPort )) + { + WCHAR port[sizeof("65535")]; + + sprintfW( port, formatW, uc->nPort ); + *url = ':'; + url++; + + len = strlenW( port ); + memcpy( url, port, len * sizeof(WCHAR) ); + url += len; + } + + /* add slash between hostname and path if necessary */ + if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') + { + *url = '/'; + url++; + } + } + if (uc->lpszUrlPath) + { + len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath ); + if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len ); + else + { + memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) ); + url += len; + } + } + if (uc->lpszExtraInfo) + { + len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo ); + if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len ); + else + { + memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) ); + url += len; + } + } + *url = 0; + return TRUE; +}
Propchange: trunk/reactos/dll/win32/winhttp/url.c ------------------------------------------------------------------------------ svn:eol-style = native
Modified: trunk/reactos/dll/win32/winhttp/winhttp.rbuild URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp.r... ============================================================================== --- trunk/reactos/dll/win32/winhttp/winhttp.rbuild [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/winhttp.rbuild [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -7,12 +7,15 @@ <include base="winhttp">.</include> <include base="ReactOS">include/reactos/wine</include> <define name="__WINESRC__" /> + <file>cookie.c</file> <file>handle.c</file> <file>main.c</file> <file>net.c</file> <file>request.c</file> <file>session.c</file> + <file>url.c</file> <library>wine</library> + <library>shlwapi</library> <library>wininet</library> <library>ws2_32</library> <library>kernel32</library>
Modified: trunk/reactos/dll/win32/winhttp/winhttp_private.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/dll/win32/winhttp/winhttp_p... ============================================================================== --- trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] (original) +++ trunk/reactos/dll/win32/winhttp/winhttp_private.h [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -26,6 +26,7 @@ #include "wine/list.h" #include "wine/unicode.h"
+#include <sys/types.h> #ifdef HAVE_NETINET_IN_H # include <netinet/in.h> #endif @@ -33,14 +34,17 @@ # include <netdb.h> #endif #if defined(__MINGW32__) || defined (_MSC_VER) -# include "ws2tcpip.h" -# ifndef MSG_WAITALL -# define MSG_WAITALL 0 -# endif +# include <ws2tcpip.h> #else -# define closesocket close -# define ioctlsocket ioctl -#endif /* __MINGW32__ */ +# define closesocket close +# define ioctlsocket ioctl +#endif + +static const WCHAR getW[] = {'G','E','T',0}; +static const WCHAR postW[] = {'P','O','S','T',0}; +static const WCHAR slashW[] = {'/',0}; +static const WCHAR http1_0[] = {'H','T','T','P','/','1','.','0',0}; +static const WCHAR http1_1[] = {'H','T','T','P','/','1','.','1',0};
typedef struct _object_header_t object_header_t;
@@ -71,6 +75,21 @@
typedef struct { + struct list entry; + WCHAR *name; + struct list cookies; +} domain_t; + +typedef struct +{ + struct list entry; + WCHAR *name; + WCHAR *value; + WCHAR *path; +} cookie_t; + +typedef struct +{ object_header_t hdr; LPWSTR agent; DWORD access; @@ -78,6 +97,7 @@ LPWSTR proxy_bypass; LPWSTR proxy_username; LPWSTR proxy_password; + struct list cookie_cache; } session_t;
typedef struct @@ -97,7 +117,6 @@ { int socket; BOOL secure; /* SSL active on connection? */ - void *ssl_ctx; void *ssl_conn; char *peek_msg; char *peek_msg_mem; @@ -127,6 +146,52 @@ DWORD num_headers; } request_t;
+typedef struct _task_header_t task_header_t; + +struct _task_header_t +{ + request_t *request; + void (*proc)( task_header_t * ); +}; + +typedef struct +{ + task_header_t hdr; + LPWSTR headers; + DWORD headers_len; + LPVOID optional; + DWORD optional_len; + DWORD total_len; + DWORD_PTR context; +} send_request_t; + +typedef struct +{ + task_header_t hdr; +} receive_response_t; + +typedef struct +{ + task_header_t hdr; + LPDWORD available; +} query_data_t; + +typedef struct +{ + task_header_t hdr; + LPVOID buffer; + DWORD to_read; + LPDWORD read; +} read_data_t; + +typedef struct +{ + task_header_t hdr; + LPCVOID buffer; + DWORD to_write; + LPDWORD written; +} write_data_t; + object_header_t *addref_object( object_header_t * ); object_header_t *grab_object( HINTERNET ); void release_object( object_header_t * ); @@ -134,6 +199,7 @@ BOOL free_handle( HINTERNET );
void set_last_error( DWORD ); +DWORD get_last_error( void ); void send_callback( object_header_t *, DWORD, LPVOID, DWORD ); void close_connection( request_t * );
@@ -148,6 +214,12 @@ BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_in * ); BOOL netconn_secure_connect( netconn_t * ); BOOL netconn_send( netconn_t *, const void *, size_t, int, int * ); +const void *netconn_get_certificate( netconn_t * ); + +BOOL set_cookies( request_t *, const WCHAR * ); +BOOL add_cookie_headers( request_t * ); +BOOL add_request_headers( request_t *, LPCWSTR, DWORD, DWORD ); +void delete_domain( domain_t * );
static inline void *heap_alloc( SIZE_T size ) {
Modified: trunk/reactos/include/psdk/winhttp.h URL: http://svn.reactos.org/svn/reactos/trunk/reactos/include/psdk/winhttp.h?rev=... ============================================================================== --- trunk/reactos/include/psdk/winhttp.h [iso-8859-1] (original) +++ trunk/reactos/include/psdk/winhttp.h [iso-8859-1] Sun Jun 7 16:32:05 2009 @@ -35,6 +35,8 @@ #define INTERNET_SCHEME_HTTP 1 #define INTERNET_SCHEME_HTTPS 2 typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME; + +#define ICU_ESCAPE 0x80000000
/* flags for WinHttpOpen */ #define WINHTTP_FLAG_ASYNC 0x10000000