From f6c7222fce96191723532dff8fe5e1bc9a3c8bbf Mon Sep 17 00:00:00 2001 From: Huw D M Davies Date: Fri, 5 Jan 2001 22:22:57 +0000 Subject: [PATCH] Implemented a few Url* functions. --- dlls/shlwapi/Makefile.in | 3 +- dlls/shlwapi/ordinal.c | 28 ---- dlls/shlwapi/shlwapi.spec | 8 +- dlls/shlwapi/url.c | 291 ++++++++++++++++++++++++++++++++++++++ include/shlwapi.h | 39 +++++ 5 files changed, 336 insertions(+), 33 deletions(-) create mode 100644 dlls/shlwapi/url.c diff --git a/dlls/shlwapi/Makefile.in b/dlls/shlwapi/Makefile.in index 0ed6fd8742e..43aae007419 100644 --- a/dlls/shlwapi/Makefile.in +++ b/dlls/shlwapi/Makefile.in @@ -14,7 +14,8 @@ C_SRCS = \ reg.c \ regstream.c \ shlwapi_main.c \ - string.c + string.c \ + url.c @MAKE_DLL_RULES@ diff --git a/dlls/shlwapi/ordinal.c b/dlls/shlwapi/ordinal.c index b1e597d182f..f72b683d899 100644 --- a/dlls/shlwapi/ordinal.c +++ b/dlls/shlwapi/ordinal.c @@ -447,34 +447,6 @@ DWORD WINAPI SHLWAPI_437 (DWORD x) return 0xabba1247; } -/************************************************************************* - * UrlEscapeA [SHLWAPI] - */ -HRESULT WINAPI UrlEscapeA( - LPCSTR pszUrl, - LPSTR pszEscaped, - LPDWORD pcchEscaped, - DWORD dwFlags) -{ - FIXME("(%s %p %p 0x%08lx)stub\n",debugstr_a(pszUrl), - pszEscaped, pcchEscaped, dwFlags); - return 0; -} - -/************************************************************************* - * UrlEscapeW [SHLWAPI] - */ -HRESULT WINAPI UrlEscapeW( - LPCWSTR pszUrl, - LPWSTR pszEscaped, - LPDWORD pcchEscaped, - DWORD dwFlags) -{ - FIXME("(%s %p %p 0x%08lx)stub\n",debugstr_w(pszUrl), - pszEscaped, pcchEscaped, dwFlags); - return 0; -} - /************************************************************************* * SHCreateShellPalette [SHLWAPI.@] diff --git a/dlls/shlwapi/shlwapi.spec b/dlls/shlwapi/shlwapi.spec index 292c23eaca8..b50f74993eb 100644 --- a/dlls/shlwapi/shlwapi.spec +++ b/dlls/shlwapi/shlwapi.spec @@ -663,8 +663,8 @@ debug_channels (shell) @ stub StrTrimW @ stub UrlApplySchemeA @ stub UrlApplySchemeW -@ stub UrlCanonicalizeA -@ stub UrlCanonicalizeW +@ stdcall UrlCanonicalizeA(str ptr ptr long) UrlCanonicalizeA +@ stdcall UrlCanonicalizeW(wstr ptr ptr long) UrlCanonicalizeW @ stub UrlCombineA @ stub UrlCombineW @ stub UrlCompareA @@ -685,8 +685,8 @@ debug_channels (shell) @ stub UrlIsOpaqueA @ stub UrlIsOpaqueW @ stub UrlIsW -@ stub UrlUnescapeA -@ stub UrlUnescapeW +@ stdcall UrlUnescapeA(str ptr ptr long) UrlUnescapeA +@ stdcall UrlUnescapeW(wstr ptr ptr long) UrlUnescapeW @ varargs wnsprintfA(ptr long str)wnsprintfA @ varargs wnsprintfW(ptr long wstr)wnsprintfW diff --git a/dlls/shlwapi/url.c b/dlls/shlwapi/url.c new file mode 100644 index 00000000000..77f79143ce3 --- /dev/null +++ b/dlls/shlwapi/url.c @@ -0,0 +1,291 @@ +/* + * Url functions + * + * Copyright 2000 Huw D M Davies for CodeWeavers. + */ + +#include "windef.h" +#include "winbase.h" +#include "winerror.h" +#include "shlwapi.h" +#include "debugtools.h" + +DEFAULT_DEBUG_CHANNEL(shell); + +static BOOL URL_NeedEscape(CHAR ch, DWORD dwFlags) +{ + + if (isalnum(ch)) + return FALSE; + + if(dwFlags & URL_ESCAPE_SPACES_ONLY) { + if(ch == ' ') + return TRUE; + else + return FALSE; + } + + if (ch <= 31 || ch >= 127) + return TRUE; + + else { + switch (ch) { + case ' ': + case '<': + case '>': + case '\"': + case '{': + case '}': + case '|': + case '\\': + case '^': + case ']': + case '[': + case '`': + case '&': + return TRUE; + + default: + return FALSE; + } + } +} + +/************************************************************************* + * UrlCanonicalizeA [SHLWAPI] + */ +HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized, + LPDWORD pcchCanonicalized, DWORD dwFlags) +{ + HRESULT hr = S_OK; + + LPSTR lpszUrlCpy; + INT nLen; + + TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszCanonicalized, + pcchCanonicalized, dwFlags); + + nLen = strlen(pszUrl); + lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nLen + 1); + + if (dwFlags & URL_DONT_SIMPLIFY) + memcpy(lpszUrlCpy, pszUrl, nLen + 1); + else { + FIXME("Simplify path\n"); + memcpy(lpszUrlCpy, pszUrl, nLen + 1); + } + + if(dwFlags & URL_UNESCAPE) + UrlUnescapeA(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE); + + if(dwFlags & (URL_ESCAPE_UNSAFE | URL_ESCAPE_SPACES_ONLY)) { + DWORD EscapeFlags = dwFlags & (URL_ESCAPE_SPACES_ONLY + /* | URL_ESCAPE_PERCENT */); + hr = UrlEscapeA(lpszUrlCpy, pszCanonicalized, pcchCanonicalized, + EscapeFlags); + } else { /* No escapping needed, just copy the string */ + nLen = strlen(lpszUrlCpy); + if(nLen < *pcchCanonicalized) + memcpy(pszCanonicalized, lpszUrlCpy, nLen + 1); + else { + hr = E_POINTER; + nLen++; + } + *pcchCanonicalized = nLen; + } + + HeapFree(GetProcessHeap(), 0, lpszUrlCpy); + + return hr; +} + +/************************************************************************* + * UrlCanonicalizeW [SHLWAPI] + */ +HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, + LPDWORD pcchCanonicalized, DWORD dwFlags) +{ + FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl), + pszCanonicalized, pcchCanonicalized, dwFlags); + return E_NOTIMPL; +} + +/************************************************************************* + * UrlEscapeA [SHLWAPI] + * + * Converts unsafe characters into their escape sequences. + * + * The converted string is returned in pszEscaped if the buffer size + * (which should be supplied in pcchEscaped) is large enough, in this + * case the function returns S_OK and pcchEscaped contains the length + * of the escaped string. If the buffer is not large enough the + * function returns E_POINTER and pcchEscaped contains the required + * buffer size (including room for the '\0'). + * + * By default the function stops converting at the first '?' or + * '#'. [MSDN says differently]. If URL_ESCAPE_SPACE_ONLY flag is set + * then only spaces are converted, but the conversion continues past a + * '?' or '#'. + * + * BUGS: + * + * None of the URL_ define values are documented, so they were + * determined by trial and error. MSDN mentions URL_ESCAPE_PERCENT + * but I can't find a value that does this under win2000. + * URL_DONT_ESCAPE_EXTRA_INFO appears to be the default which is what + * we assume here. URL_ESCAPE_SEGMENT_ONLY is not implemented + * (value??). A value of 0x2000 for dwFlags seems to escape + * '/'s too - this is neither documented on MSDN nor implemented here. + * For character values that are converted see URL_NeedEscape. + */ +HRESULT WINAPI UrlEscapeA( + LPCSTR pszUrl, + LPSTR pszEscaped, + LPDWORD pcchEscaped, + DWORD dwFlags) +{ + LPCSTR src; + DWORD needed = 0, ret; + BOOL stop_escapping = FALSE; + char next[3], *dst = pszEscaped; + char hex[] = "0123456789ABCDEF"; + INT len; + + TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszEscaped, + pcchEscaped, dwFlags); + + if(dwFlags & ~URL_ESCAPE_SPACES_ONLY) + FIXME("Unimplemented flags: %08lx\n", dwFlags); + + for(src = pszUrl; *src; src++) { + if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) && + (*src == '#' || *src == '?')) + stop_escapping = TRUE; + + if(URL_NeedEscape(*src, dwFlags) && stop_escapping == FALSE) { + next[0] = '%'; + next[1] = hex[(*src >> 4) & 0xf]; + next[2] = hex[*src & 0xf]; + len = 3; + } else { + next[0] = *src; + len = 1; + } + + if(needed + len <= *pcchEscaped) { + memcpy(dst, next, len); + dst += len; + } + needed += len; + } + + if(needed < *pcchEscaped) { + *dst = '\0'; + ret = S_OK; + } else { + needed++; /* add one for the '\0' */ + ret = E_POINTER; + } + *pcchEscaped = needed; + return ret; +} + +/************************************************************************* + * UrlEscapeW [SHLWAPI] + */ +HRESULT WINAPI UrlEscapeW( + LPCWSTR pszUrl, + LPWSTR pszEscaped, + LPDWORD pcchEscaped, + DWORD dwFlags) +{ + FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl), + pszEscaped, pcchEscaped, dwFlags); + return E_NOTIMPL; +} + + +/************************************************************************* + * UrlUnescapeA [SHLWAPI] + * + * Converts escape sequences back to ordinary characters. + * + * If URL_ESCAPE_INPLACE is set in dwFlags then pszUnescaped and + * pcchUnescaped are ignored and the converted string is returned in + * pszUrl, otherwise the string is returned in pszUnescaped. + * pcchUnescaped should contain the size of pszUnescaped on calling + * and will contain the length the the returned string on return if + * the buffer is big enough else it will contain the buffer size + * required (including room for the '\0'). The function returns S_OK + * on success or E_POINTER if the buffer is not large enough. If the + * URL_DONT_ESCAPE_EXTRA_INFO flag is set then the conversion stops at + * the first occurrence of either '?' or '#'. + * + */ +HRESULT WINAPI UrlUnescapeA( + LPCSTR pszUrl, + LPSTR pszUnescaped, + LPDWORD pcchUnescaped, + DWORD dwFlags) +{ + char *dst, next; + LPCSTR src; + HRESULT ret; + DWORD needed; + BOOL stop_unescapping = FALSE; + + TRACE("(%s, %p, %p, %08lx): stub\n", debugstr_a(pszUrl), pszUnescaped, + pcchUnescaped, dwFlags); + + if(dwFlags & URL_UNESCAPE_INPLACE) + dst = (char*)pszUrl; + else + dst = pszUnescaped; + + for(src = pszUrl, needed = 0; *src; src++, needed++) { + if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO && + (*src == '#' || *src == '?')) { + stop_unescapping = TRUE; + next = *src; + } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2)) + && stop_unescapping == FALSE) { + INT ih; + char buf[3]; + memcpy(buf, src + 1, 2); + buf[2] = '\0'; + ih = strtol(buf, NULL, 16); + next = (CHAR) ih; + src += 2; /* Advance to end of escape */ + } else + next = *src; + + if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) + *dst++ = next; + } + + if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) { + *dst = '\0'; + ret = S_OK; + } else { + needed++; /* add one for the '\0' */ + ret = E_POINTER; + } + if(!(dwFlags & URL_UNESCAPE_INPLACE)) + *pcchUnescaped = needed; + + return ret; +} + +/************************************************************************* + * UrlUnescapeW [SHLWAPI] + */ +HRESULT WINAPI UrlUnescapeW( + LPCWSTR pszUrl, + LPWSTR pszUnescaped, + LPDWORD pcchUnescaped, + DWORD dwFlags) +{ + FIXME("(%s, %p, %p, %08lx): stub\n", debugstr_w(pszUrl), pszUnescaped, + pcchUnescaped, dwFlags); + return E_NOTIMPL; +} diff --git a/include/shlwapi.h b/include/shlwapi.h index a3531c8006d..57e0a6c6192 100644 --- a/include/shlwapi.h +++ b/include/shlwapi.h @@ -7,6 +7,27 @@ extern "C" { #endif /* defined(__cplusplus) */ + +/* + * The URL_ defines were determined by trial and error. If they become + * documented please check them and add the missing ones including: + * + * URL_ESCAPE_PERCENT + * URL_PLUGGABLE_PROTOCOL + * URL_DONT_ESCAPE_EXTRA_INFO + * URL_ESCAPE_SEGMENT_ONLY + */ + +#define URL_UNESCAPE_INPLACE 0x00100000 +#define URL_DONT_UNESCAPE_EXTRA_INFO 0x02000000 + +#define URL_ESCAPE_SPACES_ONLY 0x04000000 + +#define URL_UNESCAPE 0x10000000 +#define URL_ESCAPE_UNSAFE 0x20000000 +#define URL_DONT_SIMPLIFY 0x40000000 + + BOOL WINAPI PathAppendA(LPSTR lpszPath1,LPCSTR lpszPath2); BOOL WINAPI PathAppendW(LPWSTR lpszPath1,LPCWSTR lpszPath2); @@ -130,6 +151,24 @@ DWORD WINAPI SHDeleteEmptyKeyA(HKEY hKey, LPCSTR lpszSubKey); DWORD WINAPI SHDeleteEmptyKeyW(HKEY hKey, LPCWSTR lpszSubKey); #define SHDeleteEmptyKey WINELIB_NAME_AW(SHDeleteEmptyKey) +HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized, + LPDWORD pcchCanonicalized, DWORD dwFlags); +HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized, + LPDWORD pcchCanonicalized, DWORD dwFlags); +#define UrlCanonicalize WINELIB_NAME_AW(UrlCanoncalize) + +HRESULT WINAPI UrlEscapeA(LPCSTR pszUrl, LPSTR pszEscaped, LPDWORD pcchEscaped, + DWORD dwFlags); +HRESULT WINAPI UrlEscapeW(LPCWSTR pszUrl, LPWSTR pszEscaped, + LPDWORD pcchEscaped, DWORD dwFlags); +#define UrlEscape WINELIB_NAME_AW(UrlEscape) + +HRESULT WINAPI UrlUnescapeA(LPCSTR pszUrl, LPSTR pszUnescaped, + LPDWORD pcchUnescaped, DWORD dwFlags); +HRESULT WINAPI UrlUnescapeW(LPCWSTR pszUrl, LPWSTR pszUnescaped, + LPDWORD pcchUnescaped, DWORD dwFlags); +#define UrlUnescape WINELIB_AW_NAME(UrlUnescape) + typedef struct _DllVersionInfo { DWORD cbSize; DWORD dwMajorVersion;