Merge pull request #3213 from henricm/fix-for-win-securestring-to-bstr
[mono.git] / mcs / class / referencesource / System / net / System / _UncName.cs
1 #if !PLATFORM_UNIX || MONO
2 //------------------------------------------------------------------------------
3 // <copyright file="_UncName.cs" company="Microsoft">
4 //     Copyright (c) Microsoft Corporation.  All rights reserved.
5 // </copyright>
6 //------------------------------------------------------------------------------
7 using System.Globalization;
8
9 namespace System {
10
11     // The class designed as to keep minimal the working set of Uri class.
12     // The idea is to stay with static helper methods and strings
13     internal class UncNameHelper {
14
15     // fields
16
17         internal const int MaximumInternetNameLength = 256;
18
19         private UncNameHelper() {
20         }
21
22
23     // properties
24
25     // methods
26         internal static string ParseCanonicalName(string str, int start, int end, ref bool loopback) {
27             return DomainNameHelper.ParseCanonicalName(str, start, end, ref loopback);
28         }
29
30         //
31         // IsValid
32         //
33         //
34         //   ATTN: This class has been re-designed as to conform to XP+ UNC hostname format
35         //         It is now similar to DNS name but can contain Unicode characters as well
36         //         This class will be removed and replaced by IDN specification later,
37         //         but for now we violate URI RFC cause we never escape Unicode characters on the wire
38         //         For the same reason we never unescape UNC host names since we never accept
39         //         them in escaped format.
40         //
41         //
42         //      Valid UNC server name chars:
43         //          a Unicode Letter    (not allowed as the only in a segment)
44         //          a Latin-1 digit
45         //          '-'    45 0x2D
46         //          '.'    46 0x2E    (only as a host domain delimiter)
47         //          '_'    95 0x5F
48         //
49         //
50         // Assumption is the caller will check on the resulting name length
51         // Remarks:  MUST NOT be used unless all input indexes are are verified and trusted.
52         internal unsafe static bool IsValid(char* name, ushort start, ref int returnedEnd, bool notImplicitFile) {
53             ushort end = (ushort) returnedEnd;
54
55             if (start==end)
56                 return false;
57
58             //
59             // First segment could consist of only '_' or '-' but it cannot be all digits or empty
60             //
61             bool validShortName = false;
62             ushort i = start;
63             for (; i < end; ++i)
64             {
65                 if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#')))
66                 {
67                     end = i;
68                     break;
69                 }
70                 else if (name[i] == '.')
71                 {
72                     ++i;
73                     break;
74                 }
75                 if (Char.IsLetter(name[i]) || name[i] == '-' || name[i] == '_')
76                 {
77                     validShortName = true;
78                 }
79                 else if (name[i] < '0' || name[i] > '9')
80                     return false;
81             }
82
83             if (!validShortName)
84                 return false;
85
86             //
87             // Subsequent segments must start with a letter or a digit
88             //
89
90             for (; i < end; ++i)
91             {
92                 if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#')))
93                 {
94                     end = i;
95                     break;
96                 }
97                 else if (name[i] == '.')
98                 {
99                     if (!validShortName || ((i-1) >= start && name[i-1] == '.'))
100                         return false;
101
102                     validShortName = false;
103                 }
104                 else if (name[i] == '-' || name[i] == '_')
105                 {
106                     if (!validShortName)
107                         return false;
108                 }
109                 else if (Char.IsLetter(name[i]) || (name[i] >= '0' && name[i] <= '9'))
110                 {
111                     if (!validShortName)
112                         validShortName = true;
113                 }
114                 else
115                     return false;
116             }
117
118             // last segment can end with the dot
119             if (((i-1) >= start && name[i-1] == '.'))
120                 validShortName = true;
121
122             if (!validShortName)
123                 return false;
124
125             //  caller must check for (end - start <= MaximumInternetNameLength)
126
127             returnedEnd = end;
128             return true;
129         }
130     }
131 }
132 #endif // !PLATFORM_UNIX