ReactOS 0.4.15-dev-8058-ga7cbb60
url.c
Go to the documentation of this file.
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 "ws2tcpip.h"
21#include <stdarg.h>
22
23#include "windef.h"
24#include "winbase.h"
25#include "winreg.h"
26#include "winhttp.h"
27#include "shlwapi.h"
28
29#include "wine/debug.h"
30#include "winhttp_private.h"
31
33
34static const WCHAR scheme_http[] = {'h','t','t','p',0};
35static const WCHAR scheme_https[] = {'h','t','t','p','s',0};
36
38{
41};
42
43static DWORD set_component( struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow )
44{
45 if (*comp->str && !*comp->len) return ERROR_INVALID_PARAMETER;
46 if (!*comp->len) return ERROR_SUCCESS;
47 if (!*comp->str)
48 {
49 if (len && *comp->len && (flags & (ICU_DECODE|ICU_ESCAPE))) return ERROR_INVALID_PARAMETER;
50 *comp->str = value;
51 *comp->len = len;
52 }
53 else
54 {
55 if (len >= *comp->len)
56 {
57 *comp->len = len + 1;
58 *overflow = TRUE;
59 return ERROR_SUCCESS;
60 }
61 memcpy( *comp->str, value, len * sizeof(WCHAR) );
62 (*comp->str)[len] = 0;
63 *comp->len = len;
64 }
65 return ERROR_SUCCESS;
66}
67
69{
70 const WCHAR *p = url;
71 WCHAR hex[3], *q, *ret;
72
73 if (!(ret = heap_alloc( *len * sizeof(WCHAR) ))) return NULL;
74 q = ret;
75 while (*len > 0)
76 {
77 if (p[0] == '%' && isxdigitW( p[1] ) && isxdigitW( p[2] ))
78 {
79 hex[0] = p[1];
80 hex[1] = p[2];
81 hex[2] = 0;
82 *q++ = strtolW( hex, NULL, 16 );
83 p += 3;
84 *len -= 3;
85 }
86 else
87 {
88 *q++ = *p++;
89 *len -= 1;
90 }
91 }
92 *len = q - ret;
93 return ret;
94}
95
96static inline BOOL need_escape( WCHAR ch )
97{
98 static const WCHAR escapes[] = {' ','"','#','%','<','>','[','\\',']','^','`','{','|','}','~',0};
99 const WCHAR *p = escapes;
100
101 if (ch <= 31 || ch >= 127) return TRUE;
102 while (*p)
103 {
104 if (ch == *p++) return TRUE;
105 }
106 return FALSE;
107}
108
109static BOOL escape_string( const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len )
110{
111 static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
112 WCHAR *p = dst;
113 DWORD i;
114
115 *dst_len = src_len;
116 for (i = 0; i < src_len; i++)
117 {
118 if (src[i] > 0xff) return FALSE;
119 if (need_escape( src[i] ))
120 {
121 if (dst)
122 {
123 p[0] = '%';
124 p[1] = hex[(src[i] >> 4) & 0xf];
125 p[2] = hex[src[i] & 0xf];
126 p += 3;
127 }
128 *dst_len += 2;
129 }
130 else if (dst) *p++ = src[i];
131 }
132
133 if (dst) dst[*dst_len] = 0;
134 return TRUE;
135}
136
137static DWORD escape_url( const WCHAR *url, DWORD *len, WCHAR **ret )
138{
139 const WCHAR *p;
140 DWORD len_base, len_path;
141
142 if ((p = strrchrW( url, '/' )))
143 {
144 len_base = p - url;
145 if (!escape_string( p, *len - len_base, NULL, &len_path )) return ERROR_INVALID_PARAMETER;
146 }
147 else
148 {
149 len_base = *len;
150 len_path = 0;
151 }
152
153 if (!(*ret = heap_alloc( (len_base + len_path + 1) * sizeof(WCHAR) ))) return ERROR_OUTOFMEMORY;
154 memcpy( *ret, url, len_base * sizeof(WCHAR) );
155
156 if (p) escape_string( p, *len - (p - url), *ret + len_base, &len_path );
157 (*ret)[len_base + len_path] = 0;
158
159 *len = len_base + len_path;
160 return ERROR_SUCCESS;
161}
162
164{
165 const WCHAR *p = str;
166 DWORD port = 0;
167 while (len && isdigitW( *p ))
168 {
169 if ((port = port * 10 + *p - '0') > 65535) return ERROR_WINHTTP_INVALID_URL;
170 p++; len--;
171 }
172 *ret = port;
173 return ERROR_SUCCESS;
174}
175
176/***********************************************************************
177 * WinHttpCrackUrl (winhttp.@)
178 */
180{
181 WCHAR *p, *q, *r, *url_decoded = NULL, *url_escaped = NULL;
184 BOOL overflow = FALSE;
185 DWORD err;
186
187 TRACE("%s, %d, %x, %p\n", debugstr_wn(url, len), len, flags, uc);
188
189 if (!url || !uc || uc->dwStructSize != sizeof(*uc))
190 {
192 return FALSE;
193 }
194 if (!len) len = strlenW( url );
195
196 if (flags & ICU_ESCAPE)
197 {
198 if ((err = escape_url( url, &len, &url_escaped )))
199 {
200 SetLastError( err );
201 return FALSE;
202 }
203 url = url_escaped;
204 }
205 else if (flags & ICU_DECODE)
206 {
207 if (!(url_decoded = decode_url( url, &len )))
208 {
210 return FALSE;
211 }
212 url = url_decoded;
213 }
214 if (!(p = strchrW( url, ':' )))
215 {
217 return FALSE;
218 }
220 else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) scheme_number = INTERNET_SCHEME_HTTPS;
221 else
222 {
224 goto exit;
225 }
226
227 scheme.str = &uc->lpszScheme;
228 scheme.len = &uc->dwSchemeLength;
229
230 if ((err = set_component( &scheme, (WCHAR *)url, p - url, flags, &overflow ))) goto exit;
231
232 p++; /* skip ':' */
233 if (!p[0] || p[0] != '/' || p[1] != '/')
234 {
236 goto exit;
237 }
238 p += 2;
239 if (!p[0])
240 {
242 goto exit;
243 }
244
245 username.str = &uc->lpszUserName;
246 username.len = &uc->dwUserNameLength;
247
248 password.str = &uc->lpszPassword;
249 password.len = &uc->dwPasswordLength;
250
251 if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
252 {
253
254 if ((r = memchrW( p, ':', q - p )))
255 {
256 if ((err = set_component( &username, p, r - p, flags, &overflow ))) goto exit;
257 r++;
258 if ((err = set_component( &password, r, q - r, flags, &overflow ))) goto exit;
259 }
260 else
261 {
262 if ((err = set_component( &username, p, q - p, flags, &overflow ))) goto exit;
263 if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
264 }
265 p = q + 1;
266 }
267 else
268 {
269 if ((err = set_component( &username, NULL, 0, flags, &overflow ))) goto exit;
270 if ((err = set_component( &password, NULL, 0, flags, &overflow ))) goto exit;
271 }
272
273 hostname.str = &uc->lpszHostName;
274 hostname.len = &uc->dwHostNameLength;
275
276 path.str = &uc->lpszUrlPath;
277 path.len = &uc->dwUrlPathLength;
278
279 extra.str = &uc->lpszExtraInfo;
280 extra.len = &uc->dwExtraInfoLength;
281
282 if ((q = memchrW( p, '/', len - (p - url) )))
283 {
284 if ((r = memchrW( p, ':', q - p )))
285 {
286 if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
287 r++;
288 if ((err = parse_port( r, q - r, &uc->nPort ))) goto exit;
289 }
290 else
291 {
292 if ((err = set_component( &hostname, p, q - p, flags, &overflow ))) goto exit;
295 }
296
297 if ((r = memchrW( q, '?', len - (q - url) )))
298 {
299 if (*extra.len)
300 {
301 if ((err = set_component( &path, q, r - q, flags, &overflow ))) goto exit;
302 if ((err = set_component( &extra, r, len - (r - url), flags, &overflow ))) goto exit;
303 }
304 else if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
305 }
306 else
307 {
308 if ((err = set_component( &path, q, len - (q - url), flags, &overflow ))) goto exit;
309 if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
310 }
311 }
312 else
313 {
314 if ((r = memchrW( p, ':', len - (p - url) )))
315 {
316 if ((err = set_component( &hostname, p, r - p, flags, &overflow ))) goto exit;
317 r++;
318 if ((err = parse_port( r, len - (r - url), &uc->nPort ))) goto exit;
319 }
320 else
321 {
322 if ((err = set_component( &hostname, p, len - (p - url), flags, &overflow ))) goto exit;
325 }
326 if ((err = set_component( &path, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
327 if ((err = set_component( &extra, (WCHAR *)url + len, 0, flags, &overflow ))) goto exit;
328 }
329
330 TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n", debugstr_wn(*scheme.str, *scheme.len),
331 debugstr_wn(*hostname.str, *hostname.len ), uc->nPort, debugstr_wn(*path.str, *path.len),
332 debugstr_wn(*extra.str, *extra.len));
333
334exit:
335 if (!err)
336 {
337 if (overflow) err = ERROR_INSUFFICIENT_BUFFER;
339 }
340 heap_free( url_decoded );
341 heap_free( url_escaped );
342 SetLastError( err );
343 return !err;
344}
345
347{
350 return 0;
351}
352
354{
357 return NULL;
358}
359
361{
364 return FALSE;
365}
366
368{
369 DWORD ret;
370 unsigned int i;
371
372 ret = len ? len : strlenW( comp );
373 if (!(flags & ICU_ESCAPE)) return ret;
374 for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
375 return ret;
376}
377
379{
380 static const WCHAR formatW[] = {'%','u',0};
382
383 *len = 0;
384 if (uc->lpszScheme)
385 {
386 DWORD scheme_len = get_comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
387 *len += scheme_len;
388 scheme = get_scheme( uc->lpszScheme, scheme_len );
389 }
390 else
391 {
392 scheme = uc->nScheme;
395 }
396 *len += 3; /* "://" */
397
398 if (uc->lpszUserName)
399 {
401 *len += 1; /* "@" */
402 }
403 else
404 {
405 if (uc->lpszPassword)
406 {
408 return FALSE;
409 }
410 }
411 if (uc->lpszPassword)
412 {
413 *len += 1; /* ":" */
415 }
416 if (uc->lpszHostName)
417 {
419
420 if (!uses_default_port( scheme, uc->nPort ))
421 {
422 WCHAR port[sizeof("65535")];
423
424 *len += sprintfW( port, formatW, uc->nPort );
425 *len += 1; /* ":" */
426 }
427 if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
428 }
431 return TRUE;
432}
433
434/***********************************************************************
435 * WinHttpCreateUrl (winhttp.@)
436 */
438{
439 static const WCHAR formatW[] = {'%','u',0};
440 DWORD len, len_escaped;
442
443 TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
444
445 if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required)
446 {
448 return FALSE;
449 }
450
451 if (!get_url_length( uc, flags, &len )) return FALSE;
452
453 if (*required < len)
454 {
455 *required = len + 1;
457 return FALSE;
458 }
459 if (!url)
460 {
462 return FALSE;
463 }
464
465 url[0] = 0;
466 *required = len;
467 if (uc->lpszScheme)
468 {
470 memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
471 url += len;
472
474 }
475 else
476 {
477 const WCHAR *schemeW;
478 scheme = uc->nScheme;
479
481
482 schemeW = get_scheme_string( scheme );
483 len = strlenW( schemeW );
484 memcpy( url, schemeW, len * sizeof(WCHAR) );
485 url += len;
486 }
487
488 *url++ = ':';
489 *url++ = '/';
490 *url++ = '/';
491
492 if (uc->lpszUserName)
493 {
495 memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
496 url += len;
497
498 if (uc->lpszPassword)
499 {
500 *url++ = ':';
502 memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
503 url += len;
504 }
505 *url++ = '@';
506 }
507 if (uc->lpszHostName)
508 {
510 memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
511 url += len;
512
513 if (!uses_default_port( scheme, uc->nPort ))
514 {
515 *url++ = ':';
516 url += sprintfW( url, formatW, uc->nPort );
517 }
518
519 /* add slash between hostname and path if necessary */
520 if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
521 {
522 *url++ = '/';
523 }
524 }
525 if (uc->lpszUrlPath)
526 {
528 if (flags & ICU_ESCAPE)
529 {
530 if (!escape_string( uc->lpszUrlPath, len, url, &len_escaped ))
531 {
533 return FALSE;
534 }
535 url += len_escaped;
536 }
537 else
538 {
539 memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
540 url += len;
541 }
542 }
543 if (uc->lpszExtraInfo)
544 {
546 if (flags & ICU_ESCAPE)
547 {
548 if (!escape_string( uc->lpszExtraInfo, len, url, &len_escaped ))
549 {
551 return FALSE;
552 }
553 url += len_escaped;
554 }
555 else
556 {
557 memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
558 url += len;
559 }
560 }
561 *url = 0;
563 return TRUE;
564}
static void * heap_alloc(size_t len)
Definition: appwiz.h:66
static BOOL heap_free(void *mem)
Definition: appwiz.h:76
#define WINE_DEFAULT_DEBUG_CHANNEL(t)
Definition: precomp.h:23
char * hostname
Definition: ftp.c:88
#define ERROR_INSUFFICIENT_BUFFER
Definition: dderror.h:10
#define ERROR_OUTOFMEMORY
Definition: deptool.c:13
#define ERROR_SUCCESS
Definition: deptool.c:10
#define NULL
Definition: types.h:112
#define TRUE
Definition: types.h:120
#define FALSE
Definition: types.h:117
#define ERROR_INVALID_PARAMETER
Definition: compat.h:101
#define SetLastError(x)
Definition: compat.h:752
URL_SCHEME scheme_number
Definition: url.c:64
USHORT port
Definition: uri.c:228
BOOL WINAPI WinHttpCrackUrl(LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc)
Definition: url.c:179
static DWORD parse_port(const WCHAR *str, DWORD len, INTERNET_PORT *ret)
Definition: url.c:163
static BOOL get_url_length(URL_COMPONENTS *uc, DWORD flags, DWORD *len)
Definition: url.c:378
static INTERNET_SCHEME get_scheme(const WCHAR *scheme, DWORD len)
Definition: url.c:346
BOOL WINAPI WinHttpCreateUrl(LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required)
Definition: url.c:437
static BOOL need_escape(WCHAR ch)
Definition: url.c:96
static BOOL uses_default_port(INTERNET_SCHEME scheme, INTERNET_PORT port)
Definition: url.c:360
static const WCHAR * get_scheme_string(INTERNET_SCHEME scheme)
Definition: url.c:353
static WCHAR * decode_url(LPCWSTR url, DWORD *len)
Definition: url.c:68
static DWORD set_component(struct url_component *comp, WCHAR *value, DWORD len, DWORD flags, BOOL *overflow)
Definition: url.c:43
static BOOL escape_string(const WCHAR *src, DWORD src_len, WCHAR *dst, DWORD *dst_len)
Definition: url.c:109
static const WCHAR scheme_https[]
Definition: url.c:35
static const WCHAR scheme_http[]
Definition: url.c:34
static DWORD escape_url(const WCHAR *url, DWORD *len, WCHAR **ret)
Definition: url.c:137
static DWORD get_comp_length(DWORD len, DWORD flags, WCHAR *comp)
Definition: url.c:367
unsigned int BOOL
Definition: ntddk_ex.h:94
unsigned long DWORD
Definition: ntddk_ex.h:95
GLdouble GLdouble GLdouble r
Definition: gl.h:2055
GLdouble GLdouble GLdouble GLdouble q
Definition: gl.h:2063
GLenum src
Definition: glext.h:6340
GLenum GLenum dst
Definition: glext.h:6340
GLbitfield flags
Definition: glext.h:7161
GLfloat GLfloat p
Definition: glext.h:8902
GLenum GLsizei len
Definition: glext.h:6722
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
WINE_UNICODE_INLINE WCHAR * memchrW(const WCHAR *ptr, WCHAR ch, size_t n)
Definition: unicode.h:295
int hex(char ch)
@ extra
Definition: id3.c:95
#define debugstr_wn
Definition: kernel32.h:33
#define memcpy(s1, s2, n)
Definition: mkisofs.h:878
static const WCHAR url[]
Definition: encode.c:1432
static WCHAR password[]
Definition: url.c:33
static WCHAR username[]
Definition: url.c:32
#define strncmpiW(s1, s2, n)
Definition: unicode.h:46
#define isdigitW(n)
Definition: unicode.h:56
#define strchrW(s, c)
Definition: unicode.h:40
#define strlenW(s)
Definition: unicode.h:34
#define strrchrW(s, c)
Definition: unicode.h:41
#define isxdigitW(n)
Definition: unicode.h:57
#define strncmpW(s1, s2, n)
Definition: unicode.h:42
#define sprintfW
Definition: unicode.h:64
#define strtolW(s, e, b)
Definition: unicode.h:39
#define err(...)
const WCHAR * str
DWORD scheme
#define exit(n)
Definition: config.h:202
#define TRACE(s)
Definition: solgame.cpp:4
INTERNET_PORT nPort
Definition: winhttp.h:471
LPWSTR lpszScheme
Definition: winhttp.h:466
LPWSTR lpszUserName
Definition: winhttp.h:472
LPWSTR lpszExtraInfo
Definition: winhttp.h:478
DWORD dwPasswordLength
Definition: winhttp.h:475
LPWSTR lpszUrlPath
Definition: winhttp.h:476
DWORD dwHostNameLength
Definition: winhttp.h:470
DWORD dwExtraInfoLength
Definition: winhttp.h:479
DWORD dwUrlPathLength
Definition: winhttp.h:477
LPWSTR lpszHostName
Definition: winhttp.h:469
LPWSTR lpszPassword
Definition: winhttp.h:474
INTERNET_SCHEME nScheme
Definition: winhttp.h:468
DWORD dwStructSize
Definition: winhttp.h:465
DWORD dwUserNameLength
Definition: winhttp.h:473
DWORD dwSchemeLength
Definition: winhttp.h:467
WCHAR ** str
Definition: url.c:39
DWORD * len
Definition: url.c:40
uint32_t * LPDWORD
Definition: typedefs.h:59
Definition: pdh_main.c:94
int ret
#define WINAPI
Definition: msvc.h:6
WORD INTERNET_PORT
Definition: winhttp.h:38
#define ERROR_WINHTTP_INVALID_URL
Definition: winhttp.h:191
#define ICU_DECODE
Definition: winhttp.h:291
#define INTERNET_SCHEME_HTTP
Definition: winhttp.h:42
#define ERROR_WINHTTP_UNRECOGNIZED_SCHEME
Definition: winhttp.h:192
#define INTERNET_DEFAULT_HTTP_PORT
Definition: winhttp.h:36
#define INTERNET_SCHEME_HTTPS
Definition: winhttp.h:43
#define ICU_ESCAPE
Definition: winhttp.h:48
#define INTERNET_DEFAULT_HTTPS_PORT
Definition: winhttp.h:37
INTERNET_SCHEME
Definition: wininet.h:135
__wchar_t WCHAR
Definition: xmlstorage.h:180
WCHAR * LPWSTR
Definition: xmlstorage.h:184
const WCHAR * LPCWSTR
Definition: xmlstorage.h:185