4 * Copyright 2000 Huw D M Davies for CodeWeavers.
12 #include "debugtools.h"
14 DEFAULT_DEBUG_CHANNEL(shell);
16 static BOOL URL_NeedEscape(CHAR ch, DWORD dwFlags)
22 if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
29 if (ch <= 31 || ch >= 127)
55 /*************************************************************************
56 * UrlCanonicalizeA [SHLWAPI]
58 HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
59 LPDWORD pcchCanonicalized, DWORD dwFlags)
66 TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszCanonicalized,
67 pcchCanonicalized, dwFlags);
69 nLen = strlen(pszUrl);
70 lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nLen + 1);
72 if (dwFlags & URL_DONT_SIMPLIFY)
73 memcpy(lpszUrlCpy, pszUrl, nLen + 1);
75 FIXME("Simplify path\n");
76 memcpy(lpszUrlCpy, pszUrl, nLen + 1);
79 if(dwFlags & URL_UNESCAPE)
80 UrlUnescapeA(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
82 if(dwFlags & (URL_ESCAPE_UNSAFE | URL_ESCAPE_SPACES_ONLY)) {
83 DWORD EscapeFlags = dwFlags & (URL_ESCAPE_SPACES_ONLY
84 /* | URL_ESCAPE_PERCENT */);
85 hr = UrlEscapeA(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
87 } else { /* No escapping needed, just copy the string */
88 nLen = strlen(lpszUrlCpy);
89 if(nLen < *pcchCanonicalized)
90 memcpy(pszCanonicalized, lpszUrlCpy, nLen + 1);
95 *pcchCanonicalized = nLen;
98 HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
103 /*************************************************************************
104 * UrlCanonicalizeW [SHLWAPI]
106 HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
107 LPDWORD pcchCanonicalized, DWORD dwFlags)
109 FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
110 pszCanonicalized, pcchCanonicalized, dwFlags);
114 /*************************************************************************
115 * UrlEscapeA [SHLWAPI]
117 * Converts unsafe characters into their escape sequences.
119 * The converted string is returned in pszEscaped if the buffer size
120 * (which should be supplied in pcchEscaped) is large enough, in this
121 * case the function returns S_OK and pcchEscaped contains the length
122 * of the escaped string. If the buffer is not large enough the
123 * function returns E_POINTER and pcchEscaped contains the required
124 * buffer size (including room for the '\0').
126 * By default the function stops converting at the first '?' or
127 * '#'. [MSDN says differently]. If URL_ESCAPE_SPACE_ONLY flag is set
128 * then only spaces are converted, but the conversion continues past a
133 * None of the URL_ define values are documented, so they were
134 * determined by trial and error. MSDN mentions URL_ESCAPE_PERCENT
135 * but I can't find a value that does this under win2000.
136 * URL_DONT_ESCAPE_EXTRA_INFO appears to be the default which is what
137 * we assume here. URL_ESCAPE_SEGMENT_ONLY is not implemented
138 * (value??). A value of 0x2000 for dwFlags seems to escape
139 * '/'s too - this is neither documented on MSDN nor implemented here.
140 * For character values that are converted see URL_NeedEscape.
142 HRESULT WINAPI UrlEscapeA(
149 DWORD needed = 0, ret;
150 BOOL stop_escapping = FALSE;
151 char next[3], *dst = pszEscaped;
152 char hex[] = "0123456789ABCDEF";
155 TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszEscaped,
156 pcchEscaped, dwFlags);
158 if(dwFlags & ~URL_ESCAPE_SPACES_ONLY)
159 FIXME("Unimplemented flags: %08lx\n", dwFlags);
161 for(src = pszUrl; *src; src++) {
162 if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
163 (*src == '#' || *src == '?'))
164 stop_escapping = TRUE;
166 if(URL_NeedEscape(*src, dwFlags) && stop_escapping == FALSE) {
168 next[1] = hex[(*src >> 4) & 0xf];
169 next[2] = hex[*src & 0xf];
176 if(needed + len <= *pcchEscaped) {
177 memcpy(dst, next, len);
183 if(needed < *pcchEscaped) {
187 needed++; /* add one for the '\0' */
190 *pcchEscaped = needed;
194 /*************************************************************************
195 * UrlEscapeW [SHLWAPI]
197 HRESULT WINAPI UrlEscapeW(
203 FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
204 pszEscaped, pcchEscaped, dwFlags);
209 /*************************************************************************
210 * UrlUnescapeA [SHLWAPI]
212 * Converts escape sequences back to ordinary characters.
214 * If URL_ESCAPE_INPLACE is set in dwFlags then pszUnescaped and
215 * pcchUnescaped are ignored and the converted string is returned in
216 * pszUrl, otherwise the string is returned in pszUnescaped.
217 * pcchUnescaped should contain the size of pszUnescaped on calling
218 * and will contain the length the the returned string on return if
219 * the buffer is big enough else it will contain the buffer size
220 * required (including room for the '\0'). The function returns S_OK
221 * on success or E_POINTER if the buffer is not large enough. If the
222 * URL_DONT_ESCAPE_EXTRA_INFO flag is set then the conversion stops at
223 * the first occurrence of either '?' or '#'.
226 HRESULT WINAPI UrlUnescapeA(
229 LPDWORD pcchUnescaped,
236 BOOL stop_unescapping = FALSE;
238 TRACE("(%s, %p, %p, %08lx): stub\n", debugstr_a(pszUrl), pszUnescaped,
239 pcchUnescaped, dwFlags);
241 if(dwFlags & URL_UNESCAPE_INPLACE)
246 for(src = pszUrl, needed = 0; *src; src++, needed++) {
247 if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
248 (*src == '#' || *src == '?')) {
249 stop_unescapping = TRUE;
251 } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
252 && stop_unescapping == FALSE) {
255 memcpy(buf, src + 1, 2);
257 ih = strtol(buf, NULL, 16);
259 src += 2; /* Advance to end of escape */
263 if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
267 if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
271 needed++; /* add one for the '\0' */
274 if(!(dwFlags & URL_UNESCAPE_INPLACE))
275 *pcchUnescaped = needed;
280 /*************************************************************************
281 * UrlUnescapeW [SHLWAPI]
283 HRESULT WINAPI UrlUnescapeW(
286 LPDWORD pcchUnescaped,
289 FIXME("(%s, %p, %p, %08lx): stub\n", debugstr_w(pszUrl), pszUnescaped,
290 pcchUnescaped, dwFlags);