source: trunk/src/shlwapi/url.c@ 5753

Last change on this file since 5753 was 5753, checked in by sandervl, 24 years ago

added/implemented functions

File size: 10.4 KB
Line 
1/*
2 * Url functions
3 *
4 * Copyright 2000 Huw D M Davies for CodeWeavers.
5 */
6
7#include <string.h>
8#include "windef.h"
9#include "winbase.h"
10#include "winerror.h"
11#include "shlwapi.h"
12#include "debugtools.h"
13
14#ifdef __WIN32OS2__
15#undef FIXME
16#ifdef DEBUG
17#define FIXME WriteLog("FIXME %s", __FUNCTION__); WriteLog
18#else
19#define FIXME 1 ? (void)0 : (void)((int (*)(char *, ...)) NULL)
20#endif
21#endif
22
23DEFAULT_DEBUG_CHANNEL(shell);
24
25static const unsigned char HashDataLookup[256] = {
26 0x01, 0x0E, 0x6E, 0x19, 0x61, 0xAE, 0x84, 0x77, 0x8A, 0xAA, 0x7D, 0x76, 0x1B,
27 0xE9, 0x8C, 0x33, 0x57, 0xC5, 0xB1, 0x6B, 0xEA, 0xA9, 0x38, 0x44, 0x1E, 0x07,
28 0xAD, 0x49, 0xBC, 0x28, 0x24, 0x41, 0x31, 0xD5, 0x68, 0xBE, 0x39, 0xD3, 0x94,
29 0xDF, 0x30, 0x73, 0x0F, 0x02, 0x43, 0xBA, 0xD2, 0x1C, 0x0C, 0xB5, 0x67, 0x46,
30 0x16, 0x3A, 0x4B, 0x4E, 0xB7, 0xA7, 0xEE, 0x9D, 0x7C, 0x93, 0xAC, 0x90, 0xB0,
31 0xA1, 0x8D, 0x56, 0x3C, 0x42, 0x80, 0x53, 0x9C, 0xF1, 0x4F, 0x2E, 0xA8, 0xC6,
32 0x29, 0xFE, 0xB2, 0x55, 0xFD, 0xED, 0xFA, 0x9A, 0x85, 0x58, 0x23, 0xCE, 0x5F,
33 0x74, 0xFC, 0xC0, 0x36, 0xDD, 0x66, 0xDA, 0xFF, 0xF0, 0x52, 0x6A, 0x9E, 0xC9,
34 0x3D, 0x03, 0x59, 0x09, 0x2A, 0x9B, 0x9F, 0x5D, 0xA6, 0x50, 0x32, 0x22, 0xAF,
35 0xC3, 0x64, 0x63, 0x1A, 0x96, 0x10, 0x91, 0x04, 0x21, 0x08, 0xBD, 0x79, 0x40,
36 0x4D, 0x48, 0xD0, 0xF5, 0x82, 0x7A, 0x8F, 0x37, 0x69, 0x86, 0x1D, 0xA4, 0xB9,
37 0xC2, 0xC1, 0xEF, 0x65, 0xF2, 0x05, 0xAB, 0x7E, 0x0B, 0x4A, 0x3B, 0x89, 0xE4,
38 0x6C, 0xBF, 0xE8, 0x8B, 0x06, 0x18, 0x51, 0x14, 0x7F, 0x11, 0x5B, 0x5C, 0xFB,
39 0x97, 0xE1, 0xCF, 0x15, 0x62, 0x71, 0x70, 0x54, 0xE2, 0x12, 0xD6, 0xC7, 0xBB,
40 0x0D, 0x20, 0x5E, 0xDC, 0xE0, 0xD4, 0xF7, 0xCC, 0xC4, 0x2B, 0xF9, 0xEC, 0x2D,
41 0xF4, 0x6F, 0xB6, 0x99, 0x88, 0x81, 0x5A, 0xD9, 0xCA, 0x13, 0xA5, 0xE7, 0x47,
42 0xE6, 0x8E, 0x60, 0xE3, 0x3E, 0xB3, 0xF6, 0x72, 0xA2, 0x35, 0xA0, 0xD7, 0xCD,
43 0xB4, 0x2F, 0x6D, 0x2C, 0x26, 0x1F, 0x95, 0x87, 0x00, 0xD8, 0x34, 0x3F, 0x17,
44 0x25, 0x45, 0x27, 0x75, 0x92, 0xB8, 0xA3, 0xC8, 0xDE, 0xEB, 0xF8, 0xF3, 0xDB,
45 0x0A, 0x98, 0x83, 0x7B, 0xE5, 0xCB, 0x4C, 0x78, 0xD1 };
46
47static BOOL URL_NeedEscape(CHAR ch, DWORD dwFlags)
48{
49
50 if (isalnum(ch))
51 return FALSE;
52
53 if(dwFlags & URL_ESCAPE_SPACES_ONLY) {
54 if(ch == ' ')
55 return TRUE;
56 else
57 return FALSE;
58 }
59
60 if (ch <= 31 || ch >= 127)
61 return TRUE;
62
63 else {
64 switch (ch) {
65 case ' ':
66 case '<':
67 case '>':
68 case '\"':
69 case '{':
70 case '}':
71 case '|':
72 case '\\':
73 case '^':
74 case ']':
75 case '[':
76 case '`':
77 case '&':
78 return TRUE;
79
80 default:
81 return FALSE;
82 }
83 }
84}
85
86/*************************************************************************
87 * UrlCanonicalizeA [SHLWAPI]
88 */
89HRESULT WINAPI UrlCanonicalizeA(LPCSTR pszUrl, LPSTR pszCanonicalized,
90 LPDWORD pcchCanonicalized, DWORD dwFlags)
91{
92 HRESULT hr = S_OK;
93
94 LPSTR lpszUrlCpy;
95 INT nLen;
96
97 TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszCanonicalized,
98 pcchCanonicalized, dwFlags);
99
100 nLen = strlen(pszUrl);
101 lpszUrlCpy = HeapAlloc(GetProcessHeap(), 0, nLen + 1);
102
103 if (dwFlags & URL_DONT_SIMPLIFY)
104 memcpy(lpszUrlCpy, pszUrl, nLen + 1);
105 else {
106 FIXME("Simplify path\n");
107 memcpy(lpszUrlCpy, pszUrl, nLen + 1);
108 }
109
110 if(dwFlags & URL_UNESCAPE)
111 UrlUnescapeA(lpszUrlCpy, NULL, NULL, URL_UNESCAPE_INPLACE);
112
113 if(dwFlags & (URL_ESCAPE_UNSAFE | URL_ESCAPE_SPACES_ONLY)) {
114 DWORD EscapeFlags = dwFlags & (URL_ESCAPE_SPACES_ONLY
115 /* | URL_ESCAPE_PERCENT */);
116 hr = UrlEscapeA(lpszUrlCpy, pszCanonicalized, pcchCanonicalized,
117 EscapeFlags);
118 } else { /* No escapping needed, just copy the string */
119 nLen = strlen(lpszUrlCpy);
120 if(nLen < *pcchCanonicalized)
121 memcpy(pszCanonicalized, lpszUrlCpy, nLen + 1);
122 else {
123 hr = E_POINTER;
124 nLen++;
125 }
126 *pcchCanonicalized = nLen;
127 }
128
129 HeapFree(GetProcessHeap(), 0, lpszUrlCpy);
130
131 return hr;
132}
133
134/*************************************************************************
135 * UrlCanonicalizeW [SHLWAPI]
136 */
137HRESULT WINAPI UrlCanonicalizeW(LPCWSTR pszUrl, LPWSTR pszCanonicalized,
138 LPDWORD pcchCanonicalized, DWORD dwFlags)
139{
140 FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
141 pszCanonicalized, pcchCanonicalized, dwFlags);
142 return E_NOTIMPL;
143}
144
145/*************************************************************************
146 * UrlEscapeA [SHLWAPI]
147 *
148 * Converts unsafe characters into their escape sequences.
149 *
150 * The converted string is returned in pszEscaped if the buffer size
151 * (which should be supplied in pcchEscaped) is large enough, in this
152 * case the function returns S_OK and pcchEscaped contains the length
153 * of the escaped string. If the buffer is not large enough the
154 * function returns E_POINTER and pcchEscaped contains the required
155 * buffer size (including room for the '\0').
156 *
157 * By default the function stops converting at the first '?' or
158 * '#'. [MSDN says differently]. If URL_ESCAPE_SPACE_ONLY flag is set
159 * then only spaces are converted, but the conversion continues past a
160 * '?' or '#'.
161 *
162 * BUGS:
163 *
164 * None of the URL_ define values are documented, so they were
165 * determined by trial and error. MSDN mentions URL_ESCAPE_PERCENT
166 * but I can't find a value that does this under win2000.
167 * URL_DONT_ESCAPE_EXTRA_INFO appears to be the default which is what
168 * we assume here. URL_ESCAPE_SEGMENT_ONLY is not implemented
169 * (value??). A value of 0x2000 for dwFlags seems to escape
170 * '/'s too - this is neither documented on MSDN nor implemented here.
171 * For character values that are converted see URL_NeedEscape.
172 */
173HRESULT WINAPI UrlEscapeA(
174 LPCSTR pszUrl,
175 LPSTR pszEscaped,
176 LPDWORD pcchEscaped,
177 DWORD dwFlags)
178{
179 LPCSTR src;
180 DWORD needed = 0, ret;
181 BOOL stop_escapping = FALSE;
182 char next[3], *dst = pszEscaped;
183 char hex[] = "0123456789ABCDEF";
184 INT len;
185
186 TRACE("(%s %p %p 0x%08lx)\n", debugstr_a(pszUrl), pszEscaped,
187 pcchEscaped, dwFlags);
188
189 if(dwFlags & ~URL_ESCAPE_SPACES_ONLY)
190 FIXME("Unimplemented flags: %08lx\n", dwFlags);
191
192 for(src = pszUrl; *src; src++) {
193 if(!(dwFlags & URL_ESCAPE_SPACES_ONLY) &&
194 (*src == '#' || *src == '?'))
195 stop_escapping = TRUE;
196
197 if(URL_NeedEscape(*src, dwFlags) && stop_escapping == FALSE) {
198 next[0] = '%';
199 next[1] = hex[(*src >> 4) & 0xf];
200 next[2] = hex[*src & 0xf];
201 len = 3;
202 } else {
203 next[0] = *src;
204 len = 1;
205 }
206
207 if(needed + len <= *pcchEscaped) {
208 memcpy(dst, next, len);
209 dst += len;
210 }
211 needed += len;
212 }
213
214 if(needed < *pcchEscaped) {
215 *dst = '\0';
216 ret = S_OK;
217 } else {
218 needed++; /* add one for the '\0' */
219 ret = E_POINTER;
220 }
221 *pcchEscaped = needed;
222 return ret;
223}
224
225/*************************************************************************
226 * UrlEscapeW [SHLWAPI]
227 */
228HRESULT WINAPI UrlEscapeW(
229 LPCWSTR pszUrl,
230 LPWSTR pszEscaped,
231 LPDWORD pcchEscaped,
232 DWORD dwFlags)
233{
234 FIXME("(%s %p %p 0x%08lx): stub\n",debugstr_w(pszUrl),
235 pszEscaped, pcchEscaped, dwFlags);
236 return E_NOTIMPL;
237}
238
239
240/*************************************************************************
241 * UrlUnescapeA [SHLWAPI]
242 *
243 * Converts escape sequences back to ordinary characters.
244 *
245 * If URL_ESCAPE_INPLACE is set in dwFlags then pszUnescaped and
246 * pcchUnescaped are ignored and the converted string is returned in
247 * pszUrl, otherwise the string is returned in pszUnescaped.
248 * pcchUnescaped should contain the size of pszUnescaped on calling
249 * and will contain the length the the returned string on return if
250 * the buffer is big enough else it will contain the buffer size
251 * required (including room for the '\0'). The function returns S_OK
252 * on success or E_POINTER if the buffer is not large enough. If the
253 * URL_DONT_ESCAPE_EXTRA_INFO flag is set then the conversion stops at
254 * the first occurrence of either '?' or '#'.
255 *
256 */
257HRESULT WINAPI UrlUnescapeA(
258 LPCSTR pszUrl,
259 LPSTR pszUnescaped,
260 LPDWORD pcchUnescaped,
261 DWORD dwFlags)
262{
263 char *dst, next;
264 LPCSTR src;
265 HRESULT ret;
266 DWORD needed;
267 BOOL stop_unescapping = FALSE;
268
269 TRACE("(%s, %p, %p, %08lx): stub\n", debugstr_a(pszUrl), pszUnescaped,
270 pcchUnescaped, dwFlags);
271
272 if(dwFlags & URL_UNESCAPE_INPLACE)
273 dst = (char*)pszUrl;
274 else
275 dst = pszUnescaped;
276
277 for(src = pszUrl, needed = 0; *src; src++, needed++) {
278 if(dwFlags & URL_DONT_UNESCAPE_EXTRA_INFO &&
279 (*src == '#' || *src == '?')) {
280 stop_unescapping = TRUE;
281 next = *src;
282 } else if(*src == '%' && isxdigit(*(src + 1)) && isxdigit(*(src + 2))
283 && stop_unescapping == FALSE) {
284 INT ih;
285 char buf[3];
286 memcpy(buf, src + 1, 2);
287 buf[2] = '\0';
288 ih = strtol(buf, NULL, 16);
289 next = (CHAR) ih;
290 src += 2; /* Advance to end of escape */
291 } else
292 next = *src;
293
294 if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped)
295 *dst++ = next;
296 }
297
298 if(dwFlags & URL_UNESCAPE_INPLACE || needed < *pcchUnescaped) {
299 *dst = '\0';
300 ret = S_OK;
301 } else {
302 needed++; /* add one for the '\0' */
303 ret = E_POINTER;
304 }
305 if(!(dwFlags & URL_UNESCAPE_INPLACE))
306 *pcchUnescaped = needed;
307
308 return ret;
309}
310
311/*************************************************************************
312 * UrlUnescapeW [SHLWAPI]
313 */
314HRESULT WINAPI UrlUnescapeW(
315 LPCWSTR pszUrl,
316 LPWSTR pszUnescaped,
317 LPDWORD pcchUnescaped,
318 DWORD dwFlags)
319{
320 FIXME("(%s, %p, %p, %08lx): stub\n", debugstr_w(pszUrl), pszUnescaped,
321 pcchUnescaped, dwFlags);
322 return E_NOTIMPL;
323}
324
325/*************************************************************************
326 * HashData [SHLWAPI]
327 *
328 * Hash an input block into a variable sized digest.
329 */
330BOOL WINAPI HashData(const unsigned char *lpSrc, INT nSrcLen,
331 unsigned char *lpDest, INT nDestLen)
332{
333 INT srcCount = nSrcLen - 1, destCount = nDestLen - 1;
334
335 if (IsBadReadPtr(lpSrc, nSrcLen) ||
336 IsBadWritePtr(lpDest, nDestLen))
337 return FALSE;
338
339 while (destCount >= 0)
340 {
341 lpDest[destCount] = (destCount & 0xff);
342 destCount--;
343 }
344
345 while (srcCount >= 0)
346 {
347 destCount = nDestLen - 1;
348 while (destCount >= 0)
349 {
350 lpDest[destCount] = HashDataLookup[lpSrc[srcCount] ^ lpDest[destCount]];
351 destCount--;
352 }
353 srcCount--;
354 }
355 return TRUE;
356}
357
358/*************************************************************************
359 * UrlHashA [SHLWAPI]
360 *
361 * Hash an ASCII URL.
362 */
363HRESULT WINAPI UrlHashA(LPCSTR pszUrl, unsigned char *lpDest, INT nDestLen)
364{
365 if (IsBadStringPtrA(pszUrl, -1) || IsBadWritePtr(lpDest, nDestLen))
366 return E_INVALIDARG;
367
368 HashData(pszUrl, strlen(pszUrl), lpDest, nDestLen);
369 return NOERROR;
370}
371
Note: See TracBrowser for help on using the repository browser.