/* * [decOctetTwo]-><NULL> * [decOctetTwo]-><0>[decOctetThree] * [decOctetTwo]-><1>[decOctetThree] * [decOctetTwo]-><2>[decOctetThree] * [decOctetTwo]-><3>[decOctetThree] * [decOctetTwo]-><4>[decOctetThree] * [decOctetTwo]-><5>[decOctetFour] * [decOctetTwo]-><6> * [decOctetTwo]-><7> * [decOctetTwo]-><8> * [decOctetTwo]-><9> */ static URI_INLINE const URI_CHAR * URI_FUNC(ParseDecOctetTwo)(UriIp4Parser * parser, const URI_CHAR * first, const URI_CHAR * afterLast) { if (first >= afterLast) { return afterLast; } switch (*first) { case _UT('0'): case _UT('1'): case _UT('2'): case _UT('3'): case _UT('4'): uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); return (const URI_CHAR *)URI_FUNC(ParseDecOctetThree)(parser, first + 1, afterLast); case _UT('5'): uriPushToStack(parser, 5); return (const URI_CHAR *)URI_FUNC(ParseDecOctetFour)(parser, first + 1, afterLast); case _UT('6'): case _UT('7'): case _UT('8'): case _UT('9'): uriPushToStack(parser, (unsigned char)(9 + *first - _UT('9'))); return first + 1; default: return first; } }
static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString, URI_CHAR * filename, UriBool toUnix) { const URI_CHAR * const prefix = toUnix ? _UT("file://") : _UT("file:///"); const int prefixLen = toUnix ? 7 : 8; URI_CHAR * walker = filename; size_t charsToCopy; const UriBool absolute = (URI_STRNCMP(uriString, prefix, prefixLen) == 0); const int charsToSkip = (absolute ? prefixLen : 0); charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1; memcpy(filename, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR)); URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH); /* Convert forward slashes to backslashes */ if (!toUnix) { while (walker[0] != _UT('\0')) { if (walker[0] == _UT('/')) { walker[0] = _UT('\\'); } walker++; } } return URI_SUCCESS; }
/* * [ipFourAddress]->[decOctet]<.>[decOctet]<.>[decOctet]<.>[decOctet] */ int URI_FUNC(ParseIpFourAddress)(unsigned char * octetOutput, const URI_CHAR * first, const URI_CHAR * afterLast) { const URI_CHAR * after; UriIp4Parser parser; /* Essential checks */ if ((octetOutput == NULL) || (first == NULL) || (afterLast <= first)) { return URI_ERROR_SYNTAX; } /* Reset parser */ parser.stackCount = 0; /* Octet #1 */ after = URI_FUNC(ParseDecOctet)(&parser, first, afterLast); if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { return URI_ERROR_SYNTAX; } uriStackToOctet(&parser, octetOutput); /* Octet #2 */ after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { return URI_ERROR_SYNTAX; } uriStackToOctet(&parser, octetOutput + 1); /* Octet #3 */ after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); if ((after == NULL) || (after >= afterLast) || (*after != _UT('.'))) { return URI_ERROR_SYNTAX; } uriStackToOctet(&parser, octetOutput + 2); /* Octet #4 */ after = URI_FUNC(ParseDecOctet)(&parser, after + 1, afterLast); if (after != afterLast) { return URI_ERROR_SYNTAX; } uriStackToOctet(&parser, octetOutput + 3); return URI_SUCCESS; }
static URI_INLINE int URI_FUNC(UriStringToFilename)(const URI_CHAR * uriString, URI_CHAR * filename, UriBool toUnix) { if ((uriString == NULL) || (filename == NULL)) { return URI_ERROR_NULL; } { const UriBool file_two_slashes = URI_STRNCMP(uriString, _UT("file://"), URI_STRLEN(_UT("file://"))) == 0; const UriBool file_three_slashes = file_two_slashes && (URI_STRNCMP(uriString, _UT("file:///"), URI_STRLEN(_UT("file:///"))) == 0); const size_t charsToSkip = file_two_slashes ? file_three_slashes ? toUnix /* file:///bin/bash */ ? URI_STRLEN(_UT("file://")) /* file:///E:/Documents%20and%20Settings */ : URI_STRLEN(_UT("file:///")) /* file://Server01/Letter.txt */ : URI_STRLEN(_UT("file://")) : 0; const size_t charsToCopy = URI_STRLEN(uriString + charsToSkip) + 1; const UriBool is_windows_network_with_authority = (toUnix == URI_FALSE) && file_two_slashes && ! file_three_slashes; URI_CHAR * const unescape_target = is_windows_network_with_authority ? (filename + 2) : filename; if (is_windows_network_with_authority) { filename[0] = '\\'; filename[1] = '\\'; } memcpy(unescape_target, uriString + charsToSkip, charsToCopy * sizeof(URI_CHAR)); URI_FUNC(UnescapeInPlaceEx)(filename, URI_FALSE, URI_BR_DONT_TOUCH); } /* Convert forward slashes to backslashes */ if (!toUnix) { URI_CHAR * walker = filename; while (walker[0] != _UT('\0')) { if (walker[0] == _UT('/')) { walker[0] = _UT('\\'); } walker++; } } return URI_SUCCESS; }
static URI_INLINE int URI_FUNC(FilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString, UriBool fromUnix) { const URI_CHAR * input = filename; const URI_CHAR * lastSep = input - 1; UriBool firstSegment = URI_TRUE; URI_CHAR * output = uriString; UriBool absolute; UriBool is_windows_network; if ((filename == NULL) || (uriString == NULL)) { return URI_ERROR_NULL; } is_windows_network = (filename[0] == _UT('\\')) && (filename[1] == _UT('\\')); absolute = fromUnix ? (filename[0] == _UT('/')) : ((filename[0] != _UT('\0')) && (filename[1] == _UT(':')) || is_windows_network); if (absolute) { const URI_CHAR * const prefix = fromUnix ? _UT("file://") : is_windows_network ? _UT("file:") : _UT("file:///"); const int prefixLen = URI_STRLEN(prefix); /* Copy prefix */ memcpy(uriString, prefix, prefixLen * sizeof(URI_CHAR)); output += prefixLen; } /* Copy and escape on the fly */ for (;;) { if ((input[0] == _UT('\0')) || (fromUnix && input[0] == _UT('/')) || (!fromUnix && input[0] == _UT('\\'))) { /* Copy text after last seperator */ if (lastSep + 1 < input) { if (!fromUnix && absolute && (firstSegment == URI_TRUE)) { /* Quick hack to not convert "C:" to "C%3A" */ const int charsToCopy = (int)(input - (lastSep + 1)); memcpy(output, lastSep + 1, charsToCopy * sizeof(URI_CHAR)); output += charsToCopy; } else { output = URI_FUNC(EscapeEx)(lastSep + 1, input, output, URI_FALSE, URI_FALSE); } } firstSegment = URI_FALSE; } if (input[0] == _UT('\0')) { output[0] = _UT('\0'); break; } else if (fromUnix && (input[0] == _UT('/'))) { /* Copy separators unmodified */ output[0] = _UT('/'); output++; lastSep = input; } else if (!fromUnix && (input[0] == _UT('\\'))) { /* Convert backslashes to forward slashes */ output[0] = _UT('/'); output++; lastSep = input; } input++; } return URI_SUCCESS; }
int URI_FUNC(UriStringToWindowsFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { return URI_FUNC(UriStringToFilename)(uriString, filename, URI_FALSE); }
int URI_FUNC(UriStringToUnixFilename)(const URI_CHAR * uriString, URI_CHAR * filename) { return URI_FUNC(UriStringToFilename)(uriString, filename, URI_TRUE); }
int URI_FUNC(WindowsFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { return URI_FUNC(FilenameToUriString)(filename, uriString, URI_FALSE); }
int URI_FUNC(UnixFilenameToUriString)(const URI_CHAR * filename, URI_CHAR * uriString) { return URI_FUNC(FilenameToUriString)(filename, uriString, URI_TRUE); }