Moving BSTR conv to native code in SecureStringToBSTR.
[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 #if MONO
59             if (!Uri.IsWindowsFileSystem) {
60                 if (!(end - start > 2 && name[start] == '\\' && name[start + 1] == '\\')) {
61                     return false;
62                 }
63             }
64 #endif
65             //
66             // First segment could consist of only '_' or '-' but it cannot be all digits or empty
67             //
68             bool validShortName = false;
69             ushort i = start;
70             for (; i < end; ++i)
71             {
72                 if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#')))
73                 {
74                     end = i;
75                     break;
76                 }
77                 else if (name[i] == '.')
78                 {
79                     ++i;
80                     break;
81                 }
82                 if (Char.IsLetter(name[i]) || name[i] == '-' || name[i] == '_')
83                 {
84                     validShortName = true;
85                 }
86                 else if (name[i] < '0' || name[i] > '9')
87                     return false;
88             }
89
90             if (!validShortName)
91                 return false;
92
93             //
94             // Subsequent segments must start with a letter or a digit
95             //
96
97             for (; i < end; ++i)
98             {
99                 if (name[i] == '/' || name[i] == '\\' || (notImplicitFile && (name[i] == ':' || name[i] == '?' || name[i] == '#')))
100                 {
101                     end = i;
102                     break;
103                 }
104                 else if (name[i] == '.')
105                 {
106                     if (!validShortName || ((i-1) >= start && name[i-1] == '.'))
107                         return false;
108
109                     validShortName = false;
110                 }
111                 else if (name[i] == '-' || name[i] == '_')
112                 {
113                     if (!validShortName)
114                         return false;
115                 }
116                 else if (Char.IsLetter(name[i]) || (name[i] >= '0' && name[i] <= '9'))
117                 {
118                     if (!validShortName)
119                         validShortName = true;
120                 }
121                 else
122                     return false;
123             }
124
125             // last segment can end with the dot
126             if (((i-1) >= start && name[i-1] == '.'))
127                 validShortName = true;
128
129             if (!validShortName)
130                 return false;
131
132             //  caller must check for (end - start <= MaximumInternetNameLength)
133
134             returnedEnd = end;
135             return true;
136         }
137     }
138 }
139 #endif // !PLATFORM_UNIX