Commit 414d1dde authored by Robert Shearman's avatar Robert Shearman Committed by Alexandre Julliard

wininet: Rewrite InternetCreateUrlW.

- Rewrite InternetCreateUrlW to respect the lengths passed in via the URL_COMPONENTS structure and fall back to a strlenW call when a length is zero. - Expand the number of protocols supported when determining whether the port number should be added. - Fix a test by passing in the correct length of scheme.
parent 9981f337
......@@ -3691,39 +3691,52 @@ BOOL WINAPI InternetCombineUrlW(LPCWSTR lpszBaseUrl, LPCWSTR lpszRelativeUrl,
/* max port num is 65535 => 5 digits */
#define MAX_WORD_DIGITS 5
#define URL_GET_COMP_LENGTH(url, component) ((url)->dw##component##Length ? \
(url)->dw##component##Length : strlenW((url)->lpsz##component))
#define URL_GET_COMP_LENGTHA(url, component) ((url)->dw##component##Length ? \
(url)->dw##component##Length : strlen((url)->lpsz##component))
static BOOL url_uses_default_port(LPURL_COMPONENTSW lpUrlComponents)
{
static const WCHAR httpW[] = {'h','t','t','p',0};
static const WCHAR httpsW[] = {'h','t','t','p','s',0};
static const WCHAR ftpW[] = {'f','t','p',0};
static const WCHAR gopherW[] = {'g','o','p','h','e','r',0};
DWORD len;
if (!lpUrlComponents->lpszScheme) return FALSE;
len = URL_GET_COMP_LENGTH(lpUrlComponents, Scheme);
if (!strncmpW(lpUrlComponents->lpszScheme, httpW, len) &&
(lpUrlComponents->nPort == INTERNET_DEFAULT_HTTP_PORT))
return TRUE;
if (!strncmpW(lpUrlComponents->lpszScheme, httpsW, len) &&
(lpUrlComponents->nPort == INTERNET_DEFAULT_HTTPS_PORT))
return TRUE;
if (!strncmpW(lpUrlComponents->lpszScheme, ftpW, len) &&
(lpUrlComponents->nPort == INTERNET_DEFAULT_FTP_PORT))
return TRUE;
if (!strncmpW(lpUrlComponents->lpszScheme, gopherW, len) &&
(lpUrlComponents->nPort == INTERNET_DEFAULT_GOPHER_PORT))
return TRUE;
return FALSE;
}
/* we can calculate using ansi strings because we're just
* calculating string length, not size
*/
static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents,
LPDWORD lpdwUrlLength, LPDWORD lpdwSchemeLength)
LPDWORD lpdwUrlLength)
{
static const WCHAR httpW[] = {'h','t','t','p',0};
*lpdwUrlLength = 0;
switch (lpUrlComponents->nScheme)
{
case INTERNET_SCHEME_FTP:
case INTERNET_SCHEME_RES:
*lpdwSchemeLength = 3;
break;
case INTERNET_SCHEME_HTTP:
case INTERNET_SCHEME_FILE:
case INTERNET_SCHEME_NEWS:
*lpdwSchemeLength = 4;
break;
default:
*lpdwSchemeLength = 4;
break;
}
*lpdwUrlLength += *lpdwSchemeLength;
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, Scheme);
*lpdwUrlLength += strlen("://");
if (lpUrlComponents->lpszUserName)
{
*lpdwUrlLength += lpUrlComponents->dwUserNameLength;
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UserName);
*lpdwUrlLength += strlen("@");
}
else
......@@ -3738,13 +3751,12 @@ static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents,
if (lpUrlComponents->lpszPassword)
{
*lpdwUrlLength += strlen(":");
*lpdwUrlLength += lpUrlComponents->dwPasswordLength;
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, Password);
}
*lpdwUrlLength += lpUrlComponents->dwHostNameLength;
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, HostName);
if (lpUrlComponents->nPort != 80 ||
(lpUrlComponents->lpszScheme && strncmpW(lpUrlComponents->lpszScheme, httpW, lpUrlComponents->dwSchemeLength)))
if (!url_uses_default_port(lpUrlComponents))
{
char szPort[MAX_WORD_DIGITS];
......@@ -3753,7 +3765,7 @@ static BOOL calc_url_length(LPURL_COMPONENTSW lpUrlComponents,
*lpdwUrlLength += strlen(":");
}
*lpdwUrlLength += lpUrlComponents->dwUrlPathLength;
*lpdwUrlLength += URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath);
return TRUE;
}
......@@ -3775,7 +3787,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszScheme)
{
len = lpUrlComponents->dwSchemeLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, Scheme) + 1;
urlCompW->lpszScheme = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszScheme,
-1, urlCompW->lpszScheme, len);
......@@ -3783,7 +3795,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszHostName)
{
len = lpUrlComponents->dwHostNameLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, HostName) + 1;
urlCompW->lpszHostName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszHostName,
-1, urlCompW->lpszHostName, len);
......@@ -3791,7 +3803,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszUserName)
{
len = lpUrlComponents->dwUserNameLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, UserName) + 1;
urlCompW->lpszUserName = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszUserName,
-1, urlCompW->lpszUserName, len);
......@@ -3799,7 +3811,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszPassword)
{
len = lpUrlComponents->dwPasswordLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, Password) + 1;
urlCompW->lpszPassword = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszPassword,
-1, urlCompW->lpszPassword, len);
......@@ -3807,7 +3819,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszUrlPath)
{
len = lpUrlComponents->dwUrlPathLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, UrlPath) + 1;
urlCompW->lpszUrlPath = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszUrlPath,
-1, urlCompW->lpszUrlPath, len);
......@@ -3815,7 +3827,7 @@ static void convert_urlcomp_atow(LPURL_COMPONENTSA lpUrlComponents, LPURL_COMPON
if (lpUrlComponents->lpszExtraInfo)
{
len = lpUrlComponents->dwExtraInfoLength + 1;
len = URL_GET_COMP_LENGTHA(lpUrlComponents, ExtraInfo) + 1;
urlCompW->lpszExtraInfo = HeapAlloc(GetProcessHeap(), 0, len * sizeof(WCHAR));
MultiByteToWideChar(CP_ACP, 0, lpUrlComponents->lpszExtraInfo,
-1, urlCompW->lpszExtraInfo, len);
......@@ -3883,12 +3895,9 @@ BOOL WINAPI InternetCreateUrlA(LPURL_COMPONENTSA lpUrlComponents, DWORD dwFlags,
BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
LPWSTR lpszUrl, LPDWORD lpdwUrlLength)
{
DWORD dwLen, dwSchemeLen;
DWORD dwLen;
static const WCHAR colonSlashW[] = {':','/','/',0};
static const WCHAR httpW[] = {'h','t','t','p',0};
static const WCHAR colonW[] = {':',0};
static const WCHAR atW[] = {'@',0};
static const WCHAR colonSlashW[] = {':','/','/'};
static const WCHAR percentD[] = {'%','d',0};
TRACE("(%p,%ld,%s,%p)\n", lpUrlComponents, dwFlags, debugstr_w(lpszUrl), lpdwUrlLength);
......@@ -3902,7 +3911,7 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
return FALSE;
}
if (!calc_url_length(lpUrlComponents, &dwLen, &dwSchemeLen))
if (!calc_url_length(lpUrlComponents, &dwLen))
return FALSE;
if (!lpszUrl || *lpdwUrlLength < dwLen)
......@@ -3915,45 +3924,59 @@ BOOL WINAPI InternetCreateUrlW(LPURL_COMPONENTSW lpUrlComponents, DWORD dwFlags,
*lpdwUrlLength = dwLen;
lpszUrl[0] = 0x00;
dwLen = 0;
if (lpUrlComponents->lpszScheme)
lstrcpynW(lpszUrl, lpUrlComponents->lpszScheme,
min(lpUrlComponents->dwSchemeLength, dwSchemeLen) + 1);
{
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, Scheme);
memcpy(lpszUrl, lpUrlComponents->lpszScheme, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
}
lstrcatW(lpszUrl, colonSlashW);
memcpy(lpszUrl, colonSlashW, sizeof(colonSlashW));
lpszUrl += sizeof(colonSlashW)/sizeof(colonSlashW[0]);
if (lpUrlComponents->lpszUserName)
{
if (!*lpUrlComponents->lpszUserName)
return TRUE;
lstrcatW(lpszUrl, lpUrlComponents->lpszUserName);
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UserName);
memcpy(lpszUrl, lpUrlComponents->lpszUserName, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
if (lpUrlComponents->lpszPassword)
{
lstrcatW(lpszUrl, colonW);
*lpszUrl = ':';
lpszUrl++;
if (!*lpUrlComponents->lpszPassword)
return TRUE;
else
lstrcatW(lpszUrl, lpUrlComponents->lpszPassword);
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, Password);
memcpy(lpszUrl, lpUrlComponents->lpszPassword, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
}
lstrcatW(lpszUrl, atW);
*lpszUrl = '@';
lpszUrl++;
}
lstrcatW(lpszUrl, lpUrlComponents->lpszHostName);
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, HostName);
memcpy(lpszUrl, lpUrlComponents->lpszHostName, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
if (lpUrlComponents->nPort != 80 || (lpUrlComponents->lpszScheme &&
strncmpW(lpUrlComponents->lpszScheme, httpW, lpUrlComponents->dwSchemeLength)))
if (!url_uses_default_port(lpUrlComponents))
{
WCHAR szPort[MAX_WORD_DIGITS];
sprintfW(szPort, percentD, lpUrlComponents->nPort);
lstrcatW(lpszUrl, colonW);
lstrcatW(lpszUrl, szPort);
*lpszUrl = ':';
lpszUrl++;
dwLen = strlenW(szPort);
memcpy(lpszUrl, szPort, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
}
lstrcatW(lpszUrl, lpUrlComponents->lpszUrlPath);
dwLen = URL_GET_COMP_LENGTH(lpUrlComponents, UrlPath);
memcpy(lpszUrl, lpUrlComponents->lpszUrlPath, dwLen * sizeof(WCHAR));
lpszUrl += dwLen;
*lpszUrl = '\0';
return TRUE;
}
......
......@@ -911,15 +911,18 @@ static void InternetCreateUrlA_test(void)
ok(len == 51, "Expected len 51, got %ld\n", len);
/* alloced szUrl, NULL lpszScheme
* shows that it uses dwXLength instead of strlen(lpszX)
* shows that it uses nScheme instead
*/
SetLastError(0xdeadbeef);
urlComp.lpszScheme = NULL;
ret = InternetCreateUrlA(&urlComp, 0, szUrl, &len);
todo_wine {
ok(ret, "Expected success\n");
ok(GetLastError() == 0xdeadbeef,
"Expected 0xdeadbeef, got %ld\n", GetLastError());
ok(len == 50, "Expected len 50, got %ld\n", len);
ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
}
/* alloced szUrl, invalid nScheme
* any nScheme out of range seems ignored
......@@ -1035,14 +1038,13 @@ static void InternetCreateUrlA_test(void)
szUrl = (char *)HeapAlloc(GetProcessHeap(), 0, len);
ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
ok(ret, "Expected success\n");
todo_wine {
ok(len == strlen(CREATE_URL6), "Expected len %d, got %ld\n", strlen(CREATE_URL6) + 1, len);
ok(!strcmp(szUrl, CREATE_URL6), "Expected %s, got %s\n", CREATE_URL6, szUrl);
}
/* if lpszScheme != "http" or nPort != 80, display nPort */
HeapFree(GetProcessHeap(), 0, szUrl);
urlComp.lpszScheme = "http";
urlComp.dwSchemeLength = strlen(urlComp.lpszScheme);
urlComp.nPort = 42;
szUrl = HeapAlloc(GetProcessHeap(), 0, ++len);
ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
......@@ -1073,10 +1075,8 @@ static void InternetCreateUrlA_test(void)
szUrl = (char *)HeapAlloc(GetProcessHeap(), 0, ++len);
ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
ok(ret, "Expected success\n");
todo_wine {
ok(len == strlen(CREATE_URL1), "Expected len %d, got %ld\n", strlen(CREATE_URL1), len);
ok(!strcmp(szUrl, CREATE_URL1), "Expected %s, got %s\n", CREATE_URL1, szUrl);
}
memset(&urlComp, 0, sizeof(urlComp));
urlComp.dwStructSize = sizeof(URL_COMPONENTS);
......@@ -1098,10 +1098,8 @@ static void InternetCreateUrlA_test(void)
szUrl = (char *)HeapAlloc(GetProcessHeap(), 0, ++len);
ret = InternetCreateUrlA(&urlComp, ICU_ESCAPE, szUrl, &len);
ok(ret, "Expected success\n");
todo_wine {
ok(len == strlen(CREATE_URL8), "Expected len %d, got %ld\n", strlen(CREATE_URL8), len);
ok(!strcmp(szUrl, CREATE_URL8), "Expected %s, got %s\n", CREATE_URL8, szUrl);
}
HeapFree(GetProcessHeap(), 0, szUrl);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment