4 // Author: Jeffrey Stedfast <jeff@xamarin.com>
6 // Copyright (c) 2012-2014 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 void 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, /* CFIndex */ IntPtr 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, (IntPtr) 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 /* CFIndex */ IntPtr CFArrayGetCount (IntPtr handle);
157 get { return (int) CFArrayGetCount (Handle); }
160 [DllImport (CoreFoundationLibrary)]
161 extern static IntPtr CFArrayGetValueAtIndex (IntPtr handle, /* CFIndex */ IntPtr index);
163 public IntPtr this[int index] {
165 return CFArrayGetValueAtIndex (Handle, (IntPtr) index);
170 internal class CFNumber : CFObject
172 public CFNumber (IntPtr handle, bool own) : base (handle, own) { }
174 [DllImport (CoreFoundationLibrary)]
175 [return: MarshalAs (UnmanagedType.I1)]
176 extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, [MarshalAs (UnmanagedType.I1)] out bool value);
178 public static bool AsBool (IntPtr handle)
182 if (handle == IntPtr.Zero)
185 CFNumberGetValue (handle, (IntPtr) 1, out value);
190 public static implicit operator bool (CFNumber number)
192 return AsBool (number.Handle);
195 [DllImport (CoreFoundationLibrary)]
196 [return: MarshalAs (UnmanagedType.I1)]
197 extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, out int value);
199 public static int AsInt32 (IntPtr handle)
203 if (handle == IntPtr.Zero)
206 // 9 == kCFNumberIntType == C int
207 CFNumberGetValue (handle, (IntPtr) 9, out value);
212 public static implicit operator int (CFNumber number)
214 return AsInt32 (number.Handle);
218 internal struct CFRange {
219 public IntPtr Location, Length;
221 public CFRange (int loc, int len)
223 Location = (IntPtr) loc;
224 Length = (IntPtr) len;
228 internal class CFString : CFObject
232 public CFString (IntPtr handle, bool own) : base (handle, own) { }
234 [DllImport (CoreFoundationLibrary)]
235 extern static IntPtr CFStringCreateWithCharacters (IntPtr alloc, IntPtr chars, /* CFIndex */ IntPtr length);
237 public static CFString Create (string value)
242 fixed (char *ptr = value) {
243 handle = CFStringCreateWithCharacters (IntPtr.Zero, (IntPtr) ptr, (IntPtr) value.Length);
247 if (handle == IntPtr.Zero)
250 return new CFString (handle, true);
253 [DllImport (CoreFoundationLibrary)]
254 extern static /* CFIndex */ IntPtr CFStringGetLength (IntPtr handle);
261 return (int) CFStringGetLength (Handle);
265 [DllImport (CoreFoundationLibrary)]
266 extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
268 [DllImport (CoreFoundationLibrary)]
269 extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
271 public static string AsString (IntPtr handle)
273 if (handle == IntPtr.Zero)
276 int len = (int) CFStringGetLength (handle);
281 IntPtr chars = CFStringGetCharactersPtr (handle);
282 IntPtr buffer = IntPtr.Zero;
284 if (chars == IntPtr.Zero) {
285 CFRange range = new CFRange (0, len);
286 buffer = Marshal.AllocHGlobal (len * 2);
287 CFStringGetCharacters (handle, range, buffer);
294 str = new string ((char *) chars, 0, len);
297 if (buffer != IntPtr.Zero)
298 Marshal.FreeHGlobal (buffer);
303 public override string ToString ()
306 str = AsString (Handle);
311 public static implicit operator string (CFString str)
313 return str.ToString ();
316 public static implicit operator CFString (string str)
322 internal class CFDictionary : CFObject
324 public CFDictionary (IntPtr handle, bool own) : base (handle, own) { }
326 [DllImport (CoreFoundationLibrary)]
327 extern static IntPtr CFDictionaryGetValue (IntPtr handle, IntPtr key);
329 public IntPtr GetValue (IntPtr key)
331 return CFDictionaryGetValue (Handle, key);
334 public IntPtr this[IntPtr key] {
336 return GetValue (key);
341 internal class CFUrl : CFObject
343 public CFUrl (IntPtr handle, bool own) : base (handle, own) { }
345 [DllImport (CoreFoundationLibrary)]
346 extern static IntPtr CFURLCreateWithString (IntPtr allocator, IntPtr str, IntPtr baseURL);
348 public static CFUrl Create (string absolute)
350 if (string.IsNullOrEmpty (absolute))
353 CFString str = CFString.Create (absolute);
354 IntPtr handle = CFURLCreateWithString (IntPtr.Zero, str.Handle, IntPtr.Zero);
357 if (handle == IntPtr.Zero)
360 return new CFUrl (handle, true);
364 internal enum CFProxyType {
366 AutoConfigurationUrl,
367 AutoConfigurationJavaScript,
374 internal class CFProxy {
375 //static IntPtr kCFProxyAutoConfigurationHTTPResponseKey;
376 static IntPtr kCFProxyAutoConfigurationJavaScriptKey;
377 static IntPtr kCFProxyAutoConfigurationURLKey;
378 static IntPtr kCFProxyHostNameKey;
379 static IntPtr kCFProxyPasswordKey;
380 static IntPtr kCFProxyPortNumberKey;
381 static IntPtr kCFProxyTypeKey;
382 static IntPtr kCFProxyUsernameKey;
384 //static IntPtr kCFProxyTypeNone;
385 static IntPtr kCFProxyTypeAutoConfigurationURL;
386 static IntPtr kCFProxyTypeAutoConfigurationJavaScript;
387 static IntPtr kCFProxyTypeFTP;
388 static IntPtr kCFProxyTypeHTTP;
389 static IntPtr kCFProxyTypeHTTPS;
390 static IntPtr kCFProxyTypeSOCKS;
394 IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
396 //kCFProxyAutoConfigurationHTTPResponseKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationHTTPResponseKey");
397 kCFProxyAutoConfigurationJavaScriptKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationJavaScriptKey");
398 kCFProxyAutoConfigurationURLKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationURLKey");
399 kCFProxyHostNameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyHostNameKey");
400 kCFProxyPasswordKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPasswordKey");
401 kCFProxyPortNumberKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPortNumberKey");
402 kCFProxyTypeKey = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeKey");
403 kCFProxyUsernameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyUsernameKey");
405 //kCFProxyTypeNone = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeNone");
406 kCFProxyTypeAutoConfigurationURL = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationURL");
407 kCFProxyTypeAutoConfigurationJavaScript = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationJavaScript");
408 kCFProxyTypeFTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeFTP");
409 kCFProxyTypeHTTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTP");
410 kCFProxyTypeHTTPS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTPS");
411 kCFProxyTypeSOCKS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeSOCKS");
413 CFObject.dlclose (handle);
416 CFDictionary settings;
418 internal CFProxy (CFDictionary settings)
420 this.settings = settings;
423 static CFProxyType CFProxyTypeToEnum (IntPtr type)
425 if (type == kCFProxyTypeAutoConfigurationJavaScript)
426 return CFProxyType.AutoConfigurationJavaScript;
428 if (type == kCFProxyTypeAutoConfigurationURL)
429 return CFProxyType.AutoConfigurationUrl;
431 if (type == kCFProxyTypeFTP)
432 return CFProxyType.FTP;
434 if (type == kCFProxyTypeHTTP)
435 return CFProxyType.HTTP;
437 if (type == kCFProxyTypeHTTPS)
438 return CFProxyType.HTTPS;
440 if (type == kCFProxyTypeSOCKS)
441 return CFProxyType.SOCKS;
443 return CFProxyType.None;
447 // AFAICT these get used with CFNetworkExecuteProxyAutoConfiguration*()
449 // TODO: bind CFHTTPMessage so we can return the proper type here.
450 public IntPtr AutoConfigurationHTTPResponse {
451 get { return settings[kCFProxyAutoConfigurationHTTPResponseKey]; }
455 public IntPtr AutoConfigurationJavaScript {
457 if (kCFProxyAutoConfigurationJavaScriptKey == IntPtr.Zero)
460 return settings[kCFProxyAutoConfigurationJavaScriptKey];
464 public IntPtr AutoConfigurationUrl {
466 if (kCFProxyAutoConfigurationURLKey == IntPtr.Zero)
469 return settings[kCFProxyAutoConfigurationURLKey];
473 public string HostName {
475 if (kCFProxyHostNameKey == IntPtr.Zero)
478 return CFString.AsString (settings[kCFProxyHostNameKey]);
482 public string Password {
484 if (kCFProxyPasswordKey == IntPtr.Zero)
487 return CFString.AsString (settings[kCFProxyPasswordKey]);
493 if (kCFProxyPortNumberKey == IntPtr.Zero)
496 return CFNumber.AsInt32 (settings[kCFProxyPortNumberKey]);
500 public CFProxyType ProxyType {
502 if (kCFProxyTypeKey == IntPtr.Zero)
503 return CFProxyType.None;
505 return CFProxyTypeToEnum (settings[kCFProxyTypeKey]);
509 public string Username {
511 if (kCFProxyUsernameKey == IntPtr.Zero)
514 return CFString.AsString (settings[kCFProxyUsernameKey]);
519 internal class CFProxySettings {
520 static IntPtr kCFNetworkProxiesHTTPEnable;
521 static IntPtr kCFNetworkProxiesHTTPPort;
522 static IntPtr kCFNetworkProxiesHTTPProxy;
523 static IntPtr kCFNetworkProxiesProxyAutoConfigEnable;
524 static IntPtr kCFNetworkProxiesProxyAutoConfigJavaScript;
525 static IntPtr kCFNetworkProxiesProxyAutoConfigURLString;
527 static CFProxySettings ()
529 IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
531 kCFNetworkProxiesHTTPEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPEnable");
532 kCFNetworkProxiesHTTPPort = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPPort");
533 kCFNetworkProxiesHTTPProxy = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPProxy");
534 kCFNetworkProxiesProxyAutoConfigEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigEnable");
535 kCFNetworkProxiesProxyAutoConfigJavaScript = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigJavaScript");
536 kCFNetworkProxiesProxyAutoConfigURLString = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigURLString");
538 CFObject.dlclose (handle);
541 CFDictionary settings;
543 public CFProxySettings (CFDictionary settings)
545 this.settings = settings;
548 public CFDictionary Dictionary {
549 get { return settings; }
552 public bool HTTPEnable {
554 if (kCFNetworkProxiesHTTPEnable == IntPtr.Zero)
557 return CFNumber.AsBool (settings[kCFNetworkProxiesHTTPEnable]);
561 public int HTTPPort {
563 if (kCFNetworkProxiesHTTPPort == IntPtr.Zero)
566 return CFNumber.AsInt32 (settings[kCFNetworkProxiesHTTPPort]);
570 public string HTTPProxy {
572 if (kCFNetworkProxiesHTTPProxy == IntPtr.Zero)
575 return CFString.AsString (settings[kCFNetworkProxiesHTTPProxy]);
579 public bool ProxyAutoConfigEnable {
581 if (kCFNetworkProxiesProxyAutoConfigEnable == IntPtr.Zero)
584 return CFNumber.AsBool (settings[kCFNetworkProxiesProxyAutoConfigEnable]);
588 public string ProxyAutoConfigJavaScript {
590 if (kCFNetworkProxiesProxyAutoConfigJavaScript == IntPtr.Zero)
593 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigJavaScript]);
597 public string ProxyAutoConfigURLString {
599 if (kCFNetworkProxiesProxyAutoConfigURLString == IntPtr.Zero)
602 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigURLString]);
607 internal static class CFNetwork {
609 public const string CFNetworkLibrary = "/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork";
611 public const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
614 [DllImport (CFNetworkLibrary, EntryPoint = "CFNetworkCopyProxiesForAutoConfigurationScript")]
615 // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error);
616 extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error);
618 class GetProxyData : IDisposable {
619 public IntPtr script;
620 public IntPtr targetUri;
622 public IntPtr result;
623 public ManualResetEvent evt = new ManualResetEvent (false);
625 public void Dispose ()
631 static object lock_obj = new object ();
632 static Queue<GetProxyData> get_proxy_queue;
633 static AutoResetEvent proxy_event;
635 static void CFNetworkCopyProxiesForAutoConfigurationScriptThread ()
638 var data_left = true;
641 proxy_event.WaitOne ();
645 if (get_proxy_queue.Count == 0)
647 data = get_proxy_queue.Dequeue ();
648 data_left = get_proxy_queue.Count > 0;
651 data.result = CFNetworkCopyProxiesForAutoConfigurationScriptSequential (data.script, data.targetUri, out data.error);
657 static IntPtr CFNetworkCopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error)
659 // This method must only be called on only one thread during an application's life time.
660 // Note that it's not enough to use a lock to make calls sequential across different threads,
661 // it has to be one thread. Also note that that thread can't be the main thread, because the
662 // main thread might be blocking waiting for this network request to finish.
663 // Another possibility would be to use JavaScriptCore to execute this piece of
664 // javascript ourselves, but unfortunately it's not available before iOS7.
665 // See bug #7923 comment #21+.
667 using (var data = new GetProxyData ()) {
668 data.script = proxyAutoConfigurationScript;
669 data.targetUri = targetURL;
672 if (get_proxy_queue == null) {
673 get_proxy_queue = new Queue<GetProxyData> ();
674 proxy_event = new AutoResetEvent (false);
675 new Thread (CFNetworkCopyProxiesForAutoConfigurationScriptThread) {
679 get_proxy_queue.Enqueue (data);
691 static CFArray CopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
693 IntPtr err = IntPtr.Zero;
694 IntPtr native = CFNetworkCopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL.Handle, out err);
696 if (native == IntPtr.Zero)
699 return new CFArray (native, true);
702 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
704 if (proxyAutoConfigurationScript == IntPtr.Zero)
705 throw new ArgumentNullException ("proxyAutoConfigurationScript");
707 if (targetURL == null)
708 throw new ArgumentNullException ("targetURL");
710 CFArray array = CopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
715 CFProxy[] proxies = new CFProxy [array.Count];
716 for (int i = 0; i < proxies.Length; i++) {
717 CFDictionary dict = new CFDictionary (array[i], false);
718 proxies[i] = new CFProxy (dict);
726 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, Uri targetUri)
728 if (proxyAutoConfigurationScript == IntPtr.Zero)
729 throw new ArgumentNullException ("proxyAutoConfigurationScript");
731 if (targetUri == null)
732 throw new ArgumentNullException ("targetUri");
734 CFUrl targetURL = CFUrl.Create (targetUri.AbsoluteUri);
735 CFProxy[] proxies = GetProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
736 targetURL.Dispose ();
741 [DllImport (CFNetworkLibrary)]
742 // CFArrayRef CFNetworkCopyProxiesForURL (CFURLRef url, CFDictionaryRef proxySettings);
743 extern static IntPtr CFNetworkCopyProxiesForURL (IntPtr url, IntPtr proxySettings);
745 static CFArray CopyProxiesForURL (CFUrl url, CFDictionary proxySettings)
747 IntPtr native = CFNetworkCopyProxiesForURL (url.Handle, proxySettings != null ? proxySettings.Handle : IntPtr.Zero);
749 if (native == IntPtr.Zero)
752 return new CFArray (native, true);
755 public static CFProxy[] GetProxiesForURL (CFUrl url, CFProxySettings proxySettings)
757 if (url == null || url.Handle == IntPtr.Zero)
758 throw new ArgumentNullException ("url");
760 if (proxySettings == null)
761 proxySettings = GetSystemProxySettings ();
763 CFArray array = CopyProxiesForURL (url, proxySettings.Dictionary);
768 CFProxy[] proxies = new CFProxy [array.Count];
769 for (int i = 0; i < proxies.Length; i++) {
770 CFDictionary dict = new CFDictionary (array[i], false);
771 proxies[i] = new CFProxy (dict);
779 public static CFProxy[] GetProxiesForUri (Uri uri, CFProxySettings proxySettings)
782 throw new ArgumentNullException ("uri");
784 CFUrl url = CFUrl.Create (uri.AbsoluteUri);
788 CFProxy[] proxies = GetProxiesForURL (url, proxySettings);
794 [DllImport (CFNetworkLibrary)]
795 // CFDictionaryRef CFNetworkCopySystemProxySettings (void);
796 extern static IntPtr CFNetworkCopySystemProxySettings ();
798 public static CFProxySettings GetSystemProxySettings ()
800 IntPtr native = CFNetworkCopySystemProxySettings ();
802 if (native == IntPtr.Zero)
805 var dict = new CFDictionary (native, true);
807 return new CFProxySettings (dict);
810 class CFWebProxy : IWebProxy {
811 ICredentials credentials;
818 public ICredentials Credentials {
819 get { return credentials; }
821 userSpecified = true;
826 static Uri GetProxyUri (CFProxy proxy, out NetworkCredential credentials)
830 switch (proxy.ProxyType) {
831 case CFProxyType.FTP:
834 case CFProxyType.HTTP:
835 case CFProxyType.HTTPS:
836 protocol = "http://";
843 string username = proxy.Username;
844 string password = proxy.Password;
845 string hostname = proxy.HostName;
846 int port = proxy.Port;
849 if (username != null)
850 credentials = new NetworkCredential (username, password);
854 uri = protocol + hostname + (port != 0 ? ':' + port.ToString () : string.Empty);
856 return new Uri (uri, UriKind.Absolute);
859 static Uri GetProxyUriFromScript (IntPtr script, Uri targetUri, out NetworkCredential credentials)
861 CFProxy[] proxies = CFNetwork.GetProxiesForAutoConfigurationScript (script, targetUri);
863 if (proxies == null) {
868 for (int i = 0; i < proxies.Length; i++) {
869 switch (proxies[i].ProxyType) {
870 case CFProxyType.HTTPS:
871 case CFProxyType.HTTP:
872 case CFProxyType.FTP:
873 // create a Uri based on the hostname/port/etc info
874 return GetProxyUri (proxies[i], out credentials);
875 case CFProxyType.SOCKS:
877 // unsupported proxy type, try the next one
879 case CFProxyType.None:
880 // no proxy should be used
891 public Uri GetProxy (Uri targetUri)
893 NetworkCredential credentials = null;
896 if (targetUri == null)
897 throw new ArgumentNullException ("targetUri");
900 CFProxySettings settings = CFNetwork.GetSystemProxySettings ();
901 CFProxy[] proxies = CFNetwork.GetProxiesForUri (targetUri, settings);
903 if (proxies != null) {
904 for (int i = 0; i < proxies.Length && proxy == null; i++) {
905 switch (proxies[i].ProxyType) {
906 case CFProxyType.AutoConfigurationJavaScript:
907 proxy = GetProxyUriFromScript (proxies[i].AutoConfigurationJavaScript, targetUri, out credentials);
909 case CFProxyType.AutoConfigurationUrl:
910 // unsupported proxy type (requires fetching script from remote url)
912 case CFProxyType.HTTPS:
913 case CFProxyType.HTTP:
914 case CFProxyType.FTP:
915 // create a Uri based on the hostname/port/etc info
916 proxy = GetProxyUri (proxies[i], out credentials);
918 case CFProxyType.SOCKS:
919 // unsupported proxy type, try the next one
921 case CFProxyType.None:
922 // no proxy should be used
929 // no supported proxies for this Uri, fall back to trying to connect to targetUri directly
936 // ignore errors while retrieving proxy data
941 this.credentials = credentials;
946 public bool IsBypassed (Uri targetUri)
948 if (targetUri == null)
949 throw new ArgumentNullException ("targetUri");
951 return GetProxy (targetUri) == targetUri;
955 public static IWebProxy GetDefaultProxy ()
957 return new CFWebProxy ();