ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

url.c
Go to the documentation of this file.
00001 /*
00002  * Copyright 2008 Hans Leidekker for CodeWeavers
00003  *
00004  * This library is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU Lesser General Public
00006  * License as published by the Free Software Foundation; either
00007  * version 2.1 of the License, or (at your option) any later version.
00008  *
00009  * This library is distributed in the hope that it will be useful,
00010  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * Lesser General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU Lesser General Public
00015  * License along with this library; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00017  */
00018 
00019 #include "config.h"
00020 #include <stdarg.h>
00021 
00022 #include "wine/debug.h"
00023 
00024 #include "windef.h"
00025 #include "winbase.h"
00026 #include "winreg.h"
00027 #include "winhttp.h"
00028 #include "shlwapi.h"
00029 
00030 #include "winhttp_private.h"
00031 
00032 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
00033 
00034 static const WCHAR scheme_http[] = {'h','t','t','p',0};
00035 static const WCHAR scheme_https[] = {'h','t','t','p','s',0};
00036 
00037 static BOOL set_component( WCHAR **str, DWORD *str_len, WCHAR *value, DWORD len, DWORD flags )
00038 {
00039     if (!*str)
00040     {
00041         if (len && (flags & ICU_DECODE))
00042         {
00043             set_last_error( ERROR_INVALID_PARAMETER );
00044             return FALSE;
00045         }
00046         *str = value;
00047         *str_len = len;
00048     }
00049     else
00050     {
00051         if (len > (*str_len) - 1)
00052         {
00053             *str_len = len + 1;
00054             set_last_error( ERROR_INSUFFICIENT_BUFFER );
00055             return FALSE;
00056         }
00057         memcpy( *str, value, len * sizeof(WCHAR) );
00058         (*str)[len] = 0;
00059         *str_len = len;
00060     }
00061     return TRUE;
00062 }
00063 
00064 static BOOL decode_url( LPCWSTR url, LPWSTR buffer, LPDWORD buflen )
00065 {
00066     HRESULT hr = UrlCanonicalizeW( url, buffer, buflen, URL_WININET_COMPATIBILITY | URL_UNESCAPE );
00067     if (hr == E_POINTER) set_last_error( ERROR_INSUFFICIENT_BUFFER );
00068     if (hr == E_INVALIDARG) set_last_error( ERROR_INVALID_PARAMETER );
00069     return (SUCCEEDED(hr)) ? TRUE : FALSE;
00070 }
00071 
00072 /***********************************************************************
00073  *          WinHttpCrackUrl (winhttp.@)
00074  */
00075 BOOL WINAPI WinHttpCrackUrl( LPCWSTR url, DWORD len, DWORD flags, LPURL_COMPONENTSW uc )
00076 {
00077     BOOL ret = FALSE;
00078     WCHAR *p, *q, *r;
00079     WCHAR *url_decoded = NULL;
00080 
00081     TRACE("%s, %d, %x, %p\n", debugstr_w(url), len, flags, uc);
00082 
00083     if (flags & ICU_ESCAPE) FIXME("flag ICU_ESCAPE not supported\n");
00084 
00085     if (!url || !uc || uc->dwStructSize != sizeof(URL_COMPONENTS))
00086     {
00087         set_last_error( ERROR_INVALID_PARAMETER );
00088         return FALSE;
00089     }
00090     if (!len) len = strlenW( url );
00091 
00092     if (flags & ICU_DECODE)
00093     {
00094         WCHAR *url_tmp;
00095         DWORD url_len = len + 1;
00096 
00097         if (!(url_tmp = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
00098         {
00099             set_last_error( ERROR_OUTOFMEMORY );
00100             return FALSE;
00101         }
00102         memcpy( url_tmp, url, len * sizeof(WCHAR) );
00103         url_tmp[len] = 0;
00104         if (!(url_decoded = HeapAlloc( GetProcessHeap(), 0, url_len * sizeof(WCHAR) )))
00105         {
00106             HeapFree( GetProcessHeap(), 0, url_tmp );
00107             set_last_error( ERROR_OUTOFMEMORY );
00108             return FALSE;
00109         }
00110         if (decode_url( url_tmp, url_decoded, &url_len ))
00111         {
00112             len = url_len;
00113             url = url_decoded;
00114         }
00115         HeapFree( GetProcessHeap(), 0, url_tmp );
00116     }
00117     if (!(p = strchrW( url, ':' )))
00118     {
00119         set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
00120         return FALSE;
00121     }
00122     if (p - url == 4 && !strncmpiW( url, scheme_http, 4 )) uc->nScheme = INTERNET_SCHEME_HTTP;
00123     else if (p - url == 5 && !strncmpiW( url, scheme_https, 5 )) uc->nScheme = INTERNET_SCHEME_HTTPS;
00124     else
00125     {
00126         set_last_error( ERROR_WINHTTP_UNRECOGNIZED_SCHEME );
00127         goto exit;
00128     }
00129     if (!(set_component( &uc->lpszScheme, &uc->dwSchemeLength, (WCHAR *)url, p - url, flags ))) goto exit;
00130 
00131     p++; /* skip ':' */
00132     if (!p[0] || p[0] != '/' || p[1] != '/') goto exit;
00133     p += 2;
00134 
00135     if (!p[0]) goto exit;
00136     if ((q = memchrW( p, '@', len - (p - url) )) && !(memchrW( p, '/', q - p )))
00137     {
00138         if ((r = memchrW( p, ':', q - p )))
00139         {
00140             if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, r - p, flags ))) goto exit;
00141             r++;
00142             if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, r, q - r, flags ))) goto exit;
00143         }
00144         else
00145         {
00146             if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, p, q - p, flags ))) goto exit;
00147             if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
00148         }
00149         p = q + 1;
00150     }
00151     else
00152     {
00153         if (!(set_component( &uc->lpszUserName, &uc->dwUserNameLength, NULL, 0, flags ))) goto exit;
00154         if (!(set_component( &uc->lpszPassword, &uc->dwPasswordLength, NULL, 0, flags ))) goto exit;
00155     }
00156     if ((q = memchrW( p, '/', len - (p - url) )))
00157     {
00158         if ((r = memchrW( p, ':', q - p )))
00159         {
00160             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
00161             r++;
00162             uc->nPort = atoiW( r );
00163         }
00164         else
00165         {
00166             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, q - p, flags ))) goto exit;
00167             if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
00168             if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
00169         }
00170 
00171         if ((r = memchrW( q, '?', len - (q - url) )))
00172         {
00173             if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, r - q, flags ))) goto exit;
00174             if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, r, len - (r - url), flags ))) goto exit;
00175         }
00176         else
00177         {
00178             if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, q, len - (q - url), flags ))) goto exit;
00179             if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
00180         }
00181     }
00182     else
00183     {
00184         if ((r = memchrW( p, ':', len - (p - url) )))
00185         {
00186             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, r - p, flags ))) goto exit;
00187             r++;
00188             uc->nPort = atoiW( r );
00189         }
00190         else
00191         {
00192             if (!(set_component( &uc->lpszHostName, &uc->dwHostNameLength, p, len - (p - url), flags ))) goto exit;
00193             if (uc->nScheme == INTERNET_SCHEME_HTTP) uc->nPort = INTERNET_DEFAULT_HTTP_PORT;
00194             if (uc->nScheme == INTERNET_SCHEME_HTTPS) uc->nPort = INTERNET_DEFAULT_HTTPS_PORT;
00195         }
00196         if (!(set_component( &uc->lpszUrlPath, &uc->dwUrlPathLength, (WCHAR *)url + len, 0, flags ))) goto exit;
00197         if (!(set_component( &uc->lpszExtraInfo, &uc->dwExtraInfoLength, (WCHAR *)url + len, 0, flags ))) goto exit;
00198     }
00199 
00200     ret = TRUE;
00201 
00202     TRACE("scheme(%s) host(%s) port(%d) path(%s) extra(%s)\n",
00203           debugstr_wn( uc->lpszScheme, uc->dwSchemeLength ),
00204           debugstr_wn( uc->lpszHostName, uc->dwHostNameLength ),
00205           uc->nPort,
00206           debugstr_wn( uc->lpszUrlPath, uc->dwUrlPathLength ),
00207           debugstr_wn( uc->lpszExtraInfo, uc->dwExtraInfoLength ));
00208 
00209 exit:
00210     HeapFree( GetProcessHeap(), 0, url_decoded );
00211     return ret;
00212 }
00213 
00214 static INTERNET_SCHEME get_scheme( const WCHAR *scheme, DWORD len )
00215 {
00216     if (!strncmpW( scheme, scheme_http, len )) return INTERNET_SCHEME_HTTP;
00217     if (!strncmpW( scheme, scheme_https, len )) return INTERNET_SCHEME_HTTPS;
00218     return 0;
00219 }
00220 
00221 static const WCHAR *get_scheme_string( INTERNET_SCHEME scheme )
00222 {
00223     if (scheme == INTERNET_SCHEME_HTTP) return scheme_http;
00224     if (scheme == INTERNET_SCHEME_HTTPS) return scheme_https;
00225     return NULL;
00226 }
00227 
00228 static BOOL uses_default_port( INTERNET_SCHEME scheme, INTERNET_PORT port )
00229 {
00230     if ((scheme == INTERNET_SCHEME_HTTP) && (port == INTERNET_DEFAULT_HTTP_PORT)) return TRUE;
00231     if ((scheme == INTERNET_SCHEME_HTTPS) && (port == INTERNET_DEFAULT_HTTPS_PORT)) return TRUE;
00232     return FALSE;
00233 }
00234 
00235 static BOOL need_escape( WCHAR c )
00236 {
00237     if (isalnumW( c )) return FALSE;
00238 
00239     if (c <= 31 || c >= 127) return TRUE;
00240     else
00241     {
00242         switch (c)
00243         {
00244         case ' ':
00245         case '"':
00246         case '#':
00247         case '%':
00248         case '<':
00249         case '>':
00250         case ']':
00251         case '\\':
00252         case '[':
00253         case '^':
00254         case '`':
00255         case '{':
00256         case '|':
00257         case '}':
00258         case '~':
00259             return TRUE;
00260         default:
00261             return FALSE;
00262         }
00263     }
00264 }
00265 
00266 static DWORD copy_escape( WCHAR *dst, const WCHAR *src, DWORD len )
00267 {
00268     static const WCHAR hex[] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'};
00269     DWORD ret = len;
00270     unsigned int i;
00271     WCHAR *p = dst;
00272 
00273     for (i = 0; i < len; i++, p++)
00274     {
00275         if (need_escape( src[i] ))
00276         {
00277             p[0] = '%';
00278             p[1] = hex[(src[i] >> 4) & 0xf];
00279             p[2] = hex[src[i] & 0xf];
00280             ret += 2;
00281             p += 2;
00282         }
00283         else *p = src[i];
00284     }
00285     dst[ret] = 0;
00286     return ret;
00287 }
00288 
00289 static DWORD comp_length( DWORD len, DWORD flags, WCHAR *comp )
00290 {
00291     DWORD ret;
00292     unsigned int i;
00293 
00294     ret = len ? len : strlenW( comp );
00295     if (!(flags & ICU_ESCAPE)) return ret;
00296     for (i = 0; i < len; i++) if (need_escape( comp[i] )) ret += 2;
00297     return ret;
00298 }
00299 
00300 static BOOL calc_length( URL_COMPONENTS *uc, DWORD flags, LPDWORD len )
00301 {
00302     static const WCHAR formatW[] = {'%','u',0};
00303     INTERNET_SCHEME scheme;
00304 
00305     *len = 0;
00306     if (uc->lpszScheme)
00307     {
00308         DWORD scheme_len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
00309         *len += scheme_len;
00310         scheme = get_scheme( uc->lpszScheme, scheme_len );
00311     }
00312     else
00313     {
00314         scheme = uc->nScheme;
00315         if (!scheme) scheme = INTERNET_SCHEME_HTTP;
00316         *len += strlenW( get_scheme_string( scheme ) );
00317     }
00318     *len += 1; /* ':' */
00319     if (uc->lpszHostName) *len += 2; /* "//" */
00320 
00321     if (uc->lpszUserName)
00322     {
00323         *len += comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
00324         *len += 1; /* "@" */
00325     }
00326     else
00327     {
00328         if (uc->lpszPassword)
00329         {
00330             set_last_error( ERROR_INVALID_PARAMETER );
00331             return FALSE;
00332         }
00333     }
00334     if (uc->lpszPassword)
00335     {
00336         *len += 1; /* ":" */
00337         *len += comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
00338     }
00339     if (uc->lpszHostName)
00340     {
00341         *len += comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
00342 
00343         if (!uses_default_port( scheme, uc->nPort ))
00344         {
00345             WCHAR port[sizeof("65535")];
00346 
00347             sprintfW( port, formatW, uc->nPort );
00348             *len += strlenW( port );
00349             *len += 1; /* ":" */
00350         }
00351         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/') *len += 1; /* '/' */
00352     }
00353     if (uc->lpszUrlPath) *len += comp_length( uc->dwUrlPathLength, flags, uc->lpszUrlPath );
00354     if (uc->lpszExtraInfo) *len += comp_length( uc->dwExtraInfoLength, flags, uc->lpszExtraInfo );
00355     return TRUE;
00356 }
00357 
00358 /***********************************************************************
00359  *          WinHttpCreateUrl (winhttp.@)
00360  */
00361 BOOL WINAPI WinHttpCreateUrl( LPURL_COMPONENTS uc, DWORD flags, LPWSTR url, LPDWORD required )
00362 {
00363     static const WCHAR formatW[] = {'%','u',0};
00364     static const WCHAR twoslashW[] = {'/','/'};
00365 
00366     DWORD len;
00367     INTERNET_SCHEME scheme;
00368 
00369     TRACE("%p, 0x%08x, %p, %p\n", uc, flags, url, required);
00370 
00371     if (!uc || uc->dwStructSize != sizeof(URL_COMPONENTS) || !required || !url)
00372     {
00373         set_last_error( ERROR_INVALID_PARAMETER );
00374         return FALSE;
00375     }
00376 
00377     if (!calc_length( uc, flags, &len )) return FALSE;
00378 
00379     if (*required < len)
00380     {
00381         *required = len + 1;
00382         set_last_error( ERROR_INSUFFICIENT_BUFFER );
00383         return FALSE;
00384     }
00385 
00386     url[0] = 0;
00387     *required = len;
00388     if (uc->lpszScheme)
00389     {
00390         len = comp_length( uc->dwSchemeLength, 0, uc->lpszScheme );
00391         memcpy( url, uc->lpszScheme, len * sizeof(WCHAR) );
00392         url += len;
00393 
00394         scheme = get_scheme( uc->lpszScheme, len );
00395     }
00396     else
00397     {
00398         const WCHAR *schemeW;
00399         scheme = uc->nScheme;
00400 
00401         if (!scheme) scheme = INTERNET_SCHEME_HTTP;
00402 
00403         schemeW = get_scheme_string( scheme );
00404         len = strlenW( schemeW );
00405         memcpy( url, schemeW, len * sizeof(WCHAR) );
00406         url += len;
00407     }
00408 
00409     /* all schemes are followed by at least a colon */
00410     *url = ':';
00411     url++;
00412 
00413     if (uc->lpszHostName)
00414     {
00415         memcpy( url, twoslashW, sizeof(twoslashW) );
00416         url += sizeof(twoslashW) / sizeof(twoslashW[0]);
00417     }
00418     if (uc->lpszUserName)
00419     {
00420         len = comp_length( uc->dwUserNameLength, 0, uc->lpszUserName );
00421         memcpy( url, uc->lpszUserName, len * sizeof(WCHAR) );
00422         url += len;
00423 
00424         if (uc->lpszPassword)
00425         {
00426             *url = ':';
00427             url++;
00428 
00429             len = comp_length( uc->dwPasswordLength, 0, uc->lpszPassword );
00430             memcpy( url, uc->lpszPassword, len * sizeof(WCHAR) );
00431             url += len;
00432         }
00433         *url = '@';
00434         url++;
00435     }
00436     if (uc->lpszHostName)
00437     {
00438         len = comp_length( uc->dwHostNameLength, 0, uc->lpszHostName );
00439         memcpy( url, uc->lpszHostName, len * sizeof(WCHAR) );
00440         url += len;
00441 
00442         if (!uses_default_port( scheme, uc->nPort ))
00443         {
00444             WCHAR port[sizeof("65535")];
00445 
00446             sprintfW( port, formatW, uc->nPort );
00447             *url = ':';
00448             url++;
00449 
00450             len = strlenW( port );
00451             memcpy( url, port, len * sizeof(WCHAR) );
00452             url += len;
00453         }
00454 
00455         /* add slash between hostname and path if necessary */
00456         if (uc->lpszUrlPath && *uc->lpszUrlPath != '/')
00457         {
00458             *url = '/';
00459             url++;
00460         }
00461     }
00462     if (uc->lpszUrlPath)
00463     {
00464         len = comp_length( uc->dwUrlPathLength, 0, uc->lpszUrlPath );
00465         if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszUrlPath, len );
00466         else
00467         {
00468             memcpy( url, uc->lpszUrlPath, len * sizeof(WCHAR) );
00469             url += len;
00470         }
00471     }
00472     if (uc->lpszExtraInfo)
00473     {
00474         len = comp_length( uc->dwExtraInfoLength, 0, uc->lpszExtraInfo );
00475         if (flags & ICU_ESCAPE) url += copy_escape( url, uc->lpszExtraInfo, len );
00476         else
00477         {
00478             memcpy( url, uc->lpszExtraInfo, len * sizeof(WCHAR) );
00479             url += len;
00480         }
00481     }
00482     *url = 0;
00483     return TRUE;
00484 }

Generated on Wed May 23 2012 04:24:28 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.