- Timestamp:
- Oct 6, 2015 8:52:48 PM (9 years ago)
- Location:
- trunk
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/mangling.h
r57955 r58067 1862 1862 # define RTUriCreate RT_MANGLER(RTUriCreate) 1863 1863 # define RTUriFileCreate RT_MANGLER(RTUriFileCreate) 1864 # define RTUriFileCreateEx RT_MANGLER(RTUriFileCreateEx) 1864 1865 # define RTUriFileNPath RT_MANGLER(RTUriFileNPath) 1865 1866 # define RTUriFilePath RT_MANGLER(RTUriFilePath) -
trunk/include/iprt/uri.h
r57944 r58067 275 275 * The returned pointer must be freed using RTStrFree(). 276 276 * 277 * @see RTUriCreate278 *279 277 * @returns The new URI on success, NULL otherwise. Free With RTStrFree. 280 278 * @param pszPath The path of the URI. 279 * 280 * @sa RTUriFileCreateEx, RTUriCreate 281 281 */ 282 282 RTDECL(char *) RTUriFileCreate(const char *pszPath); 283 284 /** 285 * Creates an file URL for the given path. 286 * 287 * This API works like RTStrToUtf16Ex with regard to result allocation or 288 * buffering (i.e. it's a bit complicated but very flexible). 289 * 290 * @returns iprt status code. 291 * @param pszPath The path to convert to a file:// URL. 292 * @param fPathStyle The input path style, exactly one of 293 * RTPATH_STR_F_STYLE_HOST, RTPATH_STR_F_STYLE_DOS and 294 * RTPATH_STR_F_STYLE_UNIX. Must include iprt/path.h. 295 * @param ppszUri If cbUri is non-zero, this must either be pointing 296 * to pointer to a buffer of the specified size, or 297 * pointer to a NULL pointer. If *ppszUri is NULL or 298 * cbUri is zero a buffer of at least cbUri chars will 299 * be allocated to hold the URL. If a buffer was 300 * requested it must be freed using RTStrFree(). 301 * @param cbUri The buffer size in bytes (includes terminator). 302 * @param pcchUri Where to store the length of the URI string, 303 * excluding the terminator. (Optional) 304 * 305 * This may be set under some error conditions, 306 * however, only for VERR_BUFFER_OVERFLOW and 307 * VERR_NO_STR_MEMORY will it contain a valid string 308 * length that can be used to resize the buffer. 309 * @sa RTUriCreate, RTUriFileCreate 310 */ 311 RTDECL(int) RTUriFileCreateEx(const char *pszPath, uint32_t fPathStyle, char **ppszUri, size_t cbUri, size_t *pcchUri); 283 312 284 313 /** -
trunk/src/VBox/Runtime/common/misc/uri.cpp
r58066 r58067 116 116 117 117 return pszRes; 118 } 119 120 121 /** 122 * Calculates the encoded string length. 123 * 124 * @returns Number of chars (excluding the terminator). 125 * @param pszString The string to encode. 126 * @param cchMax The maximum string length (e.g. RTSTR_MAX). 127 * @param fEncodeDosSlash Whether to encode DOS slashes or not. 128 */ 129 static size_t rtUriCalcEncodedLength(const char *pszString, size_t cchMax, bool fEncodeDosSlash) 130 { 131 size_t cchEncoded = 0; 132 if (pszString) 133 { 134 size_t cchSrcLeft = RTStrNLen(pszString, cchMax); 135 while (cchSrcLeft-- > 0) 136 { 137 char const ch = *pszString++; 138 if (!URI_EXCLUDED(ch) || (ch == '\\' && !fEncodeDosSlash)) 139 cchEncoded += 1; 140 else 141 cchEncoded += 3; 142 } 143 } 144 return cchEncoded; 145 } 146 147 148 /** 149 * Encodes an URI into a caller allocated buffer. 150 * 151 * @returns IPRT status code. 152 * @param pszString The string to encode. 153 * @param cchMax The maximum string length (e.g. RTSTR_MAX). 154 * @param fEncodeDosSlash Whether to encode DOS slashes or not. 155 * @param pszDst The destination buffer. 156 * @param cbDst The size of the destination buffer. 157 */ 158 static int rtUriEncodeIntoBuffer(const char *pszString, size_t cchMax, bool fEncodeDosSlash, char *pszDst, size_t cbDst) 159 { 160 AssertReturn(pszString, VERR_INVALID_POINTER); 161 162 /* 163 * We do buffer size checking up front and every time we encode a special 164 * character. That's faster than checking for each char. 165 */ 166 size_t cchSrcLeft = RTStrNLen(pszString, cchMax); 167 AssertMsgReturn(cbDst > cchSrcLeft, ("cbDst=%zu cchSrcLeft=%zu\n", cbDst, cchSrcLeft), VERR_BUFFER_OVERFLOW); 168 cbDst -= cchSrcLeft; 169 170 while (cchSrcLeft-- > 0) 171 { 172 char const ch = *pszString++; 173 if (!URI_EXCLUDED(ch) || (ch == '\\' && !fEncodeDosSlash)) 174 *pszDst++ = ch; 175 else 176 { 177 AssertReturn(cbDst >= 3, VERR_BUFFER_OVERFLOW); /* 2 extra bytes + zero terminator. */ 178 cbDst -= 2; 179 180 *pszDst++ = '%'; 181 ssize_t cchTmp = RTStrFormatU8(pszDst, 3, (unsigned char)ch, 16, 2, 2, RTSTR_F_CAPITAL | RTSTR_F_ZEROPAD); 182 Assert(cchTmp == 2); NOREF(cchTmp); 183 pszDst += 2; 184 } 185 } 186 187 *pszDst = '\0'; 188 return VINF_SUCCESS; 118 189 } 119 190 … … 677 748 678 749 750 RTDECL(int) RTUriFileCreateEx(const char *pszPath, uint32_t fPathStyle, char **ppszUri, size_t cbUri, size_t *pcchUri) 751 { 752 /* 753 * Validate and adjust input. (RTPathParse check pszPath out for us) 754 */ 755 if (pcchUri) 756 { 757 AssertPtrReturn(pcchUri, VERR_INVALID_POINTER); 758 *pcchUri = ~(size_t)0; 759 } 760 AssertPtrReturn(ppszUri, VERR_INVALID_POINTER); 761 AssertReturn(!(fPathStyle & ~RTPATH_STR_F_STYLE_MASK) && fPathStyle != RTPATH_STR_F_STYLE_RESERVED, VERR_INVALID_FLAGS); 762 if (fPathStyle == RTPATH_STR_F_STYLE_HOST) 763 fPathStyle = RTPATH_STYLE; 764 765 /* 766 * Let the RTPath code parse the stuff (no reason to duplicate path parsing 767 * and get it slightly wrong here). 768 */ 769 RTPATHPARSED ParsedPath; 770 int rc = RTPathParse(pszPath, &ParsedPath, sizeof(ParsedPath), fPathStyle); 771 if (RT_SUCCESS(rc) || rc == VERR_BUFFER_OVERFLOW) 772 { 773 /* Skip leading slashes. */ 774 if (ParsedPath.fProps & RTPATH_PROP_ROOT_SLASH) 775 { 776 if (fPathStyle == RTPATH_STR_F_STYLE_DOS) 777 while (pszPath[0] == '/' || pszPath[0] == '\\') 778 pszPath++; 779 else 780 while (pszPath[0] == '/') 781 pszPath++; 782 } 783 const size_t cchPath = strlen(pszPath); 784 785 /* 786 * Calculate the encoded length and figure destination buffering. 787 */ 788 static const char s_szPrefix[] = "file:///"; 789 size_t const cchPrefix = sizeof(s_szPrefix) - (ParsedPath.fProps & RTPATH_PROP_UNC ? 2 : 1); 790 size_t cchEncoded = rtUriCalcEncodedLength(pszPath, cchPath, fPathStyle != RTPATH_STR_F_STYLE_DOS); 791 792 if (pcchUri) 793 *pcchUri = cchEncoded; 794 795 char *pszDst; 796 char *pszFreeMe = NULL; 797 if (!cbUri || *ppszUri == NULL) 798 { 799 cbUri = RT_MAX(cbUri, cchPrefix + cchEncoded + 1); 800 *ppszUri = pszFreeMe = pszDst = RTStrAlloc(cbUri); 801 AssertReturn(pszDst, VERR_NO_STR_MEMORY); 802 } 803 else if (cchEncoded < cbUri) 804 pszDst = *ppszUri; 805 else 806 return VERR_BUFFER_OVERFLOW; 807 808 /* 809 * Construct the URI. 810 */ 811 memcpy(pszDst, s_szPrefix, cchPrefix); 812 pszDst[cchPrefix] = '\0'; 813 rc = rtUriEncodeIntoBuffer(pszPath, cchPath, fPathStyle != RTPATH_STR_F_STYLE_DOS, &pszDst[cchPrefix], cbUri - cchPrefix); 814 if (RT_SUCCESS(rc)) 815 { 816 Assert(strlen(pszDst) == cbUri - 1); 817 if (fPathStyle == RTPATH_STR_F_STYLE_DOS) 818 RTPathChangeToUnixSlashes(pszDst, true /*fForce*/); 819 return VINF_SUCCESS; 820 } 821 822 AssertRC(rc); /* Impossible! rtUriCalcEncodedLength or something above is busted! */ 823 if (pszFreeMe) 824 RTStrFree(pszFreeMe); 825 } 826 return rc; 827 } 828 829 679 830 RTDECL(char *) RTUriFileCreate(const char *pszPath) 680 831 { 681 /* Empty paths are invalid. */ 682 AssertPtrReturn(pszPath, NULL); 683 AssertReturn(*pszPath, NULL); 684 685 char *pszResult = NULL; 686 if (pszPath) 687 { 688 /* Check if it's an UNC path. Skip any leading slashes. */ 689 while (pszPath) 690 { 691 if ( *pszPath != '\\' 692 && *pszPath != '/') 693 break; 694 pszPath++; 695 } 696 697 /* Create the percent encoded strings and calculate the necessary URI length. */ 698 char *pszPath1 = rtUriPercentEncodeN(pszPath, RTSTR_MAX); 699 if (pszPath1) 700 { 701 /* Always change DOS slashes to Unix slashes. */ 702 RTPathChangeToUnixSlashes(pszPath1, true); /** @todo Flags? */ 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 721 return pszResult; 832 char *pszUri = NULL; 833 int rc = RTUriFileCreateEx(pszPath, RTPATH_STR_F_STYLE_HOST, &pszUri, 0 /*cbUri*/, NULL /*pcchUri*/); 834 if (RT_SUCCESS(rc)) 835 return pszUri; 836 return NULL; 722 837 } 723 838 -
trunk/src/VBox/Runtime/testcase/tstRTUri.cpp
r58066 r58067 34 34 #include <iprt/err.h> 35 35 #include <iprt/mem.h> 36 #include <iprt/path.h> 36 37 #include <iprt/test.h> 37 38 … … 312 313 { /* #0: */ 313 314 /* .pszPath =*/ "C:\\over\\ <>#%\"{}|^[]`\\there", 314 /* .pszUri =*/ "file:///C:%5Cover %5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",315 /* .pszUri =*/ "file:///C:%5Cover/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere", 315 316 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 316 317 /* .pszCreatedPath =*/ "C:\\over\\ <>#%\"{}|^[]`\\there", 317 /* .pszCreatedUri =*/ "file:///C: %5Cover%5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",318 /* .pszCreatedUri =*/ "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", 318 319 /* PathCreateFromUrl = "C:\\over\\ <>#%\"{}|^[]`\\there" - same */ 319 /* UrlCreateFromPath = "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - differs*/320 /* UrlCreateFromPath = "file:///C:/over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ 320 321 }, 321 322 { /* #1: */ … … 378 379 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 379 380 /* .pszCreatedPath =*/ "\\foo\\bar", 380 /* .pszCreatedUri =*/ "file:///foo %5Cbar",381 /* .pszCreatedUri =*/ "file:///foo/bar", 381 382 /* PathCreateFromUrl = "\\foo\\bar" - same */ 382 /* UrlCreateFromPath = "file:///foo/bar" - differs*/383 /* UrlCreateFromPath = "file:///foo/bar" - same */ 383 384 }, 384 385 { /* #8: */ … … 393 394 { /* #9: */ 394 395 /* .pszPath =*/ "\\over\\ <>#%\"{}|^[]`\\there", 395 /* .pszUri =*/ "file:///over %5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",396 /* .pszUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", 396 397 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 397 398 /* .pszCreatedPath =*/ "\\over\\ <>#%\"{}|^[]`\\there", 398 /* .pszCreatedUri =*/ "file:///over %5C%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60%5Cthere",399 /* .pszCreatedUri =*/ "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there", 399 400 /* PathCreateFromUrl = "\\over\\ <>#%\"{}|^[]`\\there" - same */ 400 /* UrlCreateFromPath = "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - differs*/401 /* UrlCreateFromPath = "file:///over/%20%3C%3E%23%25%22%7B%7D%7C%5E%5B%5D%60/there" - same */ 401 402 }, 402 403 { /* #10: */ … … 411 412 { /* #11: */ 412 413 /* .pszPath =*/ "\\usr\\bin\\grep", 413 /* .pszUri =*/ "file:///usr %5Cbin%5Cgrep",414 /* .pszUri =*/ "file:///usr/bin/grep", 414 415 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 415 416 /* .pszCreatedPath =*/ "\\usr\\bin\\grep", 416 /* .pszCreatedUri =*/ "file:///usr %5Cbin%5Cgrep",417 /* .pszCreatedUri =*/ "file:///usr/bin/grep", 417 418 /* PathCreateFromUrl = "\\usr\\bin\\grep" - same */ 418 /* UrlCreateFromPath = "file:///usr/bin/grep" - differs*/419 /* UrlCreateFromPath = "file:///usr/bin/grep" - same */ 419 420 }, 420 421 { /* #12: */ … … 429 430 { /* #13: */ 430 431 /* .pszPath =*/ "\\not-a-cifsserver\\isos\\files.lst", 431 /* .pszUri =*/ "file:///not-a-cifsserver %5Cisos%5Cfiles.lst",432 /* .pszUri =*/ "file:///not-a-cifsserver/isos/files.lst", 432 433 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 433 434 /* .pszCreatedPath =*/ "\\not-a-cifsserver\\isos\\files.lst", 434 /* .pszCreatedUri =*/ "file:///not-a-cifsserver %5Cisos%5Cfiles.lst",435 /* .pszCreatedUri =*/ "file:///not-a-cifsserver/isos/files.lst", 435 436 /* PathCreateFromUrl = "\\not-a-cifsserver\\isos\\files.lst" - same */ 436 /* UrlCreateFromPath = "file:///not-a-cifsserver/isos/files.lst" - differs*/437 /* UrlCreateFromPath = "file:///not-a-cifsserver/isos/files.lst" - same */ 437 438 }, 438 439 { /* #14: */ … … 447 448 { /* #15: */ 448 449 /* .pszPath =*/ "\\not-a-cifsserver-either\\isos\\files.lst", 449 /* .pszUri =*/ "file:///not-a-cifsserver-either %5Cisos%5Cfiles.lst",450 /* .pszUri =*/ "file:///not-a-cifsserver-either/isos/files.lst", 450 451 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 451 452 /* .pszCreatedPath =*/ "\\not-a-cifsserver-either\\isos\\files.lst", 452 /* .pszCreatedUri =*/ "file:///not-a-cifsserver-either %5Cisos%5Cfiles.lst",453 /* .pszCreatedUri =*/ "file:///not-a-cifsserver-either/isos/files.lst", 453 454 /* PathCreateFromUrl = "\\not-a-cifsserver-either\\isos\\files.lst" - same */ 454 /* UrlCreateFromPath = "file:///not-a-cifsserver-either/isos/files.lst" - differs */ 455 }, 456 #if 0 /** @todo r=bird: this ain't working right. It's in the wikipedia article on file:// ... */ 455 /* UrlCreateFromPath = "file:///not-a-cifsserver-either/isos/files.lst" - same */ 456 }, 457 457 { /* #16: */ 458 458 /* .pszPath =*/ "\\\\cifsserver\\isos\\files.lst", 459 459 /* .pszUri =*/ "file:////cifsserver/isos/files.lst", 460 460 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 461 /* .pszCreatedPath =*/ NULL, /* Same as pszPath. */461 /* .pszCreatedPath =*/ "\\\\cifsserver\\isos\\files.lst", 462 462 /* .pszCreatedUri =*/ "file://cifsserver/isos/files.lst", 463 463 /* PathCreateFromUrl = "\\\\cifsserver\\isos\\files.lst" - same */ 464 /* UrlCreateFromPath = "file:// //cifsserver/isos/files.lst" - differs*/464 /* UrlCreateFromPath = "file://cifsserver/isos/files.lst" - same */ 465 465 }, 466 466 { /* #17: */ … … 468 468 /* .pszUri =*/ "file://localhost/c:boot.ini", 469 469 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 470 /* .pszCreatedPath =*/ NULL, /* Same as pszPath. */470 /* .pszCreatedPath =*/ "c:boot.ini", 471 471 /* .pszCreatedUri =*/ "file:///c:boot.ini", 472 472 /* PathCreateFromUrl = "c:boot.ini" - same */ … … 477 477 /* .pszUri =*/ "file:///c|boot.ini", 478 478 /* .uFormat =*/ URI_FILE_FORMAT_WIN, 479 /* .pszCreatedPath =*/ NULL, /* Same as pszPath. */479 /* .pszCreatedPath =*/ "c:boot.ini", 480 480 /* .pszCreatedUri =*/ "file:///c:boot.ini", 481 481 /* PathCreateFromUrl = "c:boot.ini" - same */ 482 482 /* UrlCreateFromPath = "file:///c:boot.ini" - same */ 483 483 }, 484 #endif485 484 }; 486 485 … … 561 560 RTPrintf(" /* PathCreateFromUrl = "); 562 561 tstPrintCString(pszResult); 563 if ( g_aCreateFileURIs[i].psz Path562 if ( g_aCreateFileURIs[i].pszCreatedPath 564 563 && strcmp(pszResult, g_aCreateFileURIs[i].pszCreatedPath) == 0) 565 564 RTPrintf(" - same */\n"); … … 593 592 RTPrintf(" /* UrlCreateFromPath = "); 594 593 tstPrintCString(pszResult); 595 if ( g_aCreateFileURIs[i].psz Uri594 if ( g_aCreateFileURIs[i].pszCreatedUri 596 595 && strcmp(pszResult, g_aCreateFileURIs[i].pszCreatedUri) == 0) 597 596 RTPrintf(" - same */\n"); … … 610 609 611 610 #endif /* TSTRTURI_WITH_WINDOWS_REFERENCE_RESULTS */ 611 612 613 static void tstRTUriFileCreateEx(void) 614 { 615 RTTestISub("RTUriFileCreateEx"); 616 for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs); ++i) 617 { 618 uint32_t const fPathStyle = g_aCreateFileURIs[i].uFormat == URI_FILE_FORMAT_WIN 619 ? RTPATH_STR_F_STYLE_DOS : RTPATH_STR_F_STYLE_UNIX; 620 char *pszUri = (char *)&pszUri; 621 int rc = RTUriFileCreateEx(g_aCreateFileURIs[i].pszPath, fPathStyle, &pszUri, 0, NULL); 622 if (RT_SUCCESS(rc)) 623 { 624 if (g_aCreateFileURIs[i].pszCreatedUri) 625 { 626 if (strcmp(pszUri, g_aCreateFileURIs[i].pszCreatedUri) == 0) 627 { 628 /** @todo check out the other variations of the API. */ 629 } 630 else 631 RTTestIFailed("#%u: '%s'/%#x => '%s', expected '%s'", i, 632 g_aCreateFileURIs[i].pszPath, fPathStyle, 633 pszUri, g_aCreateFileURIs[i].pszCreatedUri); 634 } 635 else 636 RTTestIFailed("#%u: bad testcase; pszCreatedUri is NULL\n", i); 637 } 638 else if (rc != VERR_INVALID_POINTER || g_aCreateFileURIs[i].pszPath != NULL) 639 RTTestIFailed("#%u: '%s'/%#x => %Rrc", i, g_aCreateFileURIs[i].pszPath, fPathStyle, rc); 640 } 641 } 612 642 613 643 … … 672 702 /* File Uri path */ 673 703 RTTestISub("RTUriFilePath"); 674 for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs) ; ++i)704 for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs) - 3; ++i) /** @todo r=bird: Fixed last three tests in RTUriFilePath */ 675 705 CHECK_STR_API(RTUriFilePath(g_aCreateFileURIs[i].pszUri, g_aCreateFileURIs[i].uFormat), 676 706 g_aCreateFileURIs[i].pszCreatedPath); 677 707 678 708 /* File Uri creation */ 679 RTTestISub("RTUriFileCreate"); 680 for (size_t i = 0; i < RT_ELEMENTS(g_aCreateFileURIs); ++i) 681 CHECK_STR_API(RTUriFileCreate(g_aCreateFileURIs[i].pszPath), g_aCreateFileURIs[i].pszCreatedUri); 709 tstRTUriFileCreateEx(); 682 710 683 711 RTAssertSetMayPanic(fSavedMayPanic);
Note:
See TracChangeset
for help on using the changeset viewer.