Merge branch 'cecil-light'
[mono.git] / mcs / class / System / System.Net / WebProxy.cs
1 //
2 // System.Net.WebProxy.cs
3 //
4 // Authors:
5 //   Lawrence Pit (loz@cable.a2000.nl)
6 //   Andreas Nahr (ClassDevelopment@A-SoftTech.com)
7 //
8
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System;
31 using System.Collections;
32 using System.Globalization;
33 using System.Runtime.Serialization;
34 using System.Text.RegularExpressions;
35
36 namespace System.Net 
37 {
38         [Serializable]
39         public class WebProxy : IWebProxy, ISerializable
40         {
41                 Uri address;
42                 bool bypassOnLocal;
43                 ArrayList bypassList;
44                 ICredentials credentials;
45 #if NET_2_0
46                 bool useDefaultCredentials;
47 #endif
48
49                 // Constructors
50
51                 public WebProxy ()
52                         : this ((Uri) null, false, null, null) {}
53
54                 public WebProxy (string address)
55                         : this (ToUri (address), false, null, null) {}
56
57                 public WebProxy (Uri address) 
58                         : this (address, false, null, null) {}
59
60                 public WebProxy (string address, bool bypassOnLocal) 
61                         : this (ToUri (address), bypassOnLocal, null, null) {}
62
63                 public WebProxy (string host, int port)
64                         : this (new Uri ("http://" + host + ":" + port)) {}
65
66                 public WebProxy (Uri address, bool bypassOnLocal)
67                         : this (address, bypassOnLocal, null, null) {}
68
69                 public WebProxy (string address, bool bypassOnLocal, string [] bypassList)
70                         : this (ToUri (address), bypassOnLocal, bypassList, null) {}
71
72                 public WebProxy (Uri address, bool bypassOnLocal, string [] bypassList)
73                         : this (address, bypassOnLocal, bypassList, null) {}
74
75                 public WebProxy (string address, bool bypassOnLocal, string [] bypassList,
76                                 ICredentials credentials)
77                         : this (ToUri (address), bypassOnLocal, bypassList, credentials) {}
78
79                 public WebProxy (Uri address, bool bypassOnLocal, 
80                                  string[] bypassList, ICredentials credentials)
81                 {
82                         this.address = address;
83                         this.bypassOnLocal = bypassOnLocal;
84                         if (bypassList != null)
85                                 this.bypassList = new ArrayList (bypassList);
86                         this.credentials = credentials;
87                         CheckBypassList ();
88                 }
89
90                 protected WebProxy (SerializationInfo serializationInfo, StreamingContext streamingContext) 
91                 {
92                         this.address = (Uri) serializationInfo.GetValue ("_ProxyAddress", typeof (Uri));
93                         this.bypassOnLocal = serializationInfo.GetBoolean ("_BypassOnLocal");
94                         this.bypassList = (ArrayList) serializationInfo.GetValue ("_BypassList", typeof (ArrayList));
95 #if NET_2_0
96                         this.useDefaultCredentials =  serializationInfo.GetBoolean ("_UseDefaultCredentials");
97 #endif
98                         this.credentials = null;
99                         CheckBypassList ();
100                 }
101
102                 // Properties
103                 public Uri Address {
104                         get { return address; }
105                         set { address = value; }
106                 }
107
108                 public ArrayList BypassArrayList {
109                         get {
110                                 if (bypassList == null)
111                                         bypassList = new ArrayList ();
112                                 return bypassList;
113                         }
114                 }
115
116                 public string [] BypassList {
117                         get { return (string []) BypassArrayList.ToArray (typeof (string)); }
118                         set { 
119                                 if (value == null)
120                                         throw new ArgumentNullException ();
121                                 bypassList = new ArrayList (value); 
122                                 CheckBypassList ();
123                         }
124                 }
125
126                 public bool BypassProxyOnLocal {
127                         get { return bypassOnLocal; }
128                         set { bypassOnLocal = value; }
129                 }
130
131                 public ICredentials Credentials {
132                         get { return credentials; }
133                         set { credentials = value; }
134                 }
135
136 #if NET_2_0
137                 [MonoTODO ("Does not affect Credentials, since CredentialCache.DefaultCredentials is not implemented.")]
138                 public bool UseDefaultCredentials {
139                         get { return useDefaultCredentials; }
140                         set { useDefaultCredentials = value; }
141                 }
142 #endif
143
144                 // Methods
145 #if NET_2_0
146                 [Obsolete ("This method has been deprecated", false)]
147 #endif
148                 [MonoTODO("Can we get this info under windows from the system?")]
149                 public static WebProxy GetDefaultProxy ()
150                 {
151                         // Select gets a WebProxy from config files, if available.
152                         IWebProxy p = GlobalProxySelection.Select;
153                         if (p is WebProxy)
154                                 return (WebProxy) p;
155
156                         return new WebProxy ();
157                 }
158
159                 public Uri GetProxy (Uri destination)
160                 {
161                         if (IsBypassed (destination))
162                                 return destination;
163
164                         return address;
165                 }
166
167                 public bool IsBypassed (Uri host)
168                 {
169 #if NET_2_0
170                         if (host == null)
171                                 throw new ArgumentNullException ("host");
172 #endif
173
174                         if (host.IsLoopback && bypassOnLocal)
175                                 return true;
176
177                         if (address == null)
178                                 return true;
179
180                         string server = host.Host;
181                         if (bypassOnLocal && server.IndexOf ('.') == -1)
182                                 return true;
183
184                         // LAMESPEC
185                         if (!bypassOnLocal) {
186                                 if (String.Compare (server, "localhost", true, CultureInfo.InvariantCulture) == 0)
187                                         return true;
188                                 if (String.Compare (server, "loopback", true, CultureInfo.InvariantCulture) == 0)
189                                         return true;
190
191                                 IPAddress addr = null;
192                                 if (IPAddress.TryParse (server, out addr) && IPAddress.IsLoopback (addr))
193                                         return true;
194                         }
195
196                         if (bypassList == null || bypassList.Count == 0)
197                                 return false;
198
199                         try {
200                                 string hostStr = host.Scheme + "://" + host.Authority;
201                                 int i = 0;
202                                 for (; i < bypassList.Count; i++) {
203                                         Regex regex = new Regex ((string) bypassList [i], 
204                                                 // TODO: RegexOptions.Compiled |  // not implemented yet by Regex
205                                                 RegexOptions.IgnoreCase |
206                                                 RegexOptions.Singleline);
207
208                                         if (regex.IsMatch (hostStr))
209                                                 break;
210                                 }
211
212                                 if (i == bypassList.Count)
213                                         return false;
214
215                                 // continue checking correctness of regular expressions..
216                                 // will throw expression when an invalid one is found
217                                 for (; i < bypassList.Count; i++)
218                                         new Regex ((string) bypassList [i]);
219
220                                 return true;
221                         } catch (ArgumentException) {
222                                 return false;
223                         }
224                 }
225
226 #if NET_2_0
227                 protected virtual 
228 #endif
229                 void GetObjectData (SerializationInfo serializationInfo, StreamingContext streamingContext)
230                 {
231                         serializationInfo.AddValue ("_BypassOnLocal", bypassOnLocal);
232                         serializationInfo.AddValue ("_ProxyAddress", address);
233                         serializationInfo.AddValue ("_BypassList", bypassList);
234 #if NET_2_0
235                         serializationInfo.AddValue ("_UseDefaultCredentials", UseDefaultCredentials);
236 #endif
237                 }
238
239                 void ISerializable.GetObjectData (SerializationInfo serializationInfo,
240                                                   StreamingContext streamingContext)
241                 {
242                         GetObjectData (serializationInfo, streamingContext);
243                 }
244
245                 // Private Methods
246                 // this compiles the regular expressions, and will throw
247                 // an exception when an invalid one is found.
248                 void CheckBypassList ()
249                 {
250                         if (bypassList == null)
251                                 return;
252                         for (int i = 0; i < bypassList.Count; i++)
253                                 new Regex ((string) bypassList [i]);
254                 }
255
256                 static Uri ToUri (string address)
257                 {
258                         if (address == null)
259                                 return null;
260                                 
261                         if (address.IndexOf ("://", StringComparison.Ordinal) == -1) 
262                                 address = "http://" + address;
263
264                         return new Uri (address);
265                 }
266         }
267 }