wininet: Support Punycode in CreateUrlCacheEntryW.
This commit is contained in:
parent
41b582beff
commit
d40867121f
|
@ -213,6 +213,20 @@ typedef struct
|
||||||
/* List of all containers available */
|
/* List of all containers available */
|
||||||
static struct list UrlContainers = LIST_INIT(UrlContainers);
|
static struct list UrlContainers = LIST_INIT(UrlContainers);
|
||||||
|
|
||||||
|
static inline char *heap_strdupWtoUTF8(LPCWSTR str)
|
||||||
|
{
|
||||||
|
char *ret = NULL;
|
||||||
|
|
||||||
|
if(str) {
|
||||||
|
DWORD size = WideCharToMultiByte(CP_UTF8, 0, str, -1, NULL, 0, NULL, NULL);
|
||||||
|
ret = heap_alloc(size);
|
||||||
|
if(ret)
|
||||||
|
WideCharToMultiByte(CP_UTF8, 0, str, -1, ret, size, NULL, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* urlcache_block_is_free (Internal)
|
* urlcache_block_is_free (Internal)
|
||||||
*
|
*
|
||||||
|
@ -2567,212 +2581,117 @@ BOOL WINAPI UnlockUrlCacheEntryFileW(LPCWSTR lpszUrlName, DWORD dwReserved)
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
BOOL urlcache_entry_create(const char *url, const char *ext, WCHAR *full_path)
|
||||||
* CreateUrlCacheEntryA (WININET.@)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateUrlCacheEntryA(
|
|
||||||
IN LPCSTR lpszUrlName,
|
|
||||||
IN DWORD dwExpectedFileSize,
|
|
||||||
IN LPCSTR lpszFileExtension,
|
|
||||||
OUT LPSTR lpszFileName,
|
|
||||||
IN DWORD dwReserved
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
WCHAR *url_name;
|
cache_container *container;
|
||||||
WCHAR *file_extension = NULL;
|
urlcache_header *header;
|
||||||
WCHAR file_name[MAX_PATH];
|
char file_name[MAX_PATH];
|
||||||
BOOL bSuccess = FALSE;
|
const char *url_part, *url_end;
|
||||||
DWORD dwError = 0;
|
const WCHAR *file_name_ext;
|
||||||
|
WCHAR *file_name_no_path;
|
||||||
TRACE("(%s %d %s %p %d)\n", debugstr_a(lpszUrlName), dwExpectedFileSize,
|
WCHAR extW[MAX_PATH];
|
||||||
debugstr_a(lpszFileExtension), lpszFileName, dwReserved);
|
int i, len, len_no_ext;
|
||||||
|
BYTE cache_dir;
|
||||||
if (lpszUrlName && (url_name = heap_strdupAtoW(lpszUrlName)))
|
LONG buffer_size;
|
||||||
{
|
BOOL found = FALSE, generate_name = FALSE;
|
||||||
if (!lpszFileExtension || (file_extension = heap_strdupAtoW(lpszFileExtension)))
|
|
||||||
{
|
|
||||||
if (CreateUrlCacheEntryW(url_name, dwExpectedFileSize, file_extension, file_name, dwReserved))
|
|
||||||
{
|
|
||||||
if (WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL) < MAX_PATH)
|
|
||||||
{
|
|
||||||
bSuccess = TRUE;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dwError = GetLastError();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dwError = GetLastError();
|
|
||||||
}
|
|
||||||
heap_free(file_extension);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
dwError = GetLastError();
|
|
||||||
}
|
|
||||||
heap_free(url_name);
|
|
||||||
if (!bSuccess) SetLastError(dwError);
|
|
||||||
}
|
|
||||||
return bSuccess;
|
|
||||||
}
|
|
||||||
/***********************************************************************
|
|
||||||
* CreateUrlCacheEntryW (WININET.@)
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
BOOL WINAPI CreateUrlCacheEntryW(
|
|
||||||
IN LPCWSTR lpszUrlName,
|
|
||||||
IN DWORD dwExpectedFileSize,
|
|
||||||
IN LPCWSTR lpszFileExtension,
|
|
||||||
OUT LPWSTR lpszFileName,
|
|
||||||
IN DWORD dwReserved
|
|
||||||
)
|
|
||||||
{
|
|
||||||
cache_container *pContainer;
|
|
||||||
urlcache_header *pHeader;
|
|
||||||
CHAR szFile[MAX_PATH];
|
|
||||||
WCHAR szExtension[MAX_PATH];
|
|
||||||
LPCWSTR lpszUrlPart;
|
|
||||||
LPCWSTR lpszUrlEnd;
|
|
||||||
LPCWSTR lpszFileNameExtension;
|
|
||||||
LPWSTR lpszFileNameNoPath;
|
|
||||||
int i;
|
|
||||||
int countnoextension;
|
|
||||||
BYTE CacheDir;
|
|
||||||
LONG lBufferSize;
|
|
||||||
BOOL bFound = FALSE;
|
|
||||||
BOOL generate_name = FALSE;
|
|
||||||
int count;
|
|
||||||
DWORD error;
|
DWORD error;
|
||||||
HANDLE hFile;
|
HANDLE file;
|
||||||
FILETIME ft;
|
FILETIME ft;
|
||||||
|
|
||||||
static const WCHAR szWWW[] = {'w','w','w',0};
|
TRACE("(%s, %s, %p)\n", debugstr_a(url), debugstr_a(ext), full_path);
|
||||||
|
|
||||||
TRACE("(%s, 0x%08x, %s, %p, 0x%08x)\n",
|
url_end = url + strlen(url);
|
||||||
debugstr_w(lpszUrlName),
|
|
||||||
dwExpectedFileSize,
|
|
||||||
debugstr_w(lpszFileExtension),
|
|
||||||
lpszFileName,
|
|
||||||
dwReserved);
|
|
||||||
|
|
||||||
if (dwReserved)
|
|
||||||
FIXME("dwReserved 0x%08x\n", dwReserved);
|
|
||||||
|
|
||||||
lpszUrlEnd = lpszUrlName + strlenW(lpszUrlName);
|
|
||||||
|
|
||||||
if (((lpszUrlEnd - lpszUrlName) > 1) && (*(lpszUrlEnd - 1) == '/' || *(lpszUrlEnd - 1) == '\\'))
|
if(((url_end - url) > 1) && (*(url_end - 1) == '/' || *(url_end - 1) == '\\'))
|
||||||
lpszUrlEnd--;
|
url_end--;
|
||||||
|
|
||||||
lpszUrlPart = memchrW(lpszUrlName, '?', lpszUrlEnd - lpszUrlName);
|
url_part = memchr(url, '?', url_end - url);
|
||||||
if (!lpszUrlPart)
|
if(!url_part)
|
||||||
lpszUrlPart = memchrW(lpszUrlName, '#', lpszUrlEnd - lpszUrlName);
|
url_part = memchr(url, '#', url_end - url);
|
||||||
if (lpszUrlPart)
|
if(url_part)
|
||||||
lpszUrlEnd = lpszUrlPart;
|
url_end = url_part;
|
||||||
|
|
||||||
for (lpszUrlPart = lpszUrlEnd;
|
for(url_part = url_end; (url_part >= url); url_part--) {
|
||||||
(lpszUrlPart >= lpszUrlName);
|
if((*url_part == '/' || *url_part == '\\') && ((url_end - url_part) > 1)) {
|
||||||
lpszUrlPart--)
|
found = TRUE;
|
||||||
{
|
url_part++;
|
||||||
if ((*lpszUrlPart == '/' || *lpszUrlPart == '\\') && ((lpszUrlEnd - lpszUrlPart) > 1))
|
|
||||||
{
|
|
||||||
bFound = TRUE;
|
|
||||||
lpszUrlPart++;
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(!bFound)
|
if(!found)
|
||||||
lpszUrlPart++;
|
url_part++;
|
||||||
|
|
||||||
if (!lstrcmpW(lpszUrlPart, szWWW))
|
if(!lstrcmpA(url_part, "www"))
|
||||||
{
|
url_part += 3;
|
||||||
lpszUrlPart += lstrlenW(szWWW);
|
|
||||||
}
|
|
||||||
|
|
||||||
count = lpszUrlEnd - lpszUrlPart;
|
len = url_end - url_part;
|
||||||
|
|
||||||
if (bFound && (count < MAX_PATH))
|
if(found && (len < MAX_PATH-1)) {
|
||||||
{
|
memcpy(file_name, url_part, len);
|
||||||
int len = WideCharToMultiByte(CP_ACP, 0, lpszUrlPart, count, szFile, sizeof(szFile) - 1, NULL, NULL);
|
file_name[len] = '\0';
|
||||||
if (!len)
|
while(len && file_name[--len] == '/') file_name[len] = '\0';
|
||||||
return FALSE;
|
|
||||||
szFile[len] = '\0';
|
|
||||||
while(len && szFile[--len] == '/') szFile[len] = '\0';
|
|
||||||
|
|
||||||
/* FIXME: get rid of illegal characters like \, / and : */
|
/* FIXME: get rid of illegal characters like \, / and : */
|
||||||
TRACE("File name: %s\n", debugstr_a(szFile));
|
TRACE("File name: %s\n", debugstr_a(file_name));
|
||||||
}
|
}else {
|
||||||
else
|
|
||||||
{
|
|
||||||
generate_name = TRUE;
|
generate_name = TRUE;
|
||||||
szFile[0] = 0;
|
file_name[0] = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = cache_containers_findW(lpszUrlName, &pContainer);
|
error = cache_containers_find(url, &container);
|
||||||
if (error != ERROR_SUCCESS)
|
if(error != ERROR_SUCCESS) {
|
||||||
{
|
|
||||||
SetLastError(error);
|
SetLastError(error);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
error = cache_container_open_index(pContainer, MIN_BLOCK_NO);
|
error = cache_container_open_index(container, MIN_BLOCK_NO);
|
||||||
if (error != ERROR_SUCCESS)
|
if(error != ERROR_SUCCESS) {
|
||||||
{
|
|
||||||
SetLastError(error);
|
SetLastError(error);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(pHeader = cache_container_lock_index(pContainer)))
|
if(!(header = cache_container_lock_index(container)))
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
if(pHeader->dirs_no)
|
if(header->dirs_no)
|
||||||
CacheDir = (BYTE)(rand() % pHeader->dirs_no);
|
cache_dir = (BYTE)(rand() % header->dirs_no);
|
||||||
else
|
else
|
||||||
CacheDir = CACHE_CONTAINER_NO_SUBDIR;
|
cache_dir = CACHE_CONTAINER_NO_SUBDIR;
|
||||||
|
|
||||||
lBufferSize = MAX_PATH * sizeof(WCHAR);
|
buffer_size = MAX_PATH * sizeof(WCHAR);
|
||||||
if (!urlcache_create_file_pathW(pContainer, pHeader, szFile, CacheDir, lpszFileName, &lBufferSize))
|
if(!urlcache_create_file_pathW(container, header, file_name, cache_dir, full_path, &buffer_size)) {
|
||||||
{
|
|
||||||
WARN("Failed to get full path for filename %s, needed %u bytes.\n",
|
WARN("Failed to get full path for filename %s, needed %u bytes.\n",
|
||||||
debugstr_a(szFile), lBufferSize);
|
debugstr_a(file_name), buffer_size);
|
||||||
cache_container_unlock_index(pContainer, pHeader);
|
cache_container_unlock_index(container, header);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
cache_container_unlock_index(pContainer, pHeader);
|
cache_container_unlock_index(container, header);
|
||||||
|
|
||||||
for (lpszFileNameNoPath = lpszFileName + lBufferSize / sizeof(WCHAR) - 2;
|
for(file_name_no_path = full_path + buffer_size / sizeof(WCHAR) - 2;
|
||||||
lpszFileNameNoPath >= lpszFileName;
|
file_name_no_path >= full_path; --file_name_no_path) {
|
||||||
--lpszFileNameNoPath)
|
if (*file_name_no_path == '/' || *file_name_no_path == '\\')
|
||||||
{
|
|
||||||
if (*lpszFileNameNoPath == '/' || *lpszFileNameNoPath == '\\')
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
countnoextension = lstrlenW(lpszFileNameNoPath);
|
len_no_ext = lstrlenW(file_name_no_path);
|
||||||
lpszFileNameExtension = PathFindExtensionW(lpszFileNameNoPath);
|
file_name_ext = PathFindExtensionW(file_name_no_path);
|
||||||
if (lpszFileNameExtension)
|
if(file_name_ext)
|
||||||
countnoextension -= lstrlenW(lpszFileNameExtension);
|
len_no_ext -= lstrlenW(file_name_ext);
|
||||||
*szExtension = '\0';
|
*extW = '\0';
|
||||||
|
|
||||||
if (lpszFileExtension)
|
if(ext) {
|
||||||
{
|
extW[0] = '.';
|
||||||
szExtension[0] = '.';
|
MultiByteToWideChar(CP_ACP, 0, ext, -1, extW+1, MAX_PATH-1);
|
||||||
lstrcpyW(szExtension+1, lpszFileExtension);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (i = 0; i<255 && !generate_name; i++)
|
for(i=0; i<255 && !generate_name; i++) {
|
||||||
{
|
static const WCHAR format[] = {'[','%','u',']','%','s',0};
|
||||||
static const WCHAR szFormat[] = {'[','%','u',']','%','s',0};
|
|
||||||
WCHAR *p;
|
WCHAR *p;
|
||||||
|
|
||||||
wsprintfW(lpszFileNameNoPath + countnoextension, szFormat, i, szExtension);
|
wsprintfW(file_name_no_path + len_no_ext, format, i, extW);
|
||||||
for (p = lpszFileNameNoPath + 1; *p; p++)
|
for(p=file_name_no_path+1; *p; p++) {
|
||||||
{
|
switch(*p) {
|
||||||
switch (*p)
|
|
||||||
{
|
|
||||||
case '<': case '>':
|
case '<': case '>':
|
||||||
case ':': case '"':
|
case ':': case '"':
|
||||||
case '/': case '\\':
|
case '/': case '\\':
|
||||||
|
@ -2782,41 +2701,37 @@ BOOL WINAPI CreateUrlCacheEntryW(
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (p[-1] == ' ' || p[-1] == '.') p[-1] = '_';
|
if(p[-1] == ' ' || p[-1] == '.') p[-1] = '_';
|
||||||
|
|
||||||
TRACE("Trying: %s\n", debugstr_w(lpszFileName));
|
TRACE("Trying: %s\n", debugstr_w(full_path));
|
||||||
hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
|
file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
if(file != INVALID_HANDLE_VALUE) {
|
||||||
{
|
CloseHandle(file);
|
||||||
CloseHandle(hFile);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Try to generate random name */
|
/* Try to generate random name */
|
||||||
GetSystemTimeAsFileTime(&ft);
|
GetSystemTimeAsFileTime(&ft);
|
||||||
strcpyW(lpszFileNameNoPath+countnoextension+8, szExtension);
|
strcpyW(file_name_no_path+len_no_ext+8, extW);
|
||||||
|
|
||||||
for(i=0; i<255; i++)
|
for(i=0; i<255; i++) {
|
||||||
{
|
|
||||||
int j;
|
int j;
|
||||||
ULONGLONG n = ft.dwHighDateTime;
|
ULONGLONG n = ft.dwHighDateTime;
|
||||||
n <<= 32;
|
n <<= 32;
|
||||||
n += ft.dwLowDateTime;
|
n += ft.dwLowDateTime;
|
||||||
n ^= (ULONGLONG)i<<48;
|
n ^= (ULONGLONG)i<<48;
|
||||||
|
|
||||||
for(j=0; j<8; j++)
|
for(j=0; j<8; j++) {
|
||||||
{
|
|
||||||
int r = (n % 36);
|
int r = (n % 36);
|
||||||
n /= 37;
|
n /= 37;
|
||||||
lpszFileNameNoPath[countnoextension+j] = (r < 10 ? '0' + r : 'A' + r - 10);
|
file_name_no_path[len_no_ext+j] = (r < 10 ? '0' + r : 'A' + r - 10);
|
||||||
}
|
}
|
||||||
|
|
||||||
TRACE("Trying: %s\n", debugstr_w(lpszFileName));
|
TRACE("Trying: %s\n", debugstr_w(full_path));
|
||||||
hFile = CreateFileW(lpszFileName, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
|
file = CreateFileW(full_path, GENERIC_READ, 0, NULL, CREATE_NEW, 0, NULL);
|
||||||
if (hFile != INVALID_HANDLE_VALUE)
|
if(file != INVALID_HANDLE_VALUE) {
|
||||||
{
|
CloseHandle(file);
|
||||||
CloseHandle(hFile);
|
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -2825,6 +2740,55 @@ BOOL WINAPI CreateUrlCacheEntryW(
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateUrlCacheEntryA (WININET.@)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateUrlCacheEntryA(LPCSTR lpszUrlName, DWORD dwExpectedFileSize,
|
||||||
|
LPCSTR lpszFileExtension, LPSTR lpszFileName, DWORD dwReserved)
|
||||||
|
{
|
||||||
|
WCHAR file_name[MAX_PATH];
|
||||||
|
|
||||||
|
if(dwReserved)
|
||||||
|
FIXME("dwReserved 0x%08x\n", dwReserved);
|
||||||
|
|
||||||
|
if(!urlcache_entry_create(lpszUrlName, lpszFileExtension, file_name))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if(!WideCharToMultiByte(CP_ACP, 0, file_name, -1, lpszFileName, MAX_PATH, NULL, NULL))
|
||||||
|
return FALSE;
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
/***********************************************************************
|
||||||
|
* CreateUrlCacheEntryW (WININET.@)
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
BOOL WINAPI CreateUrlCacheEntryW(LPCWSTR lpszUrlName, DWORD dwExpectedFileSize,
|
||||||
|
LPCWSTR lpszFileExtension, LPWSTR lpszFileName, DWORD dwReserved)
|
||||||
|
{
|
||||||
|
char *url, *ext = NULL;
|
||||||
|
BOOL ret;
|
||||||
|
|
||||||
|
if(dwReserved)
|
||||||
|
FIXME("dwReserved 0x%08x\n", dwReserved);
|
||||||
|
|
||||||
|
if(lpszFileExtension) {
|
||||||
|
ext = heap_strdupWtoUTF8(lpszFileExtension);
|
||||||
|
if(!ext)
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!urlcache_encode_url_alloc(lpszUrlName, &url)) {
|
||||||
|
heap_free(ext);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = urlcache_entry_create(url, ext, lpszFileName);
|
||||||
|
heap_free(ext);
|
||||||
|
heap_free(url);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************************
|
/***********************************************************************
|
||||||
* urlcache_entry_commit (Compensates for an MS bug)
|
* urlcache_entry_commit (Compensates for an MS bug)
|
||||||
*
|
*
|
||||||
|
|
Loading…
Reference in New Issue