4 // Author: Jeffrey Stedfast <jeff@xamarin.com>
6 // Copyright (c) 2012 Xamarin Inc.
8 // Permission is hereby granted, free of charge, to any person obtaining a copy
9 // of this software and associated documentation files (the "Software"), to deal
10 // in the Software without restriction, including without limitation the rights
11 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 // copies of the Software, and to permit persons to whom the Software is
13 // furnished to do so, subject to the following conditions:
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
18 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
28 using System.Collections.Generic;
29 using System.Runtime.InteropServices;
30 using System.Threading;
34 internal class CFObject : IDisposable
36 public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
37 const string SystemLibrary = "/usr/lib/libSystem.dylib";
39 [DllImport (SystemLibrary)]
40 public static extern IntPtr dlopen (string path, int mode);
42 [DllImport (SystemLibrary)]
43 public static extern IntPtr dlsym (IntPtr handle, string symbol);
45 [DllImport (SystemLibrary)]
46 public static extern void dlclose (IntPtr handle);
48 public static IntPtr GetIndirect (IntPtr handle, string symbol)
50 return dlsym (handle, symbol);
53 public static IntPtr GetCFObjectHandle (IntPtr handle, string symbol)
55 var indirect = dlsym (handle, symbol);
56 if (indirect == IntPtr.Zero)
59 return Marshal.ReadIntPtr (indirect);
62 public CFObject (IntPtr handle, bool own)
75 public IntPtr Handle { get; private set; }
77 [DllImport (CoreFoundationLibrary)]
78 extern static IntPtr CFRetain (IntPtr handle);
85 [DllImport (CoreFoundationLibrary)]
86 extern static IntPtr CFRelease (IntPtr handle);
93 protected virtual void Dispose (bool disposing)
95 if (Handle != IntPtr.Zero) {
101 public void Dispose ()
104 GC.SuppressFinalize (this);
108 internal class CFArray : CFObject
110 public CFArray (IntPtr handle, bool own) : base (handle, own) { }
112 [DllImport (CoreFoundationLibrary)]
113 extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, int numValues, IntPtr callbacks);
114 static readonly IntPtr kCFTypeArrayCallbacks;
118 var handle = dlopen (CoreFoundationLibrary, 0);
119 if (handle == IntPtr.Zero)
123 kCFTypeArrayCallbacks = GetIndirect (handle, "kCFTypeArrayCallBacks");
129 static unsafe CFArray Create (params IntPtr[] values)
132 throw new ArgumentNullException ("values");
134 fixed (IntPtr *pv = values) {
135 IntPtr handle = CFArrayCreate (IntPtr.Zero, (IntPtr) pv, values.Length, kCFTypeArrayCallbacks);
137 return new CFArray (handle, false);
141 public static CFArray Create (params CFObject[] values)
144 throw new ArgumentNullException ("values");
146 IntPtr[] _values = new IntPtr [values.Length];
147 for (int i = 0; i < _values.Length; i++)
148 _values[i] = values[i].Handle;
150 return Create (_values);
153 [DllImport (CoreFoundationLibrary)]
154 extern static int CFArrayGetCount (IntPtr handle);
157 get { return CFArrayGetCount (Handle); }
160 [DllImport (CoreFoundationLibrary)]
161 extern static IntPtr CFArrayGetValueAtIndex (IntPtr handle, int index);
163 public IntPtr this[int index] {
165 return CFArrayGetValueAtIndex (Handle, index);
170 internal class CFNumber : CFObject
172 public CFNumber (IntPtr handle, bool own) : base (handle, own) { }
174 [DllImport (CoreFoundationLibrary)]
175 extern static bool CFNumberGetValue (IntPtr handle, int type, out bool value);
177 public static bool AsBool (IntPtr handle)
181 if (handle == IntPtr.Zero)
184 CFNumberGetValue (handle, 1, out value);
189 public static implicit operator bool (CFNumber number)
191 return AsBool (number.Handle);
194 [DllImport (CoreFoundationLibrary)]
195 extern static bool CFNumberGetValue (IntPtr handle, int type, out int value);
197 public static int AsInt32 (IntPtr handle)
201 if (handle == IntPtr.Zero)
204 CFNumberGetValue (handle, 9, out value);
209 public static implicit operator int (CFNumber number)
211 return AsInt32 (number.Handle);
215 internal struct CFRange {
216 public int Location, Length;
218 public CFRange (int loc, int len)
225 internal class CFString : CFObject
229 public CFString (IntPtr handle, bool own) : base (handle, own) { }
231 [DllImport (CoreFoundationLibrary)]
232 extern static IntPtr CFStringCreateWithCharacters (IntPtr alloc, IntPtr chars, int length);
234 public static CFString Create (string value)
239 fixed (char *ptr = value) {
240 handle = CFStringCreateWithCharacters (IntPtr.Zero, (IntPtr) ptr, value.Length);
244 if (handle == IntPtr.Zero)
247 return new CFString (handle, true);
250 [DllImport (CoreFoundationLibrary)]
251 extern static int CFStringGetLength (IntPtr handle);
258 return CFStringGetLength (Handle);
262 [DllImport (CoreFoundationLibrary)]
263 extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
265 [DllImport (CoreFoundationLibrary)]
266 extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
268 public static string AsString (IntPtr handle)
270 if (handle == IntPtr.Zero)
273 int len = CFStringGetLength (handle);
278 IntPtr chars = CFStringGetCharactersPtr (handle);
279 IntPtr buffer = IntPtr.Zero;
281 if (chars == IntPtr.Zero) {
282 CFRange range = new CFRange (0, len);
283 buffer = Marshal.AllocHGlobal (len * 2);
284 CFStringGetCharacters (handle, range, buffer);
291 str = new string ((char *) chars, 0, len);
294 if (buffer != IntPtr.Zero)
295 Marshal.FreeHGlobal (buffer);
300 public override string ToString ()
303 str = AsString (Handle);
308 public static implicit operator string (CFString str)
310 return str.ToString ();
313 public static implicit operator CFString (string str)
319 internal class CFDictionary : CFObject
321 public CFDictionary (IntPtr handle, bool own) : base (handle, own) { }
323 [DllImport (CoreFoundationLibrary)]
324 extern static IntPtr CFDictionaryGetValue (IntPtr handle, IntPtr key);
326 public IntPtr GetValue (IntPtr key)
328 return CFDictionaryGetValue (Handle, key);
331 public IntPtr this[IntPtr key] {
333 return GetValue (key);
338 internal class CFUrl : CFObject
340 public CFUrl (IntPtr handle, bool own) : base (handle, own) { }
342 [DllImport (CoreFoundationLibrary)]
343 extern static IntPtr CFURLCreateWithString (IntPtr allocator, IntPtr str, IntPtr baseURL);
345 public static CFUrl Create (string absolute)
347 if (string.IsNullOrEmpty (absolute))
350 CFString str = CFString.Create (absolute);
351 IntPtr handle = CFURLCreateWithString (IntPtr.Zero, str.Handle, IntPtr.Zero);
354 if (handle == IntPtr.Zero)
357 return new CFUrl (handle, true);
361 internal enum CFProxyType {
363 AutoConfigurationUrl,
364 AutoConfigurationJavaScript,
371 internal class CFProxy {
372 //static IntPtr kCFProxyAutoConfigurationHTTPResponseKey;
373 static IntPtr kCFProxyAutoConfigurationJavaScriptKey;
374 static IntPtr kCFProxyAutoConfigurationURLKey;
375 static IntPtr kCFProxyHostNameKey;
376 static IntPtr kCFProxyPasswordKey;
377 static IntPtr kCFProxyPortNumberKey;
378 static IntPtr kCFProxyTypeKey;
379 static IntPtr kCFProxyUsernameKey;
381 //static IntPtr kCFProxyTypeNone;
382 static IntPtr kCFProxyTypeAutoConfigurationURL;
383 static IntPtr kCFProxyTypeAutoConfigurationJavaScript;
384 static IntPtr kCFProxyTypeFTP;
385 static IntPtr kCFProxyTypeHTTP;
386 static IntPtr kCFProxyTypeHTTPS;
387 static IntPtr kCFProxyTypeSOCKS;
391 IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
393 //kCFProxyAutoConfigurationHTTPResponseKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationHTTPResponseKey");
394 kCFProxyAutoConfigurationJavaScriptKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationJavaScriptKey");
395 kCFProxyAutoConfigurationURLKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationURLKey");
396 kCFProxyHostNameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyHostNameKey");
397 kCFProxyPasswordKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPasswordKey");
398 kCFProxyPortNumberKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPortNumberKey");
399 kCFProxyTypeKey = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeKey");
400 kCFProxyUsernameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyUsernameKey");
402 //kCFProxyTypeNone = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeNone");
403 kCFProxyTypeAutoConfigurationURL = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationURL");
404 kCFProxyTypeAutoConfigurationJavaScript = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationJavaScript");
405 kCFProxyTypeFTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeFTP");
406 kCFProxyTypeHTTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTP");
407 kCFProxyTypeHTTPS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTPS");
408 kCFProxyTypeSOCKS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeSOCKS");
410 CFObject.dlclose (handle);
413 CFDictionary settings;
415 internal CFProxy (CFDictionary settings)
417 this.settings = settings;
420 static CFProxyType CFProxyTypeToEnum (IntPtr type)
422 if (type == kCFProxyTypeAutoConfigurationJavaScript)
423 return CFProxyType.AutoConfigurationJavaScript;
425 if (type == kCFProxyTypeAutoConfigurationURL)
426 return CFProxyType.AutoConfigurationUrl;
428 if (type == kCFProxyTypeFTP)
429 return CFProxyType.FTP;
431 if (type == kCFProxyTypeHTTP)
432 return CFProxyType.HTTP;
434 if (type == kCFProxyTypeHTTPS)
435 return CFProxyType.HTTPS;
437 if (type == kCFProxyTypeSOCKS)
438 return CFProxyType.SOCKS;
440 return CFProxyType.None;
444 // AFAICT these get used with CFNetworkExecuteProxyAutoConfiguration*()
446 // TODO: bind CFHTTPMessage so we can return the proper type here.
447 public IntPtr AutoConfigurationHTTPResponse {
448 get { return settings[kCFProxyAutoConfigurationHTTPResponseKey]; }
452 public IntPtr AutoConfigurationJavaScript {
454 if (kCFProxyAutoConfigurationJavaScriptKey == IntPtr.Zero)
457 return settings[kCFProxyAutoConfigurationJavaScriptKey];
461 public IntPtr AutoConfigurationUrl {
463 if (kCFProxyAutoConfigurationURLKey == IntPtr.Zero)
466 return settings[kCFProxyAutoConfigurationURLKey];
470 public string HostName {
472 if (kCFProxyHostNameKey == IntPtr.Zero)
475 return CFString.AsString (settings[kCFProxyHostNameKey]);
479 public string Password {
481 if (kCFProxyPasswordKey == IntPtr.Zero)
484 return CFString.AsString (settings[kCFProxyPasswordKey]);
490 if (kCFProxyPortNumberKey == IntPtr.Zero)
493 return CFNumber.AsInt32 (settings[kCFProxyPortNumberKey]);
497 public CFProxyType ProxyType {
499 if (kCFProxyTypeKey == IntPtr.Zero)
500 return CFProxyType.None;
502 return CFProxyTypeToEnum (settings[kCFProxyTypeKey]);
506 public string Username {
508 if (kCFProxyUsernameKey == IntPtr.Zero)
511 return CFString.AsString (settings[kCFProxyUsernameKey]);
516 internal class CFProxySettings {
517 static IntPtr kCFNetworkProxiesHTTPEnable;
518 static IntPtr kCFNetworkProxiesHTTPPort;
519 static IntPtr kCFNetworkProxiesHTTPProxy;
520 static IntPtr kCFNetworkProxiesProxyAutoConfigEnable;
521 static IntPtr kCFNetworkProxiesProxyAutoConfigJavaScript;
522 static IntPtr kCFNetworkProxiesProxyAutoConfigURLString;
524 static CFProxySettings ()
526 IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
528 kCFNetworkProxiesHTTPEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPEnable");
529 kCFNetworkProxiesHTTPPort = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPPort");
530 kCFNetworkProxiesHTTPProxy = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPProxy");
531 kCFNetworkProxiesProxyAutoConfigEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigEnable");
532 kCFNetworkProxiesProxyAutoConfigJavaScript = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigJavaScript");
533 kCFNetworkProxiesProxyAutoConfigURLString = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigURLString");
535 CFObject.dlclose (handle);
538 CFDictionary settings;
540 public CFProxySettings (CFDictionary settings)
542 this.settings = settings;
545 public CFDictionary Dictionary {
546 get { return settings; }
549 public bool HTTPEnable {
551 if (kCFNetworkProxiesHTTPEnable == IntPtr.Zero)
554 return CFNumber.AsBool (settings[kCFNetworkProxiesHTTPEnable]);
558 public int HTTPPort {
560 if (kCFNetworkProxiesHTTPPort == IntPtr.Zero)
563 return CFNumber.AsInt32 (settings[kCFNetworkProxiesHTTPPort]);
567 public string HTTPProxy {
569 if (kCFNetworkProxiesHTTPProxy == IntPtr.Zero)
572 return CFString.AsString (settings[kCFNetworkProxiesHTTPProxy]);
576 public bool ProxyAutoConfigEnable {
578 if (kCFNetworkProxiesProxyAutoConfigEnable == IntPtr.Zero)
581 return CFNumber.AsBool (settings[kCFNetworkProxiesProxyAutoConfigEnable]);
585 public string ProxyAutoConfigJavaScript {
587 if (kCFNetworkProxiesProxyAutoConfigJavaScript == IntPtr.Zero)
590 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigJavaScript]);
594 public string ProxyAutoConfigURLString {
596 if (kCFNetworkProxiesProxyAutoConfigURLString == IntPtr.Zero)
599 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigURLString]);
604 internal static class CFNetwork {
606 public const string CFNetworkLibrary = "/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork";
608 public const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
611 [DllImport (CFNetworkLibrary, EntryPoint = "CFNetworkCopyProxiesForAutoConfigurationScript")]
612 // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error);
613 extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error);
615 class GetProxyData : IDisposable {
616 public IntPtr script;
617 public IntPtr targetUri;
619 public IntPtr result;
620 public ManualResetEvent evt = new ManualResetEvent (false);
622 public void Dispose ()
628 static object lock_obj = new object ();
629 static Queue<GetProxyData> get_proxy_queue;
630 static AutoResetEvent proxy_event;
632 static void CFNetworkCopyProxiesForAutoConfigurationScriptThread ()
635 var data_left = true;
638 proxy_event.WaitOne ();
642 if (get_proxy_queue.Count == 0)
644 data = get_proxy_queue.Dequeue ();
645 data_left = get_proxy_queue.Count > 0;
648 data.result = CFNetworkCopyProxiesForAutoConfigurationScriptSequential (data.script, data.targetUri, out data.error);
654 static IntPtr CFNetworkCopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error)
656 // This method must only be called on only one thread during an application's life time.
657 // Note that it's not enough to use a lock to make calls sequential across different threads,
658 // it has to be one thread. Also note that that thread can't be the main thread, because the
659 // main thread might be blocking waiting for this network request to finish.
660 // Another possibility would be to use JavaScriptCore to execute this piece of
661 // javascript ourselves, but unfortunately it's not available before iOS7.
662 // See bug #7923 comment #21+.
664 using (var data = new GetProxyData ()) {
665 data.script = proxyAutoConfigurationScript;
666 data.targetUri = targetURL;
669 if (get_proxy_queue == null) {
670 get_proxy_queue = new Queue<GetProxyData> ();
671 proxy_event = new AutoResetEvent (false);
672 new Thread (CFNetworkCopyProxiesForAutoConfigurationScriptThread) {
676 get_proxy_queue.Enqueue (data);
688 static CFArray CopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
690 IntPtr err = IntPtr.Zero;
691 IntPtr native = CFNetworkCopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL.Handle, out err);
693 if (native == IntPtr.Zero)
696 return new CFArray (native, true);
699 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
701 if (proxyAutoConfigurationScript == IntPtr.Zero)
702 throw new ArgumentNullException ("proxyAutoConfigurationScript");
704 if (targetURL == null)
705 throw new ArgumentNullException ("targetURL");
707 CFArray array = CopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
712 CFProxy[] proxies = new CFProxy [array.Count];
713 for (int i = 0; i < proxies.Length; i++) {
714 CFDictionary dict = new CFDictionary (array[i], false);
715 proxies[i] = new CFProxy (dict);
723 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, Uri targetUri)
725 if (proxyAutoConfigurationScript == IntPtr.Zero)
726 throw new ArgumentNullException ("proxyAutoConfigurationScript");
728 if (targetUri == null)
729 throw new ArgumentNullException ("targetUri");
731 CFUrl targetURL = CFUrl.Create (targetUri.AbsoluteUri);
732 CFProxy[] proxies = GetProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
733 targetURL.Dispose ();
738 [DllImport (CFNetworkLibrary)]
739 // CFArrayRef CFNetworkCopyProxiesForURL (CFURLRef url, CFDictionaryRef proxySettings);
740 extern static IntPtr CFNetworkCopyProxiesForURL (IntPtr url, IntPtr proxySettings);
742 static CFArray CopyProxiesForURL (CFUrl url, CFDictionary proxySettings)
744 IntPtr native = CFNetworkCopyProxiesForURL (url.Handle, proxySettings != null ? proxySettings.Handle : IntPtr.Zero);
746 if (native == IntPtr.Zero)
749 return new CFArray (native, true);
752 public static CFProxy[] GetProxiesForURL (CFUrl url, CFProxySettings proxySettings)
754 if (url == null || url.Handle == IntPtr.Zero)
755 throw new ArgumentNullException ("url");
757 if (proxySettings == null)
758 proxySettings = GetSystemProxySettings ();
760 CFArray array = CopyProxiesForURL (url, proxySettings.Dictionary);
765 CFProxy[] proxies = new CFProxy [array.Count];
766 for (int i = 0; i < proxies.Length; i++) {
767 CFDictionary dict = new CFDictionary (array[i], false);
768 proxies[i] = new CFProxy (dict);
776 public static CFProxy[] GetProxiesForUri (Uri uri, CFProxySettings proxySettings)
779 throw new ArgumentNullException ("uri");
781 CFUrl url = CFUrl.Create (uri.AbsoluteUri);
785 CFProxy[] proxies = GetProxiesForURL (url, proxySettings);
791 [DllImport (CFNetworkLibrary)]
792 // CFDictionaryRef CFNetworkCopySystemProxySettings (void);
793 extern static IntPtr CFNetworkCopySystemProxySettings ();
795 public static CFProxySettings GetSystemProxySettings ()
797 IntPtr native = CFNetworkCopySystemProxySettings ();
799 if (native == IntPtr.Zero)
802 var dict = new CFDictionary (native, true);
804 return new CFProxySettings (dict);
807 class CFWebProxy : IWebProxy {
808 ICredentials credentials;
815 public ICredentials Credentials {
816 get { return credentials; }
818 userSpecified = true;
823 static Uri GetProxyUri (CFProxy proxy, out NetworkCredential credentials)
827 switch (proxy.ProxyType) {
828 case CFProxyType.FTP:
831 case CFProxyType.HTTP:
832 case CFProxyType.HTTPS:
833 protocol = "http://";
840 string username = proxy.Username;
841 string password = proxy.Password;
842 string hostname = proxy.HostName;
843 int port = proxy.Port;
846 if (username != null)
847 credentials = new NetworkCredential (username, password);
851 uri = protocol + hostname + (port != 0 ? ':' + port.ToString () : string.Empty);
853 return new Uri (uri, UriKind.Absolute);
856 static Uri GetProxyUriFromScript (IntPtr script, Uri targetUri, out NetworkCredential credentials)
858 CFProxy[] proxies = CFNetwork.GetProxiesForAutoConfigurationScript (script, targetUri);
860 if (proxies == null) {
865 for (int i = 0; i < proxies.Length; i++) {
866 switch (proxies[i].ProxyType) {
867 case CFProxyType.HTTPS:
868 case CFProxyType.HTTP:
869 case CFProxyType.FTP:
870 // create a Uri based on the hostname/port/etc info
871 return GetProxyUri (proxies[i], out credentials);
872 case CFProxyType.SOCKS:
874 // unsupported proxy type, try the next one
876 case CFProxyType.None:
877 // no proxy should be used
888 public Uri GetProxy (Uri targetUri)
890 NetworkCredential credentials = null;
893 if (targetUri == null)
894 throw new ArgumentNullException ("targetUri");
897 CFProxySettings settings = CFNetwork.GetSystemProxySettings ();
898 CFProxy[] proxies = CFNetwork.GetProxiesForUri (targetUri, settings);
900 if (proxies != null) {
901 for (int i = 0; i < proxies.Length && proxy == null; i++) {
902 switch (proxies[i].ProxyType) {
903 case CFProxyType.AutoConfigurationJavaScript:
904 proxy = GetProxyUriFromScript (proxies[i].AutoConfigurationJavaScript, targetUri, out credentials);
906 case CFProxyType.AutoConfigurationUrl:
907 // unsupported proxy type (requires fetching script from remote url)
909 case CFProxyType.HTTPS:
910 case CFProxyType.HTTP:
911 case CFProxyType.FTP:
912 // create a Uri based on the hostname/port/etc info
913 proxy = GetProxyUri (proxies[i], out credentials);
915 case CFProxyType.SOCKS:
916 // unsupported proxy type, try the next one
918 case CFProxyType.None:
919 // no proxy should be used
926 // no supported proxies for this Uri, fall back to trying to connect to targetUri directly
933 // ignore errors while retrieving proxy data
938 this.credentials = credentials;
943 public bool IsBypassed (Uri targetUri)
945 if (targetUri == null)
946 throw new ArgumentNullException ("targetUri");
948 return GetProxy (targetUri) == targetUri;
952 public static IWebProxy GetDefaultProxy ()
954 return new CFWebProxy ();