| | | 1 | | // Licensed to the .NET Foundation under one or more agreements. |
| | | 2 | | // The .NET Foundation licenses this file to you under the MIT license. |
| | | 3 | | |
| | | 4 | | namespace System |
| | | 5 | | { |
| | | 6 | | // The class designed as to keep minimal the working set of Uri class. |
| | | 7 | | // The idea is to stay with static helper methods and strings |
| | | 8 | | internal static class UncNameHelper |
| | | 9 | | { |
| | | 10 | | public const int MaximumInternetNameLength = 256; |
| | | 11 | | |
| | | 12 | | public static string ParseCanonicalName(string str, int start, int end, ref bool loopback) |
| | 0 | 13 | | { |
| | 0 | 14 | | return DomainNameHelper.ParseCanonicalName(str, start, end, ref loopback); |
| | 0 | 15 | | } |
| | | 16 | | |
| | | 17 | | // |
| | | 18 | | // IsValid |
| | | 19 | | // |
| | | 20 | | // |
| | | 21 | | // ATTN: This class has been re-designed as to conform to XP+ UNC hostname format |
| | | 22 | | // It is now similar to DNS name but can contain Unicode characters as well |
| | | 23 | | // This class will be removed and replaced by IDN specification later, |
| | | 24 | | // but for now we violate URI RFC cause we never escape Unicode characters on the wire |
| | | 25 | | // For the same reason we never unescape UNC host names since we never accept |
| | | 26 | | // them in escaped format. |
| | | 27 | | // |
| | | 28 | | // |
| | | 29 | | // Valid UNC server name chars: |
| | | 30 | | // a Unicode Letter (not allowed as the only in a segment) |
| | | 31 | | // a Latin-1 digit |
| | | 32 | | // '-' 45 0x2D |
| | | 33 | | // '.' 46 0x2E (only as a host domain delimiter) |
| | | 34 | | // '_' 95 0x5F |
| | | 35 | | // |
| | | 36 | | // |
| | | 37 | | // Assumption is the caller will check on the resulting name length |
| | | 38 | | // Remarks: MUST NOT be used unless all input indexes are verified and trusted. |
| | | 39 | | public static bool IsValid(ReadOnlySpan<char> name, bool notImplicitFile, out int nameLength) |
| | 0 | 40 | | { |
| | 0 | 41 | | nameLength = 0; |
| | | 42 | | |
| | | 43 | | // First segment could consist of only '_' or '-' but it cannot be all digits or empty |
| | 0 | 44 | | bool validShortName = false; |
| | 0 | 45 | | int i = 0; |
| | 0 | 46 | | for (; i < name.Length; i++) |
| | 0 | 47 | | { |
| | 0 | 48 | | if (char.IsLetter(name[i]) || name[i] == '-' || name[i] == '_') |
| | 0 | 49 | | { |
| | 0 | 50 | | validShortName = true; |
| | 0 | 51 | | } |
| | 0 | 52 | | else if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || n |
| | 0 | 53 | | { |
| | 0 | 54 | | break; |
| | | 55 | | } |
| | 0 | 56 | | else if (name[i] == '.') |
| | 0 | 57 | | { |
| | 0 | 58 | | i++; |
| | 0 | 59 | | break; |
| | | 60 | | } |
| | 0 | 61 | | else if (!char.IsAsciiDigit(name[i])) |
| | 0 | 62 | | { |
| | 0 | 63 | | return false; |
| | | 64 | | } |
| | 0 | 65 | | } |
| | | 66 | | |
| | 0 | 67 | | if (!validShortName) |
| | 0 | 68 | | return false; |
| | | 69 | | |
| | | 70 | | // Subsequent segments must start with a letter or a digit |
| | | 71 | | |
| | 0 | 72 | | for (; (uint)i < (uint)name.Length; i++) |
| | 0 | 73 | | { |
| | 0 | 74 | | if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i |
| | 0 | 75 | | { |
| | 0 | 76 | | break; |
| | | 77 | | } |
| | 0 | 78 | | else if (name[i] == '.') |
| | 0 | 79 | | { |
| | 0 | 80 | | if (!validShortName || name[i - 1] == '.') |
| | 0 | 81 | | return false; |
| | | 82 | | |
| | 0 | 83 | | validShortName = false; |
| | 0 | 84 | | } |
| | 0 | 85 | | else if (name[i] == '-' || name[i] == '_') |
| | 0 | 86 | | { |
| | 0 | 87 | | if (!validShortName) |
| | 0 | 88 | | return false; |
| | 0 | 89 | | } |
| | 0 | 90 | | else if (char.IsLetter(name[i]) || char.IsAsciiDigit(name[i])) |
| | 0 | 91 | | { |
| | 0 | 92 | | validShortName = true; |
| | 0 | 93 | | } |
| | | 94 | | else |
| | 0 | 95 | | { |
| | 0 | 96 | | return false; |
| | | 97 | | } |
| | 0 | 98 | | } |
| | | 99 | | |
| | 0 | 100 | | if (!validShortName) |
| | 0 | 101 | | { |
| | | 102 | | // last segment can end with the dot |
| | 0 | 103 | | if ((uint)(i - 1) >= (uint)name.Length || name[i - 1] != '.') |
| | 0 | 104 | | { |
| | 0 | 105 | | return false; |
| | | 106 | | } |
| | 0 | 107 | | } |
| | | 108 | | |
| | | 109 | | // Caller must check that (nameLength <= MaximumInternetNameLength) |
| | 0 | 110 | | nameLength = i; |
| | 0 | 111 | | return true; |
| | 0 | 112 | | } |
| | | 113 | | } |
| | | 114 | | } |
| | | 115 | | |