~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

Wine Cross Reference
wine/dlls/winhttp/url.c

Version: ~ [ wine-1.5.30 ] ~ [ wine-1.5.29 ] ~ [ wine-1.5.28 ] ~ [ wine-1.5.27 ] ~ [ wine-1.5.26 ] ~ [ wine-1.5.25 ] ~ [ wine-1.5.24 ] ~ [ wine-1.5.23 ] ~ [ wine-1.5.22 ] ~ [ wine-1.5.21 ] ~ [ wine-1.5.20 ] ~ [ wine-1.5.19 ] ~ [ wine-1.5.18 ] ~ [ wine-1.5.17 ] ~ [ wine-1.5.16 ] ~ [ wine-1.5.15 ] ~ [ wine-1.5.14 ] ~ [ wine-1.5.13 ] ~ [ wine-1.5.12 ] ~ [ wine-1.5.11 ] ~ [ wine-1.5.10 ] ~ [ wine-1.5.9 ] ~ [ wine-1.5.8 ] ~ [ wine-1.5.7 ] ~ [ wine-1.4.1 ] ~ [ wine-1.5.6 ] ~ [ wine-1.5.5 ] ~ [ wine-1.5.4 ] ~ [ wine-1.5.3 ] ~ [ wine-1.5.2 ] ~ [ wine-1.5.1 ] ~ [ wine-1.5.0 ] ~ [ wine-1.4 ] ~ [ wine-1.4-rc6 ] ~ [ wine-1.4-rc5 ] ~ [ wine-1.4-rc4 ] ~ [ wine-1.4-rc3 ] ~ [ wine-1.4-rc2 ] ~ [ wine-1.4-rc1 ] ~ [ wine-1.3.37 ] ~ [ wine-1.3.36 ] ~ [ wine-1.3.35 ] ~ [ wine-1.3.34 ] ~ [ wine-1.3.33 ] ~ [ wine-1.3.32 ] ~ [ wine-1.3.31 ] ~ [ wine-1.3.30 ] ~ [ wine-1.3.29 ] ~ [ wine-1.3.28 ] ~ [ wine-1.3.27 ] ~ [ wine-1.3.26 ] ~ [ wine-1.3.25 ] ~ [ wine-1.3.24 ] ~ [ wine-1.3.23 ] ~ [ wine-1.3.22 ] ~ [ wine-1.3.21 ] ~ [ wine-1.3.20 ] ~ [ wine-1.3.19 ] ~ [ wine-1.3.18 ] ~ [ wine-1.2.3 ] ~ [ wine-1.3.17 ] ~ [ wine-1.3.16 ] ~ [ wine-1.3.15 ] ~ [ wine-1.3.14 ] ~ [ wine-1.3.13 ] ~ [ wine-1.3.12 ] ~ [ wine-1.3.11 ] ~ [ wine-1.3.10 ] ~ [ wine-1.3.9 ] ~ [ wine-1.2.2 ] ~ [ wine-1.3.8 ] ~ [ wine-1.3.7 ] ~ [ wine-1.3.6 ] ~ [ wine-1.3.5 ] ~ [ wine-1.2.1 ] ~ [ wine-1.3.4 ] ~ [ wine-1.3.3 ] ~ [ wine-1.3.2 ] ~ [ wine-1.3.1 ] ~ [ wine-1.3.0 ] ~ [ wine-1.2 ] ~ [ wine-1.2-rc7 ] ~ [ wine-1.2-rc6 ] ~ [ wine-1.2-rc5 ] ~ [ wine-1.2-rc4 ] ~ [ wine-1.2-rc3 ] ~ [ wine-1.2-rc2 ] ~ [ wine-1.2-rc1 ] ~ [ wine-1.1.44 ] ~ [ wine-1.1.43 ] ~ [ wine-1.1.42 ] ~ [ wine-1.1.41 ] ~ [ wine-1.1.40 ] ~ [ wine-1.1.39 ] ~ [ wine-1.1.38 ] ~ [ wine-1.1.37 ] ~ [ wine-1.1.36 ] ~ [ wine-1.1.35 ] ~ [ wine-1.1.34 ] ~ [ wine-1.1.33 ] ~ [ wine-1.1.32 ] ~ [ wine-1.1.31 ] ~ [ wine-1.1.30 ] ~ [ wine-1.1.29 ] ~ [ wine-1.1.28 ] ~ [ wine-1.1.27 ] ~ [ wine-1.1.26 ] ~ [ wine-1.1.25 ] ~ [ wine-1.1.24 ] ~ [ wine-1.1.23 ] ~ [ wine-1.1.22 ] ~ [ wine-1.1.21 ] ~ [ wine-1.1.20 ] ~ [ wine-1.1.19 ] ~ [ wine-1.1.18 ] ~ [ wine-1.1.17 ] ~ [ wine-1.1.16 ] ~ [ wine-1.1.15 ] ~ [ wine-1.1.14 ] ~ [ wine-1.1.13 ] ~ [ wine-1.1.12 ] ~ [ wine-1.1.11 ] ~ [ wine-1.1.10 ] ~ [ wine-1.1.9 ] ~ [ wine-1.1.8 ] ~ [ wine-1.1.7 ] ~ [ wine-1.0.1 ] ~ [ wine-1.1.6 ] ~ [ wine-1.1.5 ] ~ [ wine-1.1.4 ] ~ [ wine-1.1.3 ] ~ [ wine-1.1.2 ] ~ [ wine-1.1.1 ] ~ [ wine-1.1.0 ] ~ [ wine-1.0 ] ~

  1 /*
  2  * Copyright 2008 Hans Leidekker for CodeWeavers
  3  *
  4  * This library is free software; you can redistribute it and/or
  5  * modify it under the terms of the GNU Lesser General Public
  6  * License as published by the Free Software Foundation; either
  7  * version 2.1 of the License, or (at your option) any later version.
  8  *
  9  * This library is distributed in the hope that it will be useful,
 10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
 11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 12  * Lesser General Public License for more details.
 13  *
 14  * You should have received a copy of the GNU Lesser General Public
 15  * License along with this library; if not, write to the Free Software
 16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
 17  */
 18 
 19 #include "config.h"
 20 #include <stdarg.h>
 21 
 22 #include "wine/debug.h"
 23 
 24 #include "windef.h"
 25 #include "winbase.h"
 26 #include "winreg.h"
 27 #include "winhttp.h"
 28 #include "shlwapi.h"
 29 
 30 #include "winhttp_private.h"
 31 
 32 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
 33 
 34 static const WCHAR scheme_http[] = {'h','t','t','p',0};
 35 static const WCHAR scheme_https[] = {'h','t','t','p','s',0};
 36 
 37 static BOOL set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags )
 38 {
 39     if (!*str)
 40     {
 41         if (len && (flags & ICU_DECODE))
 42         {
 43             set_last_error( ERROR_INVALID_PARAMETER );
 44             return FALSE;
 45         }
 46         *str = value;
 47         *str_len = len;
 48     }
 49     else
 50     {
 51         if (len > (*str_len) - 1)
 52         {
 53             *str_len = len + 1;
 54             set_last_error( ERROR_INSUFFICIENT_BUFFER );
 55             return FALSE;
 56         }
 57         memcpy( *str, value, len * sizeof(WCHAR) );
 58         (*str)[len] = 0;
 59         *str_len = len;
 60     }
 61     return TRUE;
 62 }
 63 
 64 static BOOL decode_url( LPCWSTR url, LPWSTR buffer, LPDWORD buflen )
 65 {
 66     HRESULT hr = UrlCanonicalizeW( url, buffer, buflen, URL_WININET_COMPATIBILITY | URL_UNESCAPE );
 67     if (hr == E_POINTER) set_last_error( ERROR_INSUFFICIENT_BUFFER );
 68     if (hr == E_INVALIDARG) set_last_error( ERROR_INVALID_PARAMETER );
 69     return (SUCCEEDED(hr)) ? TRUE : FALSE;
 70 }
 71 
 72 /***********************************************************************
 73  *          WinHttpCrackUrl (winhttp.@)
 74  */
 75 BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc )
 76 {
 77     BOOL ret = FALSE;
 78     WCHAR *p, *q, *r;
 79     WCHAR *url_decoded = NULL;
 80 
 81     TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, uc);
 82 
 83     if (flags & ICU_ESCAPE) FIXME("flag ICU_ESCAPE not supported\n");
 84 
 85     if (!url || !url[0] || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS))
 86     {
 87         set_last_error( ERROR_INVALID_PARAMETER );
 88         return FALSE;
 89     }
 90     if (!len) len = strlenW( url );
 91 
 92     if (flags & ICU_DECODE)
 93     {
 94         WCHAR *url_tmp;
 95         DWORD url_len = len + 1;
 96 
 97         if (!(url_tmp = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
 98         {
 99             set_last_error( ERROR_OUTOFMEMORY );
100             return FALSE;
101         }
102         memcpy( url_tmp, url, len * sizeof(WCHAR) );
103         url_tmp[len] = 0;
104         if (!(url_decoded = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
105         {
106             HeapFree( GetProcessHeap(), 0, url_tmp );
107             set_last_error( ERROR_OUTOFMEMORY );
108             return FALSE;
109         }
110         if (decode_url( url_tmp, url_decoded, &url_len ))
111         {
112             len = url_len;
113             url = url_decoded;
114         }
115         HeapFree( GetProcessHeap(), 0, url_tmp );
116     }
117     if (!(p = strchrW( url, ':' ))) return FALSE;
118 
119     if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) uc->nScheme = INTERNET_SCHEME_HTTP;
120     else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) uc->nScheme = INTERNET_SCHEME_HTTPS;
121     else goto exit;
122 
123     if (!(set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags ))) goto exit;
124 
125     p++; /* skip ':' */
126     if (!p[0] || p[0] != '/' || p[1] != '/') goto exit;
127     p += 2;
128 
129     if (!p[0]) goto exit;
130     if ((q = memchrW( p, '@', len - (p - url) )))
131     {
132         if ((r = memchrW( p, ':', q - p )))
133         {
134             if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags ))) goto exit;
135             r++;
136             if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags ))) goto exit;
137         }
138         else
139         {
140             if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags ))) goto exit;
141             if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
142         }
143         p = q + 1;
144     }
145     else
146     {
147         if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags ))) goto exit;
148         if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
149     }
150     if ((q = memchrW( p, '/', len - (p - url) )))
151     {
152         if ((r = memchrW( p, ':', q - p )))
153         {
154             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
155             r++;
156             uc->nPort = atoiW( r );
157         }
158         else
159         {
160             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags ))) goto exit;
161             if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
162             if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
163         }
164 
165         if ((r = memchrW( q, '?', len - (q - url) )))
166         {
167             if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags ))) goto exit;
168             if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags ))) goto exit;
169         }
170         else
171         {
172             if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags ))) goto exit;
173             if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
174         }
175     }
176     else
177     {
178         if ((r = memchrW( p, ':', len - (p - url) )))
179         {
180             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
181             r++;
182             uc->nPort = atoiW( r );
183         }
184         else
185         {
186             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags ))) goto exit;
187             if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
188             if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
189         }
190         if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags ))) goto exit;
191         if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
192     }
193 
194     ret = TRUE;
195 
196     TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n",
197           debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ),
198           debugstr_wn( uc->lpszHostName, uc->dwHostNameLength ),
199           uc->nPort,
200           debugstr_wn( uc->lpszUrlPath, uc->dwUrlPathLength ),
201           debugstr_wn( uc->lpszExtraInfo, uc->dwExtraInfoLength ));
202 
203 exit:
204     HeapFree( GetProcessHeap(), 0, url_decoded );
205     return ret;
206 }
207 
208 static INTERNET_SCHEME get_scheme( const WCHAR *scheme, DWORD len )
209 {
210     if (!strncmpW( scheme, scheme_http, len )) return INTERNET_SCHEME_HTTP;
211     if (!strncmpW( scheme, scheme_https, len )) return INTERNET_SCHEME_HTTPS;
212     return 0;
213 }
214 
215 static const WCHAR *get_scheme_string( INTERNET_SCHEME scheme )
216 {
217     if (scheme == INTERNET_SCHEME_HTTP) return scheme_http;
218     if (scheme == INTERNET_SCHEME_HTTPS) return scheme_https;
219     return NULL;
220 }
221 
222 static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port )
223 {
224     if ((scheme == INTERNET_SCHEME_HTTP) && (port == INTERNET_DEFAULT_HTTP_PORT)) return TRUE;
225     if ((scheme == INTERNET_SCHEME_HTTPS) && (port == INTERNET_DEFAULT_HTTPS_PORT)) return TRUE;
226     return FALSE;
227 }
228 
229 static BOOL need_escape( WCHAR c )
230 {
231     if (isalnumW( c )) return FALSE;
232 
233     if (c <= 31 || c >= 127) return TRUE;
234     else
235     {
236         switch (c)
237         {
238         case ' ':
239         case '"':
240         case '#':
241         case '%':
242         case '<':
243         case '>':
244         case ']':
245         case '\\':
246         case '[':
247         case '^':
248         case '`':
249         case '{':
250         case '|':
251         case '}':
252         case '~':
253             return TRUE;
254         default:
255             return FALSE;
256         }
257     }
258 }
259 
260 static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD len )
261 {
262     static const WCHAR hex[] = {'','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
263     DWORD ret = len;
264     unsigned int i;
265     WCHAR *p = dst;
266 
267     for (i = 0; i < len; i++, p++)
268     {
269         if (need_escape( src[i] ))
270         {
271             p[0] = '%';
272             p[1] = hex[(src[i] >> 4) & 0xf];
273             p[2] = hex[src[i] & 0xf];
274             ret += 2;
275             p += 2;
276         }
277         else *p = src[i];
278     }
279     dst[ret] = 0;
280     return ret;
281 }
282 
283 static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp )
284 {
285     DWORD ret;
286     unsigned int i;
287 
288     ret = len ? len : strlenW( comp );
289     if (!(flags & ICU_ESCAPE)) return ret;
290     for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
291     return ret;
292 }
293 
294 static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
295 {
296     static const WCHAR formatW[] = {'%','d',0};
297     INTERNET_SCHEME scheme;
298 
299     *len = 0;
300     if (uc->lpszScheme)
301     {
302         DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
303         *len += scheme_len;
304         scheme = get_scheme( uc->lpszScheme, scheme_len );
305     }
306     else
307     {
308         scheme = uc->nScheme;
309         if (!scheme) scheme = INTERNET_SCHEME_HTTP;
310         *len += strlenW( get_scheme_string( scheme ) );
311     }
312     *len += 1; /* ':' */
313     if (uc->lpszHostName) *len += 2; /* "//" */
314 
315     if (uc->lpszUserName)
316     {
317         *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
318         *len += 1; /* "@" */
319     }
320     else
321     {
322         if (uc->lpszPassword)
323         {
324             set_last_error( ERROR_INVALID_PARAMETER );
325             return FALSE;
326         }
327     }
328     if (uc->lpszPassword)
329     {
330         *len += 1; /* ":" */
331         *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
332     }
333     if (uc->lpszHostName)
334     {
335         *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
336 
337         if (!uses_default_port( scheme, uc->nPort ))
338         {
339             WCHAR port[sizeof("65535")];
340 
341             sprintfW( port, formatW, uc->nPort );
342             *len += strlenW( port );
343             *len += 1; /* ":" */
344         }
345         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
346     }
347     if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
348     if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
349     return TRUE;
350 }
351 
352 /***********************************************************************
353  *          WinHttpCreateUrl (winhttp.@)
354  */
355 BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required )
356 {
357     static const WCHAR formatW[] = {'%','d',0};
358     static const WCHAR twoslashW[] = {'/','/'};
359 
360     DWORD len;
361     INTERNET_SCHEME scheme;
362 
363     TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
364 
365     if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
366     {
367         set_last_error( ERROR_INVALID_PARAMETER );
368         return FALSE;
369     }
370 
371     if (!calc_length( uc, flags, &len )) return FALSE;
372 
373     if (!url || *required < len)
374     {
375         *required = len + 1;
376         set_last_error( ERROR_INSUFFICIENT_BUFFER );
377         return FALSE;
378     }
379 
380     url[0] = 0;
381     *required = len;
382     if (uc->lpszScheme)
383     {
384         len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
385         memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
386         url += len;
387 
388         scheme = get_scheme( uc->lpszScheme, len );
389     }
390     else
391     {
392         const WCHAR *schemeW;
393         scheme = uc->nScheme;
394 
395         if (!scheme) scheme = INTERNET_SCHEME_HTTP;
396 
397         schemeW = get_scheme_string( scheme );
398         len = strlenW( schemeW );
399         memcpy( url, schemeW, len * sizeof(WCHAR) );
400         url += len;
401     }
402 
403     /* all schemes are followed by at least a colon */
404     *url = ':';
405     url++;
406 
407     if (uc->lpszHostName)
408     {
409         memcpy( url, twoslashW, sizeof(twoslashW) );
410         url += sizeof(twoslashW) / sizeof(twoslashW[0]);
411     }
412     if (uc->lpszUserName)
413     {
414         len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
415         memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
416         url += len;
417 
418         if (uc->lpszPassword)
419         {
420             *url = ':';
421             url++;
422 
423             len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
424             memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
425             url += len;
426         }
427         *url = '@';
428         url++;
429     }
430     if (uc->lpszHostName)
431     {
432         len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
433         memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
434         url += len;
435 
436         if (!uses_default_port( scheme, uc->nPort ))
437         {
438             WCHAR port[sizeof("65535")];
439 
440             sprintfW( port, formatW, uc->nPort );
441             *url = ':';
442             url++;
443 
444             len = strlenW( port );
445             memcpy( url, port, len * sizeof(WCHAR) );
446             url += len;
447         }
448 
449         /* add slash between hostname and path if necessary */
450         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
451         {
452             *url = '/';
453             url++;
454         }
455     }
456     if (uc->lpszUrlPath)
457     {
458         len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
459         if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len );
460         else
461         {
462             memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
463             url += len;
464         }
465     }
466     if (uc->lpszExtraInfo)
467     {
468         len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
469         if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len );
470         else
471         {
472             memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
473             url += len;
474         }
475     }
476     *url = 0;
477     return TRUE;
478 }
479 

~ [ source navigation ] ~ [ diff markup ] ~ [ identifier search ] ~ [ freetext search ] ~ [ file search ] ~

This page was automatically generated by the LXR engine.
Visit the LXR main site for more information.