diff --git a/reactos/dll/win32/wininet/cookie.c b/reactos/dll/win32/wininet/cookie.c index 96f212b3de0..cf4ae88fc7a 100644 --- a/reactos/dll/win32/wininet/cookie.c +++ b/reactos/dll/win32/wininet/cookie.c @@ -22,6 +22,8 @@ #include "internet.h" +#include + #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ /* FIXME @@ -46,7 +48,8 @@ typedef struct _cookie_t { typedef struct _cookie_container_t { struct list entry; - WCHAR *path; + WCHAR *cookie_url; + substr_t path; struct _cookie_domain_t *domain; struct list cookie_list; @@ -75,19 +78,20 @@ static CRITICAL_SECTION_DEBUG cookie_cs_debug = static CRITICAL_SECTION cookie_cs = { &cookie_cs_debug, -1, 0, 0, 0, 0 }; static struct list domain_list = LIST_INIT(domain_list); -static cookie_domain_t *get_cookie_domain(const WCHAR *domain, BOOL create) +static cookie_domain_t *get_cookie_domain(substr_t domain, BOOL create) { - const WCHAR *ptr = domain + strlenW(domain), *ptr_end, *subdomain_ptr; + const WCHAR *ptr = domain.str + domain.len, *ptr_end, *subdomain_ptr; cookie_domain_t *iter, *current_domain, *prev_domain = NULL; struct list *current_list = &domain_list; while(1) { - for(ptr_end = ptr--; ptr > domain && *ptr != '.'; ptr--); + for(ptr_end = ptr--; ptr > domain.str && *ptr != '.'; ptr--); subdomain_ptr = *ptr == '.' ? ptr+1 : ptr; current_domain = NULL; LIST_FOR_EACH_ENTRY(iter, current_list, cookie_domain_t, entry) { - if(ptr_end-subdomain_ptr == iter->subdomain_len && !memcmp(subdomain_ptr, iter->domain, iter->subdomain_len)) { + if(ptr_end-subdomain_ptr == iter->subdomain_len + && !memcmp(subdomain_ptr, iter->domain, iter->subdomain_len*sizeof(WCHAR))) { current_domain = iter; break; } @@ -101,7 +105,7 @@ static cookie_domain_t *get_cookie_domain(const WCHAR *domain, BOOL create) if(!current_domain) return NULL; - current_domain->domain = heap_strdupW(subdomain_ptr); + current_domain->domain = heap_strndupW(subdomain_ptr, domain.str + domain.len - subdomain_ptr); if(!current_domain->domain) { heap_free(current_domain); return NULL; @@ -116,7 +120,7 @@ static cookie_domain_t *get_cookie_domain(const WCHAR *domain, BOOL create) list_add_tail(current_list, ¤t_domain->entry); } - if(ptr == domain) + if(ptr == domain.str) return current_domain; prev_domain = current_domain; @@ -124,24 +128,57 @@ static cookie_domain_t *get_cookie_domain(const WCHAR *domain, BOOL create) } } -static cookie_container_t *get_cookie_container(const WCHAR *domain, const WCHAR *path, BOOL create) +static WCHAR *create_cookie_url(substr_t domain, substr_t path, substr_t *ret_path) +{ + WCHAR user[UNLEN], *p, *url; + DWORD len, user_len, i; + + static const WCHAR cookie_prefix[] = {'C','o','o','k','i','e',':'}; + + user_len = sizeof(user)/sizeof(WCHAR); + if(!GetUserNameW(user, &user_len)) + return FALSE; + user_len--; + + len = sizeof(cookie_prefix)/sizeof(WCHAR) + user_len + 1 /* @ */ + domain.len + path.len; + url = heap_alloc((len+1) * sizeof(WCHAR)); + if(!url) + return NULL; + + memcpy(url, cookie_prefix, sizeof(cookie_prefix)); + p = url + sizeof(cookie_prefix)/sizeof(WCHAR); + + memcpy(p, user, user_len*sizeof(WCHAR)); + p += user_len; + + *p++ = '@'; + + memcpy(p, domain.str, domain.len*sizeof(WCHAR)); + p += domain.len; + + for(i=0; i < path.len; i++) + p[i] = tolowerW(path.str[i]); + p[path.len] = 0; + + ret_path->str = p; + ret_path->len = path.len; + return url; +} + +static cookie_container_t *get_cookie_container(substr_t domain, substr_t path, BOOL create) { cookie_domain_t *cookie_domain; cookie_container_t *cookie_container, *iter; - size_t path_len, len; cookie_domain = get_cookie_domain(domain, create); if(!cookie_domain) return NULL; - path_len = strlenW(path); - LIST_FOR_EACH_ENTRY(cookie_container, &cookie_domain->path_list, cookie_container_t, entry) { - len = strlenW(cookie_container->path); - if(len < path_len) + if(cookie_container->path.len < path.len) break; - if(!strcmpiW(cookie_container->path, path)) + if(path.len == cookie_container->path.len && !strncmpiW(cookie_container->path.str, path.str, path.len)) return cookie_container; } @@ -152,8 +189,8 @@ static cookie_container_t *get_cookie_container(const WCHAR *domain, const WCHAR if(!cookie_container) return NULL; - cookie_container->path = heap_strdupW(path); - if(!cookie_container->path) { + cookie_container->cookie_url = create_cookie_url(substrz(cookie_domain->domain), path, &cookie_container->path); + if(!cookie_container->cookie_url) { heap_free(cookie_container); return NULL; } @@ -161,9 +198,8 @@ static cookie_container_t *get_cookie_container(const WCHAR *domain, const WCHAR cookie_container->domain = cookie_domain; list_init(&cookie_container->cookie_list); - LIST_FOR_EACH_ENTRY(iter, &cookie_domain->path_list, cookie_container_t, entry) { - if(strlenW(iter->path) <= path_len) { + if(iter->path.len <= path.len) { list_add_before(&iter->entry, &cookie_container->entry); return cookie_container; } @@ -182,7 +218,7 @@ static void delete_cookie(cookie_t *cookie) heap_free(cookie); } -static cookie_t *alloc_cookie(const WCHAR *name, const WCHAR *data, FILETIME expiry, FILETIME create_time, DWORD flags) +static cookie_t *alloc_cookie(substr_t name, substr_t data, FILETIME expiry, FILETIME create_time, DWORD flags) { cookie_t *new_cookie; @@ -195,9 +231,9 @@ static cookie_t *alloc_cookie(const WCHAR *name, const WCHAR *data, FILETIME exp new_cookie->flags = flags; list_init(&new_cookie->entry); - new_cookie->name = heap_strdupW(name); - new_cookie->data = heap_strdupW(data); - if((name && !new_cookie->name) || (data && !new_cookie->data)) { + new_cookie->name = heap_strndupW(name.str, name.len); + new_cookie->data = heap_strndupW(data.str, data.len); + if(!new_cookie->name || !new_cookie->data) { delete_cookie(new_cookie); return NULL; } @@ -205,12 +241,12 @@ static cookie_t *alloc_cookie(const WCHAR *name, const WCHAR *data, FILETIME exp return new_cookie; } -static cookie_t *find_cookie(cookie_container_t *container, const WCHAR *name) +static cookie_t *find_cookie(cookie_container_t *container, substr_t name) { cookie_t *iter; LIST_FOR_EACH_ENTRY(iter, &container->cookie_list, cookie_t, entry) { - if(!strcmpiW(iter->name, name)) + if(strlenW(iter->name) == name.len && !strncmpiW(iter->name, name.str, name.len)) return iter; } @@ -219,8 +255,8 @@ static cookie_t *find_cookie(cookie_container_t *container, const WCHAR *name) static void add_cookie(cookie_container_t *container, cookie_t *new_cookie) { - TRACE("Adding %s=%s to %s %s\n", debugstr_w(new_cookie->name), debugstr_w(new_cookie->data), - debugstr_w(container->domain->domain), debugstr_w(container->path)); + TRACE("Adding %s=%s to %s\n", debugstr_w(new_cookie->name), debugstr_w(new_cookie->data), + debugstr_w(container->cookie_url)); list_add_tail(&container->cookie_list, &new_cookie->entry); new_cookie->container = container; @@ -230,86 +266,41 @@ static void replace_cookie(cookie_container_t *container, cookie_t *new_cookie) { cookie_t *old_cookie; - old_cookie = find_cookie(container, new_cookie->name); + old_cookie = find_cookie(container, substrz(new_cookie->name)); if(old_cookie) delete_cookie(old_cookie); add_cookie(container, new_cookie); } -static BOOL cookie_match_path(cookie_container_t *container, const WCHAR *path) +static BOOL cookie_match_path(cookie_container_t *container, substr_t path) { - return !strncmpiW(container->path, path, strlenW(container->path)); + return path.len >= container->path.len && !strncmpiW(container->path.str, path.str, container->path.len); } -static BOOL create_cookie_url(LPCWSTR domain, LPCWSTR path, WCHAR *buf, DWORD buf_len) -{ - static const WCHAR cookie_prefix[] = {'C','o','o','k','i','e',':'}; - - WCHAR *p; - DWORD len; - - if(buf_len < sizeof(cookie_prefix)/sizeof(WCHAR)) - return FALSE; - memcpy(buf, cookie_prefix, sizeof(cookie_prefix)); - buf += sizeof(cookie_prefix)/sizeof(WCHAR); - buf_len -= sizeof(cookie_prefix)/sizeof(WCHAR); - p = buf; - - len = buf_len; - if(!GetUserNameW(buf, &len)) - return FALSE; - buf += len-1; - buf_len -= len-1; - - if(!buf_len) - return FALSE; - *(buf++) = '@'; - buf_len--; - - len = strlenW(domain); - if(len >= buf_len) - return FALSE; - memcpy(buf, domain, len*sizeof(WCHAR)); - buf += len; - buf_len -= len; - - len = strlenW(path); - if(len >= buf_len) - return FALSE; - memcpy(buf, path, len*sizeof(WCHAR)); - buf += len; - - *buf = 0; - - for(; *p; p++) - *p = tolowerW(*p); - return TRUE; -} - -static BOOL load_persistent_cookie(LPCWSTR domain, LPCWSTR path) +static BOOL load_persistent_cookie(substr_t domain, substr_t path) { INTERNET_CACHE_ENTRY_INFOW *info; cookie_container_t *cookie_container; cookie_t *new_cookie; - WCHAR cookie_url[MAX_PATH]; HANDLE cookie; char *str = NULL, *pbeg, *pend; DWORD size, flags; WCHAR *name, *data; FILETIME expiry, create, time; - if (!create_cookie_url(domain, path, cookie_url, sizeof(cookie_url)/sizeof(cookie_url[0]))) + cookie_container = get_cookie_container(domain, path, TRUE); + if(!cookie_container) return FALSE; size = 0; - RetrieveUrlCacheEntryStreamW(cookie_url, NULL, &size, FALSE, 0); + RetrieveUrlCacheEntryStreamW(cookie_container->cookie_url, NULL, &size, FALSE, 0); if(GetLastError() != ERROR_INSUFFICIENT_BUFFER) return TRUE; info = heap_alloc(size); if(!info) return FALSE; - cookie = RetrieveUrlCacheEntryStreamW(cookie_url, info, &size, FALSE, 0); + cookie = RetrieveUrlCacheEntryStreamW(cookie_container->cookie_url, info, &size, FALSE, 0); size = info->dwSizeLow; heap_free(info); if(!cookie) @@ -323,12 +314,6 @@ static BOOL load_persistent_cookie(LPCWSTR domain, LPCWSTR path) str[size] = 0; UnlockUrlCacheEntryStream(cookie, 0); - cookie_container = get_cookie_container(domain, path, TRUE); - if(!cookie_container) { - heap_free(str); - return FALSE; - } - GetSystemTimeAsFileTime(&time); for(pbeg=str; pbeg && *pbeg; name=data=NULL) { pend = strchr(pbeg, '\n'); @@ -362,7 +347,7 @@ static BOOL load_persistent_cookie(LPCWSTR domain, LPCWSTR path) break; if(CompareFileTime(&time, &expiry) <= 0) { - new_cookie = alloc_cookie(NULL, NULL, expiry, create, flags); + new_cookie = alloc_cookie(substr(NULL, 0), substr(NULL, 0), expiry, create, flags); if(!new_cookie) break; @@ -386,16 +371,14 @@ static BOOL save_persistent_cookie(cookie_container_t *container) { static const WCHAR txtW[] = {'t','x','t',0}; - WCHAR cookie_url[MAX_PATH], cookie_file[MAX_PATH]; + WCHAR cookie_file[MAX_PATH]; HANDLE cookie_handle; cookie_t *cookie_container = NULL, *cookie_iter; BOOL do_save = FALSE; char buf[64], *dyn_buf; FILETIME time; DWORD bytes_written; - - if (!create_cookie_url(container->domain->domain, container->path, cookie_url, sizeof(cookie_url)/sizeof(cookie_url[0]))) - return FALSE; + size_t len; /* check if there's anything to save */ GetSystemTimeAsFileTime(&time); @@ -412,13 +395,15 @@ static BOOL save_persistent_cookie(cookie_container_t *container) break; } } + if(!do_save) { - DeleteUrlCacheEntryW(cookie_url); + DeleteUrlCacheEntryW(container->cookie_url); return TRUE; } - if(!CreateUrlCacheEntryW(cookie_url, 0, txtW, cookie_file, 0)) + if(!CreateUrlCacheEntryW(container->cookie_url, 0, txtW, cookie_file, 0)) return FALSE; + cookie_handle = CreateFileW(cookie_file, GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); if(cookie_handle == INVALID_HANDLE_VALUE) { DeleteFileW(cookie_file); @@ -462,7 +447,12 @@ static BOOL save_persistent_cookie(cookie_container_t *container) } heap_free(dyn_buf); - dyn_buf = heap_strdupWtoA(container->path); + len = WideCharToMultiByte(CP_ACP, 0, container->path.str, container->path.len, NULL, 0, NULL, NULL); + dyn_buf = heap_alloc(len+1); + if(dyn_buf) { + WideCharToMultiByte(CP_ACP, 0, container->path.str, container->path.len, dyn_buf, len, NULL, NULL); + dyn_buf[len] = 0; + } if(!dyn_buf || !WriteFile(cookie_handle, dyn_buf, strlen(dyn_buf), &bytes_written, NULL)) { heap_free(dyn_buf); do_save = FALSE; @@ -487,47 +477,26 @@ static BOOL save_persistent_cookie(cookie_container_t *container) } memset(&time, 0, sizeof(time)); - return CommitUrlCacheEntryW(cookie_url, cookie_file, time, time, 0, NULL, 0, txtW, 0); + return CommitUrlCacheEntryW(container->cookie_url, cookie_file, time, time, 0, NULL, 0, txtW, 0); } -static BOOL COOKIE_crackUrlSimple(LPCWSTR lpszUrl, LPWSTR hostName, int hostNameLen, LPWSTR path, int pathLen) +static BOOL cookie_parse_url(const WCHAR *url, substr_t *host, substr_t *path) { - URL_COMPONENTSW UrlComponents; + URL_COMPONENTSW comp = { sizeof(comp) }; + static const WCHAR rootW[] = {'/',0}; - UrlComponents.lpszExtraInfo = NULL; - UrlComponents.lpszPassword = NULL; - UrlComponents.lpszScheme = NULL; - UrlComponents.lpszUrlPath = path; - UrlComponents.lpszUserName = NULL; - UrlComponents.lpszHostName = hostName; - UrlComponents.dwExtraInfoLength = 0; - UrlComponents.dwPasswordLength = 0; - UrlComponents.dwSchemeLength = 0; - UrlComponents.dwUserNameLength = 0; - UrlComponents.dwHostNameLength = hostNameLen; - UrlComponents.dwUrlPathLength = pathLen; + comp.dwHostNameLength = 1; + comp.dwUrlPathLength = 1; - if (!InternetCrackUrlW(lpszUrl, 0, 0, &UrlComponents)) return FALSE; + if(!InternetCrackUrlW(url, 0, 0, &comp) || !comp.dwHostNameLength) + return FALSE; /* discard the webpage off the end of the path */ - if (UrlComponents.dwUrlPathLength) - { - if (path[UrlComponents.dwUrlPathLength - 1] != '/') - { - WCHAR *ptr; - if ((ptr = strrchrW(path, '/'))) *(++ptr) = 0; - else - { - path[0] = '/'; - path[1] = 0; - } - } - } - else if (pathLen >= 2) - { - path[0] = '/'; - path[1] = 0; - } + while(comp.dwUrlPathLength && comp.lpszUrlPath[comp.dwUrlPathLength-1] != '/') + comp.dwUrlPathLength--; + + *host = substr(comp.lpszHostName, comp.dwHostNameLength); + *path = comp.dwUrlPathLength ? substr(comp.lpszUrlPath, comp.dwUrlPathLength) : substr(rootW, 1); return TRUE; } @@ -539,45 +508,38 @@ typedef struct { unsigned string_len; } cookie_set_t; -static DWORD get_cookie(const WCHAR *host, const WCHAR *path, DWORD flags, cookie_set_t *res) +static DWORD get_cookie(substr_t host, substr_t path, DWORD flags, cookie_set_t *res) { static const WCHAR empty_path[] = { '/',0 }; - WCHAR *ptr, subpath[INTERNET_MAX_PATH_LENGTH]; const WCHAR *p; cookie_domain_t *domain; cookie_container_t *container; - unsigned len; FILETIME tm; GetSystemTimeAsFileTime(&tm); - len = strlenW(host); - p = host+len; - while(p>host && p[-1]!='.') p--; - while(p != host) { + p = host.str + host.len; + while(p > host.str && p[-1] != '.') p--; + while(p != host.str) { p--; - while(p>host && p[-1]!='.') p--; - if(p == host) break; + while(p > host.str && p[-1] != '.') p--; + if(p == host.str) break; - load_persistent_cookie(p, empty_path); + load_persistent_cookie(substr(p, host.str+host.len-p), substr(empty_path, 1)); } - len = strlenW(path); - assert(len+1 < INTERNET_MAX_PATH_LENGTH); - memcpy(subpath, path, (len+1)*sizeof(WCHAR)); - ptr = subpath+len; + p = path.str + path.len; do { - *ptr = 0; - load_persistent_cookie(host, subpath); + load_persistent_cookie(host, substr(path.str, p-path.str)); - ptr--; - while(ptr>subpath && ptr[-1]!='/') ptr--; - }while(ptr != subpath); + p--; + while(p > path.str && p[-1] != '/') p--; + }while(p != path.str); domain = get_cookie_domain(host, FALSE); if(!domain) { - TRACE("Unknown host %s\n", debugstr_w(host)); + TRACE("Unknown host %s\n", debugstr_wn(host.str, host.len)); return ERROR_NO_MORE_ITEMS; } @@ -587,7 +549,7 @@ static DWORD get_cookie(const WCHAR *host, const WCHAR *path, DWORD flags, cooki LIST_FOR_EACH_ENTRY(container, &domain->path_list, cookie_container_t, entry) { struct list *cursor, *cursor2; - TRACE("path %s\n", debugstr_w(container->path)); + TRACE("path %s\n", debugstr_wn(container->path.str, container->path.len)); if(!cookie_match_path(container, path)) continue; @@ -672,7 +634,7 @@ DWORD get_cookie_header(const WCHAR *host, const WCHAR *path, WCHAR **ret) EnterCriticalSection(&cookie_cs); - res = get_cookie(host, path, INTERNET_COOKIE_HTTPONLY, &cookie_set); + res = get_cookie(substrz(host), substrz(path), INTERNET_COOKIE_HTTPONLY, &cookie_set); if(res != ERROR_SUCCESS) { LeaveCriticalSection(&cookie_cs); return res; @@ -722,8 +684,8 @@ DWORD get_cookie_header(const WCHAR *host, const WCHAR *path, WCHAR **ret) BOOL WINAPI InternetGetCookieExW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPWSTR lpCookieData, LPDWORD lpdwSize, DWORD flags, void *reserved) { - WCHAR host[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH]; cookie_set_t cookie_set = {0}; + substr_t host, path; DWORD res; BOOL ret; @@ -738,9 +700,8 @@ BOOL WINAPI InternetGetCookieExW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, return FALSE; } - host[0] = 0; - ret = COOKIE_crackUrlSimple(lpszUrl, host, sizeof(host)/sizeof(host[0]), path, sizeof(path)/sizeof(path[0])); - if (!ret || !host[0]) { + ret = cookie_parse_url(lpszUrl, &host, &path); + if (!ret) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -768,7 +729,7 @@ BOOL WINAPI InternetGetCookieExW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, lpCookieData[cookie_set.string_len] = 0; } }else { - TRACE("no cookies found for %s\n", debugstr_w(host)); + TRACE("no cookies found for %s\n", debugstr_wn(host.str, host.len)); SetLastError(ERROR_NO_MORE_ITEMS); ret = FALSE; } @@ -855,40 +816,25 @@ BOOL WINAPI InternetGetCookieExA(LPCSTR lpszUrl, LPCSTR lpszCookieName, */ BOOL WINAPI InternetGetCookieA(const char *url, const char *name, char *data, DWORD *size) { - TRACE("(%s, %s, %s, %p)\n", debugstr_a(url), debugstr_a(name), debugstr_a(data), size); + TRACE("(%s, %s, %p, %p)\n", debugstr_a(url), debugstr_a(name), data, size); return InternetGetCookieExA(url, name, data, size, 0, NULL); } -/*********************************************************************** - * IsDomainLegalCookieDomainW (WININET.@) - */ -BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 ) +static BOOL is_domain_legal_for_cookie(substr_t domain, substr_t full_domain) { - DWORD s1_len, s2_len; + const WCHAR *ptr; - FIXME("(%s, %s) semi-stub\n", debugstr_w(s1), debugstr_w(s2)); - - if (!s1 || !s2) - { - SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - if (s1[0] == '.' || !s1[0] || s2[0] == '.' || !s2[0]) - { + if(!domain.len || *domain.str == '.' || !full_domain.len || *full_domain.str == '.') { SetLastError(ERROR_INVALID_NAME); return FALSE; } - if(!strchrW(s1, '.') || !strchrW(s2, '.')) + + if(domain.len > full_domain.len || !memchrW(domain.str, '.', domain.len) || !memchrW(full_domain.str, '.', full_domain.len)) return FALSE; - s1_len = strlenW(s1); - s2_len = strlenW(s2); - if (s1_len > s2_len) - return FALSE; - - if (strncmpiW(s1, s2+s2_len-s1_len, s1_len) || (s2_len>s1_len && s2[s2_len-s1_len-1]!='.')) - { + ptr = full_domain.str + full_domain.len - domain.len; + if (strncmpiW(domain.str, ptr, domain.len) || (full_domain.len > domain.len && ptr[-1] != '.')) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -896,129 +842,130 @@ BOOL WINAPI IsDomainLegalCookieDomainW( LPCWSTR s1, LPCWSTR s2 ) return TRUE; } -DWORD set_cookie(const WCHAR *domain, const WCHAR *path, const WCHAR *cookie_name, const WCHAR *cookie_data, DWORD flags) +/*********************************************************************** + * IsDomainLegalCookieDomainW (WININET.@) + */ +BOOL WINAPI IsDomainLegalCookieDomainW(const WCHAR *domain, const WCHAR *full_domain) +{ + FIXME("(%s, %s) semi-stub\n", debugstr_w(domain), debugstr_w(full_domain)); + + if (!domain || !full_domain) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; + } + + return is_domain_legal_for_cookie(substrz(domain), substrz(full_domain)); +} + +static void substr_skip(substr_t *str, size_t len) +{ + assert(str->len >= len); + str->str += len; + str->len -= len; +} + +DWORD set_cookie(substr_t domain, substr_t path, substr_t name, substr_t data, DWORD flags) { cookie_container_t *container; cookie_t *thisCookie; - LPWSTR data, value; - WCHAR *ptr; + substr_t value; + const WCHAR *end_ptr; FILETIME expiry, create; BOOL expired = FALSE, update_persistent = FALSE; - DWORD cookie_flags = 0; + DWORD cookie_flags = 0, len; - TRACE("%s %s %s=%s %x\n", debugstr_w(domain), debugstr_w(path), debugstr_w(cookie_name), debugstr_w(cookie_data), flags); - - value = data = heap_strdupW(cookie_data); - if (!data) - { - ERR("could not allocate the cookie data buffer\n"); - return COOKIE_STATE_UNKNOWN; - } + TRACE("%s %s %s=%s %x\n", debugstr_wn(domain.str, domain.len), debugstr_wn(path.str, path.len), + debugstr_wn(name.str, name.len), debugstr_wn(data.str, data.len), flags); memset(&expiry,0,sizeof(expiry)); GetSystemTimeAsFileTime(&create); /* lots of information can be parsed out of the cookie value */ - ptr = data; - for (;;) - { - static const WCHAR szDomain[] = {'d','o','m','a','i','n','=',0}; - static const WCHAR szPath[] = {'p','a','t','h','=',0}; - static const WCHAR szExpires[] = {'e','x','p','i','r','e','s','=',0}; - static const WCHAR szSecure[] = {'s','e','c','u','r','e',0}; - static const WCHAR szHttpOnly[] = {'h','t','t','p','o','n','l','y',0}; - static const WCHAR szVersion[] = {'v','e','r','s','i','o','n','=',0}; + if(!(end_ptr = memchrW(data.str, ';', data.len))) + end_ptr = data.str + data.len; + value = substr(data.str, end_ptr-data.str); + data.str += value.len; + data.len -= value.len; - if (!(ptr = strchrW(ptr,';'))) break; - *ptr++ = 0; + for(;;) { + static const WCHAR szDomain[] = {'d','o','m','a','i','n','='}; + static const WCHAR szPath[] = {'p','a','t','h','='}; + static const WCHAR szExpires[] = {'e','x','p','i','r','e','s','='}; + static const WCHAR szSecure[] = {'s','e','c','u','r','e'}; + static const WCHAR szHttpOnly[] = {'h','t','t','p','o','n','l','y'}; + static const WCHAR szVersion[] = {'v','e','r','s','i','o','n','='}; - if (value != data) heap_free(value); - value = heap_alloc((ptr - data) * sizeof(WCHAR)); - if (value == NULL) - { - heap_free(data); - ERR("could not allocate the cookie value buffer\n"); - return COOKIE_STATE_UNKNOWN; - } - strcpyW(value, data); + /* Skip ';' */ + if(data.len) + substr_skip(&data, 1); - while (*ptr == ' ') ptr++; /* whitespace */ + while(data.len && *data.str == ' ') + substr_skip(&data, 1); - if (strncmpiW(ptr, szDomain, 7) == 0) - { - WCHAR *end_ptr; + if(!data.len) + break; - ptr += sizeof(szDomain)/sizeof(szDomain[0])-1; - if(*ptr == '.') - ptr++; - end_ptr = strchrW(ptr, ';'); - if(end_ptr) - *end_ptr = 0; + if(!(end_ptr = memchrW(data.str, ';', data.len))) + end_ptr = data.str + data.len; - if(!IsDomainLegalCookieDomainW(ptr, domain)) - { - if(value != data) - heap_free(value); - heap_free(data); + if(data.len >= (len = sizeof(szDomain)/sizeof(WCHAR)) && !strncmpiW(data.str, szDomain, len)) { + substr_skip(&data, len); + + if(data.len && *data.str == '.') + substr_skip(&data, 1); + + if(!is_domain_legal_for_cookie(substr(data.str, end_ptr-data.str), domain)) return COOKIE_STATE_UNKNOWN; - } - if(end_ptr) - *end_ptr = ';'; - - domain = ptr; - TRACE("Parsing new domain %s\n",debugstr_w(domain)); - } - else if (strncmpiW(ptr, szPath, 5) == 0) - { - ptr+=strlenW(szPath); - path = ptr; - TRACE("Parsing new path %s\n",debugstr_w(path)); - } - else if (strncmpiW(ptr, szExpires, 8) == 0) - { + domain = substr(data.str, end_ptr-data.str); + TRACE("Parsing new domain %s\n", debugstr_wn(domain.str, domain.len)); + }else if(data.len >= (len = sizeof(szPath)/sizeof(WCHAR)) && !strncmpiW(data.str, szPath, len)) { + substr_skip(&data, len); + path = substr(data.str, end_ptr - data.str); + TRACE("Parsing new path %s\n", debugstr_wn(path.str, path.len)); + }else if(data.len >= (len = sizeof(szExpires)/sizeof(WCHAR)) && !strncmpiW(data.str, szExpires, len)) { SYSTEMTIME st; - ptr+=strlenW(szExpires); - if (InternetTimeToSystemTimeW(ptr, &st, 0)) - { - SystemTimeToFileTime(&st, &expiry); + WCHAR buf[128]; - if (CompareFileTime(&create,&expiry) > 0) - { - TRACE("Cookie already expired.\n"); - expired = TRUE; + substr_skip(&data, len); + + if(end_ptr - data.str < sizeof(buf)/sizeof(WCHAR)-1) { + memcpy(buf, data.str, data.len*sizeof(WCHAR)); + buf[data.len] = 0; + + if (InternetTimeToSystemTimeW(data.str, &st, 0)) { + SystemTimeToFileTime(&st, &expiry); + + if (CompareFileTime(&create,&expiry) > 0) { + TRACE("Cookie already expired.\n"); + expired = TRUE; + } } } - } - else if (strncmpiW(ptr, szSecure, 6) == 0) - { - FIXME("secure not handled (%s)\n",debugstr_w(ptr)); - ptr += strlenW(szSecure); - } - else if (strncmpiW(ptr, szHttpOnly, 8) == 0) - { + }else if(data.len >= (len = sizeof(szSecure)/sizeof(WCHAR)) && !strncmpiW(data.str, szSecure, len)) { + substr_skip(&data, len); + FIXME("secure not handled\n"); + }else if(data.len >= (len = sizeof(szHttpOnly)/sizeof(WCHAR)) && !strncmpiW(data.str, szHttpOnly, len)) { + substr_skip(&data, len); + if(!(flags & INTERNET_COOKIE_HTTPONLY)) { WARN("HTTP only cookie added without INTERNET_COOKIE_HTTPONLY flag\n"); - heap_free(data); - if (value != data) heap_free(value); SetLastError(ERROR_INVALID_OPERATION); return COOKIE_STATE_REJECT; } cookie_flags |= INTERNET_COOKIE_HTTPONLY; - ptr += strlenW(szHttpOnly); - } - else if (strncmpiW(ptr, szVersion, 8) == 0) - { - FIXME("version not handled (%s)\n",debugstr_w(ptr)); - ptr += strlenW(szVersion); - } - else if (*ptr) - { - FIXME("Unknown additional option %s\n",debugstr_w(ptr)); + }else if(data.len >= (len = sizeof(szVersion)/sizeof(WCHAR)) && !strncmpiW(data.str, szVersion, len)) { + substr_skip(&data, len); + + FIXME("version not handled (%s)\n",debugstr_wn(data.str, data.len)); + }else if(data.len) { + FIXME("Unknown additional option %s\n", debugstr_wn(data.str, data.len)); break; } + + substr_skip(&data, end_ptr - data.str); } EnterCriticalSection(&cookie_cs); @@ -1027,8 +974,6 @@ DWORD set_cookie(const WCHAR *domain, const WCHAR *path, const WCHAR *cookie_nam container = get_cookie_container(domain, path, !expired); if(!container) { - heap_free(data); - if (value != data) heap_free(value); LeaveCriticalSection(&cookie_cs); return COOKIE_STATE_ACCEPT; } @@ -1038,13 +983,10 @@ DWORD set_cookie(const WCHAR *domain, const WCHAR *path, const WCHAR *cookie_nam else update_persistent = TRUE; - if ((thisCookie = find_cookie(container, cookie_name))) - { + if ((thisCookie = find_cookie(container, name))) { if ((thisCookie->flags & INTERNET_COOKIE_HTTPONLY) && !(flags & INTERNET_COOKIE_HTTPONLY)) { WARN("An attempt to override httponly cookie\n"); SetLastError(ERROR_INVALID_OPERATION); - heap_free(data); - if (value != data) heap_free(value); return COOKIE_STATE_REJECT; } @@ -1053,24 +995,21 @@ DWORD set_cookie(const WCHAR *domain, const WCHAR *path, const WCHAR *cookie_nam delete_cookie(thisCookie); } - TRACE("setting cookie %s=%s for domain %s path %s\n", debugstr_w(cookie_name), - debugstr_w(value), debugstr_w(container->domain->domain),debugstr_w(container->path)); + TRACE("setting cookie %s=%s for domain %s path %s\n", debugstr_wn(name.str, name.len), + debugstr_wn(value.str, value.len), debugstr_w(container->domain->domain), + debugstr_wn(container->path.str, container->path.len)); if (!expired) { cookie_t *new_cookie; - new_cookie = alloc_cookie(cookie_name, value, expiry, create, cookie_flags); + new_cookie = alloc_cookie(name, value, expiry, create, cookie_flags); if(!new_cookie) { - heap_free(data); - if (value != data) heap_free(value); LeaveCriticalSection(&cookie_cs); return COOKIE_STATE_UNKNOWN; } add_cookie(container, new_cookie); } - heap_free(data); - if (value != data) heap_free(value); if (!update_persistent || save_persistent_cookie(container)) { @@ -1089,8 +1028,8 @@ DWORD set_cookie(const WCHAR *domain, const WCHAR *path, const WCHAR *cookie_nam DWORD WINAPI InternetSetCookieExW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, LPCWSTR lpCookieData, DWORD flags, DWORD_PTR reserved) { + substr_t host, path, name, data; BOOL ret; - WCHAR hostName[INTERNET_MAX_HOST_NAME_LENGTH], path[INTERNET_MAX_PATH_LENGTH]; TRACE("(%s, %s, %s, %x, %lx)\n", debugstr_w(lpszUrl), debugstr_w(lpszCookieName), debugstr_w(lpCookieData), flags, reserved); @@ -1104,34 +1043,26 @@ DWORD WINAPI InternetSetCookieExW(LPCWSTR lpszUrl, LPCWSTR lpszCookieName, return COOKIE_STATE_UNKNOWN; } - hostName[0] = 0; - ret = COOKIE_crackUrlSimple(lpszUrl, hostName, sizeof(hostName)/sizeof(hostName[0]), path, sizeof(path)/sizeof(path[0])); - if (!ret || !hostName[0]) return COOKIE_STATE_UNKNOWN; + ret = cookie_parse_url(lpszUrl, &host, &path); + if (!ret || !host.len) return COOKIE_STATE_UNKNOWN; - if (!lpszCookieName) - { - WCHAR *cookie, *data; - DWORD res; - - cookie = heap_strdupW(lpCookieData); - if (!cookie) - { - SetLastError(ERROR_OUTOFMEMORY); - return COOKIE_STATE_UNKNOWN; - } + if (!lpszCookieName) { + const WCHAR *ptr; /* some apps (or is it us??) try to add a cookie with no cookie name, but * the cookie data in the form of name[=data]. */ - if (!(data = strchrW(cookie, '='))) data = cookie + strlenW(cookie); - else *data++ = 0; + if (!(ptr = strchrW(lpCookieData, '='))) + ptr = lpCookieData + strlenW(lpCookieData); - res = set_cookie(hostName, path, cookie, data, flags); - - heap_free(cookie); - return res; + name = substr(lpCookieData, ptr - lpCookieData); + data = substrz(*ptr == '=' ? ptr+1 : ptr); + }else { + name = substrz(lpszCookieName); + data = substrz(lpCookieData); } - return set_cookie(hostName, path, lpszCookieName, lpCookieData, flags); + + return set_cookie(host, path, name, data, flags); } /*********************************************************************** diff --git a/reactos/dll/win32/wininet/http.c b/reactos/dll/win32/wininet/http.c index 9f8084c184c..eb1edf07c04 100644 --- a/reactos/dll/win32/wininet/http.c +++ b/reactos/dll/win32/wininet/http.c @@ -179,7 +179,6 @@ static INT HTTP_GetCustomHeaderIndex(http_request_t *req, LPCWSTR lpszField, INT static BOOL HTTP_DeleteCustomHeader(http_request_t *req, DWORD index); static LPWSTR HTTP_build_req( LPCWSTR *list, int len ); static DWORD HTTP_HttpQueryInfoW(http_request_t*, DWORD, LPVOID, LPDWORD, LPDWORD); -static LPWSTR HTTP_GetRedirectURL(http_request_t *req, LPCWSTR lpszUrl); static UINT HTTP_DecodeBase64(LPCWSTR base64, LPSTR bin); static BOOL drain_content(http_request_t*,BOOL); @@ -247,7 +246,7 @@ static BOOL process_host_port(server_t *server) return TRUE; } -server_t *get_server(const WCHAR *name, INTERNET_PORT port, BOOL is_https, BOOL do_create) +server_t *get_server(substr_t name, INTERNET_PORT port, BOOL is_https, BOOL do_create) { server_t *iter, *server = NULL; @@ -257,7 +256,8 @@ server_t *get_server(const WCHAR *name, INTERNET_PORT port, BOOL is_https, BOOL EnterCriticalSection(&connection_pool_cs); LIST_FOR_EACH_ENTRY(iter, &connection_pool, server_t, entry) { - if(iter->port == port && !strcmpW(iter->name, name) && iter->is_https == is_https) { + if(iter->port == port && name.len == strlenW(iter->name) && !strncmpW(iter->name, name.str, name.len) + && iter->is_https == is_https) { server = iter; server_addref(server); break; @@ -271,7 +271,7 @@ server_t *get_server(const WCHAR *name, INTERNET_PORT port, BOOL is_https, BOOL server->port = port; server->is_https = is_https; list_init(&server->conn_pool); - server->name = heap_strdupW(name); + server->name = heap_strndupW(name.str, name.len); if(server->name && process_host_port(server)) { list_add_head(&connection_pool, &server->entry); }else { @@ -767,7 +767,7 @@ static void HTTP_ProcessCookies( http_request_t *request ) while((HeaderIndex = HTTP_GetCustomHeaderIndex(request, szSet_Cookie, numCookies++, FALSE)) != -1) { const WCHAR *data; - WCHAR *name; + substr_t name; setCookieHeader = &request->custHeaders[HeaderIndex]; @@ -778,13 +778,9 @@ static void HTTP_ProcessCookies( http_request_t *request ) if(!data) continue; - name = heap_strndupW(setCookieHeader->lpszValue, data-setCookieHeader->lpszValue); - if(!name) - continue; - + name = substr(setCookieHeader->lpszValue, data - setCookieHeader->lpszValue); data++; - set_cookie(request->server->name, path, name, data, INTERNET_COOKIE_HTTPONLY); - heap_free(name); + set_cookie(substrz(request->server->name), substrz(path), name, substrz(data), INTERNET_COOKIE_HTTPONLY); } LeaveCriticalSection( &request->headers_section ); @@ -1371,21 +1367,17 @@ BOOL WINAPI HttpAddRequestHeadersW(HINTERNET hHttpRequest, BOOL WINAPI HttpAddRequestHeadersA(HINTERNET hHttpRequest, LPCSTR lpszHeader, DWORD dwHeaderLength, DWORD dwModifier) { - DWORD len; - LPWSTR hdr; + WCHAR *headers = NULL; BOOL r; TRACE("%p, %s, %i, %i\n", hHttpRequest, debugstr_an(lpszHeader, dwHeaderLength), dwHeaderLength, dwModifier); - len = MultiByteToWideChar( CP_ACP, 0, lpszHeader, dwHeaderLength, NULL, 0 ); - hdr = heap_alloc(len*sizeof(WCHAR)); - MultiByteToWideChar( CP_ACP, 0, lpszHeader, dwHeaderLength, hdr, len ); - if( dwHeaderLength != ~0U ) - dwHeaderLength = len; + if(lpszHeader) + headers = heap_strndupAtoW(lpszHeader, dwHeaderLength, &dwHeaderLength); - r = HttpAddRequestHeadersW( hHttpRequest, hdr, dwHeaderLength, dwModifier ); + r = HttpAddRequestHeadersW(hHttpRequest, headers, dwHeaderLength, dwModifier); - heap_free( hdr ); + heap_free(headers); return r; } @@ -1717,55 +1709,47 @@ static WCHAR *build_proxy_path_url(http_request_t *req) return url; } -static BOOL HTTP_DomainMatches(LPCWSTR server, LPCWSTR domain) +static BOOL HTTP_DomainMatches(LPCWSTR server, substr_t domain) { static const WCHAR localW[] = { '<','l','o','c','a','l','>',0 }; - BOOL ret = FALSE; + const WCHAR *dot, *ptr; + int len; - if (!strcmpiW( domain, localW ) && !strchrW( server, '.' )) - ret = TRUE; - else if (*domain == '*') - { - if (domain[1] == '.') - { - LPCWSTR dot; + if(domain.len == sizeof(localW)/sizeof(WCHAR)-1 && !strncmpiW(domain.str, localW, domain.len) && !strchrW(server, '.' )) + return TRUE; - /* For a hostname to match a wildcard, the last domain must match - * the wildcard exactly. E.g. if the wildcard is *.a.b, and the - * hostname is www.foo.a.b, it matches, but a.b does not. - */ - dot = strchrW( server, '.' ); - if (dot) - { - int len = strlenW( dot + 1 ); + if(domain.len && *domain.str != '*') + return domain.len == strlenW(server) && !strncmpiW(server, domain.str, domain.len); - if (len > strlenW( domain + 2 )) - { - LPCWSTR ptr; + if(domain.len < 2 || domain.str[1] != '.') + return FALSE; - /* The server's domain is longer than the wildcard, so it - * could be a subdomain. Compare the last portion of the - * server's domain. - */ - ptr = dot + len + 1 - strlenW( domain + 2 ); - if (!strcmpiW( ptr, domain + 2 )) - { - /* This is only a match if the preceding character is - * a '.', i.e. that it is a matching domain. E.g. - * if domain is '*.b.c' and server is 'www.ab.c' they - * do not match. - */ - ret = *(ptr - 1) == '.'; - } - } - else - ret = !strcmpiW( dot + 1, domain + 2 ); - } - } - } - else - ret = !strcmpiW( server, domain ); - return ret; + /* For a hostname to match a wildcard, the last domain must match + * the wildcard exactly. E.g. if the wildcard is *.a.b, and the + * hostname is www.foo.a.b, it matches, but a.b does not. + */ + dot = strchrW(server, '.'); + if(!dot) + return FALSE; + + len = strlenW(dot + 1); + if(len <= domain.len - 2) + return FALSE; + + /* The server's domain is longer than the wildcard, so it + * could be a subdomain. Compare the last portion of the + * server's domain. + */ + ptr = dot + 1 + len - domain.len + 2; + if(!strncmpiW(ptr, domain.str+2, domain.len-2)) + /* This is only a match if the preceding character is + * a '.', i.e. that it is a matching domain. E.g. + * if domain is '*.b.c' and server is 'www.ab.c' they + * do not match. + */ + return *(ptr - 1) == '.'; + + return len == domain.len-2 && !strncmpiW(dot + 1, domain.str + 2, len); } static BOOL HTTP_ShouldBypassProxy(appinfo_t *lpwai, LPCWSTR server) @@ -1775,27 +1759,19 @@ static BOOL HTTP_ShouldBypassProxy(appinfo_t *lpwai, LPCWSTR server) if (!lpwai->proxyBypass) return FALSE; ptr = lpwai->proxyBypass; - do { + while(1) { LPCWSTR tmp = ptr; ptr = strchrW( ptr, ';' ); if (!ptr) ptr = strchrW( tmp, ' ' ); - if (ptr) - { - if (ptr - tmp < INTERNET_MAX_HOST_NAME_LENGTH) - { - WCHAR domain[INTERNET_MAX_HOST_NAME_LENGTH]; - - memcpy( domain, tmp, (ptr - tmp) * sizeof(WCHAR) ); - domain[ptr - tmp] = 0; - ret = HTTP_DomainMatches( server, domain ); - } - ptr += 1; - } - else if (*tmp) - ret = HTTP_DomainMatches( server, tmp ); - } while (ptr && !ret); + if (!ptr) + ptr = tmp + strlenW(ptr); + ret = HTTP_DomainMatches( server, substr(tmp, ptr-tmp) ); + if (ret || !*ptr) + break; + ptr++; + } return ret; } @@ -1806,41 +1782,34 @@ static BOOL HTTP_DealWithProxy(appinfo_t *hIC, http_session_t *session, http_req { static const WCHAR protoHttp[] = { 'h','t','t','p',0 }; static const WCHAR szHttp[] = { 'h','t','t','p',':','/','/',0 }; - static const WCHAR szFormat[] = { 'h','t','t','p',':','/','/','%','s',0 }; - WCHAR buf[INTERNET_MAX_HOST_NAME_LENGTH]; - WCHAR protoProxy[INTERNET_MAX_URL_LENGTH]; - DWORD protoProxyLen = INTERNET_MAX_URL_LENGTH; - WCHAR proxy[INTERNET_MAX_URL_LENGTH]; static WCHAR szNul[] = { 0 }; - URL_COMPONENTSW UrlComponents; - server_t *new_server; - BOOL is_https; + URL_COMPONENTSW UrlComponents = { sizeof(UrlComponents) }; + server_t *new_server = NULL; + WCHAR *proxy; - memset( &UrlComponents, 0, sizeof UrlComponents ); - UrlComponents.dwStructSize = sizeof UrlComponents; - UrlComponents.lpszHostName = buf; - UrlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH; - - if (!INTERNET_FindProxyForProtocol(hIC->proxy, protoHttp, protoProxy, &protoProxyLen)) - return FALSE; - if( CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, - protoProxy,strlenW(szHttp),szHttp,strlenW(szHttp)) ) - sprintfW(proxy, szFormat, protoProxy); - else - strcpyW(proxy, protoProxy); - if( !InternetCrackUrlW(proxy, 0, 0, &UrlComponents) ) - return FALSE; - if( UrlComponents.dwHostNameLength == 0 ) + proxy = INTERNET_FindProxyForProtocol(hIC->proxy, protoHttp); + if(!proxy) return FALSE; + if(CSTR_EQUAL != CompareStringW(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, + proxy, strlenW(szHttp), szHttp, strlenW(szHttp))) { + WCHAR *proxy_url = heap_alloc(strlenW(proxy)*sizeof(WCHAR) + sizeof(szHttp)); + if(!proxy_url) + return FALSE; + strcpyW(proxy_url, szHttp); + strcatW(proxy_url, proxy); + heap_free(proxy); + proxy = proxy_url; + } - if( !request->path ) - request->path = szNul; + UrlComponents.dwHostNameLength = 1; + if(InternetCrackUrlW(proxy, 0, 0, &UrlComponents) && UrlComponents.dwHostNameLength) { + if( !request->path ) + request->path = szNul; - is_https = (UrlComponents.nScheme == INTERNET_SCHEME_HTTPS); - if (is_https && UrlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) - UrlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; - - new_server = get_server(UrlComponents.lpszHostName, UrlComponents.nPort, is_https, TRUE); + new_server = get_server(substr(UrlComponents.lpszHostName, UrlComponents.dwHostNameLength), + UrlComponents.nPort, UrlComponents.nScheme == INTERNET_SCHEME_HTTPS, TRUE); + } + heap_free(proxy); if(!new_server) return FALSE; @@ -1876,33 +1845,39 @@ static DWORD HTTP_ResolveName(http_request_t *request) return ERROR_SUCCESS; } -static BOOL HTTP_GetRequestURL(http_request_t *req, LPWSTR buf) +static WCHAR *compose_request_url(http_request_t *req) { static const WCHAR http[] = { 'h','t','t','p',':','/','/',0 }; static const WCHAR https[] = { 'h','t','t','p','s',':','/','/',0 }; - static const WCHAR slash[] = { '/',0 }; - LPHTTPHEADERW host_header; - const WCHAR *host; - LPCWSTR scheme; + const WCHAR *host, *scheme; + WCHAR *buf, *ptr; + size_t len; - EnterCriticalSection( &req->headers_section ); + host = req->server->canon_host_port; - host_header = HTTP_GetHeader(req, hostW); - if (host_header) host = host_header->lpszValue; - else host = req->server->canon_host_port; - - if (req->hdr.dwFlags & INTERNET_FLAG_SECURE) + if (req->server->is_https) scheme = https; else scheme = http; - strcpyW(buf, scheme); - strcatW(buf, host); - if (req->path[0] != '/') - strcatW(buf, slash); - strcatW(buf, req->path); - LeaveCriticalSection( &req->headers_section ); - return TRUE; + len = strlenW(scheme) + strlenW(host) + (req->path[0] != '/' ? 1 : 0) + strlenW(req->path); + ptr = buf = heap_alloc((len+1) * sizeof(WCHAR)); + if(buf) { + strcpyW(ptr, scheme); + ptr += strlenW(ptr); + + strcpyW(ptr, host); + ptr += strlenW(ptr); + + if(req->path[0] != '/') + *ptr++ = '/'; + + strcpyW(ptr, req->path); + ptr += strlenW(ptr); + *ptr = 0; + } + + return buf; } @@ -2140,17 +2115,18 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe return ERROR_SUCCESS; case INTERNET_OPTION_URL: { - static const WCHAR httpW[] = {'h','t','t','p',':','/','/',0}; - WCHAR url[INTERNET_MAX_URL_LENGTH]; + WCHAR *url; + DWORD res; TRACE("INTERNET_OPTION_URL\n"); - strcpyW(url, httpW); - strcatW(url, req->server->canon_host_port); - strcatW(url, req->path); + url = compose_request_url(req); + if(!url) + return ERROR_OUTOFMEMORY; - TRACE("INTERNET_OPTION_URL: %s\n",debugstr_w(url)); - return str_to_buffer(url, buffer, size, unicode); + res = str_to_buffer(url, buffer, size, unicode); + heap_free(url); + return res; } case INTERNET_OPTION_USER_AGENT: return str_to_buffer(req->session->appInfo->agent, buffer, size, unicode); @@ -2166,27 +2142,29 @@ static DWORD HTTPREQ_QueryOption(object_header_t *hdr, DWORD option, void *buffe case INTERNET_OPTION_CACHE_TIMESTAMPS: { INTERNET_CACHE_ENTRY_INFOW *info; INTERNET_CACHE_TIMESTAMPS *ts = buffer; - WCHAR url[INTERNET_MAX_URL_LENGTH]; DWORD nbytes, error; BOOL ret; TRACE("INTERNET_OPTION_CACHE_TIMESTAMPS\n"); + if(!req->req_file) + return ERROR_FILE_NOT_FOUND; + if (*size < sizeof(*ts)) { *size = sizeof(*ts); return ERROR_INSUFFICIENT_BUFFER; } + nbytes = 0; - HTTP_GetRequestURL(req, url); - ret = GetUrlCacheEntryInfoW(url, NULL, &nbytes); + ret = GetUrlCacheEntryInfoW(req->req_file->url, NULL, &nbytes); error = GetLastError(); if (!ret && error == ERROR_INSUFFICIENT_BUFFER) { if (!(info = heap_alloc(nbytes))) return ERROR_OUTOFMEMORY; - GetUrlCacheEntryInfoW(url, info, &nbytes); + GetUrlCacheEntryInfoW(req->req_file->url, info, &nbytes); ts->ftExpires = info->ExpireTime; ts->ftLastModified = info->LastModifiedTime; @@ -2375,29 +2353,25 @@ static DWORD HTTPREQ_SetOption(object_header_t *hdr, DWORD option, void *buffer, static void commit_cache_entry(http_request_t *req) { - WCHAR url[INTERNET_MAX_URL_LENGTH]; + WCHAR *header; + DWORD header_len; + BOOL res; TRACE("%p\n", req); CloseHandle(req->hCacheFile); req->hCacheFile = NULL; - if(HTTP_GetRequestURL(req, url)) { - WCHAR *header; - DWORD header_len; - BOOL res; - - header = build_response_header(req, TRUE); - header_len = (header ? strlenW(header) : 0); - res = CommitUrlCacheEntryW(url, req->req_file->file_name, req->expires, - req->last_modified, NORMAL_CACHE_ENTRY, - header, header_len, NULL, 0); - if(res) - req->req_file->is_committed = TRUE; - else - WARN("CommitUrlCacheEntry failed: %u\n", GetLastError()); - heap_free(header); - } + header = build_response_header(req, TRUE); + header_len = (header ? strlenW(header) : 0); + res = CommitUrlCacheEntryW(req->req_file->url, req->req_file->file_name, req->expires, + req->last_modified, NORMAL_CACHE_ENTRY, + header, header_len, NULL, 0); + if(res) + req->req_file->is_committed = TRUE; + else + WARN("CommitUrlCacheEntry failed: %u\n", GetLastError()); + heap_free(header); } static void create_cache_entry(http_request_t *req) @@ -2405,8 +2379,8 @@ static void create_cache_entry(http_request_t *req) static const WCHAR no_cacheW[] = {'n','o','-','c','a','c','h','e',0}; static const WCHAR no_storeW[] = {'n','o','-','s','t','o','r','e',0}; - WCHAR url[INTERNET_MAX_URL_LENGTH]; WCHAR file_name[MAX_PATH+1]; + WCHAR *url; BOOL b = TRUE; /* FIXME: We should free previous cache file earlier */ @@ -2463,8 +2437,8 @@ static void create_cache_entry(http_request_t *req) FIXME("INTERNET_FLAG_NEED_FILE is not supported correctly\n"); } - b = HTTP_GetRequestURL(req, url); - if(!b) { + url = compose_request_url(req); + if(!url) { WARN("Could not get URL\n"); return; } @@ -2476,6 +2450,7 @@ static void create_cache_entry(http_request_t *req) } create_req_file(file_name, &req->req_file); + req->req_file->url = url; req->hCacheFile = CreateFileW(file_name, GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); @@ -3036,7 +3011,7 @@ static void HTTP_ReceiveRequestData(http_request_t *req, BOOL first_notif, DWORD } /* read data from the http connection (the read section must be held) */ -static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read, BOOL sync) +static DWORD HTTPREQ_Read(http_request_t *req, void *buffer, DWORD size, DWORD *read) { DWORD current_read = 0, ret_read = 0; blocking_mode_t blocking_mode; @@ -3090,7 +3065,7 @@ static BOOL drain_content(http_request_t *req, BOOL blocking) DWORD bytes_read, res; BYTE buf[4096]; - res = HTTPREQ_Read(req, buf, sizeof(buf), &bytes_read, TRUE); + res = HTTPREQ_Read(req, buf, sizeof(buf), &bytes_read); if(res != ERROR_SUCCESS) { ret = FALSE; break; @@ -3105,23 +3080,6 @@ static BOOL drain_content(http_request_t *req, BOOL blocking) return ret; } -static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read) -{ - http_request_t *req = (http_request_t*)hdr; - DWORD res; - - EnterCriticalSection( &req->read_section ); - if(hdr->dwError == INTERNET_HANDLE_IN_USE) - hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; - - res = HTTPREQ_Read(req, buffer, size, read, TRUE); - if(res == ERROR_SUCCESS) - res = hdr->dwError; - LeaveCriticalSection( &req->read_section ); - - return res; -} - typedef struct { task_header_t hdr; void *buf; @@ -3133,11 +3091,23 @@ static void AsyncReadFileExProc(task_header_t *hdr) { read_file_ex_task_t *task = (read_file_ex_task_t*)hdr; http_request_t *req = (http_request_t*)task->hdr.hdr; - DWORD res; + DWORD res = ERROR_SUCCESS, read = 0, buffered = 0; - TRACE("INTERNETREADFILEEXW %p\n", task->hdr.hdr); + TRACE("%p\n", req); + + if(task->ret_read) + res = HTTPREQ_Read(req, task->buf, task->size, &read); + if(res == ERROR_SUCCESS) + res = refill_read_buffer(req, task->ret_read ? BLOCKING_DISALLOW : BLOCKING_ALLOW, &buffered); + if (res == ERROR_SUCCESS) + { + if(task->ret_read) + *task->ret_read = read; + read += buffered; + INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RESPONSE_RECEIVED, + &read, sizeof(read)); + } - res = HTTPREQ_Read(req, task->buf, task->size, task->ret_read, TRUE); send_request_complete(req, res == ERROR_SUCCESS, res); } @@ -3148,20 +3118,22 @@ static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWO http_request_t *req = (http_request_t*)hdr; DWORD res, read, cread, error = ERROR_SUCCESS; + TRACE("(%p %p %u %x)\n", req, buf, size, flags); + if (flags & ~(IRF_ASYNC|IRF_NO_WAIT)) FIXME("these dwFlags aren't implemented: 0x%x\n", flags & ~(IRF_ASYNC|IRF_NO_WAIT)); INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_RECEIVING_RESPONSE, NULL, 0); - if (hdr->dwFlags & INTERNET_FLAG_ASYNC) + if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) { read_file_ex_task_t *task; if (TryEnterCriticalSection( &req->read_section )) { - if (get_avail_data(req)) + if (get_avail_data(req) || end_of_read_data(req)) { - res = HTTPREQ_Read(req, buf, size, &read, FALSE); + res = HTTPREQ_Read(req, buf, size, &read); LeaveCriticalSection( &req->read_section ); goto done; } @@ -3171,7 +3143,7 @@ static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWO task = alloc_async_task(&req->hdr, AsyncReadFileExProc, sizeof(*task)); task->buf = buf; task->size = size; - task->ret_read = ret_read; + task->ret_read = (flags & IRF_NO_WAIT) ? NULL : ret_read; INTERNET_AsyncCall(&task->hdr); @@ -3187,7 +3159,7 @@ static DWORD HTTPREQ_ReadFileEx(object_header_t *hdr, void *buf, DWORD size, DWO hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; while(1) { - res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread, !(flags & IRF_NO_WAIT)); + res = HTTPREQ_Read(req, (char*)buf+read, size-read, &cread); if(res != ERROR_SUCCESS) break; @@ -3238,6 +3210,49 @@ static DWORD HTTPREQ_WriteFile(object_header_t *hdr, const void *buffer, DWORD s return res; } +static DWORD HTTPREQ_ReadFile(object_header_t *hdr, void *buffer, DWORD size, DWORD *read) +{ + http_request_t *req = (http_request_t*)hdr; + DWORD res; + + if (req->session->appInfo->hdr.dwFlags & INTERNET_FLAG_ASYNC) + { + read_file_ex_task_t *task; + + if (TryEnterCriticalSection( &req->read_section )) + { + if (get_avail_data(req) || end_of_read_data(req)) + { + res = HTTPREQ_Read(req, buffer, size, read); + LeaveCriticalSection( &req->read_section ); + return res; + } + LeaveCriticalSection( &req->read_section ); + } + + task = alloc_async_task(&req->hdr, AsyncReadFileExProc, sizeof(*task)); + task->buf = buffer; + task->size = size; + task->ret_read = read; + + *read = 0; + INTERNET_AsyncCall(&task->hdr); + + return ERROR_IO_PENDING; + } + + EnterCriticalSection( &req->read_section ); + if(hdr->dwError == INTERNET_HANDLE_IN_USE) + hdr->dwError = ERROR_INTERNET_INTERNAL_ERROR; + + res = HTTPREQ_Read(req, buffer, size, read); + if(res == ERROR_SUCCESS) + res = hdr->dwError; + LeaveCriticalSection( &req->read_section ); + + return res; +} + typedef struct { task_header_t hdr; DWORD *ret_size; @@ -3335,7 +3350,7 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session, { appinfo_t *hIC = session->appInfo; http_request_t *request; - DWORD len; + DWORD port, len; TRACE("-->\n"); @@ -3364,7 +3379,14 @@ static DWORD HTTP_HttpOpenRequestW(http_session_t *session, request->session = session; list_add_head( &session->hdr.children, &request->hdr.entry ); - request->server = get_server(session->hostName, session->hostPort, (dwFlags & INTERNET_FLAG_SECURE) != 0, TRUE); + port = session->hostPort; + if (port == INTERNET_INVALID_PORT_NUMBER) + { + port = (session->hdr.dwFlags & INTERNET_FLAG_SECURE) ? + INTERNET_DEFAULT_HTTPS_PORT : INTERNET_DEFAULT_HTTP_PORT; + } + + request->server = get_server(substrz(session->hostName), port, (dwFlags & INTERNET_FLAG_SECURE) != 0, TRUE); if(!request->server) { WININET_Release(&request->hdr); return ERROR_OUTOFMEMORY; @@ -4032,64 +4054,57 @@ BOOL WINAPI HttpQueryInfoA(HINTERNET hHttpRequest, DWORD dwInfoLevel, return result; } -/*********************************************************************** - * HTTP_GetRedirectURL (internal) - */ -static LPWSTR HTTP_GetRedirectURL(http_request_t *request, LPCWSTR lpszUrl) +static WCHAR *get_redirect_url(http_request_t *request) { static WCHAR szHttp[] = {'h','t','t','p',0}; static WCHAR szHttps[] = {'h','t','t','p','s',0}; http_session_t *session = request->session; - URL_COMPONENTSW urlComponents; - DWORD url_length = 0; - LPWSTR orig_url; - LPWSTR combined_url; - - urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); - urlComponents.lpszScheme = (request->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp; - urlComponents.dwSchemeLength = 0; - urlComponents.lpszHostName = request->server->name; - urlComponents.dwHostNameLength = 0; - urlComponents.nPort = request->server->port; - urlComponents.lpszUserName = session->userName; - urlComponents.dwUserNameLength = 0; - urlComponents.lpszPassword = NULL; - urlComponents.dwPasswordLength = 0; - urlComponents.lpszUrlPath = request->path; - urlComponents.dwUrlPathLength = 0; - urlComponents.lpszExtraInfo = NULL; - urlComponents.dwExtraInfoLength = 0; - - if (!InternetCreateUrlW(&urlComponents, 0, NULL, &url_length) && - (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) - return NULL; - - orig_url = heap_alloc(url_length); - - /* convert from bytes to characters */ - url_length = url_length / sizeof(WCHAR) - 1; - if (!InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length)) - { - heap_free(orig_url); - return NULL; - } + URL_COMPONENTSW urlComponents = { sizeof(urlComponents) }; + WCHAR *orig_url = NULL, *redirect_url = NULL, *combined_url = NULL; + DWORD url_length = 0, res; + BOOL b; url_length = 0; - if (!InternetCombineUrlW(orig_url, lpszUrl, NULL, &url_length, ICU_ENCODE_SPACES_ONLY) && - (GetLastError() != ERROR_INSUFFICIENT_BUFFER)) - { - heap_free(orig_url); + res = HTTP_HttpQueryInfoW(request, HTTP_QUERY_LOCATION, redirect_url, &url_length, NULL); + if(res == ERROR_INSUFFICIENT_BUFFER) { + redirect_url = heap_alloc(url_length); + res = HTTP_HttpQueryInfoW(request, HTTP_QUERY_LOCATION, redirect_url, &url_length, NULL); + } + if(res != ERROR_SUCCESS) { + heap_free(redirect_url); return NULL; } - combined_url = heap_alloc(url_length * sizeof(WCHAR)); - if (!InternetCombineUrlW(orig_url, lpszUrl, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY)) - { - heap_free(orig_url); - heap_free(combined_url); - return NULL; + urlComponents.lpszScheme = (request->hdr.dwFlags & INTERNET_FLAG_SECURE) ? szHttps : szHttp; + urlComponents.lpszHostName = request->server->name; + urlComponents.nPort = request->server->port; + urlComponents.lpszUserName = session->userName; + urlComponents.lpszUrlPath = request->path; + + b = InternetCreateUrlW(&urlComponents, 0, NULL, &url_length); + if(!b && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + orig_url = heap_alloc(url_length); + + /* convert from bytes to characters */ + url_length = url_length / sizeof(WCHAR) - 1; + b = InternetCreateUrlW(&urlComponents, 0, orig_url, &url_length); } + + if(b) { + url_length = 0; + b = InternetCombineUrlW(orig_url, redirect_url, NULL, &url_length, ICU_ENCODE_SPACES_ONLY); + if(!b && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { + combined_url = heap_alloc(url_length * sizeof(WCHAR)); + b = InternetCombineUrlW(orig_url, redirect_url, combined_url, &url_length, ICU_ENCODE_SPACES_ONLY); + if(!b) { + heap_free(combined_url); + combined_url = NULL; + } + } + } + heap_free(orig_url); + heap_free(redirect_url); return combined_url; } @@ -4100,84 +4115,62 @@ static LPWSTR HTTP_GetRedirectURL(http_request_t *request, LPCWSTR lpszUrl) static DWORD HTTP_HandleRedirect(http_request_t *request, LPCWSTR lpszUrl) { http_session_t *session = request->session; - WCHAR path[INTERNET_MAX_PATH_LENGTH]; + WCHAR *path; if(lpszUrl[0]=='/') { /* if it's an absolute path, keep the same session info */ - lstrcpynW(path, lpszUrl, INTERNET_MAX_URL_LENGTH); + path = heap_strdupW(lpszUrl); } else { - URL_COMPONENTSW urlComponents; - WCHAR protocol[INTERNET_MAX_SCHEME_LENGTH]; - WCHAR hostName[INTERNET_MAX_HOST_NAME_LENGTH]; - WCHAR userName[INTERNET_MAX_USER_NAME_LENGTH]; + URL_COMPONENTSW urlComponents = { sizeof(urlComponents) }; BOOL custom_port = FALSE; + substr_t host; - static const WCHAR httpW[] = {'h','t','t','p',0}; - static const WCHAR httpsW[] = {'h','t','t','p','s',0}; - - userName[0] = 0; - hostName[0] = 0; - protocol[0] = 0; - - urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); - urlComponents.lpszScheme = protocol; - urlComponents.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH; - urlComponents.lpszHostName = hostName; - urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH; - urlComponents.lpszUserName = userName; - urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH; - urlComponents.lpszPassword = NULL; - urlComponents.dwPasswordLength = 0; - urlComponents.lpszUrlPath = path; - urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH; - urlComponents.lpszExtraInfo = NULL; - urlComponents.dwExtraInfoLength = 0; + urlComponents.dwHostNameLength = 1; + urlComponents.dwUserNameLength = 1; + urlComponents.dwUrlPathLength = 1; if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents)) return INTERNET_GetLastError(); - if(!strcmpiW(protocol, httpW)) { + if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) { if(request->hdr.dwFlags & INTERNET_FLAG_SECURE) { TRACE("redirect from secure page to non-secure page\n"); /* FIXME: warn about from secure redirect to non-secure page */ request->hdr.dwFlags &= ~INTERNET_FLAG_SECURE; } - if(urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) - urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - else if(urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT) - custom_port = TRUE; - }else if(!strcmpiW(protocol, httpsW)) { + custom_port = urlComponents.nPort != INTERNET_DEFAULT_HTTP_PORT; + }else if(urlComponents.nScheme == INTERNET_SCHEME_HTTPS) { if(!(request->hdr.dwFlags & INTERNET_FLAG_SECURE)) { TRACE("redirect from non-secure page to secure page\n"); /* FIXME: notify about redirect to secure page */ request->hdr.dwFlags |= INTERNET_FLAG_SECURE; } - if(urlComponents.nPort == INTERNET_INVALID_PORT_NUMBER) - urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; - else if(urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT) - custom_port = TRUE; + custom_port = urlComponents.nPort != INTERNET_DEFAULT_HTTPS_PORT; } heap_free(session->hostName); - session->hostName = heap_strdupW(hostName); + session->hostName = heap_strndupW(urlComponents.lpszHostName, urlComponents.dwHostNameLength); session->hostPort = urlComponents.nPort; heap_free(session->userName); session->userName = NULL; - if (userName[0]) - session->userName = heap_strdupW(userName); + if (urlComponents.dwUserNameLength) + session->userName = heap_strndupW(urlComponents.lpszUserName, urlComponents.dwUserNameLength); reset_data_stream(request); - if(strcmpiW(request->server->name, hostName) || request->server->port != urlComponents.nPort) { + host = substr(urlComponents.lpszHostName, urlComponents.dwHostNameLength); + + if(host.len != strlenW(request->server->name) || strncmpiW(request->server->name, host.str, host.len) + || request->server->port != urlComponents.nPort) { server_t *new_server; - new_server = get_server(hostName, urlComponents.nPort, urlComponents.nScheme == INTERNET_SCHEME_HTTPS, TRUE); + new_server = get_server(host, urlComponents.nPort, urlComponents.nScheme == INTERNET_SCHEME_HTTPS, TRUE); server_release(request->server); request->server = new_server; } @@ -4186,16 +4179,18 @@ static DWORD HTTP_HandleRedirect(http_request_t *request, LPCWSTR lpszUrl) HTTP_ProcessHeader(request, hostW, request->server->host_port, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ); else HTTP_ProcessHeader(request, hostW, request->server->name, HTTP_ADDREQ_FLAG_ADD | HTTP_ADDREQ_FLAG_REPLACE | HTTP_ADDHDR_FLAG_REQ); + + path = heap_strndupW(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength); } heap_free(request->path); - request->path=NULL; + request->path = NULL; if (*path) { DWORD needed = 0; HRESULT rc; rc = UrlEscapeW(path, NULL, &needed, URL_ESCAPE_SPACES_ONLY); - if (rc != E_POINTER) + if (rc == E_POINTER) needed = strlenW(path)+1; request->path = heap_alloc(needed*sizeof(WCHAR)); rc = UrlEscapeW(path, request->path, &needed, @@ -4203,10 +4198,12 @@ static DWORD HTTP_HandleRedirect(http_request_t *request, LPCWSTR lpszUrl) if (rc != S_OK) { ERR("Unable to escape string!(%s) (%d)\n",debugstr_w(path),rc); - strcpyW(request->path,path); + strcpyW(request->path, path); } } + heap_free(path); + /* Remove custom content-type/length headers on redirects. */ remove_header(request, szContent_Type, TRUE); remove_header(request, szContent_Length, TRUE); @@ -5097,14 +5094,15 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders, if (!(request->hdr.dwFlags & INTERNET_FLAG_NO_AUTO_REDIRECT) && responseLen) { - WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH]; - dwBufferSize=sizeof(szNewLocation); + WCHAR *new_url; + switch(request->status_code) { case HTTP_STATUS_REDIRECT: case HTTP_STATUS_MOVED: case HTTP_STATUS_REDIRECT_KEEP_VERB: case HTTP_STATUS_REDIRECT_METHOD: - if(HTTP_HttpQueryInfoW(request,HTTP_QUERY_LOCATION,szNewLocation,&dwBufferSize,NULL) != ERROR_SUCCESS) + new_url = get_redirect_url(request); + if(!new_url) break; if (strcmpW(request->verb, szGET) && strcmpW(request->verb, szHEAD) && @@ -5114,17 +5112,13 @@ static DWORD HTTP_HttpSendRequestW(http_request_t *request, LPCWSTR lpszHeaders, request->verb = heap_strdupW(szGET); } http_release_netconn(request, drain_content(request, FALSE)); - if ((new_url = HTTP_GetRedirectURL( request, szNewLocation ))) - { - INTERNET_SendCallback(&request->hdr, request->hdr.dwContext, INTERNET_STATUS_REDIRECT, - new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); - res = HTTP_HandleRedirect(request, new_url); - if (res == ERROR_SUCCESS) - { - heap_free(requestString); - loop_next = TRUE; - } - heap_free( new_url ); + INTERNET_SendCallback(&request->hdr, request->hdr.dwContext, INTERNET_STATUS_REDIRECT, + new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); + res = HTTP_HandleRedirect(request, new_url); + heap_free(new_url); + if (res == ERROR_SUCCESS) { + heap_free(requestString); + loop_next = TRUE; } redirected = TRUE; } @@ -5267,7 +5261,6 @@ static void AsyncHttpSendRequestProc(task_header_t *hdr) static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_PTR dwContext) { - DWORD dwBufferSize; INT responseLen; DWORD res = ERROR_SUCCESS; @@ -5304,9 +5297,10 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_ case HTTP_STATUS_MOVED: case HTTP_STATUS_REDIRECT_METHOD: case HTTP_STATUS_REDIRECT_KEEP_VERB: { - WCHAR *new_url, szNewLocation[INTERNET_MAX_URL_LENGTH]; - dwBufferSize=sizeof(szNewLocation); - if (HTTP_HttpQueryInfoW(request, HTTP_QUERY_LOCATION, szNewLocation, &dwBufferSize, NULL) != ERROR_SUCCESS) + WCHAR *new_url; + + new_url = get_redirect_url(request); + if(!new_url) break; if (strcmpW(request->verb, szGET) && strcmpW(request->verb, szHEAD) && @@ -5316,15 +5310,12 @@ static DWORD HTTP_HttpEndRequestW(http_request_t *request, DWORD dwFlags, DWORD_ request->verb = heap_strdupW(szGET); } http_release_netconn(request, drain_content(request, FALSE)); - if ((new_url = HTTP_GetRedirectURL( request, szNewLocation ))) - { - INTERNET_SendCallback(&request->hdr, request->hdr.dwContext, INTERNET_STATUS_REDIRECT, - new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); - res = HTTP_HandleRedirect(request, new_url); - if (res == ERROR_SUCCESS) - res = HTTP_HttpSendRequestW(request, NULL, 0, NULL, 0, 0, TRUE); - heap_free( new_url ); - } + INTERNET_SendCallback(&request->hdr, request->hdr.dwContext, INTERNET_STATUS_REDIRECT, + new_url, (strlenW(new_url) + 1) * sizeof(WCHAR)); + res = HTTP_HandleRedirect(request, new_url); + heap_free(new_url); + if (res == ERROR_SUCCESS) + res = HTTP_HttpSendRequestW(request, NULL, 0, NULL, 0, 0, TRUE); } } } diff --git a/reactos/dll/win32/wininet/internet.c b/reactos/dll/win32/wininet/internet.c index 5fc251d1939..dd3a83d8d9a 100644 --- a/reactos/dll/win32/wininet/internet.c +++ b/reactos/dll/win32/wininet/internet.c @@ -351,15 +351,15 @@ static LONG INTERNET_SaveProxySettings( proxyinfo_t *lpwpi ) * *foundProxyLen is set to the required size in WCHARs, including the * NULL terminator, and the last error is set to ERROR_INSUFFICIENT_BUFFER. */ -BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) +WCHAR *INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto) { - LPCWSTR ptr; - BOOL ret = FALSE; + WCHAR *ret = NULL; + const WCHAR *ptr; TRACE("(%s, %s)\n", debugstr_w(szProxy), debugstr_w(proto)); /* First, look for the specified protocol (proto=scheme://host:port) */ - for (ptr = szProxy; !ret && ptr && *ptr; ) + for (ptr = szProxy; ptr && *ptr; ) { LPCWSTR end, equal; @@ -369,60 +369,36 @@ BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundP equal - ptr == strlenW(proto) && !strncmpiW(proto, ptr, strlenW(proto))) { - if (end - equal > *foundProxyLen) - { - WARN("buffer too short for %s\n", - debugstr_wn(equal + 1, end - equal - 1)); - *foundProxyLen = end - equal; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - else - { - memcpy(foundProxy, equal + 1, (end - equal) * sizeof(WCHAR)); - foundProxy[end - equal] = 0; - ret = TRUE; - } + ret = heap_strndupW(equal + 1, end - equal - 1); + TRACE("found proxy for %s: %s\n", debugstr_w(proto), debugstr_w(ret)); + return ret; } if (*end == ' ') ptr = end + 1; else ptr = end; } - if (!ret) - { - /* It wasn't found: look for no protocol */ - for (ptr = szProxy; !ret && ptr && *ptr; ) - { - LPCWSTR end; - if (!(end = strchrW(ptr, ' '))) - end = ptr + strlenW(ptr); - if (!strchrW(ptr, '=')) - { - if (end - ptr + 1 > *foundProxyLen) - { - WARN("buffer too short for %s\n", - debugstr_wn(ptr, end - ptr)); - *foundProxyLen = end - ptr + 1; - SetLastError(ERROR_INSUFFICIENT_BUFFER); - } - else - { - memcpy(foundProxy, ptr, (end - ptr) * sizeof(WCHAR)); - foundProxy[end - ptr] = 0; - ret = TRUE; - } - } - if (*end == ' ') - ptr = end + 1; - else - ptr = end; + /* It wasn't found: look for no protocol */ + for (ptr = szProxy; ptr && *ptr; ) + { + LPCWSTR end; + + if (!(end = strchrW(ptr, ' '))) + end = ptr + strlenW(ptr); + if (!strchrW(ptr, '=')) + { + ret = heap_strndupW(ptr, end - ptr); + TRACE("found proxy for %s: %s\n", debugstr_w(proto), debugstr_w(ret)); + return ret; } + if (*end == ' ') + ptr = end + 1; + else + ptr = end; } - if (ret) - TRACE("found proxy for %s: %s\n", debugstr_w(proto), - debugstr_w(foundProxy)); - return ret; + + return NULL; } /*********************************************************************** @@ -484,41 +460,32 @@ static void free_global_proxy( void ) static BOOL parse_proxy_url( proxyinfo_t *info, const WCHAR *url ) { - static const WCHAR fmt[] = {'%','s',':','%','u',0}; - WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH]; - WCHAR username[INTERNET_MAX_USER_NAME_LENGTH]; - WCHAR password[INTERNET_MAX_PASSWORD_LENGTH]; - URL_COMPONENTSW uc; + static const WCHAR fmt[] = {'%','.','*','s',':','%','u',0}; + URL_COMPONENTSW uc = {sizeof(uc)}; - hostname[0] = username[0] = password[0] = 0; - memset( &uc, 0, sizeof(uc) ); - uc.dwStructSize = sizeof(uc); - uc.lpszHostName = hostname; - uc.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH; - uc.lpszUserName = username; - uc.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH; - uc.lpszPassword = password; - uc.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH; + uc.dwHostNameLength = 1; + uc.dwUserNameLength = 1; + uc.dwPasswordLength = 1; if (!InternetCrackUrlW( url, 0, 0, &uc )) return FALSE; - if (!hostname[0]) + if (!uc.dwHostNameLength) { if (!(info->proxy = heap_strdupW( url ))) return FALSE; info->proxyUsername = NULL; info->proxyPassword = NULL; return TRUE; } - if (!(info->proxy = heap_alloc( (strlenW(hostname) + 12) * sizeof(WCHAR) ))) return FALSE; - sprintfW( info->proxy, fmt, hostname, uc.nPort ); + if (!(info->proxy = heap_alloc( (uc.dwHostNameLength + 12) * sizeof(WCHAR) ))) return FALSE; + sprintfW( info->proxy, fmt, uc.dwHostNameLength, uc.lpszHostName, uc.nPort ); - if (!username[0]) info->proxyUsername = NULL; - else if (!(info->proxyUsername = heap_strdupW( username ))) + if (!uc.dwUserNameLength) info->proxyUsername = NULL; + else if (!(info->proxyUsername = heap_strndupW( uc.lpszUserName, uc.dwUserNameLength ))) { heap_free( info->proxy ); return FALSE; } - if (!password[0]) info->proxyPassword = NULL; - else if (!(info->proxyPassword = heap_strdupW( password ))) + if (!uc.dwPasswordLength) info->proxyPassword = NULL; + else if (!(info->proxyPassword = heap_strndupW( uc.lpszPassword, uc.dwPasswordLength ))) { heap_free( info->proxyUsername ); heap_free( info->proxy ); @@ -1448,169 +1415,147 @@ BOOL WINAPI InternetCloseHandle(HINTERNET hInternet) return TRUE; } - -/*********************************************************************** - * ConvertUrlComponentValue (Internal) - * - * Helper function for InternetCrackUrlA - * - */ -static void ConvertUrlComponentValue(LPSTR* lppszComponent, LPDWORD dwComponentLen, - LPWSTR lpwszComponent, DWORD dwwComponentLen, - LPCSTR lpszStart, LPCWSTR lpwszStart) +static BOOL set_url_component(WCHAR **component, DWORD *component_length, const WCHAR *value, DWORD len) { - TRACE("%p %d %p %d %p %p\n", *lppszComponent, *dwComponentLen, lpwszComponent, dwwComponentLen, lpszStart, lpwszStart); - if (*dwComponentLen != 0) - { - DWORD nASCIILength=WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,NULL,0,NULL,NULL); - if (*lppszComponent == NULL) - { - if (lpwszComponent) - { - int offset = WideCharToMultiByte(CP_ACP, 0, lpwszStart, lpwszComponent-lpwszStart, NULL, 0, NULL, NULL); - *lppszComponent = (LPSTR)lpszStart + offset; - } - else - *lppszComponent = NULL; + TRACE("%s (%d)\n", debugstr_wn(value, len), len); - *dwComponentLen = nASCIILength; - } - else - { - DWORD ncpylen = min((*dwComponentLen)-1, nASCIILength); - WideCharToMultiByte(CP_ACP,0,lpwszComponent,dwwComponentLen,*lppszComponent,ncpylen+1,NULL,NULL); - (*lppszComponent)[ncpylen]=0; - *dwComponentLen = ncpylen; - } + if (!*component_length) + return TRUE; + + if (!*component) { + *(const WCHAR**)component = value; + *component_length = len; + return TRUE; } + + if (*component_length < len+1) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + return FALSE; + } + + *component_length = len; + if(len) + memcpy(*component, value, len*sizeof(WCHAR)); + (*component)[len] = 0; + return TRUE; } +static BOOL set_url_component_WtoA(const WCHAR *comp_w, DWORD length, const WCHAR *url_w, char **comp, DWORD *ret_length, + const char *url_a) +{ + size_t size, ret_size = *ret_length; + + if (!*ret_length) + return TRUE; + size = WideCharToMultiByte(CP_ACP, 0, comp_w, length, NULL, 0, NULL, NULL); + + if (!*comp) { + *comp = comp_w ? (char*)url_a + WideCharToMultiByte(CP_ACP, 0, url_w, comp_w-url_w, NULL, 0, NULL, NULL) : NULL; + *ret_length = size; + return TRUE; + } + + if (size+1 > ret_size) { + SetLastError(ERROR_INSUFFICIENT_BUFFER); + *ret_length = size+1; + return FALSE; + } + + *ret_length = size; + WideCharToMultiByte(CP_ACP, 0, comp_w, length, *comp, ret_size-1, NULL, NULL); + (*comp)[size] = 0; + return TRUE; +} + +static BOOL set_url_component_AtoW(const char *comp_a, DWORD len_a, WCHAR **comp_w, DWORD *len_w, WCHAR **buf) +{ + *len_w = len_a; + + if(!comp_a) { + *comp_w = NULL; + return TRUE; + } + + if(!(*comp_w = *buf = heap_alloc(len_a*sizeof(WCHAR)))) { + SetLastError(ERROR_OUTOFMEMORY); + return FALSE; + } + + return TRUE; +} /*********************************************************************** * InternetCrackUrlA (WININET.@) * * See InternetCrackUrlW. */ -BOOL WINAPI InternetCrackUrlA(LPCSTR lpszUrl, DWORD dwUrlLength, DWORD dwFlags, - LPURL_COMPONENTSA lpUrlComponents) +BOOL WINAPI InternetCrackUrlA(const char *url, DWORD url_length, DWORD flags, URL_COMPONENTSA *ret_comp) { - DWORD nLength; - URL_COMPONENTSW UCW; - BOOL ret = FALSE; - WCHAR *lpwszUrl, *hostname = NULL, *username = NULL, *password = NULL, *path = NULL, - *scheme = NULL, *extra = NULL; + WCHAR *host = NULL, *user = NULL, *pass = NULL, *path = NULL, *scheme = NULL, *extra = NULL; + URL_COMPONENTSW comp; + WCHAR *url_w = NULL; + BOOL ret; - TRACE("(%s %u %x %p)\n", - lpszUrl ? debugstr_an(lpszUrl, dwUrlLength ? dwUrlLength : strlen(lpszUrl)) : "(null)", - dwUrlLength, dwFlags, lpUrlComponents); + TRACE("(%s %u %x %p)\n", url_length ? debugstr_an(url, url_length) : debugstr_a(url), url_length, flags, ret_comp); - if (!lpszUrl || !*lpszUrl || !lpUrlComponents || - lpUrlComponents->dwStructSize != sizeof(URL_COMPONENTSA)) - { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); - return FALSE; - } - - if(dwUrlLength<=0) - dwUrlLength=-1; - nLength=MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,NULL,0); - - /* if dwUrlLength=-1 then nLength includes null but length to - InternetCrackUrlW should not include it */ - if (dwUrlLength == -1) nLength--; - - lpwszUrl = heap_alloc((nLength + 1) * sizeof(WCHAR)); - MultiByteToWideChar(CP_ACP,0,lpszUrl,dwUrlLength,lpwszUrl,nLength + 1); - lpwszUrl[nLength] = '\0'; - - memset(&UCW,0,sizeof(UCW)); - UCW.dwStructSize = sizeof(URL_COMPONENTSW); - if (lpUrlComponents->dwHostNameLength) - { - UCW.dwHostNameLength = lpUrlComponents->dwHostNameLength; - if (lpUrlComponents->lpszHostName) - { - hostname = heap_alloc(UCW.dwHostNameLength * sizeof(WCHAR)); - UCW.lpszHostName = hostname; + if (!url || !*url || !ret_comp || ret_comp->dwStructSize != sizeof(URL_COMPONENTSA)) { + SetLastError(ERROR_INVALID_PARAMETER); + return FALSE; } - } - if (lpUrlComponents->dwUserNameLength) - { - UCW.dwUserNameLength = lpUrlComponents->dwUserNameLength; - if (lpUrlComponents->lpszUserName) - { - username = heap_alloc(UCW.dwUserNameLength * sizeof(WCHAR)); - UCW.lpszUserName = username; - } - } - if (lpUrlComponents->dwPasswordLength) - { - UCW.dwPasswordLength = lpUrlComponents->dwPasswordLength; - if (lpUrlComponents->lpszPassword) - { - password = heap_alloc(UCW.dwPasswordLength * sizeof(WCHAR)); - UCW.lpszPassword = password; - } - } - if (lpUrlComponents->dwUrlPathLength) - { - UCW.dwUrlPathLength = lpUrlComponents->dwUrlPathLength; - if (lpUrlComponents->lpszUrlPath) - { - path = heap_alloc(UCW.dwUrlPathLength * sizeof(WCHAR)); - UCW.lpszUrlPath = path; - } - } - if (lpUrlComponents->dwSchemeLength) - { - UCW.dwSchemeLength = lpUrlComponents->dwSchemeLength; - if (lpUrlComponents->lpszScheme) - { - scheme = heap_alloc(UCW.dwSchemeLength * sizeof(WCHAR)); - UCW.lpszScheme = scheme; - } - } - if (lpUrlComponents->dwExtraInfoLength) - { - UCW.dwExtraInfoLength = lpUrlComponents->dwExtraInfoLength; - if (lpUrlComponents->lpszExtraInfo) - { - extra = heap_alloc(UCW.dwExtraInfoLength * sizeof(WCHAR)); - UCW.lpszExtraInfo = extra; - } - } - if ((ret = InternetCrackUrlW(lpwszUrl, nLength, dwFlags, &UCW))) - { - ConvertUrlComponentValue(&lpUrlComponents->lpszHostName, &lpUrlComponents->dwHostNameLength, - UCW.lpszHostName, UCW.dwHostNameLength, lpszUrl, lpwszUrl); - ConvertUrlComponentValue(&lpUrlComponents->lpszUserName, &lpUrlComponents->dwUserNameLength, - UCW.lpszUserName, UCW.dwUserNameLength, lpszUrl, lpwszUrl); - ConvertUrlComponentValue(&lpUrlComponents->lpszPassword, &lpUrlComponents->dwPasswordLength, - UCW.lpszPassword, UCW.dwPasswordLength, lpszUrl, lpwszUrl); - ConvertUrlComponentValue(&lpUrlComponents->lpszUrlPath, &lpUrlComponents->dwUrlPathLength, - UCW.lpszUrlPath, UCW.dwUrlPathLength, lpszUrl, lpwszUrl); - ConvertUrlComponentValue(&lpUrlComponents->lpszScheme, &lpUrlComponents->dwSchemeLength, - UCW.lpszScheme, UCW.dwSchemeLength, lpszUrl, lpwszUrl); - ConvertUrlComponentValue(&lpUrlComponents->lpszExtraInfo, &lpUrlComponents->dwExtraInfoLength, - UCW.lpszExtraInfo, UCW.dwExtraInfoLength, lpszUrl, lpwszUrl); - lpUrlComponents->nScheme = UCW.nScheme; - lpUrlComponents->nPort = UCW.nPort; + comp.dwStructSize = sizeof(comp); - TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_a(lpszUrl), - debugstr_an(lpUrlComponents->lpszScheme, lpUrlComponents->dwSchemeLength), - debugstr_an(lpUrlComponents->lpszHostName, lpUrlComponents->dwHostNameLength), - debugstr_an(lpUrlComponents->lpszUrlPath, lpUrlComponents->dwUrlPathLength), - debugstr_an(lpUrlComponents->lpszExtraInfo, lpUrlComponents->dwExtraInfoLength)); - } - heap_free(lpwszUrl); - heap_free(hostname); - heap_free(username); - heap_free(password); - heap_free(path); - heap_free(scheme); - heap_free(extra); - return ret; + ret = set_url_component_AtoW(ret_comp->lpszHostName, ret_comp->dwHostNameLength, + &comp.lpszHostName, &comp.dwHostNameLength, &host) + && set_url_component_AtoW(ret_comp->lpszUserName, ret_comp->dwUserNameLength, + &comp.lpszUserName, &comp.dwUserNameLength, &user) + && set_url_component_AtoW(ret_comp->lpszPassword, ret_comp->dwPasswordLength, + &comp.lpszPassword, &comp.dwPasswordLength, &pass) + && set_url_component_AtoW(ret_comp->lpszUrlPath, ret_comp->dwUrlPathLength, + &comp.lpszUrlPath, &comp.dwUrlPathLength, &path) + && set_url_component_AtoW(ret_comp->lpszScheme, ret_comp->dwSchemeLength, + &comp.lpszScheme, &comp.dwSchemeLength, &scheme) + && set_url_component_AtoW(ret_comp->lpszExtraInfo, ret_comp->dwExtraInfoLength, + &comp.lpszExtraInfo, &comp.dwExtraInfoLength, &extra); + + if(ret && !(url_w = heap_strndupAtoW(url, url_length ? url_length : -1, &url_length))) { + SetLastError(ERROR_OUTOFMEMORY); + ret = FALSE; + } + + if (ret && (ret = InternetCrackUrlW(url_w, url_length, flags, &comp))) { + ret_comp->nScheme = comp.nScheme; + ret_comp->nPort = comp.nPort; + + ret = set_url_component_WtoA(comp.lpszHostName, comp.dwHostNameLength, url_w, + &ret_comp->lpszHostName, &ret_comp->dwHostNameLength, url) + && set_url_component_WtoA(comp.lpszUserName, comp.dwUserNameLength, url_w, + &ret_comp->lpszUserName, &ret_comp->dwUserNameLength, url) + && set_url_component_WtoA(comp.lpszPassword, comp.dwPasswordLength, url_w, + &ret_comp->lpszPassword, &ret_comp->dwPasswordLength, url) + && set_url_component_WtoA(comp.lpszUrlPath, comp.dwUrlPathLength, url_w, + &ret_comp->lpszUrlPath, &ret_comp->dwUrlPathLength, url) + && set_url_component_WtoA(comp.lpszScheme, comp.dwSchemeLength, url_w, + &ret_comp->lpszScheme, &ret_comp->dwSchemeLength, url) + && set_url_component_WtoA(comp.lpszExtraInfo, comp.dwExtraInfoLength, url_w, + &ret_comp->lpszExtraInfo, &ret_comp->dwExtraInfoLength, url); + + if(ret) + TRACE("%s: scheme(%s) host(%s) path(%s) extra(%s)\n", debugstr_a(url), + debugstr_an(ret_comp->lpszScheme, ret_comp->dwSchemeLength), + debugstr_an(ret_comp->lpszHostName, ret_comp->dwHostNameLength), + debugstr_an(ret_comp->lpszUrlPath, ret_comp->dwUrlPathLength), + debugstr_an(ret_comp->lpszExtraInfo, ret_comp->dwExtraInfoLength)); + } + + heap_free(host); + heap_free(user); + heap_free(pass); + heap_free(path); + heap_free(scheme); + heap_free(extra); + heap_free(url_w); + return ret; } static const WCHAR url_schemes[][7] = @@ -1651,49 +1596,6 @@ static INTERNET_SCHEME GetInternetSchemeW(LPCWSTR lpszScheme, DWORD nMaxCmp) return INTERNET_SCHEME_UNKNOWN; } -/*********************************************************************** - * SetUrlComponentValueW (Internal) - * - * Helper function for InternetCrackUrlW - * - * PARAMS - * lppszComponent [O] Holds the returned string - * dwComponentLen [I] Holds the size of lppszComponent - * [O] Holds the length of the string in lppszComponent without '\0' - * lpszStart [I] Holds the string to copy from - * len [I] Holds the length of lpszStart without '\0' - * - * RETURNS - * TRUE on success - * FALSE on failure - * - */ -static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen, LPCWSTR lpszStart, DWORD len) -{ - TRACE("%s (%d)\n", debugstr_wn(lpszStart,len), len); - - if ( (*dwComponentLen == 0) && (*lppszComponent == NULL) ) - return FALSE; - - if (*dwComponentLen != 0 || *lppszComponent == NULL) - { - if (*lppszComponent == NULL) - { - *lppszComponent = (LPWSTR)lpszStart; - *dwComponentLen = len; - } - else - { - DWORD ncpylen = min((*dwComponentLen)-1, len); - memcpy(*lppszComponent, lpszStart, ncpylen*sizeof(WCHAR)); - (*lppszComponent)[ncpylen] = '\0'; - *dwComponentLen = ncpylen; - } - } - - return TRUE; -} - /*********************************************************************** * InternetCrackUrlW (WININET.@) * @@ -1703,8 +1605,7 @@ static BOOL SetUrlComponentValueW(LPWSTR* lppszComponent, LPDWORD dwComponentLen * TRUE on success * FALSE on failure */ -BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWORD dwFlags, - LPURL_COMPONENTSW lpUC) +BOOL WINAPI InternetCrackUrlW(const WCHAR *lpszUrl, DWORD dwUrlLength, DWORD dwFlags, URL_COMPONENTSW *lpUC) { /* * RFC 1808 @@ -1713,46 +1614,51 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR */ LPCWSTR lpszParam = NULL; BOOL found_colon = FALSE; - LPCWSTR lpszap, lpszUrl = lpszUrl_orig; + LPCWSTR lpszap; LPCWSTR lpszcp = NULL, lpszNetLoc; - LPWSTR lpszUrl_decode = NULL; - DWORD dwUrlLength = dwUrlLength_orig; TRACE("(%s %u %x %p)\n", lpszUrl ? debugstr_wn(lpszUrl, dwUrlLength ? dwUrlLength : strlenW(lpszUrl)) : "(null)", dwUrlLength, dwFlags, lpUC); - if (!lpszUrl_orig || !*lpszUrl_orig || !lpUC) + if (!lpszUrl || !*lpszUrl || !lpUC) { - INTERNET_SetLastError(ERROR_INVALID_PARAMETER); + SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } if (!dwUrlLength) dwUrlLength = strlenW(lpszUrl); if (dwFlags & ICU_DECODE) { - WCHAR *url_tmp; + WCHAR *url_tmp, *buffer; DWORD len = dwUrlLength + 1; + BOOL ret; - if (!(url_tmp = heap_alloc(len * sizeof(WCHAR)))) + if (!(url_tmp = heap_strndupW(lpszUrl, dwUrlLength))) { - INTERNET_SetLastError(ERROR_OUTOFMEMORY); + SetLastError(ERROR_OUTOFMEMORY); return FALSE; } - memcpy(url_tmp, lpszUrl_orig, dwUrlLength * sizeof(WCHAR)); - url_tmp[dwUrlLength] = 0; - if (!(lpszUrl_decode = heap_alloc(len * sizeof(WCHAR)))) + + buffer = url_tmp; + ret = InternetCanonicalizeUrlW(url_tmp, buffer, &len, ICU_DECODE | ICU_NO_ENCODE); + if (!ret && GetLastError() == ERROR_INSUFFICIENT_BUFFER) { - heap_free(url_tmp); - INTERNET_SetLastError(ERROR_OUTOFMEMORY); - return FALSE; - } - if (InternetCanonicalizeUrlW(url_tmp, lpszUrl_decode, &len, ICU_DECODE | ICU_NO_ENCODE)) - { - dwUrlLength = len; - lpszUrl = lpszUrl_decode; + buffer = heap_alloc(len * sizeof(WCHAR)); + if (!buffer) + { + SetLastError(ERROR_OUTOFMEMORY); + heap_free(url_tmp); + return FALSE; + } + ret = InternetCanonicalizeUrlW(url_tmp, buffer, &len, ICU_DECODE | ICU_NO_ENCODE); } + if (ret) + ret = InternetCrackUrlW(buffer, len, dwFlags & ~ICU_DECODE, lpUC); + + if (buffer != url_tmp) heap_free(buffer); heap_free(url_tmp); + return ret; } lpszap = lpszUrl; @@ -1790,14 +1696,15 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR if(!lpszParam) lpszParam = memchrW(lpszap, '#', dwUrlLength - (lpszap - lpszUrl)); - SetUrlComponentValueW(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength, - lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0); + if(!set_url_component(&lpUC->lpszExtraInfo, &lpUC->dwExtraInfoLength, + lpszParam, lpszParam ? dwUrlLength-(lpszParam-lpszUrl) : 0)) + return FALSE; /* Get scheme first. */ lpUC->nScheme = GetInternetSchemeW(lpszUrl, lpszcp - lpszUrl); - SetUrlComponentValueW(&lpUC->lpszScheme, &lpUC->dwSchemeLength, - lpszUrl, lpszcp - lpszUrl); + if(!set_url_component(&lpUC->lpszScheme, &lpUC->dwSchemeLength, lpszUrl, lpszcp - lpszUrl)) + return FALSE; /* Eat ':' in protocol. */ lpszcp++; @@ -1831,8 +1738,8 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR if (lpszHost == NULL || lpszHost > lpszNetLoc) { /* username and password not specified. */ - SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); - SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); + set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); + set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); } else /* Parse out username and password */ { @@ -1847,14 +1754,14 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR lpszcp++; } - SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, - lpszUser, lpszPasswd - lpszUser); + if(!set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, lpszUser, lpszPasswd - lpszUser)) + return FALSE; if (lpszPasswd != lpszHost) lpszPasswd++; - SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, - lpszPasswd == lpszHost ? NULL : lpszPasswd, - lpszHost - lpszPasswd); + if(!set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength, + lpszPasswd == lpszHost ? NULL : lpszPasswd, lpszHost - lpszPasswd)) + return FALSE; lpszcp++; /* Advance to beginning of host */ } @@ -1868,8 +1775,8 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR entire string up to the first '/' */ if(lpUC->nScheme==INTERNET_SCHEME_RES) { - SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, - lpszHost, lpszPort - lpszHost); + if(!set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, lpszHost, lpszPort - lpszHost)) + return FALSE; lpszcp=lpszNetLoc; } else @@ -1886,13 +1793,12 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR if(lpUC->nScheme==INTERNET_SCHEME_FILE && lpszPort <= lpszHost+1) { lpszcp=lpszHost; - SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, - NULL, 0); + set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0); } else { - SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, - lpszHost, lpszPort - lpszHost); + if(!set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, lpszHost, lpszPort - lpszHost)) + return FALSE; if (lpszPort != lpszNetLoc) lpUC->nPort = atoiW(++lpszPort); else switch (lpUC->nScheme) @@ -1918,9 +1824,9 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR } else { - SetUrlComponentValueW(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); - SetUrlComponentValueW(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); - SetUrlComponentValueW(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0); + set_url_component(&lpUC->lpszUserName, &lpUC->dwUserNameLength, NULL, 0); + set_url_component(&lpUC->lpszPassword, &lpUC->dwPasswordLength, NULL, 0); + set_url_component(&lpUC->lpszHostName, &lpUC->dwHostNameLength, NULL, 0); } /* Here lpszcp points to: @@ -1955,7 +1861,7 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR if (*lpszcp == '/') { len = MAX_PATH; - PathCreateFromUrlW(lpszUrl_orig, tmppath, &len, 0); + PathCreateFromUrlW(lpszUrl, tmppath, &len, 0); } else { @@ -1982,17 +1888,18 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR ++len; } } - SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, - tmppath, len); + if(!set_url_component(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, tmppath, len)) + return FALSE; } - else - SetUrlComponentValueW(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, - lpszcp, len); + else if(!set_url_component(&lpUC->lpszUrlPath, &lpUC->dwUrlPathLength, lpszcp, len)) + return FALSE; } else { if (lpUC->lpszUrlPath && (lpUC->dwUrlPathLength > 0)) lpUC->lpszUrlPath[0] = 0; + else if (lpUC->dwUrlPathLength > 0) + lpUC->lpszUrlPath = (WCHAR*)lpszcp; lpUC->dwUrlPathLength = 0; } @@ -2002,7 +1909,6 @@ BOOL WINAPI InternetCrackUrlW(LPCWSTR lpszUrl_orig, DWORD dwUrlLength_orig, DWOR debugstr_wn(lpUC->lpszUrlPath,lpUC->dwUrlPathLength), debugstr_wn(lpUC->lpszExtraInfo,lpUC->dwExtraInfoLength)); - heap_free( lpszUrl_decode ); return TRUE; } @@ -2333,7 +2239,7 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer, TRACE("(%p %p 0x%x 0x%lx)\n", hFile, lpBuffer, dwFlags, dwContext); - if (lpBuffer->dwStructSize != sizeof(*lpBuffer)) { + if (!lpBuffer || lpBuffer->dwStructSize != sizeof(*lpBuffer)) { SetLastError(ERROR_INVALID_PARAMETER); return FALSE; } @@ -2358,32 +2264,37 @@ BOOL WINAPI InternetReadFileExW(HINTERNET hFile, LPINTERNET_BUFFERSW lpBuffer, return res == ERROR_SUCCESS; } -static BOOL get_proxy_autoconfig_url( char *buf, DWORD buflen ) +static WCHAR *get_proxy_autoconfig_url(void) { #if defined(MAC_OS_X_VERSION_10_6) && MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_6 CFDictionaryRef settings = CFNetworkCopySystemProxySettings(); + WCHAR *ret = NULL; + SIZE_T len; const void *ref; - BOOL ret = FALSE; - if (!settings) return FALSE; + if (!settings) return NULL; if (!(ref = CFDictionaryGetValue( settings, kCFNetworkProxiesProxyAutoConfigURLString ))) { CFRelease( settings ); - return FALSE; + return NULL; } - if (CFStringGetCString( ref, buf, buflen, kCFStringEncodingASCII )) + len = CFStringGetLength( ref ); + if (len) + ret = heap_alloc( (len+1) * sizeof(WCHAR) ); + if (ret) { - TRACE( "returning %s\n", debugstr_a(buf) ); - ret = TRUE; + CFStringGetCharacters( ref, CFRangeMake(0, len), ret ); + ret[len] = 0; } + TRACE( "returning %s\n", debugstr_w(ret) ); CFRelease( settings ); return ret; #else static int once; if (!once++) FIXME( "no support on this platform\n" ); - return FALSE; + return NULL; #endif } @@ -2470,20 +2381,17 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u } case INTERNET_OPTION_PER_CONNECTION_OPTION: { - char url[INTERNET_MAX_URL_LENGTH + 1]; + WCHAR *url; INTERNET_PER_CONN_OPTION_LISTW *con = buffer; INTERNET_PER_CONN_OPTION_LISTA *conA = buffer; DWORD res = ERROR_SUCCESS, i; proxyinfo_t pi; - BOOL have_url; LONG ret; TRACE("Getting global proxy info\n"); if((ret = INTERNET_LoadProxySettings(&pi))) return ret; - have_url = get_proxy_autoconfig_url(url, sizeof(url)); - FIXME("INTERNET_OPTION_PER_CONNECTION_OPTION stub\n"); if (*size < sizeof(INTERNET_PER_CONN_OPTION_LISTW)) { @@ -2491,6 +2399,8 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u return ERROR_INSUFFICIENT_BUFFER; } + url = get_proxy_autoconfig_url(); + for (i = 0; i < con->dwOptionCount; i++) { INTERNET_PER_CONN_OPTIONW *optionW = con->pOptions + i; INTERNET_PER_CONN_OPTIONA *optionA = conA->pOptions + i; @@ -2501,7 +2411,7 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u optionW->Value.dwValue = PROXY_TYPE_PROXY; else optionW->Value.dwValue = PROXY_TYPE_DIRECT; - if (have_url) + if (url) /* native includes PROXY_TYPE_DIRECT even if PROXY_TYPE_PROXY is set */ optionW->Value.dwValue |= PROXY_TYPE_DIRECT|PROXY_TYPE_AUTO_PROXY_URL; break; @@ -2521,12 +2431,12 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u break; case INTERNET_PER_CONN_AUTOCONFIG_URL: - if (!have_url) + if (!url) optionW->Value.pszValue = NULL; else if (unicode) - optionW->Value.pszValue = heap_strdupAtoW(url); + optionW->Value.pszValue = heap_strdupW(url); else - optionA->Value.pszValue = heap_strdupA(url); + optionA->Value.pszValue = heap_strdupWtoA(url); break; case INTERNET_PER_CONN_AUTODISCOVERY_FLAGS: @@ -2547,6 +2457,7 @@ static DWORD query_global_option(DWORD option, void *buffer, DWORD *size, BOOL u break; } } + heap_free(url); FreeProxyInfo(&pi); return res; @@ -3390,13 +3301,12 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe BOOL rc = FALSE; static const CHAR ping[] = "ping -c 1 "; static const CHAR redirect[] = " >/dev/null 2>/dev/null"; - CHAR *command = NULL; - WCHAR hostW[INTERNET_MAX_HOST_NAME_LENGTH]; - DWORD len; + WCHAR *host; + DWORD len, host_len; INTERNET_PORT port; int status = -1; - FIXME("\n"); + FIXME("(%s %x %x)\n", debugstr_w(lpszUrl), dwFlags, dwReserved); /* * Crack or set the Address @@ -3415,27 +3325,34 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe } else { - URL_COMPONENTSW components; + URL_COMPONENTSW components = {sizeof(components)}; - ZeroMemory(&components,sizeof(URL_COMPONENTSW)); - components.lpszHostName = (LPWSTR)hostW; - components.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH; + components.dwHostNameLength = 1; if (!InternetCrackUrlW(lpszUrl,0,0,&components)) goto End; - TRACE("host name : %s\n",debugstr_w(components.lpszHostName)); + host = components.lpszHostName; + host_len = components.dwHostNameLength; port = components.nPort; - TRACE("port: %d\n", port); + TRACE("host name: %s port: %d\n",debugstr_wn(host, host_len), port); } if (dwFlags & FLAG_ICC_FORCE_CONNECTION) { struct sockaddr_storage saddr; - socklen_t sa_len = sizeof(saddr); + int sa_len = sizeof(saddr); + WCHAR *host_z; int fd; + BOOL b; - if (!GetAddress(hostW, port, (struct sockaddr *)&saddr, &sa_len, NULL)) + host_z = heap_strndupW(host, host_len); + if (!host_z) + return FALSE; + + b = GetAddress(host_z, port, (struct sockaddr *)&saddr, &sa_len, NULL); + heap_free(host_z); + if(!b) goto End; init_winsock(); fd = socket(saddr.ss_family, SOCK_STREAM, 0); @@ -3451,15 +3368,18 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe /* * Build our ping command */ - len = WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, NULL, 0, NULL, NULL); - command = heap_alloc(strlen(ping)+len+strlen(redirect)); - strcpy(command,ping); - WideCharToMultiByte(CP_UNIXCP, 0, hostW, -1, command+strlen(ping), len, NULL, NULL); - strcat(command,redirect); + char *command; + + len = WideCharToMultiByte(CP_UNIXCP, 0, host, host_len, NULL, 0, NULL, NULL); + command = heap_alloc(strlen(ping)+len+strlen(redirect)+1); + strcpy(command, ping); + WideCharToMultiByte(CP_UNIXCP, 0, host, host_len, command+sizeof(ping)-1, len, NULL, NULL); + strcpy(command+sizeof(ping)-1+len, redirect); TRACE("Ping command is : %s\n",command); status = system(command); + heap_free( command ); TRACE("Ping returned a code of %i\n",status); @@ -3469,7 +3389,6 @@ BOOL WINAPI InternetCheckConnectionW( LPCWSTR lpszUrl, DWORD dwFlags, DWORD dwRe } End: - heap_free( command ); if (rc == FALSE) INTERNET_SetLastError(ERROR_NOT_CONNECTED); @@ -3516,40 +3435,38 @@ BOOL WINAPI InternetCheckConnectionA(LPCSTR lpszUrl, DWORD dwFlags, DWORD dwRese static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl, LPCWSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) { - URL_COMPONENTSW urlComponents; - WCHAR protocol[INTERNET_MAX_SCHEME_LENGTH]; - WCHAR hostName[INTERNET_MAX_HOST_NAME_LENGTH]; - WCHAR userName[INTERNET_MAX_USER_NAME_LENGTH]; - WCHAR password[INTERNET_MAX_PASSWORD_LENGTH]; - WCHAR path[INTERNET_MAX_PATH_LENGTH]; - WCHAR extra[1024]; + URL_COMPONENTSW urlComponents = { sizeof(urlComponents) }; + WCHAR *host, *user = NULL, *pass = NULL, *path; HINTERNET client = NULL, client1 = NULL; DWORD res; TRACE("(%p, %s, %s, %08x, %08x, %08lx)\n", hIC, debugstr_w(lpszUrl), debugstr_w(lpszHeaders), dwHeadersLength, dwFlags, dwContext); - urlComponents.dwStructSize = sizeof(URL_COMPONENTSW); - urlComponents.lpszScheme = protocol; - urlComponents.dwSchemeLength = INTERNET_MAX_SCHEME_LENGTH; - urlComponents.lpszHostName = hostName; - urlComponents.dwHostNameLength = INTERNET_MAX_HOST_NAME_LENGTH; - urlComponents.lpszUserName = userName; - urlComponents.dwUserNameLength = INTERNET_MAX_USER_NAME_LENGTH; - urlComponents.lpszPassword = password; - urlComponents.dwPasswordLength = INTERNET_MAX_PASSWORD_LENGTH; - urlComponents.lpszUrlPath = path; - urlComponents.dwUrlPathLength = INTERNET_MAX_PATH_LENGTH; - urlComponents.lpszExtraInfo = extra; - urlComponents.dwExtraInfoLength = 1024; + urlComponents.dwHostNameLength = 1; + urlComponents.dwUserNameLength = 1; + urlComponents.dwPasswordLength = 1; + urlComponents.dwUrlPathLength = 1; + urlComponents.dwExtraInfoLength = 1; if(!InternetCrackUrlW(lpszUrl, strlenW(lpszUrl), 0, &urlComponents)) return NULL; + + if(urlComponents.nScheme == INTERNET_SCHEME_HTTP && urlComponents.dwExtraInfoLength) { + assert(urlComponents.lpszUrlPath + urlComponents.dwUrlPathLength == urlComponents.lpszExtraInfo); + urlComponents.dwUrlPathLength += urlComponents.dwExtraInfoLength; + } + + host = heap_strndupW(urlComponents.lpszHostName, urlComponents.dwHostNameLength); + path = heap_strndupW(urlComponents.lpszUrlPath, urlComponents.dwUrlPathLength); + if(urlComponents.dwUserNameLength) + user = heap_strndupW(urlComponents.lpszUserName, urlComponents.dwUserNameLength); + if(urlComponents.dwPasswordLength) + pass = heap_strndupW(urlComponents.lpszPassword, urlComponents.dwPasswordLength); + switch(urlComponents.nScheme) { case INTERNET_SCHEME_FTP: - if(urlComponents.nPort == 0) - urlComponents.nPort = INTERNET_DEFAULT_FTP_PORT; - client = FTP_Connect(hIC, hostName, urlComponents.nPort, - userName, password, dwFlags, dwContext, INET_OPENURL); + client = FTP_Connect(hIC, host, urlComponents.nPort, + user, pass, dwFlags, dwContext, INET_OPENURL); if(client == NULL) break; client1 = FtpOpenFileW(client, path, GENERIC_READ, dwFlags, dwContext); @@ -3563,39 +3480,18 @@ static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl, case INTERNET_SCHEME_HTTPS: { static const WCHAR szStars[] = { '*','/','*', 0 }; LPCWSTR accept[2] = { szStars, NULL }; - if(urlComponents.nPort == 0) { - if(urlComponents.nScheme == INTERNET_SCHEME_HTTP) - urlComponents.nPort = INTERNET_DEFAULT_HTTP_PORT; - else - urlComponents.nPort = INTERNET_DEFAULT_HTTPS_PORT; - } + if (urlComponents.nScheme == INTERNET_SCHEME_HTTPS) dwFlags |= INTERNET_FLAG_SECURE; /* FIXME: should use pointers, not handles, as handles are not thread-safe */ - res = HTTP_Connect(hIC, hostName, urlComponents.nPort, - userName, password, dwFlags, dwContext, INET_OPENURL, &client); + res = HTTP_Connect(hIC, host, urlComponents.nPort, + user, pass, dwFlags, dwContext, INET_OPENURL, &client); if(res != ERROR_SUCCESS) { INTERNET_SetLastError(res); break; } - if (urlComponents.dwExtraInfoLength) { - WCHAR *path_extra; - DWORD len = urlComponents.dwUrlPathLength + urlComponents.dwExtraInfoLength + 1; - - if (!(path_extra = heap_alloc(len * sizeof(WCHAR)))) - { - InternetCloseHandle(client); - break; - } - strcpyW(path_extra, urlComponents.lpszUrlPath); - strcatW(path_extra, urlComponents.lpszExtraInfo); - client1 = HttpOpenRequestW(client, NULL, path_extra, NULL, NULL, accept, dwFlags, dwContext); - heap_free(path_extra); - } - else - client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext); - + client1 = HttpOpenRequestW(client, NULL, path, NULL, NULL, accept, dwFlags, dwContext); if(client1 == NULL) { InternetCloseHandle(client); break; @@ -3617,7 +3513,11 @@ static HINTERNET INTERNET_InternetOpenUrlW(appinfo_t *hIC, LPCWSTR lpszUrl, } TRACE(" %p <--\n", client1); - + + heap_free(host); + heap_free(path); + heap_free(user); + heap_free(pass); return client1; } @@ -3711,9 +3611,8 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, LPCSTR lpszHeaders, DWORD dwHeadersLength, DWORD dwFlags, DWORD_PTR dwContext) { HINTERNET rc = NULL; - DWORD lenHeaders = 0; LPWSTR szUrl = NULL; - LPWSTR szHeaders = NULL; + WCHAR *headers = NULL; TRACE("\n"); @@ -3724,20 +3623,17 @@ HINTERNET WINAPI InternetOpenUrlA(HINTERNET hInternet, LPCSTR lpszUrl, } if(lpszHeaders) { - lenHeaders = MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, NULL, 0 ); - szHeaders = heap_alloc(lenHeaders*sizeof(WCHAR)); - if(!szHeaders) { + headers = heap_strndupAtoW(lpszHeaders, dwHeadersLength, &dwHeadersLength); + if(!headers) { heap_free(szUrl); return NULL; } - MultiByteToWideChar(CP_ACP, 0, lpszHeaders, dwHeadersLength, szHeaders, lenHeaders); } - rc = InternetOpenUrlW(hInternet, szUrl, szHeaders, - lenHeaders, dwFlags, dwContext); + rc = InternetOpenUrlW(hInternet, szUrl, headers, dwHeadersLength, dwFlags, dwContext); heap_free(szUrl); - heap_free(szHeaders); + heap_free(headers); return rc; } @@ -3957,6 +3853,7 @@ void req_file_release(req_file_t *req_file) if(req_file->file_handle && req_file->file_handle != INVALID_HANDLE_VALUE) CloseHandle(req_file->file_handle); heap_free(req_file->file_name); + heap_free(req_file->url); heap_free(req_file); } @@ -4554,23 +4451,20 @@ BOOL WINAPI InternetGetSecurityInfoByURLA(LPSTR lpszURL, PCCERT_CHAIN_CONTEXT *p */ BOOL WINAPI InternetGetSecurityInfoByURLW(LPCWSTR lpszURL, PCCERT_CHAIN_CONTEXT *ppCertChain, DWORD *pdwSecureFlags) { - WCHAR hostname[INTERNET_MAX_HOST_NAME_LENGTH]; URL_COMPONENTSW url = {sizeof(url)}; server_t *server; - BOOL res = FALSE; + BOOL res; TRACE("(%s %p %p)\n", debugstr_w(lpszURL), ppCertChain, pdwSecureFlags); - url.lpszHostName = hostname; - url.dwHostNameLength = sizeof(hostname)/sizeof(WCHAR); - + url.dwHostNameLength = 1; res = InternetCrackUrlW(lpszURL, 0, 0, &url); if(!res || url.nScheme != INTERNET_SCHEME_HTTPS) { SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND); return FALSE; } - server = get_server(hostname, url.nPort, TRUE, FALSE); + server = get_server(substr(url.lpszHostName, url.dwHostNameLength), url.nPort, TRUE, FALSE); if(!server) { SetLastError(ERROR_INTERNET_ITEM_NOT_FOUND); return FALSE; diff --git a/reactos/dll/win32/wininet/internet.h b/reactos/dll/win32/wininet/internet.h index 2b16ebbbd61..9567f58749b 100644 --- a/reactos/dll/win32/wininet/internet.h +++ b/reactos/dll/win32/wininet/internet.h @@ -89,10 +89,6 @@ WINE_DEFAULT_DEBUG_CHANNEL(wininet); extern HMODULE WININET_hModule DECLSPEC_HIDDEN; -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif - typedef struct { WCHAR *name; INTERNET_PORT port; @@ -227,6 +223,25 @@ static inline LPWSTR heap_strndupW(LPCWSTR str, UINT max_len) return ret; } +static inline WCHAR *heap_strndupAtoW(const char *str, int len_a, DWORD *len_w) +{ + WCHAR *ret = NULL; + + if(str) { + size_t len; + if(len_a < 0) len_a = strlen(str); + len = MultiByteToWideChar(CP_ACP, 0, str, len_a, NULL, 0); + ret = heap_alloc((len+1)*sizeof(WCHAR)); + if(ret) { + MultiByteToWideChar(CP_ACP, 0, str, len_a, ret, len); + ret[len] = 0; + *len_w = len; + } + } + + return ret; +} + static inline WCHAR *heap_strdupAtoW(const char *str) { LPWSTR ret = NULL; @@ -257,6 +272,22 @@ static inline char *heap_strdupWtoA(LPCWSTR str) return ret; } +typedef struct { + const WCHAR *str; + size_t len; +} substr_t; + +static inline substr_t substr(const WCHAR *str, size_t len) +{ + substr_t r = {str, len}; + return r; +} + +static inline substr_t substrz(const WCHAR *str) +{ + return substr(str, strlenW(str)); +} + static inline void WININET_find_data_WtoA(LPWIN32_FIND_DATAW dataW, LPWIN32_FIND_DATAA dataA) { dataA->dwFileAttributes = dataW->dwFileAttributes; @@ -294,6 +325,7 @@ typedef struct LONG ref; HANDLE file_handle; WCHAR *file_name; + WCHAR *url; BOOL is_committed; } req_file_t; @@ -461,7 +493,7 @@ DWORD HTTP_Connect(appinfo_t*,LPCWSTR, BOOL GetAddress(const WCHAR*,INTERNET_PORT,SOCKADDR*,int*,char*) DECLSPEC_HIDDEN; DWORD get_cookie_header(const WCHAR*,const WCHAR*,WCHAR**) DECLSPEC_HIDDEN; -DWORD set_cookie(const WCHAR*,const WCHAR*,const WCHAR*,const WCHAR*,DWORD) DECLSPEC_HIDDEN; +DWORD set_cookie(substr_t,substr_t,substr_t,substr_t,DWORD) DECLSPEC_HIDDEN; void INTERNET_SetLastError(DWORD dwError) DECLSPEC_HIDDEN; DWORD INTERNET_GetLastError(void) DECLSPEC_HIDDEN; @@ -475,7 +507,7 @@ VOID SendAsyncCallback(object_header_t *hdr, DWORD_PTR dwContext, VOID INTERNET_SendCallback(object_header_t *hdr, DWORD_PTR dwContext, DWORD dwInternetStatus, LPVOID lpvStatusInfo, DWORD dwStatusInfoLength) DECLSPEC_HIDDEN; -BOOL INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto, WCHAR *foundProxy, DWORD *foundProxyLen) DECLSPEC_HIDDEN; +WCHAR *INTERNET_FindProxyForProtocol(LPCWSTR szProxy, LPCWSTR proto) DECLSPEC_HIDDEN; DWORD create_netconn(BOOL,server_t*,DWORD,BOOL,DWORD,netconn_t**) DECLSPEC_HIDDEN; void free_netconn(netconn_t*) DECLSPEC_HIDDEN; @@ -492,7 +524,7 @@ DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value) DECLSPEC int sock_send(int fd, const void *msg, size_t len, int flags) DECLSPEC_HIDDEN; int sock_recv(int fd, void *msg, size_t len, int flags) DECLSPEC_HIDDEN; -server_t *get_server(const WCHAR*,INTERNET_PORT,BOOL,BOOL) DECLSPEC_HIDDEN; +server_t *get_server(substr_t,INTERNET_PORT,BOOL,BOOL) DECLSPEC_HIDDEN; DWORD create_req_file(const WCHAR*,req_file_t**) DECLSPEC_HIDDEN; void req_file_release(req_file_t*) DECLSPEC_HIDDEN; diff --git a/reactos/dll/win32/wininet/netconnection.c b/reactos/dll/win32/wininet/netconnection.c index 559fc98fd17..43dc7aa0fd7 100644 --- a/reactos/dll/win32/wininet/netconnection.c +++ b/reactos/dll/win32/wininet/netconnection.c @@ -389,6 +389,7 @@ void free_netconn(netconn_t *netconn) DeleteSecurityContext(&netconn->ssl_ctx); } + close_netconn(netconn); heap_free(netconn); } diff --git a/reactos/dll/win32/wininet/urlcache.c b/reactos/dll/win32/wininet/urlcache.c index e78b9aa4019..81954e33fad 100644 --- a/reactos/dll/win32/wininet/urlcache.c +++ b/reactos/dll/win32/wininet/urlcache.c @@ -2109,7 +2109,7 @@ static BOOL urlcache_entry_get_file(const char *url, void *entry_info, DWORD *si if (!urlcache_find_hash_entry(header, url, &hash_entry)) { cache_container_unlock_index(container, header); - TRACE("entry %s not found!\n", url); + TRACE("entry %s not found!\n", debugstr_a(url)); SetLastError(ERROR_FILE_NOT_FOUND); return FALSE; } diff --git a/reactos/dll/win32/wininet/wininet_ros.diff b/reactos/dll/win32/wininet/wininet_ros.diff index e2779269283..e5b5e51c41c 100644 --- a/reactos/dll/win32/wininet/wininet_ros.diff +++ b/reactos/dll/win32/wininet/wininet_ros.diff @@ -1,7 +1,7 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c ---- e:\wine\dlls\wininet/http.c 2015-07-14 15:44:36.040192300 +0100 -+++ e:\reactos\dll\win32\wininet/http.c 2015-07-20 14:37:24.319646400 +0100 -@@ -143,6 +118,7 @@ static const WCHAR emptyW[] = {0}; +--- e:\wine\dlls\wininet/http.c 2016-05-31 18:02:43 +0100 ++++ e:\reactos\dll\win32\wininet/http.c 2016-07-02 16:18:16 +0100 +@@ -118,6 +118,7 @@ static const WCHAR emptyW[] = {0}; #define COLLECT_TIME 60000 @@ -9,7 +9,7 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c #define ARRAYSIZE(array) (sizeof(array)/sizeof((array)[0])) struct HttpAuthInfo -@@ -229,7 +205,13 @@ void server_release(server_t *server) +@@ -203,7 +204,13 @@ void server_release(server_t *server) if(InterlockedDecrement(&server->ref)) return; @@ -23,7 +23,7 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c if(server->cert_chain) CertFreeCertificateChain(server->cert_chain); -@@ -311,7 +293,11 @@ BOOL collect_connections(collect_type_t +@@ -286,7 +293,11 @@ BOOL collect_connections(collect_type_t BOOL remaining = FALSE; DWORD64 now; @@ -35,7 +35,7 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c LIST_FOR_EACH_ENTRY_SAFE(server, server_safe, &connection_pool, server_t, entry) { LIST_FOR_EACH_ENTRY_SAFE(netconn, netconn_safe, &server->conn_pool, netconn_t, pool_entry) { -@@ -1973,13 +1959,14 @@ static void http_release_netconn(http_re +@@ -1923,13 +1934,14 @@ static void http_release_netconn(http_re if(!is_valid_netconn(req->netconn)) return; @@ -51,7 +51,7 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c req->netconn = NULL; run_collector = !collector_running; -@@ -2007,6 +1994,10 @@ static void http_release_netconn(http_re +@@ -1957,6 +1969,10 @@ static void http_release_netconn(http_re } return; } @@ -63,9 +63,9 @@ diff -pudN e:\wine\dlls\wininet/http.c e:\reactos\dll\win32\wininet/http.c INTERNET_SendCallback(&req->hdr, req->hdr.dwContext, INTERNET_STATUS_CLOSING_CONNECTION, 0, 0); diff -pudN e:\wine\dlls\wininet/internet.c e:\reactos\dll\win32\wininet/internet.c ---- e:\wine\dlls\wininet/internet.c 2015-04-12 18:21:54.309796800 +0100 -+++ e:\reactos\dll\win32\wininet/internet.c 2015-07-20 14:38:19.188784800 +0100 -@@ -1033,6 +996,9 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR l +--- e:\wine\dlls\wininet/internet.c 2016-05-31 18:05:36 +0100 ++++ e:\reactos\dll\win32\wininet/internet.c 2016-07-02 16:18:16 +0100 +@@ -963,6 +963,9 @@ HINTERNET WINAPI InternetOpenW(LPCWSTR l { appinfo_t *lpwai = NULL; @@ -77,9 +77,9 @@ diff -pudN e:\wine\dlls\wininet/internet.c e:\reactos\dll\win32\wininet/internet static const wininet_flag_info access_type[] = { diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache.c ---- e:\wine\dlls\wininet/urlcache.c 2015-07-14 15:44:36.059193400 +0100 -+++ e:\reactos\dll\win32\wininet/urlcache.c 2015-07-20 14:40:55.736738800 +0100 -@@ -202,6 +179,8 @@ typedef struct +--- e:\wine\dlls\wininet/urlcache.c 2016-05-31 18:02:43 +0100 ++++ e:\reactos\dll\win32\wininet/urlcache.c 2016-07-02 16:18:16 +0100 +@@ -179,6 +179,8 @@ typedef struct /* List of all containers available */ static struct list UrlContainers = LIST_INIT(UrlContainers); @@ -88,7 +88,7 @@ diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache static inline char *heap_strdupWtoUTF8(LPCWSTR str) { -@@ -752,6 +731,8 @@ static void cache_containers_init(void) +@@ -729,6 +731,8 @@ static void cache_containers_init(void) static const WCHAR UrlSuffix[] = {'C','o','n','t','e','n','t','.','I','E','5',0}; static const WCHAR HistorySuffix[] = {'H','i','s','t','o','r','y','.','I','E','5',0}; static const WCHAR CookieSuffix[] = {0}; @@ -97,21 +97,21 @@ diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache static const struct { int nFolder; /* CSIDL_* constant */ -@@ -766,6 +747,13 @@ static void cache_containers_init(void) +@@ -743,6 +747,13 @@ static void cache_containers_init(void) }; DWORD i; + /* ReactOS r50916 */ + if (GetEnvironmentVariableW(UserProfile, NULL, 0) == 0 && GetLastError() == ERROR_ENVVAR_NOT_FOUND) + { -+ TRACE("Environment variable 'USERPROFILE' does not exist!\n"); ++ ERR("Environment variable 'USERPROFILE' does not exist!\n"); + return; + } + for (i = 0; i < sizeof(DefaultContainerData) / sizeof(DefaultContainerData[0]); i++) { WCHAR wszCachePath[MAX_PATH]; -@@ -816,6 +804,10 @@ static void cache_containers_init(void) +@@ -793,6 +804,10 @@ static void cache_containers_init(void) cache_containers_add(DefaultContainerData[i].cache_prefix, wszCachePath, DefaultContainerData[i].default_entry_type, wszMutexName); } @@ -122,7 +122,7 @@ diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache } static void cache_containers_free(void) -@@ -835,6 +827,12 @@ static DWORD cache_containers_find(const +@@ -812,6 +827,12 @@ static DWORD cache_containers_find(const if(!url) return ERROR_INVALID_PARAMETER; @@ -135,7 +135,7 @@ diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry) { int prefix_len = strlen(container->cache_prefix); -@@ -861,6 +859,12 @@ static BOOL cache_containers_enum(char * +@@ -838,6 +859,12 @@ static BOOL cache_containers_enum(char * if (search_pattern && index > 0) return FALSE; @@ -148,7 +148,7 @@ diff -pudN e:\wine\dlls\wininet/urlcache.c e:\reactos\dll\win32\wininet/urlcache LIST_FOR_EACH_ENTRY(container, &UrlContainers, cache_container, entry) { if (search_pattern) -@@ -4018,7 +4022,9 @@ BOOL init_urlcache(void) +@@ -3995,7 +4022,9 @@ BOOL init_urlcache(void) return FALSE; } diff --git a/reactos/media/doc/README.WINE b/reactos/media/doc/README.WINE index 5273cef0301..bed4d89701d 100644 --- a/reactos/media/doc/README.WINE +++ b/reactos/media/doc/README.WINE @@ -205,7 +205,7 @@ reactos/dll/win32/windowscodecsext # Synced to WineStaging-1.9.4 reactos/dll/win32/winemp3.acm # Synced to WineStaging-1.9.4 reactos/dll/win32/wing32 # Synced to WineStaging-1.9.4 reactos/dll/win32/winhttp # Synced to WineStaging-1.9.4 -reactos/dll/win32/wininet # Synced to WineStaging-1.9.4 +reactos/dll/win32/wininet # Synced to WineStaging-1.9.11 reactos/dll/win32/winmm # Forked at Wine-20050628 reactos/dll/win32/winmm/midimap # Forked at Wine-20050628 reactos/dll/win32/winmm/wavemap # Forked at Wine-20050628