Changeset 58067 in vbox for trunk/src/VBox/Runtime/common/misc
- Timestamp:
- Oct 6, 2015 8:52:48 PM (9 years ago)
- svn:sync-xref-src-repo-rev:
- 103123
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
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
Note:
See TracChangeset
for help on using the changeset viewer.