merged Sys.Web.Services 2.0 support in my branch:
[mono.git] / mcs / class / System / System.Net / CredentialCache.cs
1 //
2 // System.Net.CredentialCache.cs
3 //
4 // Author:
5 //   Lawrence Pit (loz@cable.a2000.nl)
6 //
7
8 //
9 // Permission is hereby granted, free of charge, to any person obtaining
10 // a copy of this software and associated documentation files (the
11 // "Software"), to deal in the Software without restriction, including
12 // without limitation the rights to use, copy, modify, merge, publish,
13 // distribute, sublicense, and/or sell copies of the Software, and to
14 // permit persons to whom the Software is furnished to do so, subject to
15 // the following conditions:
16 // 
17 // The above copyright notice and this permission notice shall be
18 // included in all copies or substantial portions of the Software.
19 // 
20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
21 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
22 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
23 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
24 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
25 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
26 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
27 //
28
29 using System;
30 using System.Collections;
31 using System.Runtime.Serialization;
32
33 namespace System.Net {
34         public class CredentialCache : ICredentials, IEnumerable {
35                 static NetworkCredential empty = new NetworkCredential ("", "", "");
36                 Hashtable cache;
37
38                 public CredentialCache () 
39                 {
40                         cache = new Hashtable ();
41                 }
42                 
43                 [MonoTODO ("Need EnvironmentPermission implementation first")]
44                 public static ICredentials DefaultCredentials {
45                         get {
46                                 // This is used for NTLM, Kerberos and Negotiate under MS
47                                 return empty;
48                         }
49                 }
50
51 #if NET_2_0
52                 // MS does might return a special ICredentials which does not allow getting the
53                 // username/password information out of it for non-internal classes.
54                 public static NetworkCredential DefaultNetworkCredentials {
55                         get { return empty; }
56                 }
57 #endif
58
59                 public NetworkCredential GetCredential (Uri uriPrefix, string authType)
60                 {
61                         int longestPrefix = -1;
62                         NetworkCredential result = null;
63                         
64                         if (uriPrefix == null || authType == null)
65                                 return null;
66                                 
67                         string absPath = uriPrefix.AbsolutePath;
68                         absPath = absPath.Substring (0, absPath.LastIndexOf ('/'));
69                         
70                         IDictionaryEnumerator e = cache.GetEnumerator ();
71                         while (e.MoveNext ()) {
72                                 CredentialCacheKey key = e.Key as CredentialCacheKey;
73                                 
74                                 if (key.Length <= longestPrefix) 
75                                         continue;
76                                 
77                                 if (String.Compare (key.AuthType, authType, true) != 0)
78                                         continue;
79                                 
80                                 Uri cachedUri = key.UriPrefix;
81                                 
82                                 if (cachedUri.Scheme != uriPrefix.Scheme)
83                                         continue;
84                                         
85                                 if (cachedUri.Port != uriPrefix.Port)
86                                         continue;
87                                         
88                                 if (cachedUri.Host != uriPrefix.Host)
89                                         continue;
90                                                                 
91                                 if (!absPath.StartsWith (key.AbsPath))
92                                         continue;
93                                         
94                                 longestPrefix = key.Length;
95                                 result = (NetworkCredential) e.Value;
96                         }
97                         
98                         return result;
99                 }
100
101                 public IEnumerator GetEnumerator ()
102                 {
103                         return cache.Values.GetEnumerator ();
104                 }               
105                 
106                 public void Add (Uri uriPrefix, string authType, NetworkCredential cred)
107                 {
108                         if (uriPrefix == null) 
109                                 throw new ArgumentNullException ("uriPrefix");
110
111                         if (authType == null) 
112                                 throw new ArgumentNullException ("authType");
113                         
114                         // throws ArgumentException when same key already exists.
115                         cache.Add (new CredentialCacheKey (uriPrefix, authType), cred);
116                 }
117                 
118                 public void Remove (Uri uriPrefix, string authType)
119                 {
120                         if (uriPrefix == null) 
121                                 throw new ArgumentNullException ("uriPrefix");
122
123                         if (authType == null) 
124                                 throw new ArgumentNullException ("authType");
125
126                         cache.Remove (new CredentialCacheKey (uriPrefix, authType));
127                 }
128                 
129                 class CredentialCacheKey {
130                         Uri uriPrefix;
131                         string authType;
132                         string absPath;
133                         int len;
134                         int hash;
135                         
136                         internal CredentialCacheKey (Uri uriPrefix, string authType)
137                         {
138                                 this.uriPrefix = uriPrefix;
139                                 this.authType = authType;
140                                 
141                                 this.absPath = uriPrefix.AbsolutePath;
142                                 this.absPath = absPath.Substring (0, absPath.LastIndexOf ('/'));                                
143
144                                 this.len = uriPrefix.AbsoluteUri.Length;
145                                 this.hash = uriPrefix.GetHashCode () 
146                                           + authType.ToString ().GetHashCode ();
147                         }
148                         
149                         public int Length {
150                                 get { return len; }
151                         }                       
152                         
153                         public string AbsPath {
154                                 get { return absPath; }
155                         }
156                         
157                         public Uri UriPrefix {
158                                 get { return uriPrefix; }
159                         }
160                         
161                         public string AuthType {
162                                 get { return authType; }
163                         }
164                         
165                         public override int GetHashCode ()
166                         {
167                                 return hash;
168                         }
169                         
170                         public override bool Equals (object obj)
171                         {
172                                 CredentialCacheKey key = obj as CredentialCacheKey;
173                                 return ((key != null) && (this.hash == key.hash));
174                         }
175                         
176                         public override string ToString ()
177                         {
178                                 return absPath + " : " + authType + " : len=" + len;
179                         }
180                 }
181         } 
182 }
183