ReactOS 0.4.16-dev-1946-g52006dd
url.c File Reference
#include <stdarg.h>
#include <stdio.h>
#include "wine/test.h"
#include "windef.h"
#include "winbase.h"
#include "winreg.h"
#include "shlwapi.h"
#include "wininet.h"
#include "intshcut.h"
#include "winternl.h"
Include dependency graph for url.c:

Go to the source code of this file.

Classes

struct  _TEST_URL_APPLY
 
struct  _TEST_URL_ESCAPE
 
struct  _TEST_URL_ESCAPEW
 
struct  _TEST_URL_COMBINE
 
struct  canonicalize_test
 
struct  parse_url_test_t
 

Typedefs

typedef struct _TEST_URL_APPLY TEST_URL_APPLY
 
typedef struct _TEST_URL_ESCAPE TEST_URL_ESCAPE
 
typedef struct _TEST_URL_ESCAPEW TEST_URL_ESCAPEW
 
typedef struct _TEST_URL_COMBINE TEST_URL_COMBINE
 

Functions

static LPWSTR GetWideString (const char *szString)
 
static void FreeWideString (LPWSTR wszString)
 
static void test_UrlApplyScheme (void)
 
static void hash_url (const char *szUrl)
 
static void test_UrlHash (void)
 
static void test_UrlGetPart (void)
 
static void check_url_canonicalize (const char *url, DWORD flags, const char *expect)
 
static void test_UrlEscapeA (void)
 
static void test_UrlEscapeW (void)
 
static void test_UrlCanonicalizeA (void)
 
static void test_UrlCanonicalizeW (void)
 
static void check_url_combine (const char *szUrl1, const char *szUrl2, DWORD dwFlags, const char *szExpectUrl)
 
static void test_UrlCombine (void)
 
static void test_UrlCreateFromPath (void)
 
static void test_UrlIs_null (DWORD flag)
 
static void test_UrlIs (void)
 
static void test_UrlUnescape (void)
 
static void test_ParseURL (void)
 
static void test_HashData (void)
 
 START_TEST (url)
 

Variables

static const charTEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923"
 
static const charTEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923"
 
static const charTEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y"
 
static const WCHAR winehqW [] = L"http://www.winehq.org/"
 
static const char winehqA [] = "http://www.winehq.org/"
 
static const CHAR untouchedA [] = "untouched"
 
static const TEST_URL_APPLY TEST_APPLY []
 
static const TEST_URL_ESCAPE TEST_ESCAPE []
 
static const TEST_URL_ESCAPEW TEST_ESCAPEW []
 
static const TEST_URL_COMBINE TEST_COMBINE []
 
struct {
   const char *   path
 
   const char *   url
 
   DWORD   ret
 
TEST_URLFROMPATH []
 
struct {
   char   url [30]
 
   const char *   expect
 
TEST_URL_UNESCAPE []
 
struct {
   const WCHAR *   url
 
   const WCHAR *   expect
 
   DWORD   flags
 
TEST_URL_UNESCAPEW []
 
struct {
   const char *   path
 
   BOOL   expect
 
TEST_PATH_IS_URL []
 
struct {
   const char *   url
 
   BOOL   expectOpaque
 
   BOOL   expectFile
 
TEST_URLIS_ATTRIBS []
 
static const struct parse_url_test_t parse_url_tests []
 

Typedef Documentation

◆ TEST_URL_APPLY

◆ TEST_URL_COMBINE

◆ TEST_URL_ESCAPE

◆ TEST_URL_ESCAPEW

Function Documentation

◆ check_url_canonicalize()

static void check_url_canonicalize ( const char url,
DWORD  flags,
const char expect 
)
static

Definition at line 793 of file url.c.

794{
795 char output[INTERNET_MAX_URL_LENGTH];
797 WCHAR *urlW = GetWideString(url);
798 WCHAR *expectW;
799 HRESULT hr;
800 DWORD size;
801
802 winetest_push_context("URL %s, flags %#lx", debugstr_a(url), flags);
803
806 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
807 hr = UrlCanonicalizeA(url, output, &size, flags);
808 ok(hr == S_OK || (!url[0] && hr == S_FALSE) /* Vista+ */, "Got unexpected hr %#lx.\n", hr);
809 ok(!strcmp(output, expect), "Expected %s, got %s.\n", debugstr_a(expect), debugstr_a(output));
810
812 hr = UrlCanonicalizeW(urlW, NULL, &size, flags);
813 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
814 hr = UrlCanonicalizeW(urlW, outputW, &size, flags);
815 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
816
817 expectW = GetWideString(output);
818 ok(!wcscmp(outputW, expectW), "Expected %s, got %s.\n", debugstr_w(expectW), debugstr_w(outputW));
819 FreeWideString(expectW);
820
821 FreeWideString(urlW);
822
824}
int strcmp(const char *String1, const char *String2)
Definition: utclib.c:469
#define ok(value,...)
Definition: atltest.h:57
#define E_INVALIDARG
Definition: ddrawi.h:101
#define NULL
Definition: types.h:112
HRESULT WINAPI UrlCanonicalizeA(const char *src_url, char *canonicalized, DWORD *canonicalized_len, DWORD flags)
Definition: path.c:3542
HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, LPDWORD pcchCanonicalized, DWORD dwFlags)
Definition: url.c:282
#define INTERNET_MAX_URL_LENGTH
Definition: session.c:1418
unsigned long DWORD
Definition: ntddk_ex.h:95
GLsizeiptr size
Definition: glext.h:5919
GLbitfield flags
Definition: glext.h:7161
#define S_OK
Definition: intsafe.h:52
#define debugstr_a
Definition: kernel32.h:31
#define debugstr_w
Definition: kernel32.h:32
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl winetest_push_context(const char *fmt,...) __WINE_PRINTF_ATTR(1
void __cdecl void __cdecl void __cdecl void __cdecl void __cdecl void winetest_pop_context(void)
static const WCHAR url[]
Definition: encode.c:1384
static LPWSTR GetWideString(const char *szString)
Definition: url.c:376
static void FreeWideString(LPWSTR wszString)
Definition: url.c:386
const char * expect
Definition: url.c:286
_Check_return_ _CRTIMP int __cdecl wcscmp(_In_z_ const wchar_t *_Str1, _In_z_ const wchar_t *_Str2)
HRESULT hr
Definition: shlfolder.c:183
#define S_FALSE
Definition: winerror.h:3451
__wchar_t WCHAR
Definition: xmlstorage.h:180

Referenced by test_UrlCanonicalizeA().

◆ check_url_combine()

static void check_url_combine ( const char szUrl1,
const char szUrl2,
DWORD  dwFlags,
const char szExpectUrl 
)
static

Definition at line 2284 of file url.c.

2285{
2286 HRESULT hr;
2287 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
2288 WCHAR wszReturnUrl[INTERNET_MAX_URL_LENGTH];
2289 LPWSTR wszUrl1, wszUrl2, wszExpectUrl, wszConvertedUrl;
2290
2291 DWORD dwSize;
2292 DWORD dwExpectLen = lstrlenA(szExpectUrl);
2293
2294 wszUrl1 = GetWideString(szUrl1);
2295 wszUrl2 = GetWideString(szUrl2);
2296 wszExpectUrl = GetWideString(szExpectUrl);
2297
2298 dwSize = ARRAY_SIZE(szReturnUrl);
2299 hr = UrlCombineA(szUrl1, szUrl2, szReturnUrl, &dwSize, dwFlags);
2300 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2301 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
2302 ok(!strcmp(szReturnUrl, szExpectUrl), "Expected %s, got %s.\n", szExpectUrl, szReturnUrl);
2303
2304 dwSize = ARRAY_SIZE(wszReturnUrl);
2305 hr = UrlCombineW(wszUrl1, wszUrl2, wszReturnUrl, &dwSize, dwFlags);
2306 ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr);
2307 ok(dwSize == dwExpectLen, "Got length %ld, expected %ld\n", dwSize, dwExpectLen);
2308 wszConvertedUrl = GetWideString(szReturnUrl);
2309 ok(!wcscmp(wszReturnUrl, wszConvertedUrl), "Expected %s, got %s.\n",
2310 debugstr_w(wszConvertedUrl), debugstr_w(wszReturnUrl));
2311 FreeWideString(wszConvertedUrl);
2312
2313 FreeWideString(wszUrl1);
2314 FreeWideString(wszUrl2);
2315 FreeWideString(wszExpectUrl);
2316}
#define ARRAY_SIZE(A)
Definition: main.h:20
HRESULT WINAPI UrlCombineA(const char *base, const char *relative, char *combined, DWORD *combined_len, DWORD flags)
Definition: path.c:4932
HRESULT WINAPI UrlCombineW(LPCWSTR pszBase, LPCWSTR pszRelative, LPWSTR pszCombined, LPDWORD pcchCombined, DWORD dwFlags)
Definition: url.c:662
int WINAPI lstrlenA(LPCSTR lpString)
Definition: lstring.c:145
PSDBQUERYRESULT_VISTA PVOID DWORD * dwSize
Definition: env.c:56
_In_ LPWSTR _In_ DWORD _In_ DWORD _In_ DWORD dwFlags
Definition: netsh.h:141
WCHAR * LPWSTR
Definition: xmlstorage.h:184
char CHAR
Definition: xmlstorage.h:175

Referenced by test_UrlCombine().

◆ FreeWideString()

static void FreeWideString ( LPWSTR  wszString)
static

Definition at line 386 of file url.c.

387{
388 HeapFree(GetProcessHeap(), 0, wszString);
389}
#define GetProcessHeap()
Definition: compat.h:736
#define HeapFree(x, y, z)
Definition: compat.h:735

Referenced by check_url_canonicalize(), check_url_combine(), hash_url(), test_UrlCreateFromPath(), and test_UrlEscapeW().

◆ GetWideString()

static LPWSTR GetWideString ( const char szString)
static

Definition at line 376 of file url.c.

377{
378 LPWSTR wszString = HeapAlloc(GetProcessHeap(), 0, (2*INTERNET_MAX_URL_LENGTH) * sizeof(WCHAR));
379
380 MultiByteToWideChar(CP_ACP, 0, szString, -1, wszString, INTERNET_MAX_URL_LENGTH);
381
382 return wszString;
383}
#define CP_ACP
Definition: compat.h:109
#define HeapAlloc
Definition: compat.h:733
#define MultiByteToWideChar
Definition: compat.h:110

Referenced by check_url_canonicalize(), check_url_combine(), hash_url(), test_UrlCreateFromPath(), and test_UrlEscapeW().

◆ hash_url()

static void hash_url ( const char szUrl)
static

Definition at line 473 of file url.c.

474{
475 LPCSTR szTestUrl = szUrl;
476 LPWSTR wszTestUrl = GetWideString(szTestUrl);
477 HRESULT res;
478
479 DWORD cbSize = sizeof(DWORD);
480 DWORD dwHash1, dwHash2;
481 res = UrlHashA(szTestUrl, (LPBYTE)&dwHash1, cbSize);
482 ok(res == S_OK, "UrlHashA returned 0x%lx (expected S_OK) for %s\n", res, szUrl);
483
484 res = UrlHashW(wszTestUrl, (LPBYTE)&dwHash2, cbSize);
485 ok(res == S_OK, "UrlHashW returned 0x%lx (expected S_OK) for %s\n", res, szUrl);
486 ok(dwHash1 == dwHash2,
487 "Hashes didn't match (A: 0x%lx, W: 0x%lx) for %s\n", dwHash1, dwHash2, szUrl);
488 FreeWideString(wszTestUrl);
489}
HRESULT WINAPI UrlHashW(const WCHAR *url, unsigned char *dest, DWORD dest_len)
Definition: path.c:5284
HRESULT WINAPI UrlHashA(const char *url, unsigned char *dest, DWORD dest_len)
Definition: path.c:5270
GLuint res
Definition: glext.h:9613
#define DWORD
Definition: nt_native.h:44
unsigned char * LPBYTE
Definition: typedefs.h:53
const char * LPCSTR
Definition: xmlstorage.h:183

Referenced by test_UrlHash().

◆ START_TEST()

START_TEST ( url  )

Definition at line 2701 of file url.c.

2702{
2704 test_UrlHash();
2712 test_UrlIs();
2714 test_ParseURL();
2715 test_HashData();
2716}
static void test_UrlCombine(void)
Definition: url.c:2320
static void test_UrlEscapeW(void)
Definition: url.c:883
static void test_HashData(void)
Definition: url.c:2627
static void test_ParseURL(void)
Definition: url.c:2572
static void test_UrlHash(void)
Definition: url.c:491
static void test_UrlCanonicalizeA(void)
Definition: url.c:993
static void test_UrlIs(void)
Definition: url.c:2418
static void test_UrlEscapeA(void)
Definition: url.c:827
static void test_UrlUnescape(void)
Definition: url.c:2470
static void test_UrlCanonicalizeW(void)
Definition: url.c:2188
static void test_UrlApplyScheme(void)
Definition: url.c:393
static void test_UrlGetPart(void)
Definition: url.c:498
static void test_UrlCreateFromPath(void)
Definition: url.c:2377

◆ test_HashData()

static void test_HashData ( void  )
static

Definition at line 2627 of file url.c.

2628{
2629 HRESULT res;
2630 BYTE input[16] = {0x51, 0x33, 0x4F, 0xA7, 0x45, 0x15, 0xF0, 0x52, 0x90,
2631 0x2B, 0xE7, 0xF5, 0xFD, 0xE1, 0xA6, 0xA7};
2632 BYTE output[32];
2633 static const BYTE expected[] = {0x54, 0x9C, 0x92, 0x55, 0xCD, 0x82, 0xFF,
2634 0xA1, 0x8E, 0x0F, 0xCF, 0x93, 0x14, 0xAA,
2635 0xE3, 0x2D};
2636 static const BYTE expected2[] = {0x54, 0x9C, 0x92, 0x55, 0xCD, 0x82, 0xFF,
2637 0xA1, 0x8E, 0x0F, 0xCF, 0x93, 0x14, 0xAA,
2638 0xE3, 0x2D, 0x47, 0xFC, 0x80, 0xB8, 0xD0,
2639 0x49, 0xE6, 0x13, 0x2A, 0x30, 0x51, 0x8D,
2640 0xF9, 0x4B, 0x07, 0xA6};
2641 static const BYTE expected3[] = {0x2B, 0xDC, 0x9A, 0x1B, 0xF0, 0x5A, 0xF9,
2642 0xC6, 0xBE, 0x94, 0x6D, 0xF3, 0x33, 0xC1,
2643 0x36, 0x07};
2644 int i;
2645
2646 /* Test hashing with identically sized input/output buffers. */
2647 res = HashData(input, 16, output, 16);
2648 ok(res == S_OK, "Expected HashData to return S_OK, got 0x%08lx\n", res);
2649 ok(!memcmp(output, expected, sizeof(expected)), "data didn't match\n");
2650
2651 /* Test hashing with larger output buffer. */
2652 res = HashData(input, 16, output, 32);
2653 ok(res == S_OK, "Expected HashData to return S_OK, got 0x%08lx\n", res);
2654 ok(!memcmp(output, expected2, sizeof(expected2)), "data didn't match\n");
2655
2656 /* Test hashing with smaller input buffer. */
2657 res = HashData(input, 8, output, 16);
2658 ok(res == S_OK, "Expected HashData to return S_OK, got 0x%08lx\n", res);
2659 ok(!memcmp(output, expected3, sizeof(expected3)), "data didn't match\n");
2660
2661 /* Test passing NULL pointers for input/output parameters. */
2662 res = HashData(NULL, 0, NULL, 0);
2663 ok(res == E_INVALIDARG, "Got unexpected hr %#lx.\n", res);
2664
2665 res = HashData(input, 0, NULL, 0);
2666 ok(res == E_INVALIDARG, "Got unexpected hr %#lx.\n", res);
2667
2668 res = HashData(NULL, 0, output, 0);
2669 ok(res == E_INVALIDARG, "Got unexpected hr %#lx.\n", res);
2670
2671 /* Test passing valid pointers with sizes of zero. */
2672 for (i = 0; i < ARRAY_SIZE(input); i++)
2673 input[i] = 0x00;
2674
2675 for (i = 0; i < ARRAY_SIZE(output); i++)
2676 output[i] = 0xFF;
2677
2678 res = HashData(input, 0, output, 0);
2679 ok(res == S_OK, "Expected HashData to return S_OK, got 0x%08lx\n", res);
2680
2681 /* The buffers should be unchanged. */
2682 for (i = 0; i < ARRAY_SIZE(input); i++)
2683 ok(input[i] == 0x00, "Expected the input buffer to be unchanged\n");
2684
2685 for (i = 0; i < ARRAY_SIZE(output); i++)
2686 ok(output[i] == 0xFF, "Expected the output buffer to be unchanged\n");
2687
2688 /* Input/output parameters are not validated. */
2689 res = HashData((BYTE *)0xdeadbeef, 0, (BYTE *)0xdeadbeef, 0);
2690 ok(res == S_OK, "Expected HashData to return S_OK, got 0x%08lx\n", res);
2691
2692 if (0)
2693 {
2694 res = HashData((BYTE *)0xdeadbeef, 1, (BYTE *)0xdeadbeef, 1);
2695 trace("HashData returned 0x%08lx\n", res);
2696 }
2697}
int memcmp(void *Buffer1, void *Buffer2, ACPI_SIZE Count)
Definition: utclib.c:112
#define trace
Definition: atltest.h:70
HRESULT WINAPI HashData(const unsigned char *lpSrc, DWORD nSrcLen, unsigned char *lpDest, DWORD nDestLen)
Definition: url.c:1575
GLenum GLenum GLenum input
Definition: glext.h:9031
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint i
Definition: glfuncs.h:248
BOOL expected
Definition: store.c:2000
unsigned char BYTE
Definition: xxhash.c:193

Referenced by START_TEST().

◆ test_ParseURL()

static void test_ParseURL ( void  )
static

Definition at line 2572 of file url.c.

2573{
2574 const struct parse_url_test_t *test;
2576 PARSEDURLA parseda;
2577 PARSEDURLW parsedw;
2578 HRESULT hres;
2579
2581 memset(&parseda, 0xd0, sizeof(parseda));
2582 parseda.cbSize = sizeof(parseda);
2583 hres = ParseURLA(test->url, &parseda);
2584 ok(hres == test->hres, "ParseURL failed: %08lx, expected %08lx\n", hres, test->hres);
2585 if(hres == S_OK) {
2586 ok(parseda.pszProtocol == test->url, "parseda.pszProtocol = %s, expected %s\n",
2587 parseda.pszProtocol, test->url);
2588 ok(parseda.cchProtocol == test->protocol_len, "parseda.cchProtocol = %d, expected %d\n",
2589 parseda.cchProtocol, test->protocol_len);
2590 ok(parseda.pszSuffix == test->url+test->protocol_len+1, "parseda.pszSuffix = %s, expected %s\n",
2591 parseda.pszSuffix, test->url+test->protocol_len+1);
2592 ok(parseda.cchSuffix == strlen(test->url+test->protocol_len+1),
2593 "parseda.pszSuffix = %d, expected %d\n",
2594 parseda.cchSuffix, lstrlenA(test->url+test->protocol_len+1));
2595 ok(parseda.nScheme == test->scheme, "parseda.nScheme = %d, expected %d\n",
2596 parseda.nScheme, test->scheme);
2597 }else {
2598 ok(!parseda.pszProtocol, "parseda.pszProtocol = %p\n", parseda.pszProtocol);
2599 ok(parseda.nScheme == 0xd0d0d0d0, "nScheme = %d\n", parseda.nScheme);
2600 }
2601
2603
2604 memset(&parsedw, 0xd0, sizeof(parsedw));
2605 parsedw.cbSize = sizeof(parsedw);
2606 hres = ParseURLW(url, &parsedw);
2607 ok(hres == test->hres, "ParseURL failed: %08lx, expected %08lx\n", hres, test->hres);
2608 if(hres == S_OK) {
2609 ok(parsedw.pszProtocol == url, "parsedw.pszProtocol = %s, expected %s\n",
2611 ok(parsedw.cchProtocol == test->protocol_len, "parsedw.cchProtocol = %d, expected %d\n",
2612 parsedw.cchProtocol, test->protocol_len);
2613 ok(parsedw.pszSuffix == url+test->protocol_len+1, "parsedw.pszSuffix = %s, expected %s\n",
2614 wine_dbgstr_w(parsedw.pszSuffix), wine_dbgstr_w(url+test->protocol_len+1));
2615 ok(parsedw.cchSuffix == strlen(test->url+test->protocol_len+1),
2616 "parsedw.pszSuffix = %d, expected %d\n",
2617 parsedw.cchSuffix, lstrlenA(test->url+test->protocol_len+1));
2618 ok(parsedw.nScheme == test->scheme, "parsedw.nScheme = %d, expected %d\n",
2619 parsedw.nScheme, test->scheme);
2620 }else {
2621 ok(!parsedw.pszProtocol, "parsedw.pszProtocol = %p\n", parseda.pszProtocol);
2622 ok(parsedw.nScheme == 0xd0d0d0d0, "nScheme = %d\n", parsedw.nScheme);
2623 }
2624 }
2625}
ACPI_SIZE strlen(const char *String)
Definition: utclib.c:269
HRESULT WINAPI ParseURLW(LPCWSTR x, PARSEDURLW *y)
Definition: url.c:197
HRESULT WINAPI ParseURLA(LPCSTR x, PARSEDURLA *y)
Definition: url.c:161
#define wine_dbgstr_w
Definition: kernel32.h:34
HRESULT hres
Definition: protocol.c:465
static const struct parse_url_test_t parse_url_tests[]
#define test
Definition: rosglue.h:37
#define memset(x, y, z)
Definition: compat.h:39
UINT nScheme
Definition: shlwapi.h:612
UINT cchSuffix
Definition: shlwapi.h:611
LPCSTR pszSuffix
Definition: shlwapi.h:610
UINT cchProtocol
Definition: shlwapi.h:609
DWORD cbSize
Definition: shlwapi.h:607
LPCSTR pszProtocol
Definition: shlwapi.h:608
UINT cchProtocol
Definition: shlwapi.h:618
LPCWSTR pszSuffix
Definition: shlwapi.h:619
DWORD cbSize
Definition: shlwapi.h:616
UINT nScheme
Definition: shlwapi.h:621
UINT cchSuffix
Definition: shlwapi.h:620
LPCWSTR pszProtocol
Definition: shlwapi.h:617

Referenced by START_TEST().

◆ test_UrlApplyScheme()

static void test_UrlApplyScheme ( void  )
static

Definition at line 393 of file url.c.

394{
397 HRESULT res;
398 DWORD len;
399 DWORD i;
400
401 for (i = 0; i < ARRAY_SIZE(TEST_APPLY); i++) {
403 strcpy(newurl, "untouched");
405 ok( res == TEST_APPLY[i].res,
406 "#%ldA: got HRESULT 0x%lx (expected 0x%lx)\n", i, res, TEST_APPLY[i].res);
407 if (res == S_OK)
408 {
409 ok(len == strlen(newurl), "Test %lu: Expected length %Iu, got %lu.\n", i, strlen(newurl), len);
410 ok(!strcmp(newurl, TEST_APPLY[i].newurl), "Test %lu: Expected %s, got %s.\n",
412 }
413 else
414 {
415 ok(len == ARRAY_SIZE(newurl), "Test %lu: Got length %lu.\n", i, len);
416 ok(!strcmp(newurl, "untouched"), "Test %lu: Got %s.\n", i, debugstr_a(newurl));
417 }
418
419 /* returned length is in character */
420 MultiByteToWideChar(CP_ACP, 0, TEST_APPLY[i].url, -1, urlW, ARRAY_SIZE(urlW));
421 MultiByteToWideChar(CP_ACP, 0, TEST_APPLY[i].newurl, -1, expectW, ARRAY_SIZE(expectW));
422
423 len = ARRAY_SIZE(newurlW);
424 wcscpy(newurlW, L"untouched");
425 res = UrlApplySchemeW(urlW, newurlW, &len, TEST_APPLY[i].flags);
426 ok( res == TEST_APPLY[i].res,
427 "#%ldW: got HRESULT 0x%lx (expected 0x%lx)\n", i, res, TEST_APPLY[i].res);
428 if (res == S_OK)
429 {
430 ok(len == wcslen(newurlW), "Test %lu: Expected length %Iu, got %lu.\n", i, wcslen(newurlW), len);
431 ok(!wcscmp(newurlW, expectW), "Test %lu: Expected %s, got %s.\n",
432 i, debugstr_w(expectW), debugstr_w(newurlW));
433 }
434 else
435 {
436 ok(len == ARRAY_SIZE(newurlW), "Test %lu: Got length %lu.\n", i, len);
437 ok(!wcscmp(newurlW, L"untouched"), "Test %lu: Got %s.\n", i, debugstr_w(newurlW));
438 }
439 }
440
441 /* buffer too small */
445 ok(res == E_POINTER, "got HRESULT 0x%lx (expected E_POINTER)\n", res);
446 /* The returned length include the space for the terminating 0 */
447 i = lstrlenA(TEST_APPLY[0].newurl)+1;
448 ok(len == i, "got len %ld (expected %ld)\n", len, i);
449 ok(!lstrcmpA(newurl, untouchedA), "got '%s' (expected '%s')\n", newurl, untouchedA);
450
451 /* NULL as parameter. The length and the buffer are not modified */
455 ok(res == E_INVALIDARG, "got HRESULT 0x%lx (expected E_INVALIDARG)\n", res);
456 ok(len == ARRAY_SIZE(newurl), "got len %ld\n", len);
457 ok(!lstrcmpA(newurl, untouchedA), "got '%s' (expected '%s')\n", newurl, untouchedA);
458
461 ok(res == E_INVALIDARG, "got HRESULT 0x%lx (expected E_INVALIDARG)\n", res);
462 ok(len == ARRAY_SIZE(newurl), "got len %ld\n", len);
463
466 ok(res == E_INVALIDARG, "got HRESULT 0x%lx (expected E_INVALIDARG)\n", res);
467 ok(!lstrcmpA(newurl, untouchedA), "got '%s' (expected '%s')\n", newurl, untouchedA);
468
469}
wcscpy
int WINAPI lstrcmpA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4198
HRESULT WINAPI UrlApplySchemeA(const char *url, char *out, DWORD *out_len, DWORD flags)
Definition: path.c:4237
HRESULT WINAPI UrlApplySchemeW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwFlags)
Definition: url.c:1817
#define L(x)
Definition: resources.c:13
GLenum GLsizei len
Definition: glext.h:6722
_CRTIMP size_t __cdecl wcslen(_In_z_ const wchar_t *_Str)
LPSTR WINAPI lstrcpyA(LPSTR lpString1, LPCSTR lpString2)
Definition: lstring.c:100
static const CHAR untouchedA[]
Definition: url.c:39
static const TEST_URL_APPLY TEST_APPLY[]
Definition: url.c:48
strcpy
Definition: string.h:131
#define E_POINTER
Definition: winerror.h:3480
const char * newurl
Definition: shdocvw.c:51

Referenced by START_TEST().

◆ test_UrlCanonicalizeA()

static void test_UrlCanonicalizeA ( void  )
static

Definition at line 993 of file url.c.

994{
995 CHAR szReturnUrl[4*INTERNET_MAX_URL_LENGTH];
996 CHAR longurl[4*INTERNET_MAX_URL_LENGTH];
997 char url[200], expect[200];
998 unsigned int f, i, j;
1000 DWORD urllen;
1001 HRESULT hr;
1002
1003 static const struct canonicalize_test unk_scheme_tests[] =
1004 {
1005 /* Single and double dots behave as one would expect, with the following
1006 * notable rules:
1007 *
1008 * (1) A single or double dot as the first element (the "hostname") is
1009 * always emitted as-is.
1010 *
1011 * (2) If a double dot would undo the hostname, it is emitted as-is
1012 * instead.
1013 *
1014 * (3) If a single or double dot is the last element (either because of
1015 * the above rule or because of URL_DONT_SIMPLIFY), a trailing
1016 * backslash is appended.
1017 *
1018 * A trailing backslash is always appended after the hostname.
1019 */
1020
1021 {"//", 0, "///"},
1022 {"//a", 0, "//a/"},
1023 {"//a/", 0, "//a/"},
1024 {"//a/b", 0, "//a/b"},
1025 {"//a/b/", 0, "//a/b/"},
1026 {"//.", 0, "//./"},
1027 {"//./", 0, "//./"},
1028 {"//./a", 0, "//./a"},
1029 {"//././a", 0, "//./a"},
1030 {"//a/.", 0, "//a/"},
1031 {"//a/./", 0, "//a/"},
1032 {"//a/./b", 0, "//a/b"},
1033 {"///./a", 0, "///a"},
1034 {"//a/.b/", 0, "//a/.b/"},
1035 {"//a/b./", 0, "//a/b./"},
1036
1037 {"//..", 0, "//../"},
1038 {"//../", 0, "//../"},
1039 {"//../a", 0, "//../a"},
1040 {"//../a/..", 0, "//../"},
1041 {"//.././..", 0, "//../../"},
1042 {"//../a/../..", 0, "//../../"},
1043 {"//./a/../..", 0, "//./../"},
1044 {"//a/..", 0, "//a/../"},
1045 {"//a/../../b/./c/..", 0, "//a/../../b/"},
1046 {"//a/b/..", 0, "//a/"},
1047 {"//a/b/...", 0, "//a/b/..."},
1048 {"//a/b/../", 0, "//a/"},
1049 {"//a/b/../c", 0, "//a/c"},
1050 {"//a/b/../c/..", 0, "//a/"},
1051 {"//a/b/../c/../..", 0, "//a/../"},
1052 {"//a/b/../../../c", 0, "//a/../../c"},
1053 {"///..", 0, "///../"},
1054 {"////..", 0, "///"},
1055 {"//a/..b/", 0, "//a/..b/"},
1056 {"//a/b../", 0, "//a/b../"},
1057 {"//A/B", 0, "//A/B"},
1058
1059 {"//././a", URL_DONT_SIMPLIFY, "//././a"},
1060 {"//a/.", URL_DONT_SIMPLIFY, "//a/./"},
1061 {"//a/./", URL_DONT_SIMPLIFY, "//a/./"},
1062 {"//a/./b", URL_DONT_SIMPLIFY, "//a/./b"},
1063 {"///./a", URL_DONT_SIMPLIFY, "///./a"},
1064
1065 {"//..", URL_DONT_SIMPLIFY, "//../"},
1066 {"//../", URL_DONT_SIMPLIFY, "//../"},
1067 {"//../a", URL_DONT_SIMPLIFY, "//../a"},
1068 {"//../a/..", URL_DONT_SIMPLIFY, "//../a/../"},
1069 {"//../a/...", URL_DONT_SIMPLIFY, "//../a/..."},
1070 {"//.././..", URL_DONT_SIMPLIFY, "//.././../"},
1071 {"//../a/../..", URL_DONT_SIMPLIFY, "//../a/../../"},
1072 {"//./a/../..", URL_DONT_SIMPLIFY, "//./a/../../"},
1073 {"//a/..", URL_DONT_SIMPLIFY, "//a/../"},
1074 {"//a/../../b/./c/..", URL_DONT_SIMPLIFY, "//a/../../b/./c/../"},
1075 {"//a/b/..", URL_DONT_SIMPLIFY, "//a/b/../"},
1076 {"//a/b/../", URL_DONT_SIMPLIFY, "//a/b/../"},
1077 {"//a/b/../c", URL_DONT_SIMPLIFY, "//a/b/../c"},
1078 {"//a/b/../c/..", URL_DONT_SIMPLIFY, "//a/b/../c/../"},
1079 {"//a/b/../c/../..", URL_DONT_SIMPLIFY, "//a/b/../c/../../"},
1080 {"///..", URL_DONT_SIMPLIFY, "///../"},
1081 {"////..", URL_DONT_SIMPLIFY, "////../"},
1082
1083 /* After ? or #, dots are not simplified. */
1084 {"//a/b?c/./d", 0, "//a/b?c/./d"},
1085 {"//a/b#c/./d", 0, "//a/b#c/./d"},
1086 {"//a/b#c/.", 0, "//a/b#c/."},
1087 /* ? and # can also be considered a boundary for trailing dots. */
1088 {"//a/b/.?", 0, "//a/b/?"},
1089 {"//a/b/..?", 0, "//a/?"},
1090 {"//a/b/..?", URL_DONT_SIMPLIFY, "//a/b/../?"},
1091 {"//a/b/.#", 0, "//a/b/#"},
1092 {"//a/b/..#", 0, "//a/#"},
1093 {"//a/b/..#", URL_DONT_SIMPLIFY, "//a/b/../#"},
1094 {"//a/..?", 0, "//a/../?"},
1095 {"//a/..#", 0, "//a/../#"},
1096 {"//..?", 0, "//../?"},
1097 {"//..#", 0, "//../#"},
1098 {"//?/a/./", 0, "///?/a/./"},
1099 {"//#/a/./", 0, "///#/a/./"},
1100 /* The first ? is reordered before the first #. */
1101 {"//a/b#c?d", 0, "//a/b?d#c"},
1102 {"//a/b?c#d?e", 0, "//a/b?c#d?e"},
1103 {"//a/b#c?d#e", 0, "//a/b?d#e#c"},
1104 {"//a/b#c#d?e", 0, "//a/b?e#c#d"},
1105 {"//a/b#c?d?e", 0, "//a/b?d?e#c"},
1106
1107 /* Backslashes are not treated as path separators. */
1108 {"//a/b\\c/../.\\", 0, "//a/.\\"},
1109 {"//a\\b/../", 0, "//a\\b/../"},
1110 {"//a/b\\../", 0, "//a/b\\../"},
1111 {"//a/b/..\\", 0, "//a/b/..\\"},
1112
1113 /* Whitespace and unsafe characters are not (by default) escaped. */
1114 {"//a/b &c", 0, "//a/b &c"},
1115
1116 /* If one slash is omitted, the rules are much the same, except that
1117 * there is no "hostname". Single dots are always collapsed; double dots
1118 * are collapsed unless they would undo the "scheme". */
1119
1120 {"/a", 0, "/a"},
1121 {"/a/", 0, "/a/"},
1122 {"/.", 0, "/"},
1123 {"/./", 0, "/"},
1124 {"/././a", 0, "/a"},
1125 {"/a/.", 0, "/a/"},
1126 {"/a/./", 0, "/a/"},
1127 {"/a/./b", 0, "/a/b"},
1128
1129 {"/..", 0, "/../"},
1130 {"/../", 0, "/../"},
1131 {"/../a", 0, "/../a"},
1132 {"/../a/..", 0, "/../"},
1133 {"/a/..", 0, "/"},
1134 {"/a/../..", 0, "/../"},
1135 {"/a/b/..", 0, "/a/"},
1136 {"/a/b/../", 0, "/a/"},
1137 {"/a/b/../c", 0, "/a/c"},
1138 {"/a/b/../c/..", 0, "/a/"},
1139 {"/a/b/../c/../..", 0, "/"},
1140
1141 {"/a/b?c/./d", 0, "/a/b?c/./d"},
1142 {"/a/b#c/./d", 0, "/a/b#c/./d"},
1143 {"/a/b#c?d", 0, "/a/b?d#c"},
1144
1145 /* Just as above, backslashes are not treated as path separators. */
1146 {"/a/b\\c/../.\\", 0, "/a/.\\"},
1147 {"/a/b\\/c", 0, "/a/b\\/c"},
1148 {"/a/b\\.c", 0, "/a/b\\.c"},
1149 /* If the first character after the slash is a backslash, it is skipped.
1150 * It is not interpreted as a forward slash.
1151 * The tests above show that this is not due to the backslash being
1152 * interpreted as an escape character. */
1153 {"/\\././a", 0, "/a"},
1154 /* The sequence /\/ does not result in use of the double-slash rules.
1155 * Rather, the resulting // is treated as an empty path element. */
1156 {"/\\/././a", 0, "//a"},
1157 {"/\\/././a/", 0, "//a/"},
1158 {"/\\/..", 0, "/"},
1159 {"//a/\\b", 0, "//a/\\b"},
1160
1161 {"/a/b &c", 0, "/a/b &c"},
1162
1163 {"//a/b%20%26c", URL_UNESCAPE, "//a/b &c"},
1164 };
1165
1166 static const struct
1167 {
1168 const char *url;
1169 DWORD flags;
1170 const char *expect;
1171 const char *expect_ftp;
1172 }
1173 http_tests[] =
1174 {
1175 /* A set of schemes including http differs from the "default" behaviour
1176 * in the following ways:
1177 *
1178 * (1) If a double dot would undo the hostname, it is dropped instead.
1179 *
1180 * (2) If the first element after the hostname is a single or double
1181 * dot, no further dots are simplified.
1182 *
1183 * (3) Trailing backslashes are not automatically appended after dots.
1184 */
1185
1186 {"//", 0, "///"},
1187 {"//a", 0, "//a/"},
1188 {"//a/", 0, "//a/"},
1189 {"//a/b", 0, "//a/b"},
1190 {"//a/b/", 0, "//a/b/"},
1191 {"//.", 0, "//./"},
1192 {"//./", 0, "//./"},
1193 {"//././a/.", 0, "//././a/."},
1194 {"//a/.", 0, "//a/."},
1195 {"//a/./b/./../", 0, "//a/./b/./../"},
1196 {"//a/b/.", 0, "//a/b/"},
1197 {"//a/b/.", URL_DONT_SIMPLIFY, "//a/b/."},
1198 {"//a/b/./", 0, "//a/b/"},
1199 {"//a/b/./c", 0, "//a/b/c"},
1200 {"///./a", 0, "///./a"},
1201 {"////./a", 0, "////a"},
1202
1203 {"//..", 0, "//../"},
1204 {"//../", 0, "//../"},
1205 {"//../a", 0, "//../a"},
1206 {"//../a/..", 0, "//../"},
1207 {"//../a/../..", 0, "//../"},
1208 {"//./a/../..", 0, "//./"},
1209 {"//a/../", 0, "//a/../"},
1210 {"//a/../../b/./../", 0, "//a/../../b/./../"},
1211 {"//a/.././", 0, "//a/.././"},
1212 {"//a/b/..", 0, "//a/"},
1213 {"//a/b/..", URL_DONT_SIMPLIFY, "//a/b/.."},
1214 {"//a/b/../", 0, "//a/"},
1215 {"//a/b/.././", 0, "//a/"},
1216 {"//a/b/../c", 0, "//a/c"},
1217 {"//a/b/../c/..", 0, "//a/"},
1218 {"//a/b/../c/../..", 0, "//a/"},
1219 {"//a/b/../../../c", 0, "//a/c"},
1220 {"///a/.", 0, "///a/"},
1221 {"///..", 0, "///.."},
1222 {"////..", 0, "///"},
1223 {"//a//../../..", 0, "//a/"},
1224
1225 {"//a/b?c/./d", 0, "//a/b?c/./d"},
1226 {"//a/b#c/./d", 0, "//a/b#c/./d"},
1227 {"//a/b#c?d", 0, "//a/b#c?d"},
1228 {"//a/b?c#d", 0, "//a/b?c#d"},
1229
1230 {"//localhost/b", 0, "//localhost/b"},
1231
1232 /* Most of these schemes translates backslashes to forward slashes,
1233 * including the initial pair, and interpret them appropriately.
1234 *
1235 * A few schemes, including ftp, don't translate backslashes to forward
1236 * slashes, but still interpret them as path separators, with the
1237 * exception that the hostname must end in a forward slash. */
1238
1239 {"//a/b\\", 0, "//a/b/", "//a/b\\"},
1240 {"//a/b\\./c", 0, "//a/b/c", "//a/b\\c"},
1241 {"//a/b/.\\c", 0, "//a/b/c"},
1242 {"//a/b\\c/../.\\", 0, "//a/b/", "//a/b\\"},
1243 {"//a\\b", 0, "//a/b", "//a\\b/"},
1244 {"//a\\b/..", 0, "//a/", "//a\\b/.."},
1245 {"//a/b\\c", 0, "//a/b/c", "//a/b\\c"},
1246 {"/\\a\\..", 0, "//a/..", "/\\a\\../"},
1247 {"\\/a\\..", 0, "//a/..", "\\/a\\../"},
1248
1249 {"//a/b &c", 0, "//a/b &c"},
1250
1251 /* If one or both slashes is missing, the portion after the colon is
1252 * treated like a normal path, without a hostname. Single and double
1253 * dots are always collapsed, and double dots which would rewind past
1254 * the scheme are dropped instead. */
1255
1256 {"a", 0, "a"},
1257 {"a/", 0, "a/"},
1258 {"a/.", 0, "a/"},
1259 {"a/..", 0, ""},
1260 {"a/../..", 0, ""},
1261 {"a/../..", URL_DONT_SIMPLIFY, "a/../.."},
1262 {"", 0, ""},
1263 {"/", 0, "/"},
1264 {"/.", 0, "/"},
1265 {"/..", 0, ""},
1266 {"/../..", 0, ""},
1267 {".", 0, ""},
1268 {"..", 0, ""},
1269 {"./", 0, ""},
1270 {"../", 0, ""},
1271
1272 {"a/b?c/.\\d", 0, "a/b?c/.\\d"},
1273 {"a/b#c/.\\d", 0, "a/b#c/.\\d"},
1274
1275 {"a\\b\\", 0, "a/b/", "a\\b\\"},
1276
1277 {"a/b &c", 0, "a/b &c"},
1278
1279 {"/foo/bar/baz", URL_ESCAPE_SEGMENT_ONLY, "/foo/bar/baz"},
1280 {"/foo/bar/baz?a#b", URL_ESCAPE_SEGMENT_ONLY, "/foo/bar/baz?a#b"},
1281
1282 {"//www.winehq.org/tests\n", URL_ESCAPE_SPACES_ONLY | URL_ESCAPE_UNSAFE, "//www.winehq.org/tests"},
1283 {"//www.winehq.org/tests\r", URL_ESCAPE_SPACES_ONLY | URL_ESCAPE_UNSAFE, "//www.winehq.org/tests"},
1284 {"//www.winehq.org/tests/foo bar", URL_ESCAPE_SPACES_ONLY | URL_DONT_ESCAPE_EXTRA_INFO, "//www.winehq.org/tests/foo%20bar"},
1285 {"//www.winehq.org/tests/foo%20bar", 0, "//www.winehq.org/tests/foo%20bar"},
1286 {"//www.winehq.org/tests/foo%20bar", URL_UNESCAPE, "//www.winehq.org/tests/foo bar"},
1287 {"//www.winehq.org/%E6%A1%9C.html", 0, "//www.winehq.org/%E6%A1%9C.html"},
1288 };
1289
1290 static const struct canonicalize_test opaque_tests[] =
1291 {
1292 /* Opaque protocols, predictably, do not modify the portion after the
1293 * scheme. */
1294 {"//a/b/./c/../d\\e", 0, "//a/b/./c/../d\\e"},
1295 {"/a/b/./c/../d\\e", 0, "/a/b/./c/../d\\e"},
1296 {"a/b/./c/../d\\e", 0, "a/b/./c/../d\\e"},
1297 {"", 0, ""},
1298 {"//a/b &c", 0, "//a/b &c"},
1299 {"//a/b%20%26c", URL_UNESCAPE, "//a/b &c"},
1300 };
1301
1302 static const struct canonicalize_test file_tests[] =
1303 {
1304 /* file:// is almost identical to http://, except that a URL beginning
1305 * with file://// (four or more slashes) is stripped down to two
1306 * slashes. The first non-empty element is interpreted as a hostname;
1307 * and the rest follows the usual rules.
1308 *
1309 * The intent here is probably to detect UNC paths, although it's
1310 * unclear why an arbitrary number of slashes are skipped in that case.
1311 */
1312
1313 {"file://", 0, "file:///"},
1314 {"file://a", 0, "file://a/"},
1315 {"file://a/", 0, "file://a/"},
1316 {"file://a//", 0, "file://a//"},
1317 {"file://a/b", 0, "file://a/b"},
1318 {"file://a/b/", 0, "file://a/b/"},
1319 {"file://.", 0, "file://./"},
1320 {"file://./", 0, "file://./"},
1321 {"file://././a/.", 0, "file://././a/."},
1322 {"file://a/.", 0, "file://a/."},
1323 {"file://a/./b/./../", 0, "file://a/./b/./../"},
1324 {"file://a/b/.", 0, "file://a/b/"},
1325 {"file://a/b/.", URL_DONT_SIMPLIFY, "file://a/b/."},
1326 {"file://a/b/./", 0, "file://a/b/"},
1327 {"file://a/b/./c", 0, "file://a/b/c"},
1328 {"file:///./a", 0, "file:///./a"},
1329 {"file:////./a", 0, "file://./a"},
1330
1331 {"file://..", 0, "file://../"},
1332 {"file://../", 0, "file://../"},
1333 {"file://../a", 0, "file://../a"},
1334 {"file://../a/..", 0, "file://../"},
1335 {"file://../a/../..", 0, "file://../"},
1336 {"file://./a/../..", 0, "file://./"},
1337 {"file://a/../", 0, "file://a/../"},
1338 {"file://a/../../b/./../", 0, "file://a/../../b/./../"},
1339 {"file://a/.././", 0, "file://a/.././"},
1340 {"file://a/b/..", 0, "file://a/"},
1341 {"file://a/b/../", 0, "file://a/"},
1342 {"file://a/b/.././", 0, "file://a/"},
1343 {"file://a/b/../c", 0, "file://a/c"},
1344 {"file://a/b/../c/..", 0, "file://a/"},
1345 {"file://a/b/../c/../..", 0, "file://a/"},
1346 {"file://a/b/../../../c", 0, "file://a/c"},
1347 {"file:///.", 0, "file:///."},
1348 {"file:///..", 0, "file:///.."},
1349 {"file:///a/.", 0, "file:///a/"},
1350
1351 {"file:////", 0, "file:///"},
1352 {"file:////a/./b/../c", 0, "file://a/./b/../c"},
1353 {"file://///a/./b/../c", 0, "file://a/./b/../c"},
1354 {"file://////a/./b/../c", 0, "file://a/./b/../c"},
1355 {"file:////a/b/./../c", 0, "file://a/c"},
1356 {"file:////a/b/./../..", 0, "file://a/"},
1357 {"file://///a/b/./../c", 0, "file://a/c"},
1358 {"file://////a/b/./../c", 0, "file://a/c"},
1359 {"file:////.", 0, "file://./"},
1360 {"file:////..", 0, "file://../"},
1361 {"file:////./b/./../c", 0, "file://./c"},
1362 {"file:////./b/./../..", 0, "file://./"},
1363 {"file://///./b/./../c", 0, "file://./c"},
1364 {"file://////./b/./../c", 0, "file://./c"},
1365
1366 /* Drive-like paths get an extra slash (i.e. an empty hostname, to
1367 * signal that the host is the local machine). The drive letter is
1368 * treated as the path root. */
1369 {"file://a:", 0, "file:///a:"},
1370 {"file://a:/b", 0, "file:///a:/b"},
1371 {"file://a:/b/../..", 0, "file:///a:/"},
1372 {"file://a:/./../..", 0, "file:///a:/./../.."},
1373 {"file://a|/b", 0, "file:///a|/b"},
1374 {"file://ab:/c", 0, "file://ab:/c"},
1375 {"file:///a:", 0, "file:///a:"},
1376 {"file:////a:", 0, "file:///a:"},
1377 {"file://///a:", 0, "file:///a:"},
1378 {"file://host/a:/b/../..", 0, "file://host/a:/"},
1379
1380 /* URL_FILE_USE_PATHURL (and URL_WININET_COMPATIBILITY) have their own
1381 * set of rules:
1382 *
1383 * (1) Dot processing works exactly like the "unknown scheme" rules,
1384 * instead of the file/http rules demonstrated above.
1385 *
1386 * (2) Some number of backslashes is appended after the two forward
1387 * slashes. The number basically corresponds to the detected path
1388 * type (two for a remote path, one for a local path, none for a
1389 * local drive path). A local path is one where the hostname is
1390 * empty or "localhost". If all path elements are empty then no
1391 * backslashes are appended.
1392 */
1393
1394 {"file://", URL_FILE_USE_PATHURL, "file://"},
1395 {"file://a", URL_FILE_USE_PATHURL, "file://\\\\a"},
1396 {"file://a/", URL_FILE_USE_PATHURL, "file://\\\\a"},
1397 {"file://a//", URL_FILE_USE_PATHURL, "file://\\\\a\\\\"},
1398 {"file://a/b", URL_FILE_USE_PATHURL, "file://\\\\a\\b"},
1399 {"file://a//b", URL_FILE_USE_PATHURL, "file://\\\\a\\\\b"},
1400 {"file://a/.", URL_FILE_USE_PATHURL, "file://\\\\a\\"},
1401 {"file://a/../../b/./c/..", URL_FILE_USE_PATHURL, "file://\\\\a\\..\\..\\b\\"},
1402 {"file://./../../b/./c/..", URL_FILE_USE_PATHURL, "file://\\\\.\\..\\..\\b\\"},
1403 {"file://../../../b/./c/..", URL_FILE_USE_PATHURL, "file://\\\\..\\..\\..\\b\\"},
1404 {"file://a/b/.", URL_FILE_USE_PATHURL, "file://\\\\a\\b\\"},
1405 {"file://a/b/.", URL_FILE_USE_PATHURL | URL_DONT_SIMPLIFY, "file://\\\\a\\b\\.\\"},
1406 {"file://a/b/../../../c", URL_FILE_USE_PATHURL, "file://\\\\a\\..\\..\\c"},
1407
1408 {"file:///", URL_FILE_USE_PATHURL, "file://"},
1409 {"file:///.", URL_FILE_USE_PATHURL, "file://\\"},
1410 {"file:///..", URL_FILE_USE_PATHURL, "file://\\..\\"},
1411 {"file:///../../b/./c/..", URL_FILE_USE_PATHURL, "file://\\..\\..\\b\\"},
1412 {"file:///a/b/./c/..", URL_FILE_USE_PATHURL, "file://\\a\\b\\"},
1413
1414 {"file:////", URL_FILE_USE_PATHURL, "file://"},
1415 {"file:////.", URL_FILE_USE_PATHURL, "file://\\\\."},
1416 {"file:////a/./b/../c", URL_FILE_USE_PATHURL, "file://\\\\a\\c"},
1417 {"file://///", URL_FILE_USE_PATHURL, "file://"},
1418 {"file://///a/./b/../c", URL_FILE_USE_PATHURL, "file://\\\\a\\c"},
1419
1420 {"file://a:", URL_FILE_USE_PATHURL, "file://a:"},
1421 {"file://a:/", URL_FILE_USE_PATHURL, "file://a:\\"},
1422 {"file://a:/b", URL_FILE_USE_PATHURL, "file://a:\\b"},
1423 {"file://a:/b/../..", URL_FILE_USE_PATHURL, "file://a:\\..\\"},
1424 {"file://a|/b", URL_FILE_USE_PATHURL, "file://a|\\b"},
1425 {"file:///a:", URL_FILE_USE_PATHURL, "file://a:"},
1426 {"file:////a:", URL_FILE_USE_PATHURL, "file://a:"},
1427
1428 /* URL_WININET_COMPATIBILITY is almost identical, but ensures a trailing
1429 * backslash in two cases:
1430 *
1431 * (1) if all path elements are empty,
1432 *
1433 * (2) if the path consists of just the hostname.
1434 */
1435
1436 {"file://", URL_WININET_COMPATIBILITY, "file://\\"},
1437 {"file://a", URL_WININET_COMPATIBILITY, "file://\\\\a\\"},
1438 {"file://a/", URL_WININET_COMPATIBILITY, "file://\\\\a\\"},
1439 {"file://a//", URL_WININET_COMPATIBILITY, "file://\\\\a\\\\"},
1440 {"file://a/b", URL_WININET_COMPATIBILITY, "file://\\\\a\\b"},
1441 {"file://a//b", URL_WININET_COMPATIBILITY, "file://\\\\a\\\\b"},
1442 {"file://a/.", URL_WININET_COMPATIBILITY, "file://\\\\a\\"},
1443 {"file://a/../../b/./c/..", URL_WININET_COMPATIBILITY, "file://\\\\a\\..\\..\\b\\"},
1444 {"file://./../../b/./c/..", URL_WININET_COMPATIBILITY, "file://\\\\.\\..\\..\\b\\"},
1445 {"file://../../../b/./c/..", URL_WININET_COMPATIBILITY, "file://\\\\..\\..\\..\\b\\"},
1446 {"file://a/b/../../../c", URL_WININET_COMPATIBILITY, "file://\\\\a\\..\\..\\c"},
1447
1448 {"file:///", URL_WININET_COMPATIBILITY, "file://\\"},
1449 {"file:///.", URL_WININET_COMPATIBILITY, "file://\\"},
1450 {"file:///..", URL_WININET_COMPATIBILITY, "file://\\..\\"},
1451 {"file:///../../b/./c/..", URL_WININET_COMPATIBILITY, "file://\\..\\..\\b\\"},
1452 {"file:///a/b/./c/..", URL_WININET_COMPATIBILITY, "file://\\a\\b\\"},
1453
1454 {"file:////", URL_WININET_COMPATIBILITY, "file://\\"},
1455 {"file:////.", URL_WININET_COMPATIBILITY, "file://\\\\.\\"},
1456 {"file:////a/./b/../c", URL_WININET_COMPATIBILITY, "file://\\\\a\\c"},
1457 {"file://///", URL_WININET_COMPATIBILITY, "file://\\"},
1458 {"file://///a/./b/../c", URL_WININET_COMPATIBILITY, "file://\\\\a\\c"},
1459
1460 {"file://a:", URL_WININET_COMPATIBILITY, "file://a:"},
1461
1462 {"file://", URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY, "file://"},
1463
1464 {"file://localhost/a", 0, "file://localhost/a"},
1465 {"file://localhost//a", 0, "file://localhost//a"},
1466 {"file://localhost/a:", 0, "file://localhost/a:"},
1467 {"file://localhost/a:/b/../..", 0, "file://localhost/a:/"},
1468 {"file://localhost/a:/./../..", 0, "file://localhost/a:/./../.."},
1469 {"file://localhost", URL_FILE_USE_PATHURL, "file://"},
1470 {"file://localhost/", URL_FILE_USE_PATHURL, "file://"},
1471 {"file://localhost/b", URL_FILE_USE_PATHURL, "file://\\b"},
1472 {"file://127.0.0.1/b", URL_FILE_USE_PATHURL, "file://\\\\127.0.0.1\\b"},
1473 {"file://localhost//b", URL_FILE_USE_PATHURL, "file://\\b"},
1474 {"file://localhost///b", URL_FILE_USE_PATHURL, "file://\\\\b"},
1475 {"file:///localhost/b", URL_FILE_USE_PATHURL, "file://\\localhost\\b"},
1476 {"file:////localhost/b", URL_FILE_USE_PATHURL, "file://\\b"},
1477 {"file://///localhost/b", URL_FILE_USE_PATHURL, "file://\\b"},
1478 {"file://localhost/a:", URL_FILE_USE_PATHURL, "file://a:"},
1479 {"file://localhost/a:/b/../..", URL_FILE_USE_PATHURL, "file://a:\\..\\"},
1480 {"file://localhost?a/b", URL_FILE_USE_PATHURL, "file://"},
1481 {"file://localhost#a/b", URL_FILE_USE_PATHURL, "file://\\\\localhost#a/b"},
1482 {"file://localhostq", URL_FILE_USE_PATHURL, "file://\\\\localhostq"},
1483
1484 {"file://localhost", URL_WININET_COMPATIBILITY, "file://\\"},
1485 {"file://localhost/", URL_WININET_COMPATIBILITY, "file://\\"},
1486 {"file://localhost/b", URL_WININET_COMPATIBILITY, "file://\\b"},
1487 {"file://localhost//b", URL_WININET_COMPATIBILITY, "file://\\b"},
1488 {"file://127.0.0.1/b", URL_WININET_COMPATIBILITY, "file://\\\\127.0.0.1\\b"},
1489 {"file://localhost/a:", URL_WININET_COMPATIBILITY, "file://a:"},
1490 {"file://localhost?a/b", URL_WININET_COMPATIBILITY, "file://\\?a/b"},
1491 {"file://localhost#a/b", URL_WININET_COMPATIBILITY, "file://\\\\localhost#a/b"},
1492
1493 /* # has some weird behaviour:
1494 *
1495 * - Dot processing happens normally after it, including rewinding past
1496 * the #. It's not treated as a path separator for the purposes of
1497 * rewinding.
1498 *
1499 * - However, if neither file flag is used, and the first character
1500 * after the hostname (plus an optional slash) is a hash, no dot
1501 * processing takes place.
1502 *
1503 * - If the previous path segment ends in .htm or .html, the rest of
1504 * the URL is emitted verbatim (no dot or slash canonicalization).
1505 * This does not apply to the hostname. If URL_FILE_USE_PATHURL is
1506 * used, though, the rest of the URL including the # is omitted.
1507 *
1508 * - It is treated as a path terminator for dots, but only if neither
1509 * file flag is used. It does not begin a path element.
1510 *
1511 * - If there is a # anywhere in the output string (and the string
1512 * doesn't fall under the .html exception), all subsequent slashes
1513 * are converted to forward slashes instead of backslashes.
1514 * This means that rewinding past the hash will revert to backslashes.
1515 * (This of course only affects the case where file flags are used;
1516 * if no file flags are used then slashes are converted to forward
1517 * slashes anyway.)
1518 */
1519 {"file://a/b#c/../d\\e", 0, "file://a/d/e"},
1520 {"file://a/b#c/./d\\e", 0, "file://a/b#c/d/e"},
1521 {"file://a/b.htm#c/../d\\e", 0, "file://a/b.htm#c/../d\\e"},
1522 {"file://a/b.html#c/../d\\e", 0, "file://a/b.html#c/../d\\e"},
1523 {"file://a/b.hTmL#c/../d\\e", 0, "file://a/b.hTmL#c/../d\\e"},
1524 {"file://a/b.xhtml#c/../d\\e", 0, "file://a/d/e"},
1525 {"file://a/b.php#c/../d\\e", 0, "file://a/d/e"},
1526 {"file://a/b.asp#c/../d\\e", 0, "file://a/d/e"},
1527 {"file://a/b.aspx#c/../d\\e", 0, "file://a/d/e"},
1528 {"file://a/b.ht#c/../d\\e", 0, "file://a/d/e"},
1529 {"file://a/b.txt#c/../d\\e", 0, "file://a/d/e"},
1530 {"file://a/b.htmlq#c/../d\\e", 0, "file://a/d/e"},
1531 {"file://a/b.html/q#c/../d\\e", 0, "file://a/b.html/d/e"},
1532 {"file://a/.html#c/../d\\e", 0, "file://a/.html#c/../d\\e"},
1533 {"file://a/html#c/../d\\e", 0, "file://a/d/e"},
1534 {"file://a/b#c/./d.html#e/../f", 0, "file://a/b#c/d.html#e/../f"},
1535 {"file://a.html#/b/../c", 0, "file://a.html#/c"},
1536 {"file://a/b#c/../d/e", URL_FILE_USE_PATHURL, "file://\\\\a\\d\\e"},
1537 {"file://a/b#c/./d/e", URL_FILE_USE_PATHURL, "file://\\\\a\\b#c/d/e"},
1538 {"file://a/b.html#c/../d\\e", URL_FILE_USE_PATHURL, "file://\\\\a\\b.html"},
1539 {"file://a/b.html#c/../d\\e", URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY, "file://\\\\a\\b.html"},
1540 {"file://a/b#c/../d/e", URL_WININET_COMPATIBILITY, "file://\\\\a\\d\\e"},
1541 {"file://a/b#c/./d/e", URL_WININET_COMPATIBILITY, "file://\\\\a\\b#c/d/e"},
1542 {"file://a/b.html#c/../d\\e", URL_WININET_COMPATIBILITY, "file://\\\\a\\b.html#c/../d\\e"},
1543 {"file://a/c#/../d", 0, "file://a/d"},
1544 {"file://a/c#/../d", URL_FILE_USE_PATHURL, "file://\\\\a\\d"},
1545 {"file://a/c#/../d", URL_WININET_COMPATIBILITY, "file://\\\\a\\d"},
1546 {"file://a/#c/../d\\e", 0, "file://a/#c/../d\\e"},
1547 {"file://a/#c/../d/e", URL_FILE_USE_PATHURL, "file://\\\\a\\d\\e"},
1548 {"file://a/#c/../d/e", URL_WININET_COMPATIBILITY, "file://\\\\a\\d\\e"},
1549 {"file://a//#c/../d", 0, "file://a//#c/../d"},
1550 {"file://a//#c/../d", URL_FILE_USE_PATHURL, "file://\\\\a\\\\d"},
1551 {"file://a//#c/../d", URL_WININET_COMPATIBILITY, "file://\\\\a\\\\d"},
1552 {"file://a/\\#c/../d", 0, "file://a//#c/../d"},
1553 {"file://a///#c/../d", 0, "file://a///d"},
1554 {"file://a/b/#c/../d", 0, "file://a/b/d"},
1555 {"file://a/b/.#c", 0, "file://a/b/#c"},
1556 {"file://a/b/..#c", 0, "file://a/#c"},
1557 {"file://a/b/.#c", URL_FILE_USE_PATHURL, "file://\\\\a\\b\\.#c"},
1558 {"file://a/b/..#c", URL_FILE_USE_PATHURL, "file://\\\\a\\b\\..#c"},
1559 {"file://a/b/.#c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b\\.#c"},
1560 {"file://a/b/..#c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b\\..#c"},
1561 {"file://a/b#../c", 0, "file://a/b#../c"},
1562 {"file://a/b/#../c", 0, "file://a/b/#../c"},
1563 {"file://a/b#../c", URL_FILE_USE_PATHURL, "file://\\\\a\\b#../c"},
1564 {"file://a/b#../c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b#../c"},
1565 {"file://#/b\\./", 0, "file://#/b/"},
1566 {"file://#/./b\\./", 0, "file://#/./b/./"},
1567 {"file://#/b\\./", URL_FILE_USE_PATHURL, "file://\\\\#/b/"},
1568 {"file://#/b\\./", URL_WININET_COMPATIBILITY, "file://\\\\#/b/"},
1569 {"file://a#/b\\./", 0, "file://a#/b/"},
1570 {"file://a#/./b\\./", 0, "file://a#/./b/./"},
1571 {"file://a#/b\\./", URL_FILE_USE_PATHURL, "file://\\\\a#/b/"},
1572 {"file://a#/b\\./", URL_WININET_COMPATIBILITY, "file://\\\\a#/b/"},
1573 {"file://a#/b\\./", URL_FILE_USE_PATHURL | URL_DONT_SIMPLIFY, "file://\\\\a#/b/./"},
1574 {"file://a#/b\\.", URL_FILE_USE_PATHURL | URL_DONT_SIMPLIFY, "file://\\\\a#/b/./"},
1575 {"file://a#/b/../../", 0, "file://a#/"},
1576
1577 /* ? is similar, with the following exceptions:
1578 *
1579 * - URLs ending in .htm(l) are not treated specially.
1580 *
1581 * - With URL_FILE_USE_PATHURL, the rest of the URL including the ? is
1582 * just omitted (much like the .html case above).
1583 *
1584 * - With URL_WININET_COMPATIBILITY, the rest of the URL is always
1585 * emitted verbatim (completely opaque, like other schemes).
1586 */
1587
1588 {"file://a/b?c/../d\\e", 0, "file://a/d/e"},
1589 {"file://a/b.html?c/../d\\e", 0, "file://a/d/e"},
1590 {"file://a/b?c/../d\\e", URL_FILE_USE_PATHURL, "file://\\\\a\\b"},
1591 {"file://a/b.html?c/../d\\e", URL_FILE_USE_PATHURL, "file://\\\\a\\b.html"},
1592 {"file://a/b?c/../d\\e", URL_WININET_COMPATIBILITY, "file://\\\\a\\b?c/../d\\e"},
1593 {"file://a/b.html?c/../d\\e", URL_WININET_COMPATIBILITY, "file://\\\\a\\b.html?c/../d\\e"},
1594 {"file://a/b?c/../d", URL_FILE_USE_PATHURL | URL_WININET_COMPATIBILITY, "file://\\\\a\\b"},
1595 {"file://a/?c/../d", 0, "file://a/?c/../d"},
1596 {"file://a/?c/../d", URL_FILE_USE_PATHURL, "file://\\\\a"},
1597 {"file://a/?c/../d", URL_WININET_COMPATIBILITY, "file://\\\\a\\?c/../d"},
1598 {"file://a//?c/../d", 0, "file://a//?c/../d"},
1599 {"file://a//?c/../d", URL_FILE_USE_PATHURL, "file://\\\\a\\\\"},
1600 {"file://a//?c/../d", URL_WININET_COMPATIBILITY, "file://\\\\a\\\\?c/../d"},
1601 {"file://a/\\?c/../d", 0, "file://a//?c/../d"},
1602 {"file://a///?c/../d", 0, "file://a///d"},
1603 {"file://a/b/?c/../d", 0, "file://a/b/d"},
1604 {"file://a/b/.?c", 0, "file://a/b/?c"},
1605 {"file://a/b/..?c", 0, "file://a/?c"},
1606 {"file://a/b/.?c", URL_FILE_USE_PATHURL, "file://\\\\a\\b\\"},
1607 {"file://a/b/..?c", URL_FILE_USE_PATHURL, "file://\\\\a\\"},
1608 {"file://a/b/.?c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b\\?c"},
1609 {"file://a/b/..?c", URL_WININET_COMPATIBILITY, "file://\\\\a\\?c"},
1610 {"file://?/a\\./", 0, "file://?/a/"},
1611 {"file://?/./a\\./", 0, "file://?/./a/./"},
1612 {"file://?/a\\./", URL_FILE_USE_PATHURL, "file://"},
1613 {"file://?/a\\./", URL_WININET_COMPATIBILITY, "file://\\?/a\\./"},
1614 {"file://a?/a\\./", 0, "file://a?/a/"},
1615 {"file://a?/./a\\./", 0, "file://a?/./a/./"},
1616 {"file://a?/a\\./", URL_FILE_USE_PATHURL, "file://\\\\a"},
1617 {"file://a?/a\\./", URL_WININET_COMPATIBILITY, "file://\\\\a\\?/a\\./"},
1618
1619 {"file://a/b.html?c#d/..", 0, "file://a/"},
1620 {"file://a/b.html?c.html#d/..", 0, "file://a/b.html?c.html#d/.."},
1621 {"file://a/b?\\#c\\d", 0, "file://a/b?/#c/d"},
1622 {"file://a/b?\\#c\\d", URL_WININET_COMPATIBILITY, "file://\\\\a\\b?\\#c\\d"},
1623 {"file://a/b?\\#c\\d", URL_FILE_USE_PATHURL, "file://\\\\a\\b"},
1624 {"file://a/b#\\?c\\d", 0, "file://a/b#/?c/d"},
1625 {"file://a/b#\\?c\\d", URL_WININET_COMPATIBILITY, "file://\\\\a\\b#/?c\\d"},
1626 {"file://a/b#\\?c\\d", URL_FILE_USE_PATHURL, "file://\\\\a\\b#/"},
1627 {"file://a/b.html#c?d", URL_WININET_COMPATIBILITY, "file://\\\\a\\b.html?d#c"},
1628
1629 /* file: treats backslashes like forward slashes, including the
1630 * initial pair. */
1631 {"file://a/b\\", 0, "file://a/b/"},
1632 {"file://a/b\\c/../.\\", 0, "file://a/b/"},
1633 {"file://a\\b", 0, "file://a/b"},
1634 {"file:/\\a\\..", 0, "file://a/.."},
1635 {"file:\\/a\\..", 0, "file://a/.."},
1636 {"file:\\\\a\\b", URL_FILE_USE_PATHURL, "file://\\\\a\\b"},
1637 {"file:\\\\a\\b", URL_WININET_COMPATIBILITY, "file://\\\\a\\b"},
1638 {"file:\\///a/./b/../c", 0, "file://a/./b/../c"},
1639 {"file:/\\//a/./b/../c", 0, "file://a/./b/../c"},
1640 {"file://\\/a/./b/../c", 0, "file://a/./b/../c"},
1641 {"file:///\\a/./b/../c", 0, "file://a/./b/../c"},
1642
1643 {"file://a/b &c", 0, "file://a/b &c"},
1644 {"file://a/b &c", URL_FILE_USE_PATHURL, "file://\\\\a\\b &c"},
1645 {"file://a/b &c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b &c"},
1646 {"file://a/b !\"$%&'()*+,-:;<=>@[]^_`{|}~c", URL_ESCAPE_UNSAFE, "file://a/b%20!%22$%%26'()*+,-:;%3C=%3E@%5B%5D%5E_%60%7B%7C%7D~c"},
1647 {"file://a/b%20%26c", 0, "file://a/b%20%26c"},
1648 {"file://a/b%20%26c", URL_FILE_USE_PATHURL, "file://\\\\a\\b &c"},
1649 {"file://a/b%20%26c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b%20%26c"},
1650
1651 /* Omitting one slash behaves as if the URL had been written with an
1652 * empty hostname, and the output adds two slashes as such. */
1653
1654 {"file:/", 0, "file:///"},
1655 {"file:/a", 0, "file:///a"},
1656 {"file:/./a", 0, "file:///./a"},
1657 {"file:/../a/..", 0, "file:///../a/.."},
1658 {"file:/./..", 0, "file:///./.."},
1659 {"file:/a/.", 0, "file:///a/"},
1660 {"file:/a/../..", 0, "file:///"},
1661 {"file:/a:", 0, "file:///a:"},
1662 {"file:/a:/b/../..", 0, "file:///a:/"},
1663
1664 /* The same applies to the flags. */
1665
1666 {"file:/", URL_FILE_USE_PATHURL, "file://"},
1667 {"file:/a", URL_FILE_USE_PATHURL, "file://\\a"},
1668 {"file:/.", URL_FILE_USE_PATHURL, "file://\\"},
1669 {"file:/./a", URL_FILE_USE_PATHURL, "file://\\a"},
1670 {"file:/../a", URL_FILE_USE_PATHURL, "file://\\..\\a"},
1671 {"file:/a/../..", URL_FILE_USE_PATHURL, "file://\\..\\"},
1672 {"file:/a/.", URL_FILE_USE_PATHURL | URL_DONT_SIMPLIFY, "file://\\a\\.\\"},
1673 {"file:/a:", URL_FILE_USE_PATHURL, "file://a:"},
1674 {"file:/a:/b/../..", URL_FILE_USE_PATHURL, "file://a:\\..\\"},
1675
1676 {"file:/", URL_WININET_COMPATIBILITY, "file://\\"},
1677 {"file:/a", URL_WININET_COMPATIBILITY, "file://\\a"},
1678 {"file:/.", URL_WININET_COMPATIBILITY, "file://\\"},
1679 {"file:/a:", URL_WININET_COMPATIBILITY, "file://a:"},
1680
1681 {"file:/a/b#c/../d", 0, "file:///a/d"},
1682 {"file:/a/b?c/../d", 0, "file:///a/d"},
1683
1684 {"file:/a\\b\\", 0, "file:///a/b/"},
1685 {"file:\\a/b/", 0, "file:///a/b/"},
1686 {"file:\\a\\b", URL_FILE_USE_PATHURL, "file://\\a\\b"},
1687 {"file:\\a\\b", URL_WININET_COMPATIBILITY, "file://\\a\\b"},
1688
1689 {"file:/a/b &c", 0, "file:///a/b &c"},
1690
1691 /* Omitting both slashes causes all dots to be collapsed, in the same
1692 * way as bare http. */
1693
1694 {"file:a", 0, "file:a"},
1695 {"file:a/", 0, "file:a/"},
1696 {"file:a/.", 0, "file:a/"},
1697 {"file:a/..", 0, "file:"},
1698 {"file:a/../..", 0, "file:"},
1699 {"file:", 0, "file:"},
1700 {"file:.", 0, "file:"},
1701 {"file:..", 0, "file:"},
1702 {"file:./", 0, "file:"},
1703 {"file:../", 0, "file:"},
1704
1705 {"file:a:", 0, "file:///a:"},
1706
1707 /* URL_FILE_USE_PATHURL treats everything here as a local (relative?)
1708 * path. In the case that the path resolves to the current directory
1709 * a single backslash is emitted. */
1710 {"file:", URL_FILE_USE_PATHURL, "file://"},
1711 {"file:a", URL_FILE_USE_PATHURL, "file://a"},
1712 {"file:a/.", URL_FILE_USE_PATHURL, "file://a\\"},
1713 {"file:a/../..", URL_FILE_USE_PATHURL, "file://..\\"},
1714 {"file:./a", URL_FILE_USE_PATHURL, "file://a"},
1715 {"file:../a", URL_FILE_USE_PATHURL, "file://..\\a"},
1716 {"file:a/.", URL_FILE_USE_PATHURL | URL_DONT_SIMPLIFY, "file://a\\.\\"},
1717 {"file:a:", URL_FILE_USE_PATHURL, "file://a:"},
1718
1719 /* URL_WININET_COMPATIBILITY doesn't emit a double slash. */
1720 {"file:", URL_WININET_COMPATIBILITY, "file:"},
1721 {"file:a", URL_WININET_COMPATIBILITY, "file:a"},
1722 {"file:./a", URL_WININET_COMPATIBILITY, "file:a"},
1723 {"file:../a", URL_WININET_COMPATIBILITY, "file:..\\a"},
1724 {"file:../b/./c/../d", URL_WININET_COMPATIBILITY | URL_DONT_SIMPLIFY, "file:..\\b\\.\\c\\..\\d"},
1725 {"file:a:", URL_WININET_COMPATIBILITY, "file://a:"},
1726
1727 {"file:a/b?c/../d", 0, "file:a/d"},
1728 {"file:a/b#c/../d", 0, "file:a/d"},
1729
1730 {"file:a\\b\\", 0, "file:a/b/"},
1731
1732 {"file:a/b &c", 0, "file:a/b &c"},
1733
1734 {"fIlE://A/B", 0, "file://A/B"},
1735 {"fIlE://A/B", URL_FILE_USE_PATHURL, "file://\\\\A\\B"},
1736 {"fIlE://A/B", URL_WININET_COMPATIBILITY, "file://\\\\A\\B"},
1737 {"fIlE:A:/B", 0, "file:///A:/B"},
1738 {"fIlE:A:/B", URL_FILE_USE_PATHURL, "file://A:\\B"},
1739 {"fIlE:A:/B", URL_WININET_COMPATIBILITY, "file://A:\\B"},
1740 {"fIlE://lOcAlHoSt/B", 0, "file://lOcAlHoSt/B"},
1741 {"fIlE://lOcAlHoSt/B", URL_FILE_USE_PATHURL, "file://\\B"},
1742
1743 /* Drive paths are automatically converted to file paths. Dots are
1744 * collapsed unless the first segment after q: or q:/ is a dot. */
1745
1746 {"q:a", 0, "file:///q:a"},
1747 {"q:a/.", 0, "file:///q:a/"},
1748 {"q:a/..", 0, "file:///q:"},
1749 {"q:a/../..", 0, "file:///q:"},
1750 {"q:./a/..", 0, "file:///q:./a/.."},
1751 {"q:../a/..", 0, "file:///q:../a/.."},
1752 {"q:/", 0, "file:///q:/"},
1753 {"q:/a", 0, "file:///q:/a"},
1754 {"q:/a/.", 0, "file:///q:/a/"},
1755 {"q:/a/..", 0, "file:///q:/"},
1756 {"q:/./a/..", 0, "file:///q:/./a/.."},
1757 {"q:/../a/..", 0, "file:///q:/../a/.."},
1758 {"q://./a", 0, "file:///q://a"},
1759 {"q://../a", 0, "file:///q:/a"},
1760
1761 /* File flags use the "unknown scheme" rules, and the root of the path
1762 * is the first slash. */
1763
1764 {"q:/a", URL_FILE_USE_PATHURL, "file://q:\\a"},
1765 {"q:/a/../..", URL_FILE_USE_PATHURL, "file://q:\\..\\"},
1766 {"q:a/../../b/..", URL_FILE_USE_PATHURL, "file://q:a\\..\\..\\"},
1767 {"q:./../../b/..", URL_FILE_USE_PATHURL, "file://q:.\\..\\..\\"},
1768 {"q:/a", URL_WININET_COMPATIBILITY, "file://q:\\a"},
1769 {"q:/a/../..", URL_WININET_COMPATIBILITY, "file://q:\\..\\"},
1770 {"q:a/../../b/..", URL_WININET_COMPATIBILITY, "file://q:a\\..\\..\\"},
1771 {"q:./../../b/..", URL_WININET_COMPATIBILITY, "file://q:.\\..\\..\\"},
1772
1773 {"q:/a/b?c/../d", 0, "file:///q:/a/d"},
1774 {"q:/a/b#c/../d", 0, "file:///q:/a/d"},
1775 {"q:a?b", URL_FILE_USE_PATHURL, "file://q:a"},
1776
1777 {"q:a\\b\\", 0, "file:///q:a/b/"},
1778 {"q:\\a/b", 0, "file:///q:/a/b"},
1779
1780 /* Drive paths are also unique in that unsafe characters (and spaces)
1781 * are automatically escaped—but not if the file flags are used. */
1782
1783 {"q:/a/b !\"$%&'()*+,-:;<=>@[]^_`{|}~c", 0, "file:///q:/a/b%20!%22$%25%26'()*+,-:;%3C=%3E@%5B%5D%5E_%60%7B%7C%7D~c"},
1784 {"q:/a/b &c", URL_FILE_USE_PATHURL, "file://q:\\a\\b &c"},
1785 {"q:/a/b &c", URL_WININET_COMPATIBILITY, "file://q:\\a\\b &c"},
1786
1787 {"q:/a/b%20%26c", 0, "file:///q:/a/b%2520%2526c"},
1788 {"q:/a/b%20%26c", URL_UNESCAPE, "file:///q:/a/b &c"},
1789 {"q:/a/b%20%26c", URL_UNESCAPE | URL_ESCAPE_UNSAFE, "file:///q:/a/b%20%26c"},
1790 {"q:/a/b%20%26c", URL_FILE_USE_PATHURL, "file://q:\\a\\b &c"},
1791 {"q:/a/b%20%26c", URL_FILE_USE_PATHURL | URL_UNESCAPE, "file://q:\\a\\b &c"},
1792 {"q:/a/b%20%26c", URL_WININET_COMPATIBILITY, "file://q:\\a\\b%20%26c"},
1793 {"q:/a/b%20%26c", URL_WININET_COMPATIBILITY | URL_UNESCAPE, "file://q:\\a\\b &c"},
1794
1795 {"q|a", 0, "file:///q%7Ca"},
1796 {"-:a", 0, "-:a"},
1797 {"Q:A", 0, "file:///Q:A"},
1798
1799 /* A double initial backslash is also converted to a file path. The same
1800 * rules for hostnames apply. */
1801
1802 {"\\\\", 0, "file:///"},
1803 {"\\\\a", 0, "file://a/"},
1804 {"\\\\../a\\b/..\\c/.\\", 0, "file://../a/c/"},
1805 {"\\\\a/./b/../c", 0, "file://a/./b/../c"},
1806 /* And, of course, four or more slashes gets collapsed... */
1807 {"\\\\//./b/./../c", 0, "file://./c"},
1808 {"\\\\///./b/./../c", 0, "file://./c"},
1809
1810 {"\\\\a/b?c/../d", 0, "file://a/d"},
1811 {"\\\\a/b#c/../d", 0, "file://a/d"},
1812
1813 /* Drive paths are "recognized" too, though. The following isn't
1814 * actually a local path, but UrlCanonicalize() doesn't seem to realize
1815 * that. */
1816 {"\\\\a:/b", 0, "file:///a:/b"},
1817
1818 {"\\\\", URL_FILE_USE_PATHURL, "file://"},
1819 {"\\\\a", URL_FILE_USE_PATHURL, "file://\\\\a"},
1820 {"\\\\a/./..", URL_FILE_USE_PATHURL, "file://\\\\a\\..\\"},
1821 {"\\\\a:/b", URL_FILE_USE_PATHURL, "file://a:\\b"},
1822 {"\\\\", URL_WININET_COMPATIBILITY, "file://\\"},
1823 {"\\\\a", URL_WININET_COMPATIBILITY, "file://\\\\a\\"},
1824 {"\\\\a/./..", URL_WININET_COMPATIBILITY, "file://\\\\a\\..\\"},
1825 {"\\\\a:/b", URL_WININET_COMPATIBILITY, "file://a:\\b"},
1826
1827 /* And, as with drive paths, unsafe characters are escaped. */
1828 {"\\\\a/b !\"$%&'()*+,-:;<=>@[]^_`{|}~c", 0, "file://a/b%20!%22$%25%26'()*+,-:;%3C=%3E@%5B%5D%5E_%60%7B%7C%7D~c"},
1829 {"\\\\a/b &c", URL_FILE_USE_PATHURL, "file://\\\\a\\b &c"},
1830 {"\\\\a/b &c", URL_WININET_COMPATIBILITY, "file://\\\\a\\b &c"},
1831
1832 {"\\\\/b", 0, "file:///b"},
1833 {"\\\\/b", URL_FILE_USE_PATHURL, "file://\\b"},
1834 {"\\\\localhost/b", URL_FILE_USE_PATHURL, "file://\\b"},
1835 {"\\\\127.0.0.1/b", URL_FILE_USE_PATHURL, "file://\\\\127.0.0.1\\b"},
1836 {"\\\\localhost/b", URL_WININET_COMPATIBILITY, "file://\\b"},
1837 {"\\\\127.0.0.1/b", URL_WININET_COMPATIBILITY, "file://\\\\127.0.0.1\\b"},
1838
1839 {"\\\\A/B", 0, "file://A/B"},
1840
1841 {"file:///c:/tests/foo%20bar", URL_UNESCAPE, "file:///c:/tests/foo bar"},
1842 {"file:///c:/tests\\foo%20bar", URL_UNESCAPE, "file:///c:/tests/foo bar"},
1843 {"file:///c:/tests/foo%20bar", 0, "file:///c:/tests/foo%20bar"},
1844 {"file:///c:/tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1845 {"file://localhost/c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1846 {"file://localhost\\c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1847 {"file://localhost\\\\c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1848 {"file://localhost\\c:\\tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1849 {"file://c:/tests/../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1850 {"file://c:/tests\\../tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1851 {"file://c:/tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\tests\\foo bar"},
1852 {"file:///c://tests/foo%20bar", URL_FILE_USE_PATHURL, "file://c:\\\\tests\\foo bar"},
1853 {"file:///c:\\tests\\foo bar", 0, "file:///c:/tests/foo bar"},
1854 {"file:///c:\\tests\\foo bar", URL_DONT_SIMPLIFY, "file:///c:/tests/foo bar"},
1855 {"file:///c:\\tests\\foobar", 0, "file:///c:/tests/foobar"},
1856 {"file:///c:\\tests\\foobar", URL_WININET_COMPATIBILITY, "file://c:\\tests\\foobar"},
1857 {"file://home/user/file", 0, "file://home/user/file"},
1858 {"file:///home/user/file", 0, "file:///home/user/file"},
1859 {"file:////home/user/file", 0, "file://home/user/file"},
1860 {"file://home/user/file", URL_WININET_COMPATIBILITY, "file://\\\\home\\user\\file"},
1861 {"file:///home/user/file", URL_WININET_COMPATIBILITY, "file://\\home\\user\\file"},
1862 {"file:////home/user/file", URL_WININET_COMPATIBILITY, "file://\\\\home\\user\\file"},
1863 {"file://///home/user/file", URL_WININET_COMPATIBILITY, "file://\\\\home\\user\\file"},
1864 {"file://C:/user/file", 0, "file:///C:/user/file"},
1865 {"file://C:/user/file/../asdf", 0, "file:///C:/user/asdf"},
1866 {"file:///C:/user/file", 0, "file:///C:/user/file"},
1867 {"file:////C:/user/file", 0, "file:///C:/user/file"},
1868 {"file://C:/user/file", URL_WININET_COMPATIBILITY, "file://C:\\user\\file"},
1869 {"file:///C:/user/file", URL_WININET_COMPATIBILITY, "file://C:\\user\\file"},
1870 {"file:////C:/user/file", URL_WININET_COMPATIBILITY, "file://C:\\user\\file"},
1871 };
1872
1873 static const struct canonicalize_test misc_tests[] =
1874 {
1875 {"", 0, ""},
1876
1877 /* If both slashes are omitted, everything afterwards is replicated
1878 * as-is, with the exception that the final period is dropped from
1879 * "scheme:." */
1880
1881 {"wine:.", 0, "wine:"},
1882 {"wine:.", URL_DONT_SIMPLIFY, "wine:."},
1883 {"wine:./", 0, "wine:./"},
1884 {"wine:..", 0, "wine:.."},
1885 {"wine:../", 0, "wine:../"},
1886 {"wine:a", 0, "wine:a"},
1887 {"wine:a/", 0, "wine:a/"},
1888 {"wine:a/b/./../c", 0, "wine:a/b/./../c"},
1889
1890 {"wine:a/b?c/./d", 0, "wine:a/b?c/./d"},
1891 {"wine:a/b#c/./d", 0, "wine:a/b#c/./d"},
1892 {"wine:a/b#c?d", 0, "wine:a/b?d#c"},
1893 {"wine:.#c?d", 0, "wine:?d#c"},
1894
1895 /* A backslash directly after the colon is not treated specially. */
1896 {"wine:\\././a", 0, "wine:\\././a"},
1897
1898 {"wine:a/b &c", 0, "wine:a/b &c"},
1899
1900 /* If there's no scheme or hostname, things mostly follow the "unknown
1901 * scheme" rules, except that a would-be empty string results in a
1902 * single slash instead. */
1903
1904 {"a", 0, "a"},
1905 {"a/", 0, "a/"},
1906 {".", 0, "/"},
1907 {".", URL_DONT_SIMPLIFY, "./"},
1908 {"./", 0, "/"},
1909 {"./.", 0, "/"},
1910 {"././a", 0, "a"},
1911 {"a/.", 0, "a/"},
1912 {"a/./", 0, "a/"},
1913 {"a/./b", 0, "a/b"},
1914
1915 {"..", 0, "../"},
1916 {"../", 0, "../"},
1917 {"../a", 0, "../a"},
1918 {"../a/..", 0, "../"},
1919 {"a/..", 0, "/"},
1920 {"a/../..", 0, "../"},
1921 {"a/b/..", 0, "a/"},
1922 {"a/b/../", 0, "a/"},
1923 {"a/b/../c", 0, "a/c"},
1924 {"a/b/../c/..", 0, "a/"},
1925 {"a/b/../c/../..", 0, "/"},
1926
1927 {"a/b?c/./d", 0, "a/b?c/./d"},
1928 {"a/b#c/./d", 0, "a/b#c/./d"},
1929 {"a/b#c?d", 0, "a/b?d#c"},
1930 {"?c", 0, "?c"},
1931 {".?c", 0, "/?c"},
1932
1933 {"?c/./d", 0, "?c/./d"},
1934 {"#c/./d", 0, "#c/./d"},
1935
1936 {"a\\b/..", 0, "/"},
1937
1938 {"a/b &c", 0, "a/b &c"},
1939
1940 /* A colon by itself is not interpreted as any sort of scheme. */
1941 {"://../../a", 0, "a"},
1942
1943 /* mk: is another idiosyncratic scheme, although thankfully it behaves
1944 * rather simply. It has no concept of a hostname; if two slashes follow
1945 * the scheme it simply treats them as two empty path elements. */
1946 {"mk:", 0, "mk:"},
1947 {"mk:.", 0, "mk:"},
1948 {"mk:..", 0, "mk:"},
1949 {"mk:/", 0, "mk:/"},
1950 {"mk:/.", 0, "mk:/"},
1951 {"mk:/..", 0, "mk:"},
1952 {"mk:a", 0, "mk:a"},
1953 {"mk:a:", 0, "mk:a:"},
1954 {"mk://", 0, "mk://"},
1955 {"mk://.", 0, "mk://"},
1956 {"mk://..", 0, "mk:/"},
1957 {"mk://../..", 0, "mk:"},
1958 {"mk://../..", URL_DONT_SIMPLIFY, "mk://../.."},
1959 {"mk://../../..", 0, "mk:"},
1960
1961 /* Backslashes are not translated into forward slashes. They are treated
1962 * as path separators, but in a somewhat buggy manner: only dots before
1963 * a forward slash are collapsed, and a double dot rewinds to the
1964 * previous forward slash. */
1965 {"mk:a/.\\", 0, "mk:a/.\\"},
1966 {"mk:a/.\\b", 0, "mk:a/.\\b"},
1967 {"mk:a\\.\\b", 0, "mk:a\\.\\b"},
1968 {"mk:a\\./b", 0, "mk:a\\b"},
1969 {"mk:a./b", 0, "mk:a./b"},
1970 {"mk:a\\b/..\\c", 0, "mk:a\\b/..\\c"},
1971 {"mk:a\\b\\..\\c", 0, "mk:a\\b\\..\\c"},
1972 {"mk:a/b\\../c", 0, "mk:a/c"},
1973 {"mk:a\\b../c", 0, "mk:a\\b../c"},
1974
1975 /* Progids get a forward slash appended if there isn't one already, and
1976 * dots don't rewind past them. Despite the fact that progids are
1977 * supposed to end with a colon, UrlCanonicalize() considers them to
1978 * end with the slash.
1979 *
1980 * If the first path segment is a dot or double dot, it's treated as
1981 * a relative path, like http, but only before a forward slash. */
1982
1983 {"mk:@", 0, "mk:@/"},
1984 {"mk:@progid", 0, "mk:@progid/"},
1985 {"mk:@progid:a", 0, "mk:@progid:a/"},
1986 {"mk:@progid:a/b", 0, "mk:@progid:a/b"},
1987 {"mk:@Progid:a/b/../..", 0, "mk:@Progid:a/"},
1988 {"mk:@progid/a", 0, "mk:@progid/a"},
1989 {"mk:@progid\\a", 0, "mk:@progid\\a/"},
1990 {"mk:@progid/a/../..", 0, "mk:@progid/"},
1991 {"mk:@progid/.", 0, "mk:@progid/."},
1992 {"mk:@progid/.?", 0, "mk:@progid/.?"},
1993 {"mk:@progid/./..", 0, "mk:@progid/./.."},
1994 {"mk:@progid/../..", 0, "mk:@progid/../.."},
1995 {"mk:@progid/a\\.\\b", 0, "mk:@progid/a\\.\\b"},
1996 {"mk:@progid/a\\..\\b", 0, "mk:@progid/a\\..\\b"},
1997 {"mk:@progid/.\\..", 0, "mk:@progid/"},
1998
1999 {"mk:a/b?c/../d", 0, "mk:a/b?c/../d"},
2000 {"mk:a/b#c/../d", 0, "mk:a/b#c/../d"},
2001 {"mk:a/b#c?d", 0, "mk:a/b#c?d"},
2002 {"mk:@progid/a/b?c/../d", 0, "mk:@progid/a/b?c/../d"},
2003 {"mk:@progid?c/d/..", 0, "mk:@progid?c/"},
2004
2005 {"mk:a/b &c", 0, "mk:a/b &c"},
2006
2007 {"mk:@MSITStore:dir/test.chm::/file.html/..", 0, "mk:@MSITStore:dir/test.chm::/"},
2008 {"mk:@MSITStore:dir/test.chm::/file.html/../..", 0, "mk:@MSITStore:dir/"},
2009
2010 /* Whitespace except for plain spaces are stripped before parsing. */
2011 {" \t\n\rwi\t\n\rne\t\n\r:\t\n\r/\t\n\r/\t\n\r./../a/.\t\n\r./ \t\n\r", 0, "wine://./../"},
2012 /* Initial and final spaces and C0 control characters are also stripped,
2013 * but not 007F or C1 control characters. */
2014 {" \a\t\x01 wine://./.. \x1f\n\v ", 0, "wine://./../"},
2015 {" wine ://./..", 0, "wine :/"},
2016 {" wine: //a/../b", 0, "wine: //a/../b"},
2017 {" wine://a/b c/.. ", 0, "wine://a/"},
2018 {"\x7f/\a/\v/\x01/\x1f/\x80", 0, "\x7f/\a/\v/\x01/\x1f/\x80"},
2019
2020 /* Schemes are not case-sensitive, but are flattened to lowercase.
2021 * The hostname for http-like schemes is also flattened to lowercase
2022 * (but not for file; see above). */
2023 {"wInE://A/B", 0, "wine://A/B"},
2024 {"hTtP://A/b/../../C", 0, "http://a/C"},
2025 {"fTP://A/B\\./C", 0, "ftp://a/B\\C"},
2026 {"aBoUT://A/B/./", 0, "about://A/B/./"},
2027 {"mK://..", 0, "mk:/"},
2028
2029 /* Characters allowed in a scheme are alphanumeric, hyphen, plus, period. */
2030 {"0Aa+-.://./..", 0, "0aa+-.://./../"},
2031 {"a_://./..", 0, "a_:/"},
2032 {"a,://./..", 0, "a,:/"},
2033
2034 {"/uri-res/N2R?urn:sha1:B3K", URL_DONT_ESCAPE_EXTRA_INFO | URL_WININET_COMPATIBILITY, "/uri-res/N2R?urn:sha1:B3K"} /* LimeWire online installer calls this */,
2035 {"mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm", 0,
2036 "mk:@MSITStore:C:\\Program Files/AutoCAD 2008\\Help/acad_acg.chm::/WSfacf1429558a55de1a7524c1004e616f8b-322b.htm"},
2037 };
2038
2039 static const DWORD file_flags[] = {0, URL_FILE_USE_PATHURL, URL_WININET_COMPATIBILITY};
2040
2041 urllen = lstrlenA(winehqA);
2042
2043 /* Parameter checks */
2044 dwSize = ARRAY_SIZE(szReturnUrl);
2045 hr = UrlCanonicalizeA(NULL, szReturnUrl, &dwSize, URL_UNESCAPE);
2046 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2047 ok(dwSize == ARRAY_SIZE(szReturnUrl), "got size %lu\n", dwSize);
2048
2049 dwSize = ARRAY_SIZE(szReturnUrl);
2051 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2052 ok(dwSize == ARRAY_SIZE(szReturnUrl), "got size %lu\n", dwSize);
2053
2054 hr = UrlCanonicalizeA(winehqA, szReturnUrl, NULL, URL_UNESCAPE);
2055 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2056
2057 dwSize = 0;
2058 hr = UrlCanonicalizeA(winehqA, szReturnUrl, &dwSize, URL_UNESCAPE);
2059 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2060 ok(!dwSize, "got size %lu\n", dwSize);
2061
2062 /* buffer has no space for the result */
2063 dwSize=urllen-1;
2064 memset(szReturnUrl, '#', urllen+4);
2065 szReturnUrl[urllen+4] = '\0';
2066 SetLastError(0xdeadbeef);
2068 ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
2069 "got 0x%lx with %lu and size %lu for '%s' and %u (expected 'E_POINTER' and size %lu)\n",
2070 hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen+1);
2071
2072 /* buffer has no space for the terminating '\0' */
2073 dwSize=urllen;
2074 memset(szReturnUrl, '#', urllen+4);
2075 szReturnUrl[urllen+4] = '\0';
2076 SetLastError(0xdeadbeef);
2078 ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
2079 "got 0x%lx with %lu and size %lu for '%s' and %u (expected 'E_POINTER' and size %lu)\n",
2080 hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen+1);
2081
2082 /* buffer has the required size */
2083 dwSize=urllen+1;
2084 memset(szReturnUrl, '#', urllen+4);
2085 szReturnUrl[urllen+4] = '\0';
2086 SetLastError(0xdeadbeef);
2088 ok( (hr == S_OK) && (dwSize == urllen),
2089 "got 0x%lx with %lu and size %lu for '%s' and %u (expected 'S_OK' and size %lu)\n",
2090 hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen);
2091
2092 /* buffer is larger as the required size */
2093 dwSize=urllen+2;
2094 memset(szReturnUrl, '#', urllen+4);
2095 szReturnUrl[urllen+4] = '\0';
2096 SetLastError(0xdeadbeef);
2098 ok( (hr == S_OK) && (dwSize == urllen),
2099 "got 0x%lx with %lu and size %lu for '%s' and %u (expected 'S_OK' and size %lu)\n",
2100 hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), urllen);
2101
2102 /* length is set to 0 */
2103 dwSize=0;
2104 memset(szReturnUrl, '#', urllen+4);
2105 szReturnUrl[urllen+4] = '\0';
2106 SetLastError(0xdeadbeef);
2108 ok( (hr == E_INVALIDARG) && (dwSize == 0),
2109 "got 0x%lx with %lu and size %lu for '%s' and %u (expected 'E_INVALIDARG' and size %u)\n",
2110 hr, GetLastError(), dwSize, szReturnUrl, lstrlenA(szReturnUrl), 0);
2111
2112 /* url length > INTERNET_MAX_URL_SIZE */
2113 dwSize=sizeof(szReturnUrl);
2114 memset(longurl, 'a', sizeof(longurl));
2115 memcpy(longurl, winehqA, sizeof(winehqA)-1);
2116 longurl[sizeof(longurl)-1] = '\0';
2118 ok(hr == S_OK, "hr = %lx\n", hr);
2119 ok(dwSize == strlen(szReturnUrl), "got size %lu\n", dwSize);
2120
2121 for (f = 0; f < ARRAY_SIZE(file_flags); ++f)
2122 {
2123 for (i = 0; i < ARRAY_SIZE(unk_scheme_tests); ++i)
2124 {
2125 check_url_canonicalize(unk_scheme_tests[i].url,
2126 unk_scheme_tests[i].flags | file_flags[f], unk_scheme_tests[i].expect);
2127 sprintf(url, "wine:%s", unk_scheme_tests[i].url);
2128 sprintf(expect, "wine:%s", unk_scheme_tests[i].expect);
2129 check_url_canonicalize(url, unk_scheme_tests[i].flags | file_flags[f], expect);
2130 }
2131
2132 for (i = 0; i < ARRAY_SIZE(http_tests); ++i)
2133 {
2134 static const struct
2135 {
2136 const char *prefix;
2137 BOOL ftp_like;
2138 }
2139 prefixes[] =
2140 {
2141 {"ftp", TRUE},
2142 {"gopher"},
2143 {"http"},
2144 {"https"},
2145 {"local", TRUE},
2146 {"news"},
2147 {"nntp"},
2148 {"res", TRUE},
2149 {"snews"},
2150 {"telnet"},
2151 {"wais", TRUE},
2152 };
2153
2154 for (j = 0; j < ARRAY_SIZE(prefixes); ++j)
2155 {
2156 sprintf(url, "%s:%s", prefixes[j].prefix, http_tests[i].url);
2157 if (prefixes[j].ftp_like && http_tests[i].expect_ftp)
2158 sprintf(expect, "%s:%s", prefixes[j].prefix, http_tests[i].expect_ftp);
2159 else
2160 sprintf(expect, "%s:%s", prefixes[j].prefix, http_tests[i].expect);
2161
2162 check_url_canonicalize(url, http_tests[i].flags | file_flags[f], expect);
2163 }
2164 }
2165
2166 for (i = 0; i < ARRAY_SIZE(opaque_tests); ++i)
2167 {
2168 static const char *const prefixes[] = {"about", "javascript", "mailto", "shell", "vbscript"};
2169
2170 for (j = 0; j < ARRAY_SIZE(prefixes); ++j)
2171 {
2172 sprintf(url, "%s:%s", prefixes[j], opaque_tests[i].url);
2173 sprintf(expect, "%s:%s", prefixes[j], opaque_tests[i].expect);
2174 check_url_canonicalize(url, opaque_tests[i].flags | file_flags[f], expect);
2175 }
2176 }
2177
2178 for (i = 0; i < ARRAY_SIZE(misc_tests); i++)
2179 check_url_canonicalize(misc_tests[i].url, misc_tests[i].flags | file_flags[f], misc_tests[i].expect);
2180 }
2181
2182 for (i = 0; i < ARRAY_SIZE(file_tests); i++)
2183 check_url_canonicalize(file_tests[i].url, file_tests[i].flags, file_tests[i].expect);
2184}
#define TRUE
Definition: types.h:120
#define SetLastError(x)
Definition: compat.h:752
unsigned int BOOL
Definition: ntddk_ex.h:94
GLfloat f
Definition: glext.h:7540
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean const GLdouble const GLfloat const GLint const GLshort const GLbyte const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLdouble const GLfloat const GLfloat const GLint const GLint const GLshort const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort const GLdouble const GLfloat const GLint const GLshort GLenum GLenum GLenum GLfloat GLenum GLint GLenum GLenum GLenum GLfloat GLenum GLenum GLint GLenum GLfloat GLenum GLint GLint GLushort GLenum GLenum GLfloat GLenum GLenum GLint GLfloat const GLubyte GLenum GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLint GLint GLsizei GLsizei GLint GLenum GLenum const GLvoid GLenum GLenum const GLfloat GLenum GLenum const GLint GLenum GLenum const GLdouble GLenum GLenum const GLfloat GLenum GLenum const GLint GLsizei GLuint GLfloat GLuint GLbitfield GLfloat GLint GLuint GLboolean GLenum GLfloat GLenum GLbitfield GLenum GLfloat GLfloat GLint GLint const GLfloat GLenum GLfloat GLfloat GLint GLint GLfloat GLfloat GLint GLint const GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat GLint GLfloat GLfloat const GLdouble const GLfloat const GLdouble const GLfloat GLint GLint GLint j
Definition: glfuncs.h:250
static int prefixes
Definition: i386-dis.c:276
#define f
Definition: ke_i.h:83
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
#define sprintf
Definition: sprintf.c:45
DWORD flags
Definition: url.c:297
static void check_url_canonicalize(const char *url, DWORD flags, const char *expect)
Definition: url.c:793
static const char winehqA[]
Definition: url.c:38
#define URL_ESCAPE_UNSAFE
Definition: shlwapi.h:533
#define URL_WININET_COMPATIBILITY
Definition: shlwapi.h:535
#define URL_DONT_ESCAPE_EXTRA_INFO
Definition: shlwapi.h:529
#define URL_UNESCAPE
Definition: shlwapi.h:532
#define URL_ESCAPE_SPACES_ONLY
Definition: shlwapi.h:530
#define URL_ESCAPE_SEGMENT_ONLY
Definition: shlwapi.h:522
#define URL_DONT_SIMPLIFY
Definition: shlwapi.h:531
#define URL_FILE_USE_PATHURL
Definition: shlwapi.h:523
Character const *const prefix
Definition: tempnam.cpp:195
DWORD WINAPI GetLastError(void)
Definition: except.c:1042

Referenced by START_TEST().

◆ test_UrlCanonicalizeW()

static void test_UrlCanonicalizeW ( void  )
static

Definition at line 2188 of file url.c.

2189{
2190 WCHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
2191 DWORD dwSize;
2192 DWORD urllen;
2193 HRESULT hr;
2194 int i;
2195
2196 urllen = lstrlenW(winehqW);
2197
2198 /* Parameter checks */
2199 dwSize = ARRAY_SIZE(szReturnUrl);
2200 hr = UrlCanonicalizeW(NULL, szReturnUrl, &dwSize, URL_UNESCAPE);
2201 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2202 ok(dwSize == ARRAY_SIZE(szReturnUrl), "got size %lu\n", dwSize);
2203
2204 dwSize = ARRAY_SIZE(szReturnUrl);
2206 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2207 ok(dwSize == ARRAY_SIZE(szReturnUrl), "got size %lu\n", dwSize);
2208
2209 hr = UrlCanonicalizeW(winehqW, szReturnUrl, NULL, URL_UNESCAPE);
2210 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2211
2212 dwSize = 0;
2213 hr = UrlCanonicalizeW(winehqW, szReturnUrl, &dwSize, URL_UNESCAPE);
2214 ok(hr == E_INVALIDARG, "Got unexpected hr %#lx.\n", hr);
2215 ok(!dwSize, "got size %lu\n", dwSize);
2216
2217 /* buffer has no space for the result */
2218 dwSize = (urllen-1);
2219 memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
2220 szReturnUrl[urllen+4] = '\0';
2221 SetLastError(0xdeadbeef);
2223 ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
2224 "got 0x%lx with %lu and size %lu for %u (expected 'E_POINTER' and size %lu)\n",
2225 hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen+1);
2226
2227
2228 /* buffer has no space for the terminating '\0' */
2229 dwSize = urllen;
2230 memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
2231 szReturnUrl[urllen+4] = '\0';
2232 SetLastError(0xdeadbeef);
2234 ok( (hr == E_POINTER) && (dwSize == (urllen + 1)),
2235 "got 0x%lx with %lu and size %lu for %u (expected 'E_POINTER' and size %lu)\n",
2236 hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen+1);
2237
2238 /* buffer has the required size */
2239 dwSize = urllen +1;
2240 memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
2241 szReturnUrl[urllen+4] = '\0';
2242 SetLastError(0xdeadbeef);
2244 ok( (hr == S_OK) && (dwSize == urllen),
2245 "got 0x%lx with %lu and size %lu for %u (expected 'S_OK' and size %lu)\n",
2246 hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen);
2247
2248 /* buffer is larger as the required size */
2249 dwSize = (urllen+2);
2250 memset(szReturnUrl, '#', (urllen+4) * sizeof(WCHAR));
2251 szReturnUrl[urllen+4] = '\0';
2252 SetLastError(0xdeadbeef);
2254 ok( (hr == S_OK) && (dwSize == urllen),
2255 "got 0x%lx with %lu and size %lu for %u (expected 'S_OK' and size %lu)\n",
2256 hr, GetLastError(), dwSize, lstrlenW(szReturnUrl), urllen);
2257
2258 /* Only ASCII alphanumeric characters are allowed in a scheme. */
2259 dwSize = ARRAY_SIZE(szReturnUrl);
2260 hr = UrlCanonicalizeW(L"f\xe8ve://./..", szReturnUrl, &dwSize, 0);
2261 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2262 ok(!wcscmp(szReturnUrl, L"f\xe8ve:/"), "Got URL %s.\n", debugstr_w(szReturnUrl));
2263 ok(dwSize == wcslen(szReturnUrl), "got size %lu\n", dwSize);
2264
2265 /* check that the characters 1..32 are chopped from the end of the string */
2266 for (i = 1; i < 65536; i++)
2267 {
2268 WCHAR szUrl[128];
2269 BOOL choped;
2270 int pos;
2271
2272 wcscpy(szUrl, L"http://www.winehq.org/X");
2273 pos = lstrlenW(szUrl) - 1;
2274 szUrl[pos] = i;
2275 urllen = INTERNET_MAX_URL_LENGTH;
2276 UrlCanonicalizeW(szUrl, szReturnUrl, &urllen, 0);
2277 choped = lstrlenW(szReturnUrl) < lstrlenW(szUrl);
2278 ok(choped == (i <= 32), "Incorrect char chopping for char %d\n", i);
2279 }
2280}
#define lstrlenW
Definition: compat.h:750
static const WCHAR winehqW[]
Definition: url.c:37

Referenced by START_TEST().

◆ test_UrlCombine()

static void test_UrlCombine ( void  )
static

Definition at line 2320 of file url.c.

2321{
2322 WCHAR bufferW[30];
2323 char buffer[30];
2324 unsigned int i;
2325 HRESULT hr;
2326 DWORD size;
2327
2328 hr = UrlCombineA("http://base/", "relative", NULL, NULL, 0);
2329 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2330
2331 size = 0;
2332 hr = UrlCombineA("http://base/", "relative", NULL, &size, 0);
2333 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2334 ok(size == strlen("http://base/relative") + 1, "Got size %lu.\n", size);
2335
2336 --size;
2337 strcpy(buffer, "x");
2338 hr = UrlCombineA("http://base/", "relative", buffer, &size, 0);
2339 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2340 ok(size == strlen("http://base/relative") + 1, "Got size %lu.\n", size);
2341 ok(!strcmp(buffer, "x"), "Got buffer contents %s.\n", debugstr_a(buffer));
2342
2343 strcpy(buffer, "x");
2344 hr = UrlCombineA("http://base/", "relative", buffer, &size, 0);
2345 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2346 ok(size == strlen("http://base/relative"), "Got size %lu.\n", size);
2347 ok(!strcmp(buffer, "http://base/relative"), "Got buffer contents %s.\n", debugstr_a(buffer));
2348
2349 hr = UrlCombineW(L"http://base/", L"relative", NULL, NULL, 0);
2350 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
2351
2352 size = 0;
2353 hr = UrlCombineW(L"http://base/", L"relative", NULL, &size, 0);
2354 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2355 ok(size == strlen("http://base/relative") + 1, "Got size %lu.\n", size);
2356
2357 --size;
2358 wcscpy(bufferW, L"x");
2359 hr = UrlCombineW(L"http://base/", L"relative", bufferW, &size, 0);
2360 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
2361 ok(size == strlen("http://base/relative") + 1, "Got size %lu.\n", size);
2362 ok(!wcscmp(bufferW, L"x"), "Got buffer contents %s.\n", debugstr_a(buffer));
2363
2364 wcscpy(bufferW, L"x");
2365 hr = UrlCombineW(L"http://base/", L"relative", bufferW, &size, 0);
2366 ok(hr == S_OK, "Got hr %#lx.\n", hr);
2367 ok(size == strlen("http://base/relative"), "Got size %lu.\n", size);
2368 ok(!wcscmp(bufferW, L"http://base/relative"), "Got buffer contents %s.\n", debugstr_w(bufferW));
2369
2370 for (i = 0; i < ARRAY_SIZE(TEST_COMBINE); i++) {
2372 }
2373}
GLuint buffer
Definition: glext.h:5915
static const TEST_URL_COMBINE TEST_COMBINE[]
Definition: url.c:199
static void check_url_combine(const char *szUrl1, const char *szUrl2, DWORD dwFlags, const char *szExpectUrl)
Definition: url.c:2284
static const WCHAR url1[]
Definition: misc.c:300
static const WCHAR url2[]
Definition: misc.c:302

Referenced by START_TEST().

◆ test_UrlCreateFromPath()

static void test_UrlCreateFromPath ( void  )
static

Definition at line 2377 of file url.c.

2378{
2379 size_t i;
2380 char ret_url[INTERNET_MAX_URL_LENGTH];
2381 DWORD len, ret;
2383 WCHAR *pathW, *urlW;
2384
2385 for (i = 0; i < ARRAY_SIZE(TEST_URLFROMPATH); i++) {
2387 ret = UrlCreateFromPathA(TEST_URLFROMPATH[i].path, ret_url, &len, 0);
2388 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path %s\n", ret, TEST_URLFROMPATH[i].path);
2389 ok(!lstrcmpiA(ret_url, TEST_URLFROMPATH[i].url), "url %s from path %s\n", ret_url, TEST_URLFROMPATH[i].path);
2390 ok(len == strlen(ret_url), "ret len %ld from path %s\n", len, TEST_URLFROMPATH[i].path);
2391
2395 ret = UrlCreateFromPathW(pathW, ret_urlW, &len, 0);
2396 WideCharToMultiByte(CP_ACP, 0, ret_urlW, -1, ret_url, sizeof(ret_url),0,0);
2397 ok(ret == TEST_URLFROMPATH[i].ret, "ret %08lx from path L\"%s\", expected %08lx\n",
2399 ok(!lstrcmpiW(ret_urlW, urlW), "got %s expected %s from path L\"%s\"\n",
2401 ok(len == lstrlenW(ret_urlW), "ret len %ld from path L\"%s\"\n", len, TEST_URLFROMPATH[i].path);
2402 FreeWideString(urlW);
2403 FreeWideString(pathW);
2404 }
2405}
#define WideCharToMultiByte
Definition: compat.h:111
int WINAPI lstrcmpiW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4265
int WINAPI lstrcmpiA(LPCSTR str1, LPCSTR str2)
Definition: locale.c:4227
HRESULT WINAPI UrlCreateFromPathA(const char *path, char *url, DWORD *url_len, DWORD reserved)
Definition: path.c:4878
HRESULT WINAPI UrlCreateFromPathW(LPCWSTR pszPath, LPWSTR pszUrl, LPDWORD pcchUrl, DWORD dwReserved)
Definition: url.c:2497
return ret
Definition: mutex.c:146
static const struct @1840 TEST_URLFROMPATH[]

Referenced by START_TEST().

◆ test_UrlEscapeA()

static void test_UrlEscapeA ( void  )
static

Definition at line 827 of file url.c.

828{
829 DWORD size = 0;
830 HRESULT ret;
831 unsigned int i;
832 char empty_string[] = "";
833
834 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
835 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
836 ok(size == 0, "got %ld, expected %d\n", size, 0);
837
838 size = 0;
839 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
840 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
841 ok(size == 0, "got %ld, expected %d\n", size, 0);
842
843 size = 1;
844 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", NULL, &size, URL_ESCAPE_SPACES_ONLY);
845 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
846 ok(size == 1, "got %ld, expected %d\n", size, 1);
847
848 size = 1;
849 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, NULL, URL_ESCAPE_SPACES_ONLY);
850 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
851 ok(size == 1, "got %ld, expected %d\n", size, 1);
852
853 size = 1;
854 empty_string[0] = 127;
855 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
856 ok(ret == E_POINTER, "got %lx, expected %lx\n", ret, E_POINTER);
857 ok(size == 34, "got %ld, expected %d\n", size, 34);
858 ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
859
860 size = 1;
861 empty_string[0] = 127;
862 ret = UrlEscapeA("/woningplan/woonkamer basis.swf", empty_string, &size, URL_ESCAPE_AS_UTF8);
863#ifdef __REACTOS__
864 ok(ret == E_NOTIMPL || broken(ret == E_POINTER) /* Vista */, "Got unexpected hr %#lx.\n", ret);
865 ok(size == 1 || broken(size == 34) /* Vista */, "Got unexpected size %lu.\n", size);
866#else
867 ok(ret == E_NOTIMPL, "Got unexpected hr %#lx.\n", ret);
868 ok(size == 1, "Got unexpected size %lu.\n", size);
869#endif
870 ok(empty_string[0] == 127, "String has changed, empty_string[0] = %d\n", empty_string[0]);
871
872 for (i = 0; i < ARRAY_SIZE(TEST_ESCAPE); i++) {
874
877 ok(ret == S_OK, "Got unexpected hr %#lx for %s.\n", ret, debugstr_a(TEST_ESCAPE[i].url));
878 ok(!strcmp(ret_url, TEST_ESCAPE[i].expecturl), "Expected \"%s\", but got \"%s\" for \"%s\"\n",
879 TEST_ESCAPE[i].expecturl, ret_url, TEST_ESCAPE[i].url);
880 }
881}
#define broken(x)
Definition: atltest.h:178
#define E_NOTIMPL
Definition: ddrawi.h:99
HRESULT WINAPI UrlEscapeA(const char *url, char *escaped, DWORD *escaped_len, DWORD flags)
Definition: path.c:3305
static const TEST_URL_ESCAPE TEST_ESCAPE[]
Definition: url.c:83
#define URL_ESCAPE_AS_UTF8
Definition: shlwapi.h:524

Referenced by START_TEST().

◆ test_UrlEscapeW()

static void test_UrlEscapeW ( void  )
static

Definition at line 883 of file url.c.

884{
886 WCHAR overwrite[10] = L"foo bar";
887 WCHAR empty_string[] = {0};
888 DWORD size;
889 HRESULT ret;
890 WCHAR wc;
891 int i;
892#ifdef __REACTOS__
893 DWORD _ntVersion = GetVersion();
894 BYTE _ntMajor = LOBYTE(LOWORD(_ntVersion));
895 BYTE _ntMinor = HIBYTE(LOWORD(_ntVersion));
896#endif
897
898 /* Check error paths */
899
901 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
902
903 size = 0;
905 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
906 ok(size == 0, "got %ld, expected %d\n", size, 0);
907
908 ret = UrlEscapeW(L"/test", empty_string, NULL, URL_ESCAPE_SPACES_ONLY);
909 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
910
911 size = 0;
912 ret = UrlEscapeW(L"/test", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
913 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
914 ok(size == 0, "got %ld, expected %d\n", size, 0);
915
917 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
918
919 size = 1;
921 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
922 ok(size == 1, "got %ld, expected %d\n", size, 1);
923
924 ret = UrlEscapeW(L"/test", empty_string, NULL, URL_ESCAPE_SPACES_ONLY);
925 ok(ret == E_INVALIDARG, "got %lx, expected %lx\n", ret, E_INVALIDARG);
926
927 size = 1;
928 ret = UrlEscapeW(L"/test", empty_string, &size, URL_ESCAPE_SPACES_ONLY);
929 ok(ret == E_POINTER, "got %lx, expected %lx\n", ret, E_POINTER);
930 ok(size == 6, "got %ld, expected %d\n", size, 6);
931
932 /* Check actual escaping */
933
934 size = ARRAY_SIZE(overwrite);
935 ret = UrlEscapeW(overwrite, overwrite, &size, URL_ESCAPE_SPACES_ONLY);
936 ok(ret == S_OK, "got %lx, expected S_OK\n", ret);
937 ok(size == 9, "got %ld, expected 9\n", size);
938 ok(!wcscmp(overwrite, L"foo%20bar"), "Got unexpected string %s.\n", debugstr_w(overwrite));
939
940 size = 1;
941 wc = 127;
942 ret = UrlEscapeW(overwrite, &wc, &size, URL_ESCAPE_SPACES_ONLY);
943 ok(ret == E_POINTER, "got %lx, expected %lx\n", ret, E_POINTER);
944 ok(size == 10, "got %ld, expected 10\n", size);
945 ok(wc == 127, "String has changed, wc = %d\n", wc);
946
947 /* non-ASCII range */
948 size = ARRAY_SIZE(ret_urlW);
949 ret = UrlEscapeW(L"ftp\x1f\xff\xfa\x2122q/", ret_urlW, &size, 0);
950 ok(ret == S_OK, "got %lx, expected S_OK\n", ret);
951 ok(!wcscmp(ret_urlW, L"ftp%1F%FF%FA\x2122q/"), "Got unexpected string %s.\n", debugstr_w(ret_urlW));
952
953 for (i = 0; i < ARRAY_SIZE(TEST_ESCAPE); i++) {
954
955 WCHAR *urlW, *expected_urlW;
956
959 expected_urlW = GetWideString(TEST_ESCAPE[i].expecturl);
960 ret = UrlEscapeW(urlW, ret_urlW, &size, TEST_ESCAPE[i].flags);
961 ok(ret == S_OK, "Got unexpected hr %#lx for %s.\n", ret, debugstr_w(urlW));
962 ok(!lstrcmpW(ret_urlW, expected_urlW), "Expected %s, but got %s for %s flags %08lx\n",
963 wine_dbgstr_w(expected_urlW), wine_dbgstr_w(ret_urlW), wine_dbgstr_w(urlW), TEST_ESCAPE[i].flags);
964 FreeWideString(urlW);
965 FreeWideString(expected_urlW);
966 }
967
968 for (i = 0; i < ARRAY_SIZE(TEST_ESCAPEW); i++) {
970
971#ifdef __REACTOS__
972 /* TEST_ESCAPEW[6, 7] is incorrect for WS03, Vista. */
973 if ((i == 6 || i == 7) && (_ntMajor < 6 || (_ntMajor == 6 && _ntMinor == 0)))
974 continue;
975#endif
978 ok(ret == S_OK, "Got unexpected hr %#lx for %s.\n", ret, debugstr_w(TEST_ESCAPEW[i].url));
979 ok(!wcscmp(ret_url, TEST_ESCAPEW[i].expecturl)
980 || broken(!wcscmp(ret_url, TEST_ESCAPEW[i].win7url)),
981 "Expected %s, but got %s for %s.\n", debugstr_w(TEST_ESCAPEW[i].expecturl),
983 }
984}
int WINAPI lstrcmpW(LPCWSTR str1, LPCWSTR str2)
Definition: locale.c:4246
DWORD WINAPI GetVersion(void)
Definition: version.c:1458
HRESULT WINAPI UrlEscapeW(LPCWSTR pszUrl, LPWSTR pszEscaped, LPDWORD pcchEscaped, DWORD dwFlags)
Definition: url.c:1076
#define LOBYTE(W)
Definition: jmemdos.c:487
#define HIBYTE(W)
Definition: jmemdos.c:486
static const TEST_URL_ESCAPEW TEST_ESCAPEW[]
Definition: url.c:173
#define LOWORD(l)
Definition: pedump.c:82

Referenced by START_TEST().

◆ test_UrlGetPart()

static void test_UrlGetPart ( void  )
static

Definition at line 498 of file url.c.

499{
500 WCHAR bufferW[200];
501 char buffer[200];
502 unsigned int i;
503 HRESULT hr;
504 DWORD size;
505
506 static const struct
507 {
508 const char *url;
509 DWORD part;
510 DWORD flags;
511 HRESULT hr;
512 const char *expect;
513 }
514 tests[] =
515 {
516 {"hi", URL_PART_SCHEME, 0, S_FALSE, ""},
517 {"hi", URL_PART_USERNAME, 0, E_FAIL},
518 {"hi", URL_PART_PASSWORD, 0, E_FAIL},
519 {"hi", URL_PART_HOSTNAME, 0, E_FAIL},
520 {"hi", URL_PART_PORT, 0, E_FAIL},
521 {"hi", URL_PART_QUERY, 0, S_FALSE, ""},
522
523 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_SCHEME, 0, S_OK, "http"},
524 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_USERNAME, 0, S_OK, "foo"},
525 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PASSWORD, 0, S_OK, "bar"},
526 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
527 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PORT, 0, S_OK, "21"},
528 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, 0, S_OK, "query=x&return=y"},
529 {"http://foo:bar@localhost:21/internal.php#anchor", URL_PART_QUERY, 0, S_FALSE, ""},
530 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_SCHEME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http"},
531 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_USERNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:foo"},
532 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PASSWORD, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:bar"},
533 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:localhost"},
534 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_PORT, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:21"},
535 {"http://foo:bar@localhost:21/internal.php?query=x&return=y", URL_PART_QUERY, URL_PARTFLAG_KEEPSCHEME, S_OK, "query=x&return=y"},
536
537 {"http://localhost/", URL_PART_USERNAME, 0, E_INVALIDARG},
538 {"http://localhost/", URL_PART_PASSWORD, 0, E_INVALIDARG},
539 {"http://localhost/", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
540 {"http://localhost/", URL_PART_PORT, 0, E_INVALIDARG},
541 {"http://localhost/", URL_PART_QUERY, 0, S_FALSE, ""},
542
543 {"http://localhost:port/", URL_PART_USERNAME, 0, E_INVALIDARG},
544 {"http://localhost:port/", URL_PART_PASSWORD, 0, E_INVALIDARG},
545 {"http://localhost:port/", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
546 {"http://localhost:port/", URL_PART_PORT, 0, S_OK, "port"},
547 {"http://:", URL_PART_HOSTNAME, 0, S_FALSE, ""},
548 {"http://:", URL_PART_PORT, 0, S_FALSE, ""},
549
550 {"http://user@localhost", URL_PART_USERNAME, 0, S_OK, "user"},
551 {"http://user@localhost", URL_PART_PASSWORD, 0, E_INVALIDARG},
552 {"http://user@localhost", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
553 {"http://user@localhost", URL_PART_PORT, 0, E_INVALIDARG},
554 {"http://@", URL_PART_USERNAME, 0, S_FALSE, ""},
555 {"http://@", URL_PART_PASSWORD, 0, E_INVALIDARG},
556 {"http://@", URL_PART_HOSTNAME, 0, S_FALSE, ""},
557
558 {"http://user:pass@localhost", URL_PART_USERNAME, 0, S_OK, "user"},
559 {"http://user:pass@localhost", URL_PART_PASSWORD, 0, S_OK, "pass"},
560 {"http://user:pass@localhost", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
561 {"http://user:pass@localhost", URL_PART_PORT, 0, E_INVALIDARG},
562 {"http://:@", URL_PART_USERNAME, 0, S_FALSE, ""},
563 {"http://:@", URL_PART_PASSWORD, 0, S_FALSE, ""},
564 {"http://:@", URL_PART_HOSTNAME, 0, S_FALSE, ""},
565
566 {"http://host:port:q", URL_PART_HOSTNAME, 0, S_OK, "host"},
567 {"http://host:port:q", URL_PART_PORT, 0, S_OK, "port:q"},
568 {"http://user:pass:q@host", URL_PART_USERNAME, 0, S_OK, "user"},
569 {"http://user:pass:q@host", URL_PART_PASSWORD, 0, S_OK, "pass:q"},
570 {"http://user@host@q", URL_PART_USERNAME, 0, S_OK, "user"},
571 {"http://user@host@q", URL_PART_HOSTNAME, 0, S_OK, "host@q"},
572
573 {"http:localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL},
574 {"http:/localhost/index.html", URL_PART_HOSTNAME, 0, E_FAIL},
575
576 {"http://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
577 {"http:/\\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
578 {"http:\\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
579
580 {"ftp://localhost\\index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
581 {"ftp:/\\localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
582 {"ftp:\\/localhost/index.html", URL_PART_HOSTNAME, 0, S_OK, "localhost"},
583
584 {"http://host?a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"},
585 {"http://host?a:b@c:d", URL_PART_QUERY, 0, S_OK, "a:b@c:d"},
586 {"http://host#a:b@c:d", URL_PART_HOSTNAME, 0, S_OK, "host"},
587 {"http://host#a:b@c:d", URL_PART_QUERY, 0, S_FALSE, ""},
588
589 /* All characters, other than those with special meaning, are allowed. */
590 {"http://foo:bar@google.*.com:21/internal.php?query=x&return=y", URL_PART_HOSTNAME, 0, S_OK, "google.*.com"},
591 {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}:pass@host", URL_PART_USERNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}"},
592 {"http://user: !\"$%&'()*+,-.;<=>[]^_`{|~}@host", URL_PART_PASSWORD, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}"},
593 {"http:// !\"$%&'()*+,-.;<=>[]^_`{|~}", URL_PART_HOSTNAME, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}"},
594 {"http://host: !\"$%&'()*+,-.;<=>[]^_`{|~}", URL_PART_PORT, 0, S_OK, " !\"$%&'()*+,-.;<=>[]^_`{|~}"},
595
596 {"http:///index.html", URL_PART_HOSTNAME, 0, S_FALSE, ""},
597 {"http:///index.html", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:"},
598 {"file://h o s t/c:/windows/file", URL_PART_HOSTNAME, 0, S_OK, "h o s t"},
599 {"file://h o s t/c:/windows/file", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "h o s t"},
600 {"file://foo:bar@localhost:21/file?query=x", URL_PART_USERNAME, 0, E_FAIL},
601 {"file://foo:bar@localhost:21/file?query=x", URL_PART_PASSWORD, 0, E_FAIL},
602 {"file://foo:bar@localhost:21/file?query=x", URL_PART_HOSTNAME, 0, S_OK, "foo:bar@localhost:21"},
603 {"file://foo:bar@localhost:21/file?query=x", URL_PART_PORT, 0, E_FAIL},
604 {"file://foo:bar@localhost:21/file?query=x", URL_PART_QUERY, 0, S_OK, "query=x"},
605 {"http://user:pass 123@www.wine hq.org", URL_PART_HOSTNAME, 0, S_OK, "www.wine hq.org"},
606 {"http://user:pass 123@www.wine hq.org", URL_PART_PASSWORD, 0, S_OK, "pass 123"},
607 {"about:blank", URL_PART_SCHEME, 0, S_OK, "about"},
608 {"about:blank", URL_PART_HOSTNAME, 0, E_FAIL},
609 {"x-excid://36C00000/guid:{048B4E89-2E92-496F-A837-33BA02FF6D32}/Message.htm", URL_PART_SCHEME, 0, S_OK, "x-excid"},
610 {"x-excid://36C00000/guid:{048B4E89-2E92-496F-A837-33BA02FF6D32}/Message.htm", URL_PART_HOSTNAME, 0, E_FAIL},
611 {"x-excid://36C00000/guid:{048B4E89-2E92-496F-A837-33BA02FF6D32}/Message.htm", URL_PART_QUERY, 0, S_FALSE, ""},
612 {"foo://bar-url/test", URL_PART_SCHEME, 0, S_OK, "foo"},
613 {"foo://bar-url/test", URL_PART_HOSTNAME, 0, E_FAIL},
614 {"foo://bar-url/test", URL_PART_QUERY, 0, S_FALSE, ""},
615 {"ascheme:", URL_PART_SCHEME, 0, S_OK, "ascheme"},
616 {"res://some.dll/find.dlg", URL_PART_SCHEME, 0, S_OK, "res"},
617 {"res://some.dll/find.dlg", URL_PART_QUERY, 0, S_FALSE, ""},
618 {"http://www.winehq.org", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:www.winehq.org"},
619 {"file:///index.html", URL_PART_HOSTNAME, 0, S_FALSE, ""},
620 {"file:///index.html", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_FALSE, ""},
621 {"file://c:\\index.htm", URL_PART_HOSTNAME, 0, S_FALSE, ""},
622 {"file://c:\\index.htm", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_FALSE, ""},
623 {"file:some text", URL_PART_HOSTNAME, 0, S_FALSE, ""},
624 {"index.htm", URL_PART_HOSTNAME, 0, E_FAIL},
625 {"sChEmE-.+:", URL_PART_SCHEME, 0, S_OK, "scheme-.+"},
626 {"scheme_:", URL_PART_SCHEME, 0, S_FALSE, ""},
627 {"scheme :", URL_PART_SCHEME, 0, S_FALSE, ""},
628 {"sch eme:", URL_PART_SCHEME, 0, S_FALSE, ""},
629 {":", URL_PART_SCHEME, 0, S_FALSE, ""},
630 {"a:", URL_PART_SCHEME, 0, S_FALSE, ""},
631 {"0:", URL_PART_SCHEME, 0, S_FALSE, ""},
632 {"ab:", URL_PART_SCHEME, 0, S_OK, "ab"},
633
634 {"about://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
635 {"file://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
636 {"ftp://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
637 {"gopher://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
638 {"http://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
639 {"https://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
640 {"javascript://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
641 {"local://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
642 {"mailto://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
643 {"mk://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
644 {"news://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
645 {"nntp://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
646 {"res://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
647 {"shell://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
648 {"snews://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
649 {"telnet://hostname/", URL_PART_HOSTNAME, 0, S_OK, "hostname"},
650 {"vbscript://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
651 {"wais://hostname/", URL_PART_HOSTNAME, 0, E_FAIL},
652
653 {"file://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "hostname"},
654 {"ftp://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "ftp:hostname"},
655 {"gopher://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "gopher:hostname"},
656 {"http://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "http:hostname"},
657 {"https://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "https:hostname"},
658 {"news://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "news:hostname"},
659 {"nntp://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "nntp:hostname"},
660 {"snews://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "snews:hostname"},
661 {"telnet://hostname/", URL_PART_HOSTNAME, URL_PARTFLAG_KEEPSCHEME, S_OK, "telnet:hostname"},
662 };
663
665 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
666
668 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
669
670 hr = UrlGetPartA("res://some.dll/find.dlg", NULL, &size, URL_PART_SCHEME, 0);
671 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
672
673 hr = UrlGetPartA("res://some.dll/find.dlg", buffer, NULL, URL_PART_SCHEME, 0);
674 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
675
676 size = 0;
677 strcpy(buffer, "x");
679 ok(hr == E_INVALIDARG, "Got hr %#lx.\n", hr);
680 ok(!strcmp(buffer, "x"), "Got result %s.\n", debugstr_a(buffer));
681 ok(!size, "Got size %lu.\n", size);
682#ifdef __REACTOS__
683 if (LOBYTE(LOWORD(GetVersion())) < 6) {
684 skip("UrlGetPart test list broken on WS03.\n");
685 goto skip_UrlGetPartTestList;
686 }
687#endif
688
689 for (i = 0; i < ARRAY_SIZE(tests); ++i)
690 {
691 WCHAR urlW[200], expectW[200];
692 const char *expect = tests[i].expect;
693 const char *url = tests[i].url;
694 DWORD flags = tests[i].flags;
695 DWORD part = tests[i].part;
696
697 winetest_push_context("URL %s, part %#lx, flags %#lx", debugstr_a(url), part, flags);
698
699 size = 1;
700 strcpy(buffer, "x");
701 hr = UrlGetPartA(url, buffer, &size, part, flags);
702 if (tests[i].hr == S_OK)
703 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
704 else
705 ok(hr == tests[i].hr, "Got hr %#lx.\n", hr);
706
707 if (hr == S_FALSE)
708 {
709 ok(!size, "Got size %lu.\n", size);
710 ok(!buffer[0], "Got result %s.\n", debugstr_a(buffer));
711 }
712 else
713 {
714 if (hr == E_POINTER)
715 ok(size == strlen(expect) + 1, "Got size %lu.\n", size);
716 else
717 ok(size == 1, "Got size %lu.\n", size);
718 ok(!strcmp(buffer, "x"), "Got result %s.\n", debugstr_a(buffer));
719 }
720
721 size = sizeof(buffer);
722 strcpy(buffer, "x");
723 hr = UrlGetPartA(url, buffer, &size, part, flags);
724 ok(hr == tests[i].hr, "Got hr %#lx.\n", hr);
725 if (SUCCEEDED(hr))
726 {
727 ok(size == strlen(buffer), "Got size %lu.\n", size);
728 ok(!strcmp(buffer, expect), "Got result %s.\n", debugstr_a(buffer));
729 }
730 else
731 {
732 ok(size == sizeof(buffer), "Got size %lu.\n", size);
733 ok(!strcmp(buffer, "x"), "Got result %s.\n", debugstr_a(buffer));
734 }
735
736 MultiByteToWideChar(CP_ACP, 0, url, -1, urlW, ARRAY_SIZE(urlW));
737
738 size = 1;
739 wcscpy(bufferW, L"x");
740 hr = UrlGetPartW(urlW, bufferW, &size, part, flags);
741 if (tests[i].hr == S_OK)
742 ok(hr == E_POINTER, "Got hr %#lx.\n", hr);
743 else
744 ok(hr == (tests[i].hr == S_FALSE ? S_OK : tests[i].hr), "Got hr %#lx.\n", hr);
745
746 if (SUCCEEDED(hr))
747 {
748 ok(!size, "Got size %lu.\n", size);
749 ok(!buffer[0], "Got result %s.\n", debugstr_a(buffer));
750 }
751 else
752 {
753 if (hr == E_POINTER)
754 ok(size == strlen(expect) + 1, "Got size %lu.\n", size);
755 else
756 ok(size == 1, "Got size %lu.\n", size);
757 ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW));
758 }
759
760 size = ARRAY_SIZE(bufferW);
761 wcscpy(bufferW, L"x");
762 hr = UrlGetPartW(urlW, bufferW, &size, part, flags);
763 ok(hr == (tests[i].hr == S_FALSE ? S_OK : tests[i].hr), "Got hr %#lx.\n", hr);
764 if (SUCCEEDED(hr))
765 {
766 ok(size == wcslen(bufferW), "Got size %lu.\n", size);
767 MultiByteToWideChar(CP_ACP, 0, buffer, -1, expectW, ARRAY_SIZE(expectW));
768 ok(!wcscmp(bufferW, expectW), "Got result %s.\n", debugstr_w(bufferW));
769 }
770 else
771 {
772 ok(size == ARRAY_SIZE(bufferW), "Got size %lu.\n", size);
773 ok(!wcscmp(bufferW, L"x"), "Got result %s.\n", debugstr_w(bufferW));
774 }
775
777 }
778
779 /* Test non-ASCII characters. */
780#ifdef __REACTOS__
781skip_UrlGetPartTestList:
782#endif
783
784 size = ARRAY_SIZE(bufferW);
785 wcscpy(bufferW, L"x");
786 hr = UrlGetPartW(L"http://\x01\x7f\x80\xff:pass@host", bufferW, &size, URL_PART_USERNAME, 0);
787 ok(hr == S_OK, "Got hr %#lx.\n", hr);
788 ok(size == wcslen(bufferW), "Got size %lu.\n", size);
789 ok(!wcscmp(bufferW, L"\x01\x7f\x80\xff"), "Got result %s.\n", debugstr_w(bufferW));
790}
#define skip(...)
Definition: atltest.h:64
#define E_FAIL
Definition: ddrawi.h:102
HRESULT WINAPI UrlGetPartA(const char *url, char *out, DWORD *out_len, DWORD part, DWORD flags)
Definition: path.c:4521
HRESULT WINAPI UrlGetPartW(LPCWSTR pszIn, LPWSTR pszOut, LPDWORD pcchOut, DWORD dwPart, DWORD dwFlags)
Definition: url.c:2269
#define SUCCEEDED(hr)
Definition: intsafe.h:50
static struct test_info tests[]
@ URL_PART_SCHEME
Definition: shlwapi.h:586
@ URL_PART_QUERY
Definition: shlwapi.h:591
@ URL_PART_HOSTNAME
Definition: shlwapi.h:587
@ URL_PART_USERNAME
Definition: shlwapi.h:588
@ URL_PART_PORT
Definition: shlwapi.h:590
@ URL_PART_PASSWORD
Definition: shlwapi.h:589
#define URL_PARTFLAG_KEEPSCHEME
Definition: shlwapi.h:594

Referenced by START_TEST().

◆ test_UrlHash()

static void test_UrlHash ( void  )
static

Definition at line 491 of file url.c.

492{
496}
static const char * TEST_URL_3
Definition: url.c:35
static void hash_url(const char *szUrl)
Definition: url.c:473
static const char * TEST_URL_2
Definition: url.c:34
static const char * TEST_URL_1
Definition: url.c:33

Referenced by START_TEST().

◆ test_UrlIs()

static void test_UrlIs ( void  )
static

Definition at line 2418 of file url.c.

2419{
2420 BOOL ret;
2421 size_t i;
2422 WCHAR wurl[80];
2423
2431
2432 for (i = 0; i < ARRAY_SIZE(TEST_PATH_IS_URL); i++) {
2434
2437 "returned %d from path %s, expected %d\n", ret, TEST_PATH_IS_URL[i].path,
2439
2440 ret = UrlIsW( wurl, URLIS_URL );
2442 "returned %d from path (UrlIsW) %s, expected %d\n", ret,
2444 }
2445 for (i = 0; i < ARRAY_SIZE(TEST_URLIS_ATTRIBS); i++) {
2447
2450 "returned %d for URLIS_OPAQUE, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
2454 "returned %d for URLIS_FILEURL, url \"%s\", expected %d\n", ret, TEST_URLIS_ATTRIBS[i].url,
2456
2457 ret = UrlIsW( wurl, URLIS_OPAQUE);
2459 "returned %d for URLIS_OPAQUE (UrlIsW), url \"%s\", expected %d\n",
2461 ret = UrlIsW( wurl, URLIS_FILEURL);
2463 "returned %d for URLIS_FILEURL (UrlIsW), url \"%s\", expected %d\n",
2465 }
2466}
BOOL WINAPI UrlIsA(LPCSTR pszUrl, URLIS Urlis)
Definition: url.c:1880
BOOL WINAPI UrlIsW(LPCWSTR pszUrl, URLIS Urlis)
Definition: url.c:1933
static const struct @1843 TEST_PATH_IS_URL[]
static const struct @1844 TEST_URLIS_ATTRIBS[]
BOOL expectFile
Definition: url.c:344
BOOL expectOpaque
Definition: url.c:343
static void test_UrlIs_null(DWORD flag)
Definition: url.c:2409
@ URLIS_NOHISTORY
Definition: shlwapi.h:599
@ URLIS_OPAQUE
Definition: shlwapi.h:598
@ URLIS_APPLIABLE
Definition: shlwapi.h:601
@ URLIS_DIRECTORY
Definition: shlwapi.h:602
@ URLIS_FILEURL
Definition: shlwapi.h:600
@ URLIS_URL
Definition: shlwapi.h:597
@ URLIS_HASQUERY
Definition: shlwapi.h:603

Referenced by START_TEST().

◆ test_UrlIs_null()

static void test_UrlIs_null ( DWORD  flag)
static

Definition at line 2409 of file url.c.

2410{
2411 BOOL ret;
2412 ret = UrlIsA(NULL, flag);
2413 ok(ret == FALSE, "pUrlIsA(NULL, %ld) failed\n", flag);
2414 ret = UrlIsW(NULL, flag);
2415 ok(ret == FALSE, "pUrlIsW(NULL, %ld) failed\n", flag);
2416}
#define FALSE
Definition: types.h:117
GLsizei GLenum const GLvoid GLsizei GLenum GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLint GLint GLint GLshort GLshort GLshort GLubyte GLubyte GLubyte GLuint GLuint GLuint GLushort GLushort GLushort GLbyte GLbyte GLbyte GLbyte GLdouble GLdouble GLdouble GLdouble GLfloat GLfloat GLfloat GLfloat GLint GLint GLint GLint GLshort GLshort GLshort GLshort GLubyte GLubyte GLubyte GLubyte GLuint GLuint GLuint GLuint GLushort GLushort GLushort GLushort GLboolean flag
Definition: glfuncs.h:52

Referenced by test_UrlIs().

◆ test_UrlUnescape()

static void test_UrlUnescape ( void  )
static

Definition at line 2470 of file url.c.

2471{
2473 CHAR szReturnUrl[INTERNET_MAX_URL_LENGTH];
2474 DWORD dwEscaped, unescaped;
2475 BOOL utf8_support = TRUE;
2476 static char inplace[] = "file:///C:/Program%20Files";
2477 static char another_inplace[] = "file:///C:/Program%20Files";
2478 static const char expected[] = "file:///C:/Program Files";
2479 HRESULT res;
2480 int i;
2481
2482 for (i = 0; i < ARRAY_SIZE(TEST_URL_UNESCAPE); i++) {
2483 dwEscaped=INTERNET_MAX_URL_LENGTH;
2484 res = UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, &dwEscaped, 0);
2485 ok(res == S_OK,
2486 "UrlUnescapeA returned 0x%lx (expected S_OK) for \"%s\"\n",
2488 ok(strcmp(szReturnUrl,TEST_URL_UNESCAPE[i].expect)==0, "Expected \"%s\", but got \"%s\" from \"%s\"\n", TEST_URL_UNESCAPE[i].expect, szReturnUrl, TEST_URL_UNESCAPE[i].url);
2489
2490 ZeroMemory(szReturnUrl, sizeof(szReturnUrl));
2491 /* if we set the buffer pointer to NULL here, UrlUnescape fails and the string is not converted */
2492 res = UrlUnescapeA(TEST_URL_UNESCAPE[i].url, szReturnUrl, NULL, 0);
2493 ok(res == E_INVALIDARG,
2494 "UrlUnescapeA returned 0x%lx (expected E_INVALIDARG) for \"%s\"\n",
2496 ok(strcmp(szReturnUrl,"")==0, "Expected empty string\n");
2497 }
2498
2499 unescaped = INTERNET_MAX_URL_LENGTH;
2500 lstrcpyW(urlW, L"%F0%9F%8D%B7");
2502 ok(res == S_OK, "Got %#lx.\n", res);
2503 if (!wcscmp(urlW, L"\xf0\x9f\x8d\xb7"))
2504 {
2505 utf8_support = FALSE;
2506 win_skip("Skip URL_UNESCAPE_AS_UTF8 tests for pre-win7 systems.\n");
2507 }
2508
2509 for (i = 0; i < ARRAYSIZE(TEST_URL_UNESCAPEW); i++)
2510 {
2511 if (TEST_URL_UNESCAPEW[i].flags & URL_UNESCAPE_AS_UTF8 && !utf8_support)
2512 continue;
2513
2515
2516 memset(bufferW, 0xff, sizeof(bufferW));
2517 unescaped = INTERNET_MAX_URL_LENGTH;
2518 res = UrlUnescapeW(urlW, bufferW, &unescaped, TEST_URL_UNESCAPEW[i].flags);
2519 ok(res == S_OK, "[%d]: returned %#lx.\n", i, res);
2520 ok(unescaped == wcslen(TEST_URL_UNESCAPEW[i].expect), "[%d]: got unescaped %ld.\n", i, unescaped);
2521 ok(!wcscmp(bufferW, TEST_URL_UNESCAPEW[i].expect), "[%d]: got result %s.\n", i, debugstr_w(bufferW));
2522
2523 /* Test with URL_UNESCAPE_INPLACE */
2524 unescaped = INTERNET_MAX_URL_LENGTH;
2526 ok(res == S_OK, "[%d]: returned %#lx.\n", i, res);
2527 ok(unescaped == INTERNET_MAX_URL_LENGTH, "[%d]: got unescaped %ld.\n", i, unescaped);
2528 ok(!wcscmp(urlW, TEST_URL_UNESCAPEW[i].expect), "[%d]: got result %s.\n", i, debugstr_w(urlW));
2529
2531 unescaped = wcslen(TEST_URL_UNESCAPEW[i].expect) - 1;
2532 res = UrlUnescapeW(urlW, bufferW, &unescaped, TEST_URL_UNESCAPEW[i].flags);
2533 ok(res == E_POINTER, "[%d]: returned %#lx.\n", i, res);
2534 }
2535
2536 dwEscaped = sizeof(inplace);
2537 res = UrlUnescapeA(inplace, NULL, &dwEscaped, URL_UNESCAPE_INPLACE);
2538 ok(res == S_OK, "UrlUnescapeA returned 0x%lx (expected S_OK)\n", res);
2539 ok(!strcmp(inplace, expected), "got %s expected %s\n", inplace, expected);
2540 ok(dwEscaped == 27, "got %ld expected 27\n", dwEscaped);
2541
2542 /* if we set the buffer pointer to NULL, the string apparently still gets converted (Google Lively does this) */
2543 res = UrlUnescapeA(another_inplace, NULL, NULL, URL_UNESCAPE_INPLACE);
2544 ok(res == S_OK, "UrlUnescapeA returned 0x%lx (expected S_OK)\n", res);
2545 ok(!strcmp(another_inplace, expected), "got %s expected %s\n", another_inplace, expected);
2546}
#define ARRAYSIZE(array)
Definition: filtermapper.c:47
#define lstrcpyW
Definition: compat.h:749
HRESULT WINAPI UrlUnescapeA(char *url, char *unescaped, DWORD *unescaped_len, DWORD flags)
Definition: path.c:2858
HRESULT WINAPI UrlUnescapeW(LPWSTR pszUrl, LPWSTR pszUnescaped, LPDWORD pcchUnescaped, DWORD dwFlags)
Definition: url.c:1367
#define win_skip
Definition: minitest.h:67
#define ZeroMemory
Definition: minwinbase.h:31
static struct @1841 TEST_URL_UNESCAPE[]
static struct @1842 TEST_URL_UNESCAPEW[]
#define URL_UNESCAPE_AS_UTF8
Definition: shlwapi.h:536
#define URL_UNESCAPE_INPLACE
Definition: shlwapi.h:525

Referenced by START_TEST().

Variable Documentation

◆ expect

◆ expectFile

BOOL expectFile

Definition at line 344 of file url.c.

Referenced by test_UrlIs().

◆ expectOpaque

BOOL expectOpaque

Definition at line 343 of file url.c.

Referenced by test_UrlIs().

◆ flags

Definition at line 297 of file url.c.

Referenced by init_bind_test(), test_UrlCanonicalizeA(), and test_UrlGetPart().

◆ parse_url_tests

const struct parse_url_test_t parse_url_tests[]
static
Initial value:
= {
{"http://www.winehq.org/",S_OK,4,URL_SCHEME_HTTP},
{"https://www.winehq.org/",S_OK,5,URL_SCHEME_HTTPS},
{"ftp://www.winehq.org/",S_OK,3,URL_SCHEME_FTP},
{"test.txt?test=c:/dir",URL_E_INVALID_SYNTAX},
{"test.txt",URL_E_INVALID_SYNTAX},
{"xxx://www.winehq.org/",S_OK,3,URL_SCHEME_UNKNOWN},
{"1xx://www.winehq.org/",S_OK,3,URL_SCHEME_UNKNOWN},
{"-xx://www.winehq.org/",S_OK,3,URL_SCHEME_UNKNOWN},
{"xx0://www.winehq.org/",S_OK,3,URL_SCHEME_UNKNOWN},
{"x://www.winehq.org/",URL_E_INVALID_SYNTAX},
{"xx$://www.winehq.org/",URL_E_INVALID_SYNTAX},
{"htt?p://www.winehq.org/",URL_E_INVALID_SYNTAX},
{"ab-://www.winehq.org/",S_OK,3,URL_SCHEME_UNKNOWN},
{" http://www.winehq.org/",URL_E_INVALID_SYNTAX},
{"HTTP://www.winehq.org/",S_OK,4,URL_SCHEME_HTTP},
{"a+-.://www.winehq.org/",S_OK,4,URL_SCHEME_UNKNOWN},
}
#define URL_E_INVALID_SYNTAX
Definition: intshcut.h:32
@ URL_SCHEME_UNKNOWN
Definition: shlwapi.h:544
@ URL_SCHEME_HTTPS
Definition: shlwapi.h:555
@ URL_SCHEME_FTP
Definition: shlwapi.h:545
@ URL_SCHEME_HTTP
Definition: shlwapi.h:546

Referenced by test_ParseURL().

◆ path

Definition at line 267 of file url.c.

Referenced by InternetCrackUrl_test(), and WinHttpCrackUrl_test().

◆ ret

DWORD ret

Definition at line 269 of file url.c.

◆ TEST_APPLY

const TEST_URL_APPLY TEST_APPLY[]
static
Initial value:
= {
{"www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, "http://www.winehq.org"},
{"www.winehq.org", URL_APPLY_GUESSSCHEME, S_OK, "http://www.winehq.org"},
{"www.winehq.org", URL_APPLY_DEFAULT, S_OK, "http://www.winehq.org"},
{"ftp.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, "ftp://ftp.winehq.org"},
{"ftp.winehq.org", URL_APPLY_GUESSSCHEME, S_OK, "ftp://ftp.winehq.org"},
{"ftp.winehq.org", URL_APPLY_DEFAULT, S_OK, "http://ftp.winehq.org"},
{"winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_OK, "http://winehq.org"},
{"winehq.org", URL_APPLY_GUESSSCHEME, S_FALSE},
{"winehq.org", URL_APPLY_DEFAULT, S_OK, "http://winehq.org"},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME, S_FALSE},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY, S_FALSE},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_FORCEAPPLY | URL_APPLY_DEFAULT, S_OK, "http://http://www.winehq.org"},
{"http://www.winehq.org", URL_APPLY_GUESSSCHEME | URL_APPLY_DEFAULT, S_FALSE},
{"", URL_APPLY_DEFAULT, S_OK, "http://"},
{"u:\\windows", URL_APPLY_GUESSFILE | URL_APPLY_DEFAULT, S_OK, "file:///u:/windows"},
{"u:\\windows", URL_APPLY_GUESSFILE, S_OK, "file:///u:/windows"},
{"u:\\windows", URL_APPLY_DEFAULT, S_OK, "http://u:\\windows"},
{"file:///c:/windows", URL_APPLY_GUESSFILE, S_FALSE},
{"aa:\\windows", URL_APPLY_GUESSFILE, S_FALSE},
{"\\\\server\\share", URL_APPLY_DEFAULT, S_OK, "http://\\\\server\\share"},
{"\\\\server\\share", URL_APPLY_GUESSFILE, S_OK, "file://server/share"},
{"\\\\server\\share", URL_APPLY_GUESSSCHEME, S_FALSE},
{"file://server/share", URL_APPLY_GUESSFILE, S_FALSE},
{"file://server/share", URL_APPLY_GUESSSCHEME, S_FALSE},
}
#define URL_APPLY_FORCEAPPLY
Definition: shlwapi.h:520
#define URL_APPLY_GUESSSCHEME
Definition: shlwapi.h:518
#define URL_APPLY_DEFAULT
Definition: shlwapi.h:517
#define URL_APPLY_GUESSFILE
Definition: shlwapi.h:519

Definition at line 48 of file url.c.

Referenced by test_UrlApplyScheme().

◆ TEST_COMBINE

const TEST_URL_COMBINE TEST_COMBINE[]
static

Definition at line 199 of file url.c.

Referenced by test_UrlCombine().

◆ TEST_ESCAPE

const TEST_URL_ESCAPE TEST_ESCAPE[]
static

Definition at line 83 of file url.c.

Referenced by test_UrlEscapeA(), and test_UrlEscapeW().

◆ TEST_ESCAPEW

const TEST_URL_ESCAPEW TEST_ESCAPEW[]
static
Initial value:
= {
{L" <>\"", URL_ESCAPE_AS_UTF8, L"%20%3C%3E%22"},
{L"{}|\\", URL_ESCAPE_AS_UTF8, L"%7B%7D%7C%5C"},
{L"^][`", URL_ESCAPE_AS_UTF8, L"%5E%5D%5B%60"},
{L"&/?#", URL_ESCAPE_AS_UTF8, L"%26/?#"},
{L"Mass", URL_ESCAPE_AS_UTF8, L"Mass"},
{L"Ma\xdf", URL_ESCAPE_AS_UTF8, L"Ma%C3%9F", L"Ma%DF"},
{L"\xd841\xdf0e", URL_ESCAPE_AS_UTF8, L"%F0%A0%9C%8E", L"%EF%BF%BD%EF%BF%BD"},
{L"\xd85e\xde3e", URL_ESCAPE_AS_UTF8, L"%F0%A7%A8%BE", L"%EF%BF%BD%EF%BF%BD"},
{L"\xd85e", URL_ESCAPE_AS_UTF8, L"%EF%BF%BD", L"\xd85e"},
{L"\xd85eQ", URL_ESCAPE_AS_UTF8, L"%EF%BF%BDQ", L"\xd85eQ"},
{L"\xdc00", URL_ESCAPE_AS_UTF8, L"%EF%BF%BD", L"\xdc00"},
{L"\xffff", URL_ESCAPE_AS_UTF8, L"%EF%BF%BF", L"\xffff"},
}

Definition at line 173 of file url.c.

Referenced by test_UrlEscapeW().

◆ 

const struct { ... } TEST_PATH_IS_URL[]
Initial value:
= {
{"http://foo/bar", TRUE},
{"c:\\foo\\bar", FALSE},
{"foo://foo/bar", TRUE},
{"foo\\bar", FALSE},
{"foo.bar", FALSE},
{"bogusscheme:", TRUE},
{"http:partial", TRUE}
}

Referenced by test_UrlIs().

◆ TEST_URL_1

const char* TEST_URL_1 = "http://www.winehq.org/tests?date=10/10/1923"
static

Definition at line 33 of file url.c.

Referenced by test_UrlHash().

◆ TEST_URL_2

const char* TEST_URL_2 = "http://localhost:8080/tests%2e.html?date=Mon%2010/10/1923"
static

Definition at line 34 of file url.c.

Referenced by test_UrlHash().

◆ TEST_URL_3

const char* TEST_URL_3 = "http://foo:bar@localhost:21/internal.php?query=x&return=y"
static

Definition at line 35 of file url.c.

Referenced by test_UrlHash().

◆ 

struct { ... } TEST_URL_UNESCAPE[]
Initial value:
= {
{"file://foo/bar", "file://foo/bar"},
{"file://fo%20o%5Ca/bar", "file://fo o\\a/bar"},
{"file://%24%25foobar", "file://$%foobar"}
}

Referenced by test_UrlUnescape().

◆ 

struct { ... } TEST_URL_UNESCAPEW[]
Initial value:
=
{
{ L"file://foo/bar", L"file://foo/bar" },
{ L"file://fo%20o%5Ca/bar", L"file://fo o\\a/bar" },
{ L"file://%24%25foobar", L"file://$%foobar" },
{ L"file:///C:/Program Files", L"file:///C:/Program Files" },
{ L"file:///C:/Program Files", L"file:///C:/Program Files", URL_UNESCAPE_AS_UTF8 },
{ L"file:///C:/Program%20Files", L"file:///C:/Program Files" },
{ L"file:///C:/Program%20Files", L"file:///C:/Program Files", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%E4%B8%AD%E6%96%87/bar", L"file://foo/\xe4\xb8\xad\xe6\x96\x87/bar" },
{ L"file://foo/%E4%B8%AD%E6%96%87/bar", L"file://foo/\x4e2d\x6587/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%E4%AD%E6%96%87/bar", L"file://foo/\xfffd\x6587/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%F0%9F%8D%B7/bar", L"file://foo/\xf0\x9f\x8d\xb7/bar" },
{ L"file://foo/%F0%9F%8D%B7/bar", L"file://foo/\xd83c\xdf77/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%E4%B8%ADabc%E6%96%87/bar", L"file://foo/\x4e2d""abc""\x6587/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%E4B8%AD/bar", L"file://foo/\xfffd""B8\xfffd/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%E4%G8%AD/bar", L"file://foo/\xfffd""%G8\xfffd/bar", URL_UNESCAPE_AS_UTF8 },
{ L"file://foo/%G4%B8%AD/bar", L"file://foo/%G4\xfffd\xfffd/bar", URL_UNESCAPE_AS_UTF8 },
}

Referenced by test_UrlUnescape().

◆ 

const struct { ... } TEST_URLFROMPATH[]
Initial value:
= {
{"foo", "file:foo", S_OK},
{"foo\\bar", "file:foo/bar", S_OK},
{"\\foo\\bar", "file:///foo/bar", S_OK},
{"c:\\foo\\bar", "file:///c:/foo/bar", S_OK},
{"c:foo\\bar", "file:///c:foo/bar", S_OK},
{"c:\\foo/b a%r", "file:///c:/foo/b%20a%25r", S_OK},
{"c:\\foo\\foo bar", "file:///c:/foo/foo%20bar", S_OK},
{"file:///c:/foo/bar", "file:///c:/foo/bar", S_FALSE},
{"xx:c:\\foo\\bar", "xx:c:\\foo\\bar", S_FALSE}
}

Referenced by test_UrlCreateFromPath().

◆ 

const struct { ... } TEST_URLIS_ATTRIBS[]
Initial value:
= {
{ "ftp:", FALSE, FALSE },
{ "http:", FALSE, FALSE },
{ "gopher:", FALSE, FALSE },
{ "mailto:", TRUE, FALSE },
{ "news:", FALSE, FALSE },
{ "nntp:", FALSE, FALSE },
{ "telnet:", FALSE, FALSE },
{ "wais:", FALSE, FALSE },
{ "file:", FALSE, TRUE },
{ "mk:", FALSE, FALSE },
{ "https:", FALSE, FALSE },
{ "shell:", TRUE, FALSE },
{ "https:", FALSE, FALSE },
{ "snews:", FALSE, FALSE },
{ "local:", FALSE, FALSE },
{ "javascript:", TRUE, FALSE },
{ "vbscript:", TRUE, FALSE },
{ "about:", TRUE, FALSE },
{ "res:", FALSE, FALSE },
{ "bogusscheme:", FALSE, FALSE },
{ "file:\\\\e:\\b\\c", FALSE, TRUE },
{ "file://e:/b/c", FALSE, TRUE },
{ "http:partial", FALSE, FALSE },
{ "mailto://www.winehq.org/test.html", TRUE, FALSE },
{ "file:partial", FALSE, TRUE },
{ "File:partial", FALSE, TRUE },
}

Referenced by test_UrlIs().

◆ untouchedA

const CHAR untouchedA[] = "untouched"
static

Definition at line 39 of file url.c.

Referenced by test_UrlApplyScheme().

◆ url

const char* url

Definition at line 268 of file url.c.

◆ winehqA

const char winehqA[] = "http://www.winehq.org/"
static

Definition at line 38 of file url.c.

Referenced by test_UrlCanonicalizeA().

◆ winehqW

const WCHAR winehqW[] = L"http://www.winehq.org/"
static

Definition at line 37 of file url.c.

Referenced by test_UrlCanonicalizeW().