VirtualBox

Changeset 57720 in vbox for trunk


Ignore:
Timestamp:
Sep 11, 2015 2:49:21 PM (9 years ago)
Author:
vboxsync
Message:

RTUri: Preps for parsing the authority bits into smaller pieces for cURL proxy config.

Location:
trunk
Files:
6 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/err.h

    r57613 r57720  
    24962496/** @} */
    24972497
     2498/** @name RTUri status codes.
     2499 * @{ */
     2500/** The URI is empty */
     2501#define VERR_URI_EMPTY                              (-24600)
     2502/** The URI is too short to be a valid URI. */
     2503#define VERR_URI_TOO_SHORT                          (-24601)
     2504/** Invalid scheme.  */
     2505#define VERR_URI_INVALID_SCHEME                     (-24602)
     2506/** Invalid port number.  */
     2507#define VERR_URI_INVALID_PORT_NUMBER                (-24603)
     2508/** @} */
     2509
    24982510/* SED-END */
    24992511
  • trunk/include/iprt/mangling.h

    r57643 r57720  
    18591859# define RTUniFree                                      RT_MANGLER(RTUniFree)
    18601860# define RTUriAuthority                                 RT_MANGLER(RTUriAuthority)
     1861# define RTUriAuthorityPassword                         RT_MANGLER(RTUriAuthorityPassword)
     1862# define RTUriAuthorityPort                             RT_MANGLER(RTUriAuthorityPort)
     1863# define RTUriAuthorityUsername                         RT_MANGLER(RTUriAuthorityUsername)
    18611864# define RTUriCreate                                    RT_MANGLER(RTUriCreate)
    18621865# define RTUriFileCreate                                RT_MANGLER(RTUriFileCreate)
  • trunk/include/iprt/uri.h

    r57004 r57720  
    8080 * @returns the authority if the URI contains one, NULL otherwise.
    8181 * @param   pszUri              The URI to extract from.
     82 * @remarks The authority can have a zero length.
    8283 */
    8384RTR3DECL(char *) RTUriAuthority(const char *pszUri);
     85
     86/**
     87 * Extract the username out of the authority component in an URI.
     88 *
     89 * @returns The username if the URI contains one, otherwise NULL.
     90 * @param   pszUri              The URI to extract from.
     91 */
     92RTR3DECL(char *) RTUriAuthorityUsername(const char *pszUri);
     93
     94/**
     95 * Extract the password out of the authority component in an URI.
     96 *
     97 * @returns The password if the URI contains one, otherwise NULL.
     98 * @param   pszUri              The URI to extract from.
     99 */
     100RTR3DECL(char *) RTUriAuthorityPassword(const char *pszUri);
     101
     102/**
     103 * Extract the port number out of the authority component in an URI.
     104 *
     105 * @returns The port number if the URI contains one, otherwise UINT32_MAX.
     106 * @param   pszUri              The URI to extract from.
     107 */
     108RTR3DECL(uint32_t) RTUriAuthorityPort(const char *pszUri);
    84109
    85110/**
     
    121146
    122147/**
    123  * Creates a file URI. The returned pointer must be freed
    124  * using RTStrFree().
     148 * Creates a file URI.
     149 *
     150 * The returned pointer must be freed using RTStrFree().
    125151 *
    126152 * @see RTUriCreate
    127153 *
    128  * @returns the new URI on success, NULL otherwise.
     154 * @returns The new URI on success, NULL otherwise.  Free With RTStrFree.
    129155 * @param   pszPath             The path of the URI.
    130156 */
  • trunk/src/VBox/Runtime/common/misc/http.cpp

    r57624 r57720  
    6868    /** Whether to delete the CA on destruction. */
    6969    bool                fDeleteCaFile;
     70    /** Set if we should use the system proxy settings for a URL.
     71     * This means reconfiguring cURL for each request.  */
     72    bool                fUseSystemProxySettings;
    7073    /** Abort the current HTTP request if true. */
    7174    bool volatile       fAbort;
     
    159162            if (pThis)
    160163            {
    161                 pThis->u32Magic = RTHTTP_MAGIC;
    162                 pThis->pCurl    = pCurl;
     164                pThis->u32Magic                 = RTHTTP_MAGIC;
     165                pThis->pCurl                    = pCurl;
     166                pThis->fUseSystemProxySettings  = true;
    163167
    164168                *phHttp = (RTHTTP)pThis;
     
    261265    else if (rc == VERR_ENV_VAR_NOT_FOUND)
    262266        rc = VINF_SUCCESS;
     267
     268    return rc;
     269}
     270
     271
     272static bool rtHttpUrlInNoProxyList(const char *pszUrl,  const char *pszNoProxyList)
     273{
     274    /** @todo implement me. */
     275    return false;
     276}
     277
     278
     279static int rtHttpConfigureProxyForUrl(PRTHTTPINTERNAL pThis, const char *pszUrl)
     280{
     281    const char *pszProxy    = NULL;
     282    long        uPort       = 0;
     283    const char *pszUser     = NULL;
     284    const char *pszPassword = NULL;
     285    bool        fNoProxy    = true;
     286
     287
     288    char szTmp[_1K];
     289
     290    /*
     291     * First we consult the "no_proxy" / "NO_PROXY" environment variable.
     292     */
     293    const char *pszNoProxyVar;
     294    size_t cchActual;
     295    char  *pszNoProxyFree = NULL;
     296    char  *pszNoProxy = szTmp;
     297    int rc = RTEnvGetEx(RTENV_DEFAULT, pszNoProxyVar = "no_proxy", szTmp, sizeof(szTmp), &cchActual);
     298    if (rc == VERR_ENV_VAR_NOT_FOUND)
     299        rc = RTEnvGetEx(RTENV_DEFAULT, pszNoProxyVar = "NO_PROXY", szTmp, sizeof(szTmp), &cchActual);
     300    if (rc == VERR_BUFFER_OVERFLOW)
     301    {
     302        pszNoProxyFree = pszNoProxy = (char *)RTMemTmpAlloc(cchActual + _1K);
     303        AssertReturn(pszNoProxy, VERR_NO_TMP_MEMORY);
     304        rc = RTEnvGetEx(RTENV_DEFAULT, pszNoProxyVar, pszNoProxy, cchActual + _1K, NULL);
     305    }
     306    AssertMsg(rc == VINF_SUCCESS || rc == VERR_ENV_VAR_NOT_FOUND, ("rc=%Rrc\n", rc));
     307    fNoProxy = rtHttpUrlInNoProxyList(pszUrl, pszNoProxy);
     308    RTMemTmpFree(pszNoProxy);
     309    if (!fNoProxy)
     310    {
     311        /*
     312         * Get the schema specific specific env var, falling back on the
     313         * generic all_proxy if not found.
     314         */
     315        const char *apszEnvVars[4];
     316        unsigned    cEnvVars = 0;
     317        if (!RTStrNICmp(pszUrl, RT_STR_TUPLE("http:")))
     318            apszEnvVars[cEnvVars++] = "http_proxy"; /* Skip HTTP_PROXY because of cgi paranoia */
     319        else if (!RTStrNICmp(pszUrl, RT_STR_TUPLE("https:")))
     320        {
     321            apszEnvVars[cEnvVars++] = "https_proxy";
     322            apszEnvVars[cEnvVars++] = "HTTPS_PROXY";
     323        }
     324        else if (!RTStrNICmp(pszUrl, RT_STR_TUPLE("ftp:")))
     325        {
     326            apszEnvVars[cEnvVars++] = "ftp_proxy";
     327            apszEnvVars[cEnvVars++] = "FTP_PROXY";
     328        }
     329        else
     330            AssertMsgFailedReturn(("Unknown/unsupported schema in URL: '%s'\n", pszUrl), VERR_NOT_SUPPORTED);
     331        apszEnvVars[cEnvVars++] = "all_proxy";
     332        apszEnvVars[cEnvVars++] = "ALL_PROXY";
     333
     334        for (uint32_t i = 0; i < cEnvVars; i++)
     335        {
     336            size_t cchValue;
     337            rc = RTEnvGetEx(RTENV_DEFAULT, apszEnvVars[i], szTmp, sizeof(szTmp) - sizeof("http://"), &cchValue);
     338            if (RT_SUCCESS(rc))
     339            {
     340                if (!strstr(szTmp, "://"))
     341                {
     342                    memmove(&szTmp[sizeof("http://") - 1], szTmp, cchValue + 1);
     343                    memcpy(szTmp, RT_STR_TUPLE("http://"));
     344                }
     345                /** @todo continue where using RTUriParse... */
     346            }
     347            else
     348                AssertMsg(rc == VERR_ENV_VAR_NOT_FOUND, ("%Rrc\n"));
     349        }
     350
     351#if 0
     352        if (RT_SUCCESS(rc))
     353        {
     354            int rcCurl;
     355            if (!strncmp(szProxy, RT_STR_TUPLE("http://")))
     356            {
     357                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]);
     358                if (CURL_FAILURE(rcCurl))
     359                    return VERR_INVALID_PARAMETER;
     360                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXYPORT, 80);
     361                if (CURL_FAILURE(rcCurl))
     362                    return VERR_INVALID_PARAMETER;
     363            }
     364            else
     365            {
     366                rcCurl = curl_easy_setopt(pThis->pCurl, CURLOPT_PROXY, &szProxy[sizeof("http://") - 1]);
     367                if (CURL_FAILURE(rcCurl))
     368                    return VERR_INVALID_PARAMETER;
     369            }
     370        }
     371        else if (rc == VERR_ENV_VAR_NOT_FOUND)
     372            rc = VINF_SUCCESS;
     373#endif
     374    }
    263375
    264376    return rc;
  • trunk/src/VBox/Runtime/common/misc/uri.cpp

    r57358 r57720  
    3131#include <iprt/uri.h>
    3232
     33#include <iprt/assert.h>
     34#include <iprt/ctype.h>
     35#include <iprt/path.h>
    3336#include <iprt/string.h>
    34 #include <iprt/mem.h>
    35 #include <iprt/path.h>
    36 #include <iprt/stream.h>
    3737
    3838/* General URI format:
     
    4747*/
    4848
     49/**
     50 * Parsed URI.
     51 */
     52typedef struct RTURIPARSED
     53{
     54    /** RTURIPARSED_F_XXX. */
     55    uint32_t    fFlags;
     56
     57    /** The length of the scheme. */
     58    size_t      cchScheme;
     59
     60    /** The offset into the string of the authority. */
     61    size_t      offAuthority;
     62    /** The authority length.
     63     * @remarks The authority component can be zero length, so to check whether
     64     *          it's there or not consult RTURIPARSED_F_HAVE_AUTHORITY. */
     65    size_t      cchAuthority;
     66
     67    /** The offset into the string of the path. */
     68    size_t      offPath;
     69    /** The length of the path. */
     70    size_t      cchPath;
     71
     72    /** The offset into the string of the query. */
     73    size_t      offQuery;
     74    /** The length of the query. */
     75    size_t      cchQuery;
     76
     77    /** The offset into the string of the fragment. */
     78    size_t      offFragment;
     79    /** The length of the fragment. */
     80    size_t      cchFragment;
     81
     82    /** @name Authority subdivisions
     83     * @{ */
     84    /** If there is a userinfo part, this is the start of it. Otherwise it's the
     85     * same as offAuthorityHost. */
     86    size_t      offAuthorityUsername;
     87    /** The length of the username (zero if not present). */
     88    size_t      cchAuthorityUsername;
     89    /** If there is a userinfo part containing a password, this is the start of it.
     90     * Otherwise it's the same as offAuthorityHost. */
     91    size_t      offAuthorityPassword;
     92    /** The length of the password (zero if not present). */
     93    size_t      cchAuthorityPassword;
     94    /** The offset of the host part of the authority. */
     95    size_t      offAuthorityHost;
     96    /** The length of the host part of the authority. */
     97    size_t      cchAuthorityHost;
     98    /** The authority port number, UINT32_MAX if not present. */
     99    uint32_t    uAuthorityPort;
     100    /** @} */
     101} RTURIPARSED;
     102/** Pointer to a parsed URI. */
     103typedef RTURIPARSED *PRTURIPARSED;
     104/** Set if the URI contains escaped characters. */
     105#define RTURIPARSED_F_CONTAINS_ESCAPED_CHARS        UINT32_C(0x00000001)
     106/** Set if the URI have an authority component.  Necessary since the authority
     107 * component can have a zero length. */
     108#define RTURIPARSED_F_HAVE_AUTHORITY                UINT32_C(0x00000002)
     109
     110
    49111
    50112/*********************************************************************************************************************************
    51 *   Private RTUri helper                                                                                                         *
     113*   Internal Functions                                                                                                           *
    52114*********************************************************************************************************************************/
    53115
    54 /* The following defines characters which have to be % escaped:
    55    control = 00-1F
    56    space   = ' '
    57    delims  = '<' , '>' , '#' , '%' , '"'
    58    unwise  = '{' , '}' , '|' , '\' , '^' , '[' , ']' , '`'
    59 */
     116/**
     117 * The following defines characters which have to be % escaped:
     118 *  control = 00-1F
     119 *  space   = ' '
     120 *  delims  = '<' , '>' , '#' , '%' , '"'
     121 *  unwise  = '{' , '}' , '|' , '\' , '^' , '[' , ']' , '`'
     122 */
    60123#define URI_EXCLUDED(a) \
    61      ((a) >= 0x0  && (a) <= 0x20) \
    62   || ((a) >= 0x5B && (a) <= 0x5E) \
    63   || ((a) >= 0x7B && (a) <= 0x7D) \
    64   || (a) == '<' || (a) == '>' || (a) == '#' \
    65   || (a) == '%' || (a) == '"' || (a) == '`'
     124  (   ((a) >= 0x0  && (a) <= 0x20) \
     125   || ((a) >= 0x5B && (a) <= 0x5E) \
     126   || ((a) >= 0x7B && (a) <= 0x7D) \
     127   || (a) == '<' || (a) == '>' || (a) == '#' \
     128   || (a) == '%' || (a) == '"' || (a) == '`' )
    66129
    67130static char *rtUriPercentEncodeN(const char *pszString, size_t cchMax)
     
    74137    size_t cbLen = RT_MIN(strlen(pszString), cchMax);
    75138    /* The new string can be max 3 times in size of the original string. */
    76     char *pszNew = (char*)RTMemAlloc(cbLen * 3 + 1);
     139    char *pszNew = RTStrAlloc(cbLen * 3 + 1);
    77140    if (!pszNew)
    78141        return NULL;
     142
    79143    char *pszRes = NULL;
    80144    size_t iIn = 0;
    81145    size_t iOut = 0;
    82     while(iIn < cbLen)
     146    while (iIn < cbLen)
    83147    {
    84148        if (URI_EXCLUDED(pszString[iIn]))
     
    117181        return NULL;
    118182
    119     int rc = VINF_SUCCESS;
    120     size_t cbLen = RT_MIN(strlen(pszString), cchMax);
    121183    /* The new string can only get smaller. */
    122     char *pszNew = (char*)RTMemAlloc(cbLen + 1);
     184    size_t cchLen = strlen(pszString);
     185    cchLen = RT_MIN(cchLen, cchMax);
     186    char *pszNew = RTStrAlloc(cchLen + 1);
    123187    if (!pszNew)
    124188        return NULL;
     189
     190    int rc = VINF_SUCCESS;
    125191    char *pszRes = NULL;
    126192    size_t iIn = 0;
    127193    size_t iOut = 0;
    128     while(iIn < cbLen)
     194    while (iIn < cchLen)
    129195    {
    130196        if (pszString[iIn] == '%')
     
    169235static bool rtUriFindSchemeEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
    170236{
     237    /* The scheme has to end with ':'. */
    171238    size_t i = iStart;
    172     /* The scheme has to end with ':'. */
    173     while(i < iStart + cbLen)
     239    while (i < iStart + cbLen)
    174240    {
    175241        if (pszUri[i] == ':')
     
    199265static bool rtUriFindAuthorityEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
    200266{
     267    /* The authority can end with '/' || '?' || '#'. */
    201268    size_t i = iStart;
    202     /* The authority can end with '/' || '?' || '#'. */
    203     while(i < iStart + cbLen)
     269    while (i < iStart + cbLen)
    204270    {
    205271        if (   pszUri[i] == '/'
     
    224290        return true;
    225291    }
     292
    226293    /* '?' || '#' means there is no path. */
    227294    if (   cbLen >= 1
     
    229296            || pszUri[iStart] == '#'))
    230297        return false;
     298
    231299    /* All other values are allowed. */
    232300    *piStart = iStart;
     
    236304static bool rtUriFindPathEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
    237305{
     306    /* The path can end with '?' || '#'. */
    238307    size_t i = iStart;
    239     /* The path can end with '?' || '#'. */
    240     while(i < iStart + cbLen)
     308    while (i < iStart + cbLen)
    241309    {
    242310        if (   pszUri[i] == '?'
     
    251319}
    252320
    253 static bool rtUriCheckQueryStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
    254 {
    255     /* The query start with a '?'. */
    256     if (   cbLen >= 1
    257         && pszUri[iStart] == '?')
    258     {
    259         *piStart = iStart + 1; /* Excluding '?' */
    260         return true;
    261     }
    262     return false;
    263 }
    264 
    265 static bool rtUriFindQueryEnd(const char *pszUri, size_t iStart, size_t cbLen, size_t *piEnd)
    266 {
    267     size_t i = iStart;
    268     /* The query can end with '?' || '#'. */
    269     while(i < iStart + cbLen)
    270     {
    271         if (pszUri[i] == '#')
    272         {
    273             *piEnd = i;
    274             return true;
    275         }
    276         ++i;
    277     }
    278     return false;
    279 }
    280 
    281 static bool rtUriCheckFragmentStart(const char *pszUri, size_t iStart, size_t cbLen, size_t *piStart)
    282 {
    283     /* The fragment start with a '#'. */
    284     if (   cbLen >= 1
    285         && pszUri[iStart] == '#')
    286     {
    287         *piStart = iStart + 1; /* Excluding '#' */
    288         return true;
    289     }
    290     return false;
     321static int rtUriParse(const char *pszUri, PRTURIPARSED pParsed)
     322{
     323    /*
     324     * Validate the input and clear the output.
     325     */
     326    AssertPtrReturn(pParsed, VERR_INVALID_POINTER);
     327    RT_ZERO(*pParsed);
     328    pParsed->uAuthorityPort = UINT32_MAX;
     329
     330    AssertPtrReturn(pszUri, VERR_INVALID_POINTER);
     331    size_t const cchUri = strlen(pszUri);
     332    if (RT_LIKELY(cchUri >= 3)) { /* likely */ }
     333    else return cchUri ? VERR_URI_TOO_SHORT : VERR_URI_EMPTY;
     334
     335    /*
     336     * RFC-3986, section 3.1:
     337     *      scheme = ALPHA *( ALPHA / DIGIT / "+" / "-" / "." )
     338     *
     339     * The scheme ends with a ':', which we also skip here.
     340     */
     341    size_t off = 0;
     342    char ch = pszUri[off++];
     343    if (RT_LIKELY(RT_C_IS_ALPHA(ch))) { /* likely */ }
     344    else return VERR_URI_INVALID_SCHEME;
     345    for (;;)
     346    {
     347        ch = pszUri[off];
     348        if (ch == ':')
     349            break;
     350        if (RT_LIKELY(RT_C_IS_ALNUM(ch) || ch == '.' || ch == '-' || ch == '+')) { /* likely */ }
     351        else return VERR_URI_INVALID_SCHEME;
     352        off++;
     353    }
     354    pParsed->cchScheme = off;
     355
     356    /* Require the scheme length to be at least two chars so we won't confuse
     357       it with a path starting with a DOS drive letter specification. */
     358    if (RT_LIKELY(off >= 2)) { /* likely */ }
     359    else return VERR_URI_INVALID_SCHEME;
     360
     361    off++;                              /* (skip colon) */
     362
     363    /*
     364     * Find the end of the path, we'll need this several times.
     365     * Also, while we're potentially scanning the whole thing, check for '%'.
     366     */
     367    size_t const offHash         = RTStrOffCharOrTerm(&pszUri[off], '#') + off;
     368    size_t const offQuestionMark = RTStrOffCharOrTerm(&pszUri[off], '?') + off;
     369
     370    if (memchr(pszUri, '%', cchUri) != NULL)
     371        pParsed->fFlags |= RTURIPARSED_F_CONTAINS_ESCAPED_CHARS;
     372
     373    /*
     374     * RFC-3986, section 3.2:
     375     *      The authority component is preceeded by a double slash ("//")...
     376     */
     377    if (   pszUri[off] == '/'
     378        && pszUri[off + 1] == '/')
     379    {
     380        off += 2;
     381        pParsed->offAuthority = pParsed->offAuthorityUsername = pParsed->offAuthorityPassword = pParsed->offAuthorityHost = off;
     382        pParsed->fFlags |= RTURIPARSED_F_HAVE_AUTHORITY;
     383
     384        /*
     385         * RFC-3986, section 3.2:
     386         *      ...and is terminated by the next slash ("/"), question mark ("?"),
     387         *       or number sign ("#") character, or by the end of the URI.
     388         */
     389        const char *pszAuthority = &pszUri[off];
     390        size_t      cchAuthority = RTStrOffCharOrTerm(pszAuthority, '/');
     391        cchAuthority = RT_MIN(cchAuthority, offHash - off);
     392        cchAuthority = RT_MIN(cchAuthority, offQuestionMark - off);
     393        pParsed->cchAuthority     = cchAuthority;
     394
     395        /* The Authority can be empty, like for: file:///usr/bin/grep  */
     396        if (cchAuthority > 0)
     397        {
     398            pParsed->cchAuthorityHost = cchAuthority;
     399
     400            /*
     401             * If there is a userinfo part, it is ended by a '@'.
     402             */
     403            const char *pszAt = (const char *)memchr(pszAuthority, '@', cchAuthority);
     404            if (pszAt)
     405            {
     406                size_t cchTmp = pszAt - pszAuthority;
     407                pParsed->offAuthorityHost += cchTmp + 1;
     408                pParsed->cchAuthorityHost -= cchTmp + 1;
     409
     410                /* If there is a password part, it's separated from the username with a colon. */
     411                const char *pszColon = (const char *)memchr(pszAuthority, ':', cchTmp);
     412                if (pszColon)
     413                {
     414                    pParsed->cchAuthorityUsername = pszColon - pszAuthority;
     415                    pParsed->offAuthorityPassword = &pszColon[1] - pszUri;
     416                    pParsed->cchAuthorityPassword = pszAt - &pszColon[1];
     417                }
     418                else
     419                {
     420                    pParsed->cchAuthorityUsername = cchTmp;
     421                    pParsed->offAuthorityPassword = off + cchTmp;
     422                }
     423            }
     424
     425            /*
     426             * If there is a port part, its after the last colon in the host part.
     427             */
     428            const char *pszColon = (const char *)memrchr(&pszUri[pParsed->offAuthorityHost], ':', pParsed->cchAuthorityHost);
     429            if (pszColon)
     430            {
     431                size_t cchTmp = &pszUri[pParsed->offAuthorityHost + pParsed->cchAuthorityHost] - &pszColon[1];
     432                pParsed->cchAuthorityHost -= cchTmp + 1;
     433
     434                pParsed->uAuthorityPort = 0;
     435                while (cchTmp-- > 0)
     436                {
     437                    ch = *++pszColon;
     438                    if (   RT_C_IS_DIGIT(ch)
     439                        && pParsed->uAuthorityPort < UINT32_MAX / UINT32_C(10))
     440                    {
     441                        pParsed->uAuthorityPort *= 10;
     442                        pParsed->uAuthorityPort += ch - '0';
     443                    }
     444                    else
     445                        return VERR_URI_INVALID_PORT_NUMBER;
     446                }
     447            }
     448        }
     449
     450        /* Skip past the authority. */
     451        off += cchAuthority;
     452    }
     453    else
     454        pParsed->offAuthority = pParsed->offAuthorityUsername = pParsed->offAuthorityPassword = pParsed->offAuthorityHost = off;
     455
     456    /*
     457     * RFC-3986, section 3.3: Path
     458     *      The path is terminated by the first question mark ("?")
     459     *      or number sign ("#") character, or by the end of the URI.
     460     */
     461    pParsed->offPath = off;
     462    pParsed->cchPath = RT_MIN(offHash, offQuestionMark) - off;
     463    off += pParsed->cchPath;
     464
     465    /*
     466     * RFC-3986, section 3.4: Query
     467     *      The query component is indicated by the first question mark ("?")
     468     *      character and terminated by a number sign ("#") character or by the
     469     *      end of the URI.
     470     */
     471    if (   off == offQuestionMark
     472        && off < cchUri)
     473    {
     474        Assert(pszUri[offQuestionMark] == '?');
     475        pParsed->offQuery = ++off;
     476        pParsed->cchQuery = offHash - off;
     477        off = offHash;
     478    }
     479    else
     480    {
     481        Assert(!pszUri[offQuestionMark]);
     482        pParsed->offQuery = off;
     483    }
     484
     485    /*
     486     * RFC-3986, section 3.5: Fragment
     487     *      A fragment identifier component is indicated by the presence of a
     488     *      number sign ("#") character and terminated by the end of the URI.
     489     */
     490    if (   off == offHash
     491        && off < cchUri)
     492    {
     493        pParsed->offFragment = ++off;
     494        pParsed->cchFragment = cchUri - off;
     495    }
     496    else
     497    {
     498        Assert(!pszUri[offHash]);
     499        pParsed->offFragment = off;
     500    }
     501
     502    return VINF_SUCCESS;
    291503}
    292504
    293505
    294506/*********************************************************************************************************************************
    295 *   Public RTUri interface                                                                                                       *
     507*   Generic URI APIs                                                                                                             *
    296508*********************************************************************************************************************************/
    297509
    298 
    299 /*********************************************************************************************************************************
    300 *   Generic Uri methods                                                                                                          *
    301 *********************************************************************************************************************************/
    302 
    303 RTR3DECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment)
     510RTR3DECL(char *) RTUriCreate(const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery,
     511                             const char *pszFragment)
    304512{
    305513    if (!pszScheme) /* Scheme is minimum requirement */
     
    346554        }
    347555
    348         char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
     556        char *pszTmp = pszResult = (char *)RTStrAlloc(cbSize);
    349557        if (!pszResult)
    350558            break;
     559        RT_BZERO(pszTmp, cbSize);
     560
    351561        /* Compose the target uri string. */
    352562        RTStrCatP(&pszTmp, &cbSize, pszScheme);
     
    371581            RTStrCatP(&pszTmp, &cbSize, pszFragment1);
    372582        }
    373     }while (0);
     583    } while (0);
    374584
    375585    /* Cleanup */
     
    411621RTR3DECL(char *) RTUriAuthority(const char *pszUri)
    412622{
     623    RTURIPARSED Parsed;
     624    int rc = rtUriParse(pszUri, &Parsed);
     625    if (RT_SUCCESS(rc))
     626        if (Parsed.cchAuthority || (Parsed.fFlags & RTURIPARSED_F_HAVE_AUTHORITY))
     627            return rtUriPercentDecodeN(&pszUri[Parsed.offAuthority], Parsed.cchAuthority);
     628    return NULL;
     629}
     630
     631RTR3DECL(char *) RTUriAuthorityUsername(const char *pszUri)
     632{
     633    RTURIPARSED Parsed;
     634    int rc = rtUriParse(pszUri, &Parsed);
     635    if (RT_SUCCESS(rc))
     636        if (Parsed.cchAuthorityUsername)
     637            return rtUriPercentDecodeN(&pszUri[Parsed.offAuthorityUsername], Parsed.cchAuthorityUsername);
     638    return NULL;
     639}
     640
     641RTR3DECL(char *) RTUriAuthorityPassword(const char *pszUri)
     642{
     643    RTURIPARSED Parsed;
     644    int rc = rtUriParse(pszUri, &Parsed);
     645    if (RT_SUCCESS(rc))
     646        if (Parsed.cchAuthorityPassword)
     647            return rtUriPercentDecodeN(&pszUri[Parsed.offAuthorityPassword], Parsed.cchAuthorityPassword);
     648    return NULL;
     649}
     650
     651RTR3DECL(uint32_t) RTUriAuthorityPort(const char *pszUri)
     652{
     653    RTURIPARSED Parsed;
     654    int rc = rtUriParse(pszUri, &Parsed);
     655    if (RT_SUCCESS(rc))
     656        return Parsed.uAuthorityPort;
     657    return UINT32_MAX;
     658}
     659
     660RTR3DECL(char *) RTUriPath(const char *pszUri)
     661{
     662    RTURIPARSED Parsed;
     663    int rc = rtUriParse(pszUri, &Parsed);
     664    if (RT_SUCCESS(rc))
     665        if (Parsed.cchPath)
     666            return rtUriPercentDecodeN(&pszUri[Parsed.offPath], Parsed.cchPath);
     667    return NULL;
     668}
     669
     670RTR3DECL(char *) RTUriQuery(const char *pszUri)
     671{
     672    RTURIPARSED Parsed;
     673    int rc = rtUriParse(pszUri, &Parsed);
     674    if (RT_SUCCESS(rc))
     675        if (Parsed.cchQuery)
     676            return rtUriPercentDecodeN(&pszUri[Parsed.offQuery], Parsed.cchQuery);
     677    return NULL;
     678}
     679
     680RTR3DECL(char *) RTUriFragment(const char *pszUri)
     681{
     682    RTURIPARSED Parsed;
     683    int rc = rtUriParse(pszUri, &Parsed);
     684    if (RT_SUCCESS(rc))
     685        if (Parsed.cchFragment)
     686            return rtUriPercentDecodeN(&pszUri[Parsed.offFragment], Parsed.cchFragment);
     687    return NULL;
     688}
     689
     690
     691/*********************************************************************************************************************************
     692*   File URI APIs                                                                                                                *
     693*********************************************************************************************************************************/
     694
     695RTR3DECL(char *) RTUriFileCreate(const char *pszPath)
     696{
     697    char *pszResult = NULL;
     698    if (pszPath)
     699    {
     700        /* Create the percent encoded strings and calculate the necessary uri length. */
     701        char *pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
     702        if (pszPath1)
     703        {
     704            size_t cbSize = 7 /* file:// */ + strlen(pszPath1) + 1; /* plus zero byte */
     705            if (pszPath1[0] != '/')
     706                ++cbSize;
     707            char *pszTmp = pszResult = RTStrAlloc(cbSize);
     708            if (pszResult)
     709            {
     710                /* Compose the target uri string. */
     711                *pszTmp = '\0';
     712                RTStrCatP(&pszTmp, &cbSize, "file://");
     713                if (pszPath1[0] != '/')
     714                    RTStrCatP(&pszTmp, &cbSize, "/");
     715                RTStrCatP(&pszTmp, &cbSize, pszPath1);
     716            }
     717            RTStrFree(pszPath1);
     718        }
     719    }
     720    return pszResult;
     721}
     722
     723RTR3DECL(char *) RTUriFilePath(const char *pszUri, uint32_t uFormat)
     724{
     725    return RTUriFileNPath(pszUri, uFormat, RTSTR_MAX);
     726}
     727
     728RTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax)
     729{
    413730    AssertPtrReturn(pszUri, NULL);
    414 
    415     size_t iPos1;
    416     size_t cbLen = strlen(pszUri);
    417     /* Find the end of the scheme. */
    418     if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
    419         return NULL; /* no URI */
    420     else
    421         ++iPos1; /* Skip ':' */
    422 
    423     size_t iPos2;
    424     /* Find the start of the authority. */
    425     if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
    426     {
    427         size_t iPos3 = cbLen;
    428         /* Find the end of the authority. If not found, the rest of the string
    429          * is used. */
    430         rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3);
    431         if (iPos3 > iPos2) /* Length check */
    432             return rtUriPercentDecodeN(&pszUri[iPos2], iPos3 - iPos2);
    433         else
    434             return NULL;
     731    AssertReturn(uFormat == URI_FILE_FORMAT_AUTO || uFormat == URI_FILE_FORMAT_UNIX || uFormat == URI_FILE_FORMAT_WIN, NULL);
     732
     733    /* Auto is based on the current OS. */
     734    if (uFormat == URI_FILE_FORMAT_AUTO)
     735#if defined(RT_OS_WINDOWS) || defined(RT_OS_OS2)
     736        uFormat = URI_FILE_FORMAT_WIN;
     737#else
     738        uFormat = URI_FILE_FORMAT_UNIX;
     739#endif
     740
     741    /* Check that this is a file Uri */
     742    if (RTStrNICmp(pszUri, RT_STR_TUPLE("file:")) != 0)
     743        return NULL;
     744
     745    RTURIPARSED Parsed;
     746    int rc = rtUriParse(pszUri, &Parsed);
     747    if (RT_SUCCESS(rc) && Parsed.cchPath)
     748    {
     749        /* Special hack for DOS path like file:///c:/WINDOWS/clock.avi where we
     750           have to drop the leading slash that was used to separate the authority
     751           from the path. */
     752        if (  uFormat == URI_FILE_FORMAT_WIN
     753            && Parsed.cchPath >= 3
     754            && pszUri[Parsed.offPath] == '/'
     755            && pszUri[Parsed.offPath + 2] == ':'
     756            && RT_C_IS_ALPHA(pszUri[Parsed.offPath + 1]) )
     757        {
     758            Parsed.offPath++;
     759            Parsed.cchPath--;
     760        }
     761
     762        char *pszPath = rtUriPercentDecodeN(&pszUri[Parsed.offPath], Parsed.cchPath);
     763        if (uFormat == URI_FILE_FORMAT_UNIX)
     764            return RTPathChangeToUnixSlashes(pszPath, true);
     765        Assert(uFormat == URI_FILE_FORMAT_WIN);
     766        return RTPathChangeToDosSlashes(pszPath, true);
    435767    }
    436768    return NULL;
    437769}
    438770
    439 RTR3DECL(char *) RTUriPath(const char *pszUri)
    440 {
    441     AssertPtrReturn(pszUri, NULL);
    442 
    443     size_t iPos1;
    444     size_t cbLen = strlen(pszUri);
    445     /* Find the end of the scheme. */
    446     if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
    447         return NULL; /* no URI */
    448     else
    449         ++iPos1; /* Skip ':' */
    450 
    451     size_t iPos2;
    452     size_t iPos3 = iPos1; /* Skip if no authority is found */
    453     /* Find the start of the authority. */
    454     if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
    455     {
    456         /* Find the end of the authority. If not found, then there is no path
    457          * component, cause the authority is the rest of the string. */
    458         if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
    459             return NULL; /* no path! */
    460     }
    461 
    462     size_t iPos4;
    463     /* Find the start of the path */
    464     if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
    465     {
    466         /* Search for the end of the scheme. */
    467         size_t iPos5 = cbLen;
    468         rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
    469         if (iPos5 > iPos4) /* Length check */
    470             return rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
    471     }
    472 
    473     return NULL;
    474 }
    475 
    476 RTR3DECL(char *) RTUriQuery(const char *pszUri)
    477 {
    478     AssertPtrReturn(pszUri, NULL);
    479 
    480     size_t iPos1;
    481     size_t cbLen = strlen(pszUri);
    482     /* Find the end of the scheme. */
    483     if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
    484         return NULL; /* no URI */
    485     else
    486         ++iPos1; /* Skip ':' */
    487 
    488     size_t iPos2;
    489     size_t iPos3 = iPos1; /* Skip if no authority is found */
    490     /* Find the start of the authority. */
    491     if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
    492     {
    493         /* Find the end of the authority. If not found, then there is no path
    494          * component, cause the authority is the rest of the string. */
    495         if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
    496             return NULL; /* no path! */
    497     }
    498 
    499     size_t iPos4;
    500     size_t iPos5 = iPos3; /* Skip if no path is found */
    501     /* Find the start of the path */
    502     if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
    503     {
    504         /* Find the end of the path. If not found, then there is no query
    505          * component, cause the path is the rest of the string. */
    506         if (!rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5))
    507             return NULL; /* no query! */
    508     }
    509 
    510     size_t iPos6;
    511     /* Find the start of the query */
    512     if (rtUriCheckQueryStart(pszUri, iPos5, cbLen - iPos5, &iPos6))
    513     {
    514         /* Search for the end of the query. */
    515         size_t iPos7 = cbLen;
    516         rtUriFindQueryEnd(pszUri, iPos6, cbLen - iPos6, &iPos7);
    517         if (iPos7 > iPos6) /* Length check */
    518             return rtUriPercentDecodeN(&pszUri[iPos6], iPos7 - iPos6);
    519     }
    520 
    521     return NULL;
    522 }
    523 
    524 RTR3DECL(char *) RTUriFragment(const char *pszUri)
    525 {
    526     AssertPtrReturn(pszUri, NULL);
    527 
    528     size_t iPos1;
    529     size_t cbLen = strlen(pszUri);
    530     /* Find the end of the scheme. */
    531     if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
    532         return NULL; /* no URI */
    533     else
    534         ++iPos1; /* Skip ':' */
    535 
    536     size_t iPos2;
    537     size_t iPos3 = iPos1; /* Skip if no authority is found */
    538     /* Find the start of the authority. */
    539     if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
    540     {
    541         /* Find the end of the authority. If not found, then there is no path
    542          * component, cause the authority is the rest of the string. */
    543         if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
    544             return NULL; /* no path! */
    545     }
    546 
    547     size_t iPos4;
    548     size_t iPos5 = iPos3; /* Skip if no path is found */
    549     /* Find the start of the path */
    550     if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
    551     {
    552         /* Find the end of the path. If not found, then there is no query
    553          * component, cause the path is the rest of the string. */
    554         if (!rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5))
    555             return NULL; /* no query! */
    556     }
    557 
    558     size_t iPos6;
    559     size_t iPos7 = iPos5; /* Skip if no query is found */
    560     /* Find the start of the query */
    561     if (rtUriCheckQueryStart(pszUri, iPos5, cbLen - iPos5, &iPos6))
    562     {
    563         /* Find the end of the query If not found, then there is no fragment
    564          * component, cause the query is the rest of the string. */
    565         if (!rtUriFindQueryEnd(pszUri, iPos6, cbLen - iPos6, &iPos7))
    566             return NULL; /* no query! */
    567     }
    568 
    569 
    570     size_t iPos8;
    571     /* Find the start of the fragment */
    572     if (rtUriCheckFragmentStart(pszUri, iPos7, cbLen - iPos7, &iPos8))
    573     {
    574         /* There could be nothing behind a fragment. So use the rest of the
    575          * string. */
    576         if (cbLen > iPos8) /* Length check */
    577             return rtUriPercentDecodeN(&pszUri[iPos8], cbLen - iPos8);
    578     }
    579     return NULL;
    580 }
    581 
    582 
    583 /*********************************************************************************************************************************
    584 *   File Uri methods                                                                                                             *
    585 *********************************************************************************************************************************/
    586 
    587 RTR3DECL(char *) RTUriFileCreate(const char *pszPath)
    588 {
    589     if (!pszPath)
    590         return NULL;
    591 
    592     char *pszResult = 0;
    593     char *pszPath1 = 0;
    594 
    595     do
    596     {
    597         /* Create the percent encoded strings and calculate the necessary uri
    598          * length. */
    599         pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
    600         if (!pszPath1)
    601             break;
    602         size_t cbSize = 7 /* file:// */ + strlen(pszPath1) + 1; /* plus zero byte */
    603         if (pszPath1[0] != '/')
    604             ++cbSize;
    605         char *pszTmp = pszResult = (char*)RTMemAllocZ(cbSize);
    606         if (!pszResult)
    607             break;
    608         /* Compose the target uri string. */
    609         RTStrCatP(&pszTmp, &cbSize, "file://");
    610         if (pszPath1[0] != '/')
    611             RTStrCatP(&pszTmp, &cbSize, "/");
    612         RTStrCatP(&pszTmp, &cbSize, pszPath1);
    613     }while (0);
    614 
    615     /* Cleanup */
    616     if (pszPath1)
    617         RTStrFree(pszPath1);
    618 
    619     return pszResult;
    620 }
    621 
    622 RTR3DECL(char *) RTUriFilePath(const char *pszUri, uint32_t uFormat)
    623 {
    624     return RTUriFileNPath(pszUri, uFormat, RTSTR_MAX);
    625 }
    626 
    627 RTR3DECL(char *) RTUriFileNPath(const char *pszUri, uint32_t uFormat, size_t cchMax)
    628 {
    629     AssertPtrReturn(pszUri, NULL);
    630 
    631     size_t iPos1;
    632     size_t cbLen = RT_MIN(strlen(pszUri), cchMax);
    633     /* Find the end of the scheme. */
    634     if (!rtUriFindSchemeEnd(pszUri, 0, cbLen, &iPos1))
    635         return NULL; /* no URI */
    636     else
    637         ++iPos1; /* Skip ':' */
    638 
    639     /* Check that this is a file Uri */
    640     if (RTStrNICmp(pszUri, "file:", iPos1) != 0)
    641         return NULL;
    642 
    643     size_t iPos2;
    644     size_t iPos3 = iPos1; /* Skip if no authority is found */
    645     /* Find the start of the authority. */
    646     if (rtUriCheckAuthorityStart(pszUri, iPos1, cbLen - iPos1, &iPos2))
    647     {
    648         /* Find the end of the authority. If not found, then there is no path
    649          * component, cause the authority is the rest of the string. */
    650         if (!rtUriFindAuthorityEnd(pszUri, iPos2, cbLen - iPos2, &iPos3))
    651             return NULL; /* no path! */
    652     }
    653 
    654     size_t iPos4;
    655     /* Find the start of the path */
    656     if (rtUriCheckPathStart(pszUri, iPos3, cbLen - iPos3, &iPos4))
    657     {
    658         uint32_t uFIntern = uFormat;
    659         /* Auto is based on the current OS. */
    660         if (uFormat == URI_FILE_FORMAT_AUTO)
    661 #ifdef RT_OS_WINDOWS
    662             uFIntern = URI_FILE_FORMAT_WIN;
    663 #else /* RT_OS_WINDOWS */
    664             uFIntern = URI_FILE_FORMAT_UNIX;
    665 #endif /* !RT_OS_WINDOWS */
    666 
    667         if (   uFIntern != URI_FILE_FORMAT_UNIX
    668             && pszUri[iPos4] == '/')
    669             ++iPos4;
    670         /* Search for the end of the scheme. */
    671         size_t iPos5 = cbLen;
    672         rtUriFindPathEnd(pszUri, iPos4, cbLen - iPos4, &iPos5);
    673         if (iPos5 > iPos4) /* Length check */
    674         {
    675             char *pszPath = rtUriPercentDecodeN(&pszUri[iPos4], iPos5 - iPos4);
    676             if (uFIntern == URI_FILE_FORMAT_UNIX)
    677                 return RTPathChangeToUnixSlashes(pszPath, true);
    678             else if (uFIntern == URI_FILE_FORMAT_WIN)
    679                 return RTPathChangeToDosSlashes(pszPath, true);
    680             else
    681             {
    682                 RTStrFree(pszPath);
    683                 AssertMsgFailed(("Unknown uri file format %u", uFIntern));
    684                 return NULL;
    685             }
    686         }
    687     }
    688 
    689     return NULL;
    690 }
    691 
  • trunk/src/VBox/Runtime/testcase/tstRTUri.cpp

    r57358 r57720  
    4141*********************************************************************************************************************************/
    4242
     43static struct
     44{
     45    const char *pszUri;
     46    const char *pszScheme;
     47    const char *pszAuthority;
     48    const char *pszPath;
     49    const char *pszQuery;
     50    const char *pszFragment;
     51
     52    const char *pszUsername;
     53    const char *pszPassword;
     54    uint32_t    uPort;
     55} g_aTests[] =
     56{
     57    {   /* #0 */
     58        "foo://tt:[email protected]:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     59        /*.pszScheme    =*/ "foo",
     60        /*.pszAuthority =*/ "tt:[email protected]:8042",
     61        /*.pszPath      =*/ "/over/ <>#%\"{}|^[]`/there",
     62        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     63        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     64        /*.pszUsername  =*/ "tt",
     65        /*.pszPassword  =*/ "tt",
     66        /*.uPort        =*/ 8042,
     67    },
     68    {   /* #1 */
     69        "foo://tt:[email protected]:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret",
     70        /*.pszScheme    =*/ "foo",
     71        /*.pszAuthority =*/ "tt:[email protected]:8042",
     72        /*.pszPath      =*/ "/over/ <>#%\"{}|^[]`/there",
     73        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     74        /*.pszFragment  =*/ NULL,
     75        /*.pszUsername  =*/ "tt",
     76        /*.pszPassword  =*/ "tt",
     77        /*.uPort        =*/ 8042,
     78    },
     79    {   /* #2 */
     80        "foo://tt:[email protected]:8042/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there",
     81        /*.pszScheme    =*/ "foo",
     82        /*.pszAuthority =*/ "tt:[email protected]:8042",
     83        /*.pszPath      =*/ "/over/ <>#%\"{}|^[]`/there",
     84        /*.pszQuery     =*/ NULL,
     85        /*.pszFragment  =*/ NULL,
     86        /*.pszUsername  =*/ "tt",
     87        /*.pszPassword  =*/ "tt",
     88        /*.uPort        =*/ 8042,
     89    },
     90    {   /* #3 */
     91        "foo:[email protected]",
     92        /*.pszScheme    =*/ "foo",
     93        /*.pszAuthority =*/ NULL,
     94        /*.pszPath      =*/ "[email protected]",
     95        /*.pszQuery     =*/ NULL,
     96        /*.pszFragment  =*/ NULL,
     97        /*.pszUsername  =*/ NULL,
     98        /*.pszPassword  =*/ NULL,
     99        /*.uPort        =*/ UINT32_MAX,
     100    },
     101    {   /* #4 */
     102        "foo:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     103        /*.pszScheme    =*/ "foo",
     104        /*.pszAuthority =*/ NULL,
     105        /*.pszPath      =*/ "/over/ <>#%\"{}|^[]`/there",
     106        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     107        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     108        /*.pszUsername  =*/ NULL,
     109        /*.pszPassword  =*/ NULL,
     110        /*.uPort        =*/ UINT32_MAX,
     111    },
     112    {   /* #5 */
     113        "foo:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     114        /*.pszScheme    =*/ "foo",
     115        /*.pszAuthority =*/ NULL,
     116        /*.pszPath      =*/ "/over/ <>#%\"{}|^[]`/there",
     117        /*.pszQuery     =*/ NULL,
     118        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     119        /*.pszUsername  =*/ NULL,
     120        /*.pszPassword  =*/ NULL,
     121        /*.uPort        =*/ UINT32_MAX,
     122    },
     123    {   /* #6 */
     124        "urn:example:animal:ferret:nose",
     125        /*.pszScheme    =*/ "urn",
     126        /*.pszAuthority =*/ NULL,
     127        /*.pszPath      =*/ "example:animal:ferret:nose",
     128        /*.pszQuery     =*/ NULL,
     129        /*.pszFragment  =*/ NULL,
     130        /*.pszUsername  =*/ NULL,
     131        /*.pszPassword  =*/ NULL,
     132        /*.uPort        =*/ UINT32_MAX,
     133    },
     134    {   /* #7 */
     135        "foo:?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     136        /*.pszScheme    =*/ "foo",
     137        /*.pszAuthority =*/ NULL,
     138        /*.pszPath      =*/ NULL,
     139        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     140        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     141        /*.pszUsername  =*/ NULL,
     142        /*.pszPassword  =*/ NULL,
     143        /*.uPort        =*/ UINT32_MAX,
     144    },
     145    {   /* #8 */
     146        "foo:#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     147        /*.pszScheme    =*/ "foo",
     148        /*.pszAuthority =*/ NULL,
     149        /*.pszPath      =*/ NULL,
     150        /*.pszQuery     =*/ NULL,
     151        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     152        /*.pszUsername  =*/ NULL,
     153        /*.pszPassword  =*/ NULL,
     154        /*.uPort        =*/ UINT32_MAX,
     155    },
     156    {   /* #9 */
     157        "foo://tt:[email protected]:8042/?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     158        /*.pszScheme    =*/ "foo",
     159        /*.pszAuthority =*/ "tt:[email protected]:8042",
     160        /*.pszPath      =*/ "/",
     161        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     162        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     163        /*.pszUsername  =*/ "tt",
     164        /*.pszPassword  =*/ "tt",
     165        /*.uPort        =*/ 8042,
     166    },
     167    {   /* #10 */
     168        "foo://tt:[email protected]:8042/",
     169        /*.pszScheme    =*/ "foo",
     170        /*.pszAuthority =*/ "tt:[email protected]:8042",
     171        /*.pszPath      =*/ "/",
     172        /*.pszQuery     =*/ NULL,
     173        /*.pszFragment  =*/ NULL,
     174        /*.pszUsername  =*/ "tt",
     175        /*.pszPassword  =*/ "tt",
     176        /*.uPort        =*/ 8042,
     177    },
     178    {   /* #11 */
     179        "foo://tt:[email protected]:8042?name=%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60ferret#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     180        /*.pszScheme    =*/ "foo",
     181        /*.pszAuthority =*/ "tt:[email protected]:8042",
     182        /*.pszPath      =*/ NULL,
     183        /*.pszQuery     =*/ "name= <>#%\"{}|^[]`ferret",
     184        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     185        /*.pszUsername  =*/ "tt",
     186        /*.pszPassword  =*/ "tt",
     187        /*.uPort        =*/ 8042,
     188    },
     189    {   /* #12 */
     190        "foo://tt:[email protected]:8042#nose%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60",
     191        /*.pszScheme    =*/ "foo",
     192        /*.pszAuthority =*/ "tt:[email protected]:8042",
     193        /*.pszPath      =*/ NULL,
     194        /*.pszQuery     =*/ NULL,
     195        /*.pszFragment  =*/ "nose <>#%\"{}|^[]`",
     196        /*.pszUsername  =*/ "tt",
     197        /*.pszPassword  =*/ "tt",
     198        /*.uPort        =*/ 8042,
     199    },
     200    {   /* #13 */
     201        "foo://tt:[email protected]:8042",
     202        /*.pszScheme    =*/ "foo",
     203        /*.pszAuthority =*/ "tt:[email protected]:8042",
     204        /*.pszPath      =*/ NULL,
     205        /*.pszQuery     =*/ NULL,
     206        /*.pszFragment  =*/ NULL,
     207        /*.pszUsername  =*/ "tt",
     208        /*.pszPassword  =*/ "tt",
     209        /*.uPort        =*/ 8042,
     210    },
     211    {   /* #14 */
     212        "foo:///",
     213        /*.pszScheme    =*/ "foo",
     214        /*.pszAuthority =*/ "",
     215        /*.pszPath      =*/ "/",
     216        /*.pszQuery     =*/ NULL,
     217        /*.pszFragment  =*/ NULL,
     218        /*.pszUsername  =*/ NULL,
     219        /*.pszPassword  =*/ NULL,
     220        /*.uPort        =*/ UINT32_MAX,
     221    },
     222    {   /* #15 */
     223        "foo://",
     224        /*.pszScheme    =*/ "foo",
     225        /*.pszAuthority =*/ "",
     226        /*.pszPath      =*/ NULL,
     227        /*.pszQuery     =*/ NULL,
     228        /*.pszFragment  =*/ NULL,
     229        /*.pszUsername  =*/ NULL,
     230        /*.pszPassword  =*/ NULL,
     231        /*.uPort        =*/ UINT32_MAX,
     232    },
     233};
     234
     235
    43236static const char *g_apcszTestURIs[] =
    44237{
     
    61254};
    62255
    63 static const char *g_apcszSchemeResult[] =
    64 {
    65     "foo",
    66     "foo",
    67     "foo",
    68     "foo",
    69     "foo",
    70     "foo",
    71     "urn",
    72     "foo",
    73     "foo",
    74     "foo",
    75     "foo",
    76     "foo",
    77     "foo",
    78     "foo",
    79     "foo",
    80     "foo"
    81 };
    82 
    83 static const char *g_apcszAuthorityResult[] =
    84 {
    85     "tt:[email protected]:8042",
    86     "tt:[email protected]:8042",
    87     "tt:[email protected]:8042",
    88     NULL,
    89     NULL,
    90     NULL,
    91     NULL,
    92     NULL,
    93     NULL,
    94     "tt:[email protected]:8042",
    95     "tt:[email protected]:8042",
    96     "tt:[email protected]:8042",
    97     "tt:[email protected]:8042",
    98     "tt:[email protected]:8042",
    99     NULL,
    100     NULL
    101 };
    102 
    103 static const char *g_apcszPathResult[] =
    104 {
    105     "/over/ <>#%\"{}|^[]`/there",
    106     "/over/ <>#%\"{}|^[]`/there",
    107     "/over/ <>#%\"{}|^[]`/there",
    108     "[email protected]",
    109     "/over/ <>#%\"{}|^[]`/there",
    110     "/over/ <>#%\"{}|^[]`/there",
    111     "example:animal:ferret:nose",
    112     NULL,
    113     NULL,
    114     "/",
    115     "/",
    116     NULL,
    117     NULL,
    118     NULL,
    119     "/",
    120     NULL
    121 };
    122 
    123 static const char *g_apcszQueryResult[] =
    124 {
    125     "name= <>#%\"{}|^[]`ferret",
    126     "name= <>#%\"{}|^[]`ferret",
    127     NULL,
    128     NULL,
    129     "name= <>#%\"{}|^[]`ferret",
    130     NULL,
    131     NULL,
    132     "name= <>#%\"{}|^[]`ferret",
    133     NULL,
    134     "name= <>#%\"{}|^[]`ferret",
    135     NULL,
    136     "name= <>#%\"{}|^[]`ferret",
    137     NULL,
    138     NULL,
    139     NULL,
    140     NULL
    141 };
    142 
    143 static const char *g_apcszFragmentResult[] =
    144 {
    145     "nose <>#%\"{}|^[]`",
    146     NULL,
    147     NULL,
    148     NULL,
    149     "nose <>#%\"{}|^[]`",
    150     "nose <>#%\"{}|^[]`",
    151     NULL,
    152     "nose <>#%\"{}|^[]`",
    153     "nose <>#%\"{}|^[]`",
    154     "nose <>#%\"{}|^[]`",
    155     NULL,
    156     "nose <>#%\"{}|^[]`",
    157     "nose <>#%\"{}|^[]`",
    158     NULL,
    159     NULL,
    160     NULL
    161 };
    162 
    163256static const char *g_apcszCreateURIs[][5] =
    164257{
     
    193286    { "/", "file:///", URI_FILE_FORMAT_UNIX },
    194287    { "/C:/over/ <>#%\"{}|^[]`/there", "file:///C:%5Cover%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere", URI_FILE_FORMAT_UNIX },
    195     { "over\\ <>#%\"{}|^[]`\\there", "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", URI_FILE_FORMAT_WIN }
     288    { "\\over\\ <>#%\"{}|^[]`\\there", "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", URI_FILE_FORMAT_WIN }
    196289};
    197290
     
    199292 * Basic API checks.
    200293 */
    201 static void tstScheme(size_t iCount, const char *pszUri, const char *pszTest)
     294static void tstScheme(size_t idxTest, const char *pszUri, const char *pszTest)
    202295{
    203296    char *pszResult = RTUriScheme(pszUri);
    204297    if (pszTest)
    205298    {
    206         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    207         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    208     }
    209     else
    210         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    211 
    212     if (pszResult)
    213         RTStrFree(pszResult);
    214 }
    215 
    216 static void tstAuthority(size_t iCount, const char *pszUri, const char *pszTest)
     299        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     300        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     301    }
     302    else
     303        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     304
     305    if (pszResult)
     306        RTStrFree(pszResult);
     307}
     308
     309static void tstAuthority(size_t idxTest, const char *pszUri, const char *pszTest)
    217310{
    218311    char *pszResult = RTUriAuthority(pszUri);
    219312    if (pszTest)
    220313    {
    221         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    222         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    223     }
    224     else
    225         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    226 
    227     if (pszResult)
    228         RTStrFree(pszResult);
    229 }
    230 
    231 static void tstPath(size_t iCount, const char *pszUri, const char *pszTest)
     314        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     315        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     316    }
     317    else
     318        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     319
     320    if (pszResult)
     321        RTStrFree(pszResult);
     322}
     323
     324static void tstAuthorityUsername(size_t idxTest, const char *pszUri, const char *pszTest)
     325{
     326    char *pszResult = RTUriAuthorityUsername(pszUri);
     327    if (pszTest)
     328    {
     329        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     330        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     331    }
     332    else
     333        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     334    RTStrFree(pszResult);
     335}
     336
     337static void tstAuthorityPassword(size_t idxTest, const char *pszUri, const char *pszTest)
     338{
     339    char *pszResult = RTUriAuthorityPassword(pszUri);
     340    if (pszTest)
     341    {
     342        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     343        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     344    }
     345    else
     346        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     347    RTStrFree(pszResult);
     348}
     349
     350static void tstAuthorityPort(size_t idxTest, const char *pszUri, uint32_t uTest)
     351{
     352    uint32_t uResult = RTUriAuthorityPort(pszUri);
     353    RTTESTI_CHECK_MSG_RETV(uResult == uTest, ("#%u: Result %#x != %#x (%s)", idxTest, uResult, uTest, pszUri));
     354}
     355
     356static void tstPath(size_t idxTest, const char *pszUri, const char *pszTest)
    232357{
    233358    char *pszResult = RTUriPath(pszUri);
    234359    if (pszTest)
    235360    {
    236         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    237         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    238     }
    239     else
    240         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    241 
    242     if (pszResult)
    243         RTStrFree(pszResult);
    244 }
    245 
    246 static void tstQuery(size_t iCount, const char *pszUri, const char *pszTest)
     361        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     362        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     363    }
     364    else
     365        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     366
     367    if (pszResult)
     368        RTStrFree(pszResult);
     369}
     370
     371static void tstQuery(size_t idxTest, const char *pszUri, const char *pszTest)
    247372{
    248373    char *pszResult = RTUriQuery(pszUri);
    249374    if (pszTest)
    250375    {
    251         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    252         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    253     }
    254     else
    255         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    256 
    257     if (pszResult)
    258         RTStrFree(pszResult);
    259 }
    260 
    261 static void tstFragment(size_t iCount, const char *pszUri, const char *pszTest)
     376        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     377        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     378    }
     379    else
     380        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     381
     382    if (pszResult)
     383        RTStrFree(pszResult);
     384}
     385
     386static void tstFragment(size_t idxTest, const char *pszUri, const char *pszTest)
    262387{
    263388    char *pszResult = RTUriFragment(pszUri);
    264389    if (pszTest)
    265390    {
    266         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    267         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    268     }
    269     else
    270         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    271 
    272     if (pszResult)
    273         RTStrFree(pszResult);
    274 }
    275 
    276 static void tstCreate(size_t iCount, const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment, const char *pszTest)
     391        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     392        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     393    }
     394    else
     395        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     396
     397    if (pszResult)
     398        RTStrFree(pszResult);
     399}
     400
     401static void tstCreate(size_t idxTest, const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment, const char *pszTest)
    277402{
    278403    char *pszResult = RTUriCreate(pszScheme, pszAuthority, pszPath, pszQuery, pszFragment);
    279404    if (pszTest)
    280405    {
    281         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    282         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    283     }
    284     else
    285         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
     406        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     407        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     408    }
     409    else
     410        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
    286411
    287412    if (pszResult)
     
    290415}
    291416
    292 static void tstFileCreate(size_t iCount, const char *pszPath, const char *pszTest)
     417static void tstFileCreate(size_t idxTest, const char *pszPath, const char *pszTest)
    293418{
    294419    char *pszResult = RTUriFileCreate(pszPath);
    295420    if (pszTest)
    296421    {
    297         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    298         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    299     }
    300     else
    301         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
     422        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     423        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     424    }
     425    else
     426        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
    302427
    303428    if (pszResult)
     
    306431}
    307432
    308 static void tstFilePath(size_t iCount, const char *pszUri, const char *pszTest, uint32_t uFormat)
     433static void tstFilePath(size_t idxTest, const char *pszUri, const char *pszTest, uint32_t uFormat)
    309434{
    310435    char *pszResult = RTUriFilePath(pszUri, uFormat);
    311436    if (pszTest)
    312437    {
    313         RTTESTI_CHECK_MSG_RETV(pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
    314         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("Result '%s' != '%s'", pszResult, pszTest));
    315     }
    316     else
    317         RTTESTI_CHECK_MSG(!pszResult, ("Result '%s' != '%s'", pszResult, pszTest));
     438        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     439        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     440    }
     441    else
     442        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
    318443
    319444    if (pszResult)
     
    331456
    332457    /* Scheme */
    333     RTTestISubF("RTUriScheme");
    334     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszSchemeResult));
    335     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    336         tstScheme(i+1, g_apcszTestURIs[i], g_apcszSchemeResult[i]);
     458    RTTestISub("RTUriScheme");
     459    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     460        tstScheme(i, g_aTests[i].pszUri, g_aTests[i].pszScheme);
    337461
    338462    /* Authority */
    339     RTTestISubF("RTUriAuthority");
    340     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszAuthorityResult));
    341     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    342         tstAuthority(i+1, g_apcszTestURIs[i], g_apcszAuthorityResult[i]);
     463    RTTestISub("RTUriAuthority");
     464    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     465    {
     466        tstAuthority(i, g_aTests[i].pszUri, g_aTests[i].pszAuthority);
     467        tstAuthorityUsername(i, g_aTests[i].pszUri, g_aTests[i].pszUsername);
     468        tstAuthorityPassword(i, g_aTests[i].pszUri, g_aTests[i].pszPassword);
     469        tstAuthorityPort(i, g_aTests[i].pszUri, g_aTests[i].uPort);
     470    }
    343471
    344472    /* Path */
    345     RTTestISubF("RTUriPath");
    346     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszPathResult));
    347     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    348         tstPath(i+1, g_apcszTestURIs[i], g_apcszPathResult[i]);
     473    RTTestISub("RTUriPath");
     474    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     475        tstPath(i, g_aTests[i].pszUri, g_aTests[i].pszPath);
    349476
    350477    /* Query */
    351     RTTestISubF("RTUriQuery");
    352     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszQueryResult));
    353     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    354         tstQuery(i+1, g_apcszTestURIs[i], g_apcszQueryResult[i]);
     478    RTTestISub("RTUriQuery");
     479    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     480        tstQuery(i, g_aTests[i].pszUri, g_aTests[i].pszQuery);
    355481
    356482    /* Fragment */
    357     RTTestISubF("RTUriFragment");
    358     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszFragmentResult));
    359     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    360         tstFragment(i+1, g_apcszTestURIs[i], g_apcszFragmentResult[i]);
     483    RTTestISub("RTUriFragment");
     484    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     485        tstFragment(i, g_aTests[i].pszUri, g_aTests[i].pszFragment);
    361486
    362487    /* Creation */
    363     RTTestISubF("RTUriCreate");
    364     Assert(RT_ELEMENTS(g_apcszTestURIs) == RT_ELEMENTS(g_apcszCreateURIs));
    365     for (size_t i = 0; i < RT_ELEMENTS(g_apcszTestURIs); ++i)
    366         tstCreate(i+1, g_apcszCreateURIs[i][0], g_apcszCreateURIs[i][1], g_apcszCreateURIs[i][2],
    367                   g_apcszCreateURIs[i][3], g_apcszCreateURIs[i][4], g_apcszTestURIs[i]);
     488    RTTestISub("RTUriCreate");
     489    for (uint32_t i = 0; i < RT_ELEMENTS(g_aTests); i++)
     490        tstCreate(i, g_aTests[i].pszScheme, g_aTests[i].pszAuthority, g_aTests[i].pszPath,
     491                  g_aTests[i].pszQuery, g_aTests[i].pszFragment, g_aTests[i].pszUri);
    368492
    369493    /* File Uri path */
    370     RTTestISubF("RTUriFilePath");
     494    RTTestISub("RTUriFilePath");
    371495    for (size_t i = 0; i < RT_ELEMENTS(g_apCreateFileURIs); ++i)
    372         tstFilePath(i+1, g_apCreateFileURIs[i].pcszUri, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].uFormat);
     496        tstFilePath(i, g_apCreateFileURIs[i].pcszUri, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].uFormat);
    373497
    374498    /* File Uri creation */
    375     RTTestISubF("RTUriFileCreate");
     499    RTTestISub("RTUriFileCreate");
    376500    for (size_t i = 0; i < 3; ++i)
    377         tstFileCreate(i+1, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].pcszUri);
     501        tstFileCreate(i, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].pcszUri);
    378502
    379503    return RTTestSummaryAndDestroy(hTest);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette