VirtualBox

Changeset 57981 in vbox


Ignore:
Timestamp:
Oct 1, 2015 11:20:52 AM (9 years ago)
Author:
vboxsync
Message:

IPRT: misc/uri.cpp: Bugfixes, behave more like PathCreateFromUrl/UrlCreateFromPath on Windows. Added a couple more tests.

Location:
trunk/src/VBox/Runtime
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/misc/uri.cpp

    r57825 r57981  
    4848    foo://example.com:8042/over/there?name=ferret#nose
    4949    \_/   \______________/\_________/ \_________/ \__/
    50      |           |            |            |        |
     50     |           |             |           |        |
    5151  scheme     authority       path        query   fragment
    5252     |   _____________________|__
     
    121121static char *rtUriPercentDecodeN(const char *pszString, size_t cchString)
    122122{
    123     AssertPtr(pszString);
    124     Assert(strlen(pszString) >= cchString);
     123    AssertPtrReturn(pszString, NULL);
     124    AssertReturn(strlen(pszString) >= cchString, NULL);
    125125
    126126    /*
     
    478478
    479479
    480 
    481480RTDECL(int) RTUriParse(const char *pszUri, PRTURIPARSED pParsed)
    482481{
     
    683682    if (pszPath)
    684683    {
    685         /* Create the percent encoded strings and calculate the necessary uri length. */
     684        /* Check if it's an UNC path. Skip any leading slashes. */
     685        while (pszPath)
     686        {
     687            if (   *pszPath != '\\'
     688                && *pszPath != '/')
     689                break;
     690            pszPath++;
     691        }
     692
     693        /* Create the percent encoded strings and calculate the necessary URI length. */
    686694        char *pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX);
    687695        if (pszPath1)
    688696        {
     697            /* Always change DOS slashes to Unix slashes. */
     698            RTPathChangeToUnixSlashes(pszPath1, true); /** @todo Flags? */
     699
    689700            size_t cbSize = 7 /* file:// */ + strlen(pszPath1) + 1; /* plus zero byte */
    690701            if (pszPath1[0] != '/')
     
    693704            if (pszResult)
    694705            {
    695                 /* Compose the target uri string. */
     706                /* Compose the target URI string. */
    696707                *pszTmp = '\0';
    697708                RTStrCatP(&pszTmp, &cbSize, "file://");
     
    703714        }
    704715    }
     716    else
     717    {
     718        char *pszResTmp;
     719        int cchRes = RTStrAPrintf(&pszResTmp, "file://");
     720        if (cchRes)
     721            pszResult = pszResTmp;
     722    }
     723
    705724    return pszResult;
    706725}
     
    726745#endif
    727746
    728     /* Check that this is a file Uri */
     747    /* Check that this is a file URI. */
    729748    if (RTStrNICmp(pszUri, RT_STR_TUPLE("file:")) != 0)
    730749        return NULL;
     
    732751    RTURIPARSED Parsed;
    733752    int rc = rtUriParse(pszUri, &Parsed);
    734     if (RT_SUCCESS(rc) && Parsed.cchPath)
    735     {
    736         /* Special hack for DOS path like file:///c:/WINDOWS/clock.avi where we
    737            have to drop the leading slash that was used to separate the authority
    738            from the path. */
    739         if (  uFormat == URI_FILE_FORMAT_WIN
    740             && Parsed.cchPath >= 3
    741             && pszUri[Parsed.offPath] == '/'
    742             && pszUri[Parsed.offPath + 2] == ':'
    743             && RT_C_IS_ALPHA(pszUri[Parsed.offPath + 1]) )
     753    if (RT_SUCCESS(rc))
     754    {
     755        /* No path detected? Take authority as path then. */
     756        if (!Parsed.cchPath)
     757        {
     758            Parsed.cchPath      = Parsed.cchAuthority;
     759            Parsed.offPath      = Parsed.offAuthority;
     760            Parsed.cchAuthority = 0;
     761        }
     762    }
     763
     764    if (   RT_SUCCESS(rc)
     765        && Parsed.cchPath)
     766    {
     767        const char *pszPathOff = &pszUri[Parsed.offPath];
     768        size_t cbResult = 0;
     769
     770        /* Skip the leading slash if a DOS drive letter (e.g. "C:") is detected right after it. */
     771        if (   Parsed.cchPath >= 3
     772            && pszPathOff[0]  == '/'        /* Leading slash. */
     773            && RT_C_IS_ALPHA(pszPathOff[1]) /* Drive letter. */
     774            && pszPathOff[2]  == ':')
    744775        {
    745776            Parsed.offPath++;
    746777            Parsed.cchPath--;
    747         }
    748 
    749         char *pszPath = rtUriPercentDecodeN(&pszUri[Parsed.offPath], Parsed.cchPath);
    750         if (uFormat == URI_FILE_FORMAT_UNIX)
    751             return RTPathChangeToUnixSlashes(pszPath, true);
    752         Assert(uFormat == URI_FILE_FORMAT_WIN);
    753         return RTPathChangeToDosSlashes(pszPath, true);
    754     }
     778            pszPathOff++;
     779        }
     780
     781        if (uFormat == URI_FILE_FORMAT_WIN)
     782        {
     783            /* Authority given? */
     784            if (Parsed.cchAuthority)
     785            {
     786                /* Include authority as part of UNC path. */
     787                cbResult += 2; /* UNC slashes "\\". */
     788                cbResult += Parsed.cchAuthority;
     789            }
     790        }
     791
     792        cbResult += Parsed.cchPath;
     793        cbResult += 1; /* Zero termination. */
     794
     795        /*
     796         * Compose string.
     797         */
     798        int rc = VINF_SUCCESS;
     799        char *pszResult;
     800
     801        do
     802        {
     803            char *pszTmp = pszResult = RTStrAlloc(cbResult);
     804            if (pszTmp)
     805            {
     806                size_t cbTmp = cbResult;
     807
     808                if (uFormat == URI_FILE_FORMAT_WIN)
     809                {
     810                    /* If an authority is given, add the required UNC prefix. */
     811                    if (Parsed.cchAuthority)
     812                    {
     813                        rc = RTStrCatP(&pszTmp, &cbTmp, "\\\\");
     814                        if (RT_SUCCESS(rc))
     815                            rc = RTStrCatPEx(&pszTmp, &cbTmp, &pszUri[Parsed.offAuthority], Parsed.cchAuthority);
     816                    }
     817                    else
     818                    {
     819
     820                    }
     821                }
     822
     823                if (RT_SUCCESS(rc))
     824                    rc = RTStrCatPEx(&pszTmp, &cbTmp, &pszUri[Parsed.offPath], Parsed.cchPath);
     825
     826                if (RT_FAILURE(rc))
     827                    RTStrFree(pszResult);
     828            }
     829            else
     830                rc = VERR_NO_MEMORY;
     831
     832        } while (0);
     833
     834        if (RT_SUCCESS(rc))
     835        {
     836            AssertPtr(pszResult);
     837            Assert(cbResult);
     838            char *pszPath = rtUriPercentDecodeN(pszResult, cbResult - 1 /* Minus termination */);
     839            RTStrFree(pszResult);
     840            if (uFormat == URI_FILE_FORMAT_UNIX)
     841                return RTPathChangeToUnixSlashes(pszPath, true);
     842            Assert(uFormat == URI_FILE_FORMAT_WIN);
     843            return RTPathChangeToDosSlashes(pszPath, true);
     844        }
     845    }
     846
    755847    return NULL;
    756848}
  • trunk/src/VBox/Runtime/testcase/tstRTUri.cpp

    r57847 r57981  
    3636#include <iprt/test.h>
    3737
     38#ifdef _DEBUG
     39# ifdef RT_OS_WINDOWS
     40#  include <Shlwapi.h> /* For generating the PathCreateFromUrl/UrlCreateFromPath reference on Windows. */
     41# endif
     42#endif
    3843
    3944/*********************************************************************************************************************************
     
    314319    },
    315320    {
     321        NULL,
     322        "file://",
     323        URI_FILE_FORMAT_UNIX
     324    },
     325    {
     326        NULL,
     327        "file://",
     328        URI_FILE_FORMAT_WIN
     329    },
     330    {
    316331        "/",
    317332        "file:///",
     
    319334    },
    320335    {
    321         "/C:/over/ <>#%\"{}|^[]`/there",
    322         "file:///C:%5Cover%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",
    323         URI_FILE_FORMAT_UNIX
    324     },
    325     {
    326         "\\over\\ <>#%\"{}|^[]`\\there",
    327         "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there",
    328         URI_FILE_FORMAT_WIN
    329     },
    330     {
    331         "/",
    332         "file:///",
    333         URI_FILE_FORMAT_UNIX
    334     },
    335     {
    336336        "\\",
    337337        "file:///",
    338338        URI_FILE_FORMAT_WIN
    339339    },
     340    {
     341        "/foo/bar",
     342        "file:///foo/bar",
     343        URI_FILE_FORMAT_UNIX
     344    },
     345    {
     346        "\\foo\\bar",
     347        "file:///foo%5Cbar",
     348        URI_FILE_FORMAT_WIN
     349    },
     350    {
     351        "C:/over/ <>#%\"{}|^[]`/there",
     352        "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there",
     353        URI_FILE_FORMAT_UNIX
     354    },
     355    {
     356        "\\over\\ <>#%\"{}|^[]`\\there",
     357        "file:///over%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",
     358        URI_FILE_FORMAT_WIN
     359    },
     360    {
     361        "/usr/bin/grep",
     362        "file:///usr/bin/grep",
     363        URI_FILE_FORMAT_UNIX
     364    },
     365    {
     366        "\\usr\\bin\\grep",
     367        "file:///usr%5Cbin%5Cgrep",
     368        URI_FILE_FORMAT_WIN
     369    },
     370    {
     371        "/unixserver/isos/files.lst",
     372        "file:///unixserver/isos/files.lst",
     373        URI_FILE_FORMAT_UNIX
     374    },
     375    {
     376        "\\winserver\\isos\\files.lst",
     377        "file:///winserver%5Cisos%5Cfiles.lst",
     378        URI_FILE_FORMAT_WIN
     379    },
     380    {
     381        "/myserver/isos/files.lst",
     382        "file:///myserver/isos/files.lst",
     383        URI_FILE_FORMAT_UNIX
     384    },
     385    {
     386        "\\myserver\\isos\\files.lst",
     387        "file:///myserver%5Cisos%5Cfiles.lst",
     388        URI_FILE_FORMAT_WIN
     389    }
    340390};
    341391
    342 
     392/**
     393 * For reference, taken from output of PathCreateFromUrl/UrlCreateFromPath on Windows:
     394 *
     395 * #0: Path=C:\over\ <>#%"{}|^[]`\there, URL=file:///C:%5Cover%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere
     396 *       PathCreateFromUrl: file:///C:%5Cover%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere -> C:\over\ <>#%"{}|^[]`\there
     397 *       UrlCreateFromPath: C:\over\ <>#%"{}|^[]`\there -> file:%2F%2F%2FC:%2Fover%2F%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%2Fthere
     398 * #1: Path=/over/ <>#%"{}|^[]`/there, URL=file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there
     399 *       PathCreateFromUrl: file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there -> \over\ <>#%"{}|^[]`\there
     400 *       UrlCreateFromPath: /over/ <>#%"{}|^[]`/there -> file:%2F%2F%2Fover%2F%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%2Fthere
     401 * #2: Path=<NULL>, URL=file://
     402 *       PathCreateFromUrl: file:// ->
     403 *       UrlCreateFromPath: <NULL> ->
     404 * #3: Path=<NULL>, URL=file://
     405 *       PathCreateFromUrl: file:// ->
     406 *       UrlCreateFromPath: <NULL> ->
     407 * #4: Path=/, URL=file:///
     408 *       PathCreateFromUrl: file:/// ->
     409 *       UrlCreateFromPath: / -> file:%2F%2F%2F
     410 * #5: Path=/foo/bar, URL=file:///foo/bar
     411 *       PathCreateFromUrl: file:///foo/bar -> \foo\bar
     412 *       UrlCreateFromPath: /foo/bar -> file:%2F%2F%2Ffoo%2Fbar
     413 * #6: Path=\foo\bar, URL=file:///foo%5Cbar
     414 *       PathCreateFromUrl: file:///foo%5Cbar -> \foo\bar
     415 *       UrlCreateFromPath: \foo\bar -> file:%2F%2F%2Ffoo%2Fbar
     416 * #7: Path=C:/over/ <>#%"{}|^[]`/there, URL=file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there
     417 *       PathCreateFromUrl: file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there -> C:\over\ <>#%"{}|^[]`\there
     418 *       UrlCreateFromPath: C:/over/ <>#%"{}|^[]`/there -> file:%2F%2F%2FC:%2Fover%2F%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%2Fthere
     419 * #8: Path=\over\ <>#%"{}|^[]`\there, URL=file:///over%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere
     420 *       PathCreateFromUrl: file:///over%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere -> \over\ <>#%"{}|^[]`\there
     421 *       UrlCreateFromPath: \over\ <>#%"{}|^[]`\there -> file:%2F%2F%2Fover%2F%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%2Fthere
     422 * #9: Path=/usr/bin/grep, URL=file:///usr/bin/grep
     423 *       PathCreateFromUrl: file:///usr/bin/grep -> \usr\bin\grep
     424 *       UrlCreateFromPath: /usr/bin/grep -> file:%2F%2F%2Fusr%2Fbin%2Fgrep
     425 * #10: Path=\usr\bin\grep, URL=file:///usr%5Cbin%5Cgrep
     426 *       PathCreateFromUrl: file:///usr%5Cbin%5Cgrep -> \usr\bin\grep
     427 *       UrlCreateFromPath: \usr\bin\grep -> file:%2F%2F%2Fusr%2Fbin%2Fgrep
     428 * #11: Path=/unixserver/isos/files.lst, URL=file:///unixserver/isos/files.lst
     429 *       PathCreateFromUrl: file:///unixserver/isos/files.lst -> \unixserver\isos\files.lst
     430 *       UrlCreateFromPath: /unixserver/isos/files.lst -> file:%2F%2F%2Funixserver%2Fisos%2Ffiles.lst
     431 * #12: Path=\winserver\isos\files.lst, URL=file:///winserver%5Cisos%5Cfiles.lst
     432 *       PathCreateFromUrl: file:///winserver%5Cisos%5Cfiles.lst -> \winserver\isos\files.lst
     433 *       UrlCreateFromPath: \winserver\isos\files.lst -> file:%2F%2F%2Fwinserver%2Fisos%2Ffiles.lst
     434 * #13: Path=/myserver/isos/files.lst, URL=file:///myserver/isos/files.lst
     435 *       PathCreateFromUrl: file:///myserver/isos/files.lst -> \myserver\isos\files.lst
     436 *       UrlCreateFromPath: /myserver/isos/files.lst -> file:%2F%2F%2Fmyserver%2Fisos%2Ffiles.lst
     437 * #14: Path=\myserver\isos\files.lst, URL=file:///myserver%5Cisos%5Cfiles.lst
     438 *       PathCreateFromUrl: file:///myserver%5Cisos%5Cfiles.lst -> \myserver\isos\files.lst
     439 *       UrlCreateFromPath: \myserver\isos\files.lst -> file:%2F%2F%2Fmyserver%2Fisos%2Ffiles.lst
     440 */
    343441
    344442static void tstCreate(size_t idxTest, const char *pszScheme, const char *pszAuthority, const char *pszPath, const char *pszQuery, const char *pszFragment, const char *pszTest)
     
    363461    if (pszTest)
    364462    {
    365         RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
    366         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     463        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
     464        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
    367465    }
    368466    else
    369         RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     467        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
    370468
    371469    if (pszResult)
     
    379477    if (pszTest)
    380478    {
    381         RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
    382         RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     479        RTTESTI_CHECK_MSG_RETV(pszResult, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
     480        RTTESTI_CHECK_MSG(RTStrCmp(pszResult, pszTest) == 0, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
    383481    }
    384482    else
    385         RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'", idxTest, pszResult, pszTest));
     483        RTTESTI_CHECK_MSG(!pszResult, ("#%u: Result '%s' != '%s'\n", idxTest, pszResult, pszTest));
    386484
    387485    if (pszResult)
     
    441539                      g_aTests[i].pszCreated ? g_aTests[i].pszCreated : g_aTests[i].pszUri);
    442540
     541#ifdef _DEBUG
     542# ifdef RT_OS_WINDOWS
     543    /* To generate the PathCreateFromUrl/UrlCreateFromPath reference on Windows. */
     544    for (size_t i = 0; i < RT_ELEMENTS(g_apCreateFileURIs); ++i)
     545    {
     546        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "#%u: Path=%s, URL=%s\n", i, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].pcszUri);
     547        char szPath[255] = { 0 };
     548        DWORD dw = 255;
     549        PathCreateFromUrl(g_apCreateFileURIs[i].pcszUri, szPath, &dw, NULL);
     550        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "\tPathCreateFromUrl: %s -> %s\n", g_apCreateFileURIs[i].pcszUri, szPath);
     551        char szURL[255] = { 0 };
     552        dw = 255;
     553        UrlCreateFromPath(g_apCreateFileURIs[i].pcszPath, szURL, &dw, NULL);
     554        char szURLEsc[255] = { 0 };
     555        dw = 255;
     556        UrlEscape(szURL, szURLEsc, &dw, URL_ESCAPE_SEGMENT_ONLY);
     557        RTTestPrintf(hTest, RTTESTLVL_ALWAYS, "\tUrlCreateFromPath: %s -> %s\n", g_apCreateFileURIs[i].pcszPath, szURLEsc);
     558    }
     559# endif
     560#endif
     561
    443562    /* File Uri path */
    444563    RTTestISub("RTUriFilePath");
    445564    for (size_t i = 0; i < RT_ELEMENTS(g_apCreateFileURIs); ++i)
    446         tstFilePath(i, g_apCreateFileURIs[i].pcszUri, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].uFormat);
     565        tstFilePath(i,  g_apCreateFileURIs[i].pcszUri, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].uFormat);
    447566
    448567    /* File Uri creation */
    449568    RTTestISub("RTUriFileCreate");
    450     for (size_t i = 0; i < 3; ++i)
     569    for (size_t i = 0; i < RT_ELEMENTS(g_apCreateFileURIs); ++i)
    451570        tstFileCreate(i, g_apCreateFileURIs[i].pcszPath, g_apCreateFileURIs[i].pcszUri);
    452571
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