Merge pull request #2377 from joelmartinez/docs-multiassembly-extension-fix
[mono.git] / mcs / class / referencesource / mscorlib / system / security / util / sitestring.cs
1 // ==++==
2 // 
3 //   Copyright (c) Microsoft Corporation.  All rights reserved.
4 // 
5 // ==--==
6 // SiteString
7 // 
8 // <OWNER>[....]</OWNER>
9 // 
10
11 namespace System.Security.Util {
12     using System;
13     using System.Collections;
14     using System.Globalization;
15     using System.Diagnostics.Contracts;
16
17     [Serializable]
18     internal class SiteString
19     {
20         protected String m_site;
21         protected ArrayList m_separatedSite;
22
23         protected static char[] m_separators = { '.' };
24         
25         protected internal SiteString()
26         {
27             // Only call this in derived classes when you know what you're doing.
28         }
29         
30         public SiteString( String site )
31         {
32             m_separatedSite = CreateSeparatedSite( site );
33             m_site = site;
34         }
35
36         private SiteString(String site, ArrayList separatedSite)
37         {
38             m_separatedSite = separatedSite;
39             m_site = site;
40         }
41
42         private static ArrayList CreateSeparatedSite(String site)
43         {
44             if (site == null || site.Length == 0)
45             {
46                 throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
47             }
48             Contract.EndContractBlock();
49
50             ArrayList list = new ArrayList();
51             int braIndex = -1;
52             int ketIndex = -1;
53             braIndex = site.IndexOf('[');
54             if (braIndex == 0)
55                 ketIndex = site.IndexOf(']', braIndex+1);
56
57             if (ketIndex != -1)
58             {
59                 // Found an IPv6 address. Special case that
60                 String ipv6Addr = site.Substring(braIndex+1, ketIndex-braIndex-1);
61                 list.Add(ipv6Addr);
62                 return list;
63             }
64
65             // Regular hostnames or IPv4 addresses
66             // We dont need to do this for IPv4 addresses, but it's easier to do it anyway
67             String[] separatedArray = site.Split( m_separators );
68             
69             for (int index = separatedArray.Length-1; index > -1; --index)
70             {
71                 if (separatedArray[index] == null)
72                 {
73                     throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
74                 }
75                 else if (separatedArray[index].Equals( "" )) 
76                 {
77                     if (index != separatedArray.Length-1) 
78                     {
79                         throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
80                     }
81                 }
82                 else if (separatedArray[index].Equals( "*" ))
83                 {
84                     if (index != 0)
85                     {
86                         throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
87                     }
88                     list.Add( separatedArray[index] );
89                 }
90                 else if (!AllLegalCharacters( separatedArray[index] ))
91                 {
92                     throw new ArgumentException( Environment.GetResourceString("Argument_InvalidSite" ));
93                 }
94                 else
95                 {
96                     list.Add( separatedArray[index] );
97                 }
98             }
99             
100             return list;
101         }
102
103         // KB# Q188997 - http://support.microsoft.com/default.aspx?scid=KB;EN-US;Q188997& gives the list of allowed characters in
104         // a NETBIOS name. DNS names are a subset of that (alphanumeric or '-').
105         private static bool AllLegalCharacters( String str )
106         {
107             for (int i = 0; i < str.Length; ++i)
108             {
109                 char c = str[i];
110
111                 if (IsLegalDNSChar(c) ||
112                     IsNetbiosSplChar(c))
113                 {
114                     continue;
115                 }
116                 else
117                 {
118                     return false;
119                 }
120             }
121
122             return true;
123         }
124
125         private static bool IsLegalDNSChar(char c)
126         {
127             if ((c >= 'a' && c <= 'z') ||
128                 (c >= 'A' && c <= 'Z') ||
129                 (c >= '0' && c <= '9') ||
130                 (c == '-'))
131                 return true;
132             else
133                 return false;
134         }
135         private static bool IsNetbiosSplChar(char c)
136         {
137             //  ! @ # $ % ^ & ( ) - _ ' { } . ~ are OK
138             switch (c) {
139                 case '-':
140                 case '_':
141                 case '@':
142                 case '!':
143                 case '#':
144                 case '$':
145                 case '%':
146                 case '^':
147                 case '&':
148                 case '(':
149                 case ')':
150                 case '\'':
151                 case '{':
152                 case '}':
153                 case '.':
154                 case '~':
155                     return true;
156                 default:
157                     return false;
158             }
159         }
160
161         public override String ToString()
162         {
163             return m_site;
164         }
165         
166         public override bool Equals(Object o)
167         {
168             if (o == null || !(o is SiteString))
169                 return false;
170             else
171                 return this.Equals( (SiteString)o, true );
172         }
173
174         public override int GetHashCode()
175         {
176             TextInfo info = CultureInfo.InvariantCulture.TextInfo;
177
178             return info.GetCaseInsensitiveHashCode( this.m_site );
179         }
180
181         internal bool Equals( SiteString ss, bool ignoreCase )
182         {
183             if (this.m_site == null)
184                 return ss.m_site == null;
185             if (ss.m_site == null)
186                 return false;
187             return this.IsSubsetOf(ss, ignoreCase) && ss.IsSubsetOf(this, ignoreCase);
188         }
189             
190         
191         public virtual SiteString Copy()
192         {
193             return new SiteString( m_site, m_separatedSite );
194         }
195
196         public virtual bool IsSubsetOf( SiteString operand )
197         {
198             return this.IsSubsetOf( operand, true );
199         }
200
201         public virtual bool IsSubsetOf( SiteString operand, bool ignoreCase )
202         {
203             StringComparison strComp = (ignoreCase? StringComparison.OrdinalIgnoreCase : StringComparison.Ordinal);
204             if (operand == null)
205             {
206                 return false;
207             }
208             else if (this.m_separatedSite.Count == operand.m_separatedSite.Count &&
209                      this.m_separatedSite.Count == 0)
210             {
211                 return true;
212             }
213             else if (this.m_separatedSite.Count < operand.m_separatedSite.Count - 1)
214             {
215                 return false;
216             }
217             else if (this.m_separatedSite.Count > operand.m_separatedSite.Count &&
218                      operand.m_separatedSite.Count > 0 &&
219                      !operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*"))
220             {
221                 return false;
222             }
223             else if (String.Compare( this.m_site, operand.m_site, strComp) == 0)
224             {
225                 return true;
226             }
227
228             for (int index = 0; index < operand.m_separatedSite.Count - 1; ++index)
229             {
230                 if (String.Compare((String)this.m_separatedSite[index], (String)operand.m_separatedSite[index], strComp) != 0)
231                 {
232                     return false;
233                 }
234             }
235
236             if (this.m_separatedSite.Count < operand.m_separatedSite.Count)
237             {
238                 return operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*");
239             }
240             else if (this.m_separatedSite.Count == operand.m_separatedSite.Count)
241             {
242                 // last item must be the same or operand must have a * in its last item
243                 return (String.Compare((String)this.m_separatedSite[this.m_separatedSite.Count - 1],
244                                                     (String)operand.m_separatedSite[this.m_separatedSite.Count - 1], 
245                                                     strComp ) == 0 ||
246                            operand.m_separatedSite[operand.m_separatedSite.Count - 1].Equals("*"));
247                     
248             }
249             else 
250                 return true;
251         }
252                 
253         
254     
255         public virtual SiteString Intersect( SiteString operand )
256         {
257             if (operand == null)
258             {
259                 return null;
260             }
261             else if (this.IsSubsetOf( operand ))
262             {
263                 return this.Copy();
264             }
265             else if (operand.IsSubsetOf( this ))
266             {
267                 return operand.Copy();
268             }
269             else
270             {
271                 return null;
272             }
273         }
274         
275         public virtual SiteString Union( SiteString operand )
276         {
277             if (operand == null)
278             {
279                 return this;
280             }
281             else if (this.IsSubsetOf( operand ))
282             {
283                 return operand.Copy();
284             }
285             else if (operand.IsSubsetOf( this ))
286             {
287                 return this.Copy();
288             }
289             else
290             {
291                 return null;
292             }
293         }
294     }
295 }