bd2cdc10b9876881f10ee913c5dac33e576bc6de
[mono.git] / mcs / class / System / System.Net / MacProxy.cs
1 // 
2 // MacProxy.cs
3 //  
4 // Author: Jeffrey Stedfast <jeff@xamarin.com>
5 // 
6 // Copyright (c) 2012-2014 Xamarin Inc.
7 // 
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:
14 // 
15 // The above copyright notice and this permission notice shall be included in
16 // all copies or substantial portions of the Software.
17 // 
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
24 // THE SOFTWARE.
25 // 
26
27 using System;
28 using System.Net;
29 using System.Collections.Generic;
30 using System.Runtime.InteropServices;
31 using System.Threading;
32 using ObjCRuntime;
33
34 namespace Mono.Net
35 {
36         internal class CFType {
37                 [DllImport (CFObject.CoreFoundationLibrary, EntryPoint="CFGetTypeID")]
38                 public static extern IntPtr GetTypeID (IntPtr typeRef);
39         }
40
41         internal class CFObject : IDisposable, INativeObject
42         {
43                 public const string CoreFoundationLibrary = "/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation";
44                 const string SystemLibrary = "/usr/lib/libSystem.dylib";
45
46                 [DllImport (SystemLibrary)]
47                 public static extern IntPtr dlopen (string path, int mode);
48
49                 [DllImport (SystemLibrary)]
50                 static extern IntPtr dlsym (IntPtr handle, string symbol);
51
52                 [DllImport (SystemLibrary)]
53                 public static extern void dlclose (IntPtr handle);
54
55                 public static IntPtr GetIndirect (IntPtr handle, string symbol)
56                 {
57                         return dlsym (handle, symbol);
58                 }
59
60                 public static CFString GetStringConstant (IntPtr handle, string symbol)
61                 {
62                         var indirect = dlsym (handle, symbol);
63                         if (indirect == IntPtr.Zero)
64                                 return null;
65                         var actual = Marshal.ReadIntPtr (indirect);
66                         if (actual == IntPtr.Zero)
67                                 return null;
68                         return new CFString (actual, false);
69                 }
70
71                 public static IntPtr GetIntPtr (IntPtr handle, string symbol)
72                 {
73                         var indirect = dlsym (handle, symbol);
74                         if (indirect == IntPtr.Zero)
75                                 return IntPtr.Zero;
76                         return Marshal.ReadIntPtr (indirect);
77                 }
78
79                 public static IntPtr GetCFObjectHandle (IntPtr handle, string symbol)
80                 {
81                         var indirect = dlsym (handle, symbol);
82                         if (indirect == IntPtr.Zero)
83                                 return IntPtr.Zero;
84
85                         return Marshal.ReadIntPtr (indirect);
86                 }
87
88                 public CFObject (IntPtr handle, bool own)
89                 {
90                         Handle = handle;
91
92                         if (!own)
93                                 Retain ();
94                 }
95
96                 ~CFObject ()
97                 {
98                         Dispose (false);
99                 }
100
101                 public IntPtr Handle { get; private set; }
102
103                 [DllImport (CoreFoundationLibrary)]
104                 internal extern static IntPtr CFRetain (IntPtr handle);
105
106                 void Retain ()
107                 {
108                         CFRetain (Handle);
109                 }
110
111                 [DllImport (CoreFoundationLibrary)]
112                 internal extern static void CFRelease (IntPtr handle);
113
114                 void Release ()
115                 {
116                         CFRelease (Handle);
117                 }
118
119                 protected virtual void Dispose (bool disposing)
120                 {
121                         if (Handle != IntPtr.Zero) {
122                                 Release ();
123                                 Handle = IntPtr.Zero;
124                         }
125                 }
126
127                 public void Dispose ()
128                 {
129                         Dispose (true);
130                         GC.SuppressFinalize (this);
131                 }
132         }
133
134         internal class CFArray : CFObject
135         {
136                 public CFArray (IntPtr handle, bool own) : base (handle, own) { }
137
138                 [DllImport (CoreFoundationLibrary)]
139                 extern static IntPtr CFArrayCreate (IntPtr allocator, IntPtr values, /* CFIndex */ IntPtr numValues, IntPtr callbacks);
140                 static readonly IntPtr kCFTypeArrayCallbacks;
141
142                 static CFArray ()
143                 {
144                         var handle = dlopen (CoreFoundationLibrary, 0);
145                         if (handle == IntPtr.Zero)
146                                 return;
147
148                         try {
149                                 kCFTypeArrayCallbacks = GetIndirect (handle, "kCFTypeArrayCallBacks");
150                         } finally {
151                                 dlclose (handle);
152                         }
153                 }
154                 
155                 public static CFArray FromNativeObjects (params INativeObject[] values)
156                 {
157                         return new CFArray (Create (values), true);
158                 }
159
160                 public static unsafe IntPtr Create (params IntPtr[] values)
161                 {
162                         if (values == null)
163                                 throw new ArgumentNullException ("values");
164                         fixed (IntPtr* pv = values) {
165                                 return CFArrayCreate (IntPtr.Zero, (IntPtr) pv, (IntPtr)values.Length, kCFTypeArrayCallbacks);
166                         }
167                 }
168
169                 internal static unsafe CFArray CreateArray (params IntPtr[] values)
170                 {
171                         if (values == null)
172                                 throw new ArgumentNullException ("values");
173
174                         fixed (IntPtr *pv = values) {
175                                 IntPtr handle = CFArrayCreate (IntPtr.Zero, (IntPtr) pv, (IntPtr) values.Length, kCFTypeArrayCallbacks);
176
177                                 return new CFArray (handle, false);
178                         }
179                 }
180                 
181                 public static CFArray CreateArray (params INativeObject[] values)
182                 {
183                         return new CFArray (Create (values), true);
184                 }
185
186                 public static IntPtr Create (params INativeObject[] values)
187                 {
188                         if (values == null)
189                                 throw new ArgumentNullException ("values");
190                         IntPtr[] _values = new IntPtr [values.Length];
191                         for (int i = 0; i < _values.Length; ++i)
192                                 _values [i] = values [i].Handle;
193                         return Create (_values);
194                 }
195
196                 [DllImport (CoreFoundationLibrary)]
197                 extern static /* CFIndex */ IntPtr CFArrayGetCount (IntPtr handle);
198
199                 public int Count {
200                         get { return (int) CFArrayGetCount (Handle); }
201                 }
202
203                 [DllImport (CoreFoundationLibrary)]
204                 extern static IntPtr CFArrayGetValueAtIndex (IntPtr handle, /* CFIndex */ IntPtr index);
205
206                 public IntPtr this[int index] {
207                         get {
208                                 return CFArrayGetValueAtIndex (Handle, (IntPtr) index);
209                         }
210                 }
211                 
212                 static public T [] ArrayFromHandle<T> (IntPtr handle, Func<IntPtr, T> creation) where T : class, INativeObject
213                 {
214                         if (handle == IntPtr.Zero)
215                                 return null;
216
217                         var c = CFArrayGetCount (handle);
218                         T [] ret = new T [(int)c];
219
220                         for (uint i = 0; i < (uint)c; i++) {
221                                 ret [i] = creation (CFArrayGetValueAtIndex (handle, (IntPtr)i));
222                         }
223                         return ret;
224                 }
225         }
226
227         internal class CFNumber : CFObject
228         {
229                 public CFNumber (IntPtr handle, bool own) : base (handle, own) { }
230
231                 [DllImport (CoreFoundationLibrary)]
232                 [return: MarshalAs (UnmanagedType.I1)]
233                 extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, [MarshalAs (UnmanagedType.I1)] out bool value);
234
235                 public static bool AsBool (IntPtr handle)
236                 {
237                         bool value;
238
239                         if (handle == IntPtr.Zero)
240                                 return false;
241
242                         CFNumberGetValue (handle, (IntPtr) 1, out value);
243
244                         return value;
245                 }
246
247                 public static implicit operator bool (CFNumber number)
248                 {
249                         return AsBool (number.Handle);
250                 }
251
252                 [DllImport (CoreFoundationLibrary)]
253                 [return: MarshalAs (UnmanagedType.I1)]
254                 extern static bool CFNumberGetValue (IntPtr handle, /* CFNumberType */ IntPtr type, out int value);
255
256                 public static int AsInt32 (IntPtr handle)
257                 {
258                         int value;
259
260                         if (handle == IntPtr.Zero)
261                                 return 0;
262
263                         // 9 == kCFNumberIntType == C int
264                         CFNumberGetValue (handle, (IntPtr) 9, out value);
265
266                         return value;
267                 }
268                 
269                 [DllImport (CoreFoundationLibrary)]
270                 extern static IntPtr CFNumberCreate (IntPtr allocator, IntPtr theType, IntPtr valuePtr);        
271
272                 public static CFNumber FromInt32 (int number)
273                 {
274                         // 9 == kCFNumberIntType == C int
275                         return new CFNumber (CFNumberCreate (IntPtr.Zero, (IntPtr)9, (IntPtr)number), true);
276                 }
277
278                 public static implicit operator int (CFNumber number)
279                 {
280                         return AsInt32 (number.Handle);
281                 }
282         }
283
284         internal struct CFRange {
285                 public IntPtr Location, Length;
286                 
287                 public CFRange (int loc, int len)
288                 {
289                         Location = (IntPtr) loc;
290                         Length = (IntPtr) len;
291                 }
292         }
293
294         internal struct CFStreamClientContext {
295                 public IntPtr Version;
296                 public IntPtr Info;
297                 public IntPtr Retain;
298                 public IntPtr Release;
299                 public IntPtr CopyDescription;
300         }
301
302         internal class CFString : CFObject
303         {
304                 string str;
305
306                 public CFString (IntPtr handle, bool own) : base (handle, own) { }
307
308                 [DllImport (CoreFoundationLibrary)]
309                 extern static IntPtr CFStringCreateWithCharacters (IntPtr alloc, IntPtr chars, /* CFIndex */ IntPtr length);
310
311                 public static CFString Create (string value)
312                 {
313                         IntPtr handle;
314
315                         unsafe {
316                                 fixed (char *ptr = value) {
317                                         handle = CFStringCreateWithCharacters (IntPtr.Zero, (IntPtr) ptr, (IntPtr) value.Length);
318                                 }
319                         }
320
321                         if (handle == IntPtr.Zero)
322                                 return null;
323
324                         return new CFString (handle, true);
325                 }
326
327                 [DllImport (CoreFoundationLibrary)]
328                 extern static /* CFIndex */ IntPtr CFStringGetLength (IntPtr handle);
329
330                 public int Length {
331                         get {
332                                 if (str != null)
333                                         return str.Length;
334
335                                 return (int) CFStringGetLength (Handle);
336                         }
337                 }
338
339                 [DllImport (CoreFoundationLibrary)]
340                 extern static IntPtr CFStringGetCharactersPtr (IntPtr handle);
341
342                 [DllImport (CoreFoundationLibrary)]
343                 extern static IntPtr CFStringGetCharacters (IntPtr handle, CFRange range, IntPtr buffer);
344
345                 public static string AsString (IntPtr handle)
346                 {
347                         if (handle == IntPtr.Zero)
348                                 return null;
349                         
350                         int len = (int) CFStringGetLength (handle);
351                         
352                         if (len == 0)
353                                 return string.Empty;
354                         
355                         IntPtr chars = CFStringGetCharactersPtr (handle);
356                         IntPtr buffer = IntPtr.Zero;
357                         
358                         if (chars == IntPtr.Zero) {
359                                 CFRange range = new CFRange (0, len);
360                                 buffer = Marshal.AllocHGlobal (len * 2);
361                                 CFStringGetCharacters (handle, range, buffer);
362                                 chars = buffer;
363                         }
364
365                         string str;
366
367                         unsafe {
368                                 str = new string ((char *) chars, 0, len);
369                         }
370                         
371                         if (buffer != IntPtr.Zero)
372                                 Marshal.FreeHGlobal (buffer);
373
374                         return str;
375                 }
376
377                 public override string ToString ()
378                 {
379                         if (str == null)
380                                 str = AsString (Handle);
381
382                         return str;
383                 }
384
385                 public static implicit operator string (CFString str)
386                 {
387                         return str.ToString ();
388                 }
389
390                 public static implicit operator CFString (string str)
391                 {
392                         return Create (str);
393                 }
394         }
395
396         
397         internal class CFData : CFObject
398         {
399                 public CFData (IntPtr handle, bool own) : base (handle, own) { }
400         
401                 [DllImport (CoreFoundationLibrary)]
402                 extern static /* CFDataRef */ IntPtr CFDataCreate (/* CFAllocatorRef */ IntPtr allocator, /* UInt8* */ IntPtr bytes, /* CFIndex */ IntPtr length);
403                 public unsafe static CFData FromData (byte [] buffer)
404                 {
405                         fixed (byte* p = buffer)
406                         {
407                                 return FromData ((IntPtr)p, (IntPtr)buffer.Length);
408                         }
409                 }
410
411                 public static CFData FromData (IntPtr buffer, IntPtr length)
412                 {
413                         return new CFData (CFDataCreate (IntPtr.Zero, buffer, length), true);
414                 }
415                 
416                 public IntPtr Length {
417                         get { return CFDataGetLength (Handle); }
418                 }
419
420                 [DllImport (CoreFoundationLibrary)]
421                 extern static /* CFIndex */ IntPtr CFDataGetLength (/* CFDataRef */ IntPtr theData);
422
423                 [DllImport (CoreFoundationLibrary)]
424                 extern static /* UInt8* */ IntPtr CFDataGetBytePtr (/* CFDataRef */ IntPtr theData);
425
426                 /*
427                  * Exposes a read-only pointer to the underlying storage.
428                  */
429                 public IntPtr Bytes {
430                         get { return CFDataGetBytePtr (Handle); }
431                 }
432
433                 public byte this [long idx] {
434                         get {
435                                 if (idx < 0 || (ulong) idx > (ulong) Length)
436                                         throw new ArgumentException ("idx");
437                                 return Marshal.ReadByte (new IntPtr (Bytes.ToInt64 () + idx));
438                         }
439
440                         set {
441                                 throw new NotImplementedException ("NSData arrays can not be modified, use an NSMutableData instead");
442                         }
443                 }
444
445         }
446
447         internal class CFDictionary : CFObject
448         {
449                 static readonly IntPtr KeyCallbacks;
450                 static readonly IntPtr ValueCallbacks;
451                 
452                 static CFDictionary ()
453                 {
454                         var handle = dlopen (CoreFoundationLibrary, 0);
455                         if (handle == IntPtr.Zero)
456                                 return;
457
458                         try {           
459                                 KeyCallbacks = GetIndirect (handle, "kCFTypeDictionaryKeyCallBacks");
460                                 ValueCallbacks = GetIndirect (handle, "kCFTypeDictionaryValueCallBacks");
461                         } finally {
462                                 dlclose (handle);
463                         }
464                 }
465
466                 public CFDictionary (IntPtr handle, bool own) : base (handle, own) { }
467
468                 public static CFDictionary FromObjectAndKey (IntPtr obj, IntPtr key)
469                 {
470                         return new CFDictionary (CFDictionaryCreate (IntPtr.Zero, new IntPtr[] { key }, new IntPtr [] { obj }, (IntPtr)1, KeyCallbacks, ValueCallbacks), true);
471                 }
472                 
473                 [DllImport (CoreFoundationLibrary)]
474                 extern static IntPtr CFDictionaryCreate (IntPtr allocator, IntPtr[] keys, IntPtr[] vals, IntPtr len, IntPtr keyCallbacks, IntPtr valCallbacks);
475
476                 [DllImport (CoreFoundationLibrary)]
477                 extern static IntPtr CFDictionaryGetValue (IntPtr handle, IntPtr key);
478
479                 [DllImport (CoreFoundationLibrary)]
480                 extern static IntPtr CFDictionaryCreateCopy (IntPtr allocator, IntPtr handle);
481
482                 public CFDictionary Copy ()
483                 {
484                         return new CFDictionary (CFDictionaryCreateCopy (IntPtr.Zero, Handle), true);
485                 }
486                 
487                 public CFMutableDictionary MutableCopy ()
488                 {
489                         return new CFMutableDictionary (CFDictionaryCreateMutableCopy (IntPtr.Zero, IntPtr.Zero, Handle), true);
490                 }
491
492                 [DllImport (CoreFoundationLibrary)]
493                 extern static IntPtr CFDictionaryCreateMutableCopy (IntPtr allocator, IntPtr capacity, IntPtr theDict);
494
495                 public IntPtr GetValue (IntPtr key)
496                 {
497                         return CFDictionaryGetValue (Handle, key);
498                 }
499
500                 public IntPtr this[IntPtr key] {
501                         get {
502                                 return GetValue (key);
503                         }
504                 }
505         }
506         
507         internal class CFMutableDictionary : CFDictionary
508         {
509                 public CFMutableDictionary (IntPtr handle, bool own) : base (handle, own) { }
510
511                 public void SetValue (IntPtr key, IntPtr val)
512                 {
513                         CFDictionarySetValue (Handle, key, val);
514                 }
515
516                 [DllImport (CoreFoundationLibrary)]
517                 extern static void CFDictionarySetValue (IntPtr handle, IntPtr key, IntPtr val);
518         }
519
520         internal class CFUrl : CFObject
521         {
522                 public CFUrl (IntPtr handle, bool own) : base (handle, own) { }
523
524                 [DllImport (CoreFoundationLibrary)]
525                 extern static IntPtr CFURLCreateWithString (IntPtr allocator, IntPtr str, IntPtr baseURL);
526
527                 public static CFUrl Create (string absolute)
528                 {
529                         if (string.IsNullOrEmpty (absolute))
530                                 return null;
531
532                         CFString str = CFString.Create (absolute);
533                         IntPtr handle = CFURLCreateWithString (IntPtr.Zero, str.Handle, IntPtr.Zero);
534                         str.Dispose ();
535
536                         if (handle == IntPtr.Zero)
537                                 return null;
538
539                         return new CFUrl (handle, true);
540                 }
541         }
542
543         internal class CFRunLoop : CFObject
544         {
545                 [DllImport (CFObject.CoreFoundationLibrary)]
546                 static extern void CFRunLoopAddSource (IntPtr rl, IntPtr source, IntPtr mode);
547
548                 [DllImport (CFObject.CoreFoundationLibrary)]
549                 static extern void CFRunLoopRemoveSource (IntPtr rl, IntPtr source, IntPtr mode);
550
551                 [DllImport (CFObject.CoreFoundationLibrary)]
552                 static extern int CFRunLoopRunInMode (IntPtr mode, double seconds, bool returnAfterSourceHandled);
553
554                 [DllImport (CFObject.CoreFoundationLibrary)]
555                 static extern IntPtr CFRunLoopGetCurrent ();
556
557                 [DllImport (CFObject.CoreFoundationLibrary)]
558                 static extern void CFRunLoopStop (IntPtr rl);
559
560                 public CFRunLoop (IntPtr handle, bool own): base (handle, own)
561                 {
562                 }
563
564                 public static CFRunLoop CurrentRunLoop {
565                         get { return new CFRunLoop (CFRunLoopGetCurrent (), false); }
566                 }
567
568                 public void AddSource (IntPtr source, CFString mode)
569                 {
570                         CFRunLoopAddSource (Handle, source, mode.Handle);
571                 }
572
573                 public void RemoveSource (IntPtr source, CFString mode)
574                 {
575                         CFRunLoopRemoveSource (Handle, source, mode.Handle);
576                 }
577
578                 public int RunInMode (CFString mode, double seconds, bool returnAfterSourceHandled)
579                 {
580                         return CFRunLoopRunInMode (mode.Handle, seconds, returnAfterSourceHandled);
581                 }
582
583                 public void Stop ()
584                 {
585                         CFRunLoopStop (Handle);
586                 }
587         }
588
589         internal enum CFProxyType {
590                 None,
591                 AutoConfigurationUrl,
592                 AutoConfigurationJavaScript,
593                 FTP,
594                 HTTP,
595                 HTTPS,
596                 SOCKS
597         }
598         
599         internal class CFProxy {
600                 //static IntPtr kCFProxyAutoConfigurationHTTPResponseKey;
601                 static IntPtr kCFProxyAutoConfigurationJavaScriptKey;
602                 static IntPtr kCFProxyAutoConfigurationURLKey;
603                 static IntPtr kCFProxyHostNameKey;
604                 static IntPtr kCFProxyPasswordKey;
605                 static IntPtr kCFProxyPortNumberKey;
606                 static IntPtr kCFProxyTypeKey;
607                 static IntPtr kCFProxyUsernameKey;
608
609                 //static IntPtr kCFProxyTypeNone;
610                 static IntPtr kCFProxyTypeAutoConfigurationURL;
611                 static IntPtr kCFProxyTypeAutoConfigurationJavaScript;
612                 static IntPtr kCFProxyTypeFTP;
613                 static IntPtr kCFProxyTypeHTTP;
614                 static IntPtr kCFProxyTypeHTTPS;
615                 static IntPtr kCFProxyTypeSOCKS;
616
617                 static CFProxy ()
618                 {
619                         IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
620
621                         //kCFProxyAutoConfigurationHTTPResponseKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationHTTPResponseKey");
622                         kCFProxyAutoConfigurationJavaScriptKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationJavaScriptKey");
623                         kCFProxyAutoConfigurationURLKey = CFObject.GetCFObjectHandle (handle, "kCFProxyAutoConfigurationURLKey");
624                         kCFProxyHostNameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyHostNameKey");
625                         kCFProxyPasswordKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPasswordKey");
626                         kCFProxyPortNumberKey = CFObject.GetCFObjectHandle (handle, "kCFProxyPortNumberKey");
627                         kCFProxyTypeKey = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeKey");
628                         kCFProxyUsernameKey = CFObject.GetCFObjectHandle (handle, "kCFProxyUsernameKey");
629
630                         //kCFProxyTypeNone = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeNone");
631                         kCFProxyTypeAutoConfigurationURL = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationURL");
632                         kCFProxyTypeAutoConfigurationJavaScript = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeAutoConfigurationJavaScript");
633                         kCFProxyTypeFTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeFTP");
634                         kCFProxyTypeHTTP = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTP");
635                         kCFProxyTypeHTTPS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeHTTPS");
636                         kCFProxyTypeSOCKS = CFObject.GetCFObjectHandle (handle, "kCFProxyTypeSOCKS");
637
638                         CFObject.dlclose (handle);
639                 }
640
641                 CFDictionary settings;
642                 
643                 internal CFProxy (CFDictionary settings)
644                 {
645                         this.settings = settings;
646                 }
647                 
648                 static CFProxyType CFProxyTypeToEnum (IntPtr type)
649                 {
650                         if (type == kCFProxyTypeAutoConfigurationJavaScript)
651                                 return CFProxyType.AutoConfigurationJavaScript;
652
653                         if (type == kCFProxyTypeAutoConfigurationURL)
654                                 return CFProxyType.AutoConfigurationUrl;
655
656                         if (type == kCFProxyTypeFTP)
657                                 return CFProxyType.FTP;
658
659                         if (type == kCFProxyTypeHTTP)
660                                 return CFProxyType.HTTP;
661
662                         if (type == kCFProxyTypeHTTPS)
663                                 return CFProxyType.HTTPS;
664
665                         if (type == kCFProxyTypeSOCKS)
666                                 return CFProxyType.SOCKS;
667                         
668                         return CFProxyType.None;
669                 }
670                 
671 #if false
672                 // AFAICT these get used with CFNetworkExecuteProxyAutoConfiguration*()
673                 
674                 // TODO: bind CFHTTPMessage so we can return the proper type here.
675                 public IntPtr AutoConfigurationHTTPResponse {
676                         get { return settings[kCFProxyAutoConfigurationHTTPResponseKey]; }
677                 }
678 #endif
679
680                 public IntPtr AutoConfigurationJavaScript {
681                         get {
682                                 if (kCFProxyAutoConfigurationJavaScriptKey == IntPtr.Zero)
683                                         return IntPtr.Zero;
684                                 
685                                 return settings[kCFProxyAutoConfigurationJavaScriptKey];
686                         }
687                 }
688                 
689                 public IntPtr AutoConfigurationUrl {
690                         get {
691                                 if (kCFProxyAutoConfigurationURLKey == IntPtr.Zero)
692                                         return IntPtr.Zero;
693                                 
694                                 return settings[kCFProxyAutoConfigurationURLKey];
695                         }
696                 }
697                 
698                 public string HostName {
699                         get {
700                                 if (kCFProxyHostNameKey == IntPtr.Zero)
701                                         return null;
702                                 
703                                 return CFString.AsString (settings[kCFProxyHostNameKey]);
704                         }
705                 }
706                 
707                 public string Password {
708                         get {
709                                 if (kCFProxyPasswordKey == IntPtr.Zero)
710                                         return null;
711
712                                 return CFString.AsString (settings[kCFProxyPasswordKey]);
713                         }
714                 }
715                 
716                 public int Port {
717                         get {
718                                 if (kCFProxyPortNumberKey == IntPtr.Zero)
719                                         return 0;
720                                 
721                                 return CFNumber.AsInt32 (settings[kCFProxyPortNumberKey]);
722                         }
723                 }
724                 
725                 public CFProxyType ProxyType {
726                         get {
727                                 if (kCFProxyTypeKey == IntPtr.Zero)
728                                         return CFProxyType.None;
729                                 
730                                 return CFProxyTypeToEnum (settings[kCFProxyTypeKey]);
731                         }
732                 }
733                 
734                 public string Username {
735                         get {
736                                 if (kCFProxyUsernameKey == IntPtr.Zero)
737                                         return null;
738
739                                 return CFString.AsString (settings[kCFProxyUsernameKey]);
740                         }
741                 }
742         }
743         
744         internal class CFProxySettings {
745                 static IntPtr kCFNetworkProxiesHTTPEnable;
746                 static IntPtr kCFNetworkProxiesHTTPPort;
747                 static IntPtr kCFNetworkProxiesHTTPProxy;
748                 static IntPtr kCFNetworkProxiesProxyAutoConfigEnable;
749                 static IntPtr kCFNetworkProxiesProxyAutoConfigJavaScript;
750                 static IntPtr kCFNetworkProxiesProxyAutoConfigURLString;
751
752                 static CFProxySettings ()
753                 {
754                         IntPtr handle = CFObject.dlopen (CFNetwork.CFNetworkLibrary, 0);
755
756                         kCFNetworkProxiesHTTPEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPEnable");
757                         kCFNetworkProxiesHTTPPort = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPPort");
758                         kCFNetworkProxiesHTTPProxy = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesHTTPProxy");
759                         kCFNetworkProxiesProxyAutoConfigEnable = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigEnable");
760                         kCFNetworkProxiesProxyAutoConfigJavaScript = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigJavaScript");
761                         kCFNetworkProxiesProxyAutoConfigURLString = CFObject.GetCFObjectHandle (handle, "kCFNetworkProxiesProxyAutoConfigURLString");
762
763                         CFObject.dlclose (handle);
764                 }
765
766                 CFDictionary settings;
767                 
768                 public CFProxySettings (CFDictionary settings)
769                 {
770                         this.settings = settings;
771                 }
772                 
773                 public CFDictionary Dictionary {
774                         get { return settings; }
775                 }
776                 
777                 public bool HTTPEnable {
778                         get {
779                                 if (kCFNetworkProxiesHTTPEnable == IntPtr.Zero)
780                                         return false;
781
782                                 return CFNumber.AsBool (settings[kCFNetworkProxiesHTTPEnable]);
783                         }
784                 }
785                 
786                 public int HTTPPort {
787                         get {
788                                 if (kCFNetworkProxiesHTTPPort == IntPtr.Zero)
789                                         return 0;
790                                 
791                                 return CFNumber.AsInt32 (settings[kCFNetworkProxiesHTTPPort]);
792                         }
793                 }
794                 
795                 public string HTTPProxy {
796                         get {
797                                 if (kCFNetworkProxiesHTTPProxy == IntPtr.Zero)
798                                         return null;
799                                 
800                                 return CFString.AsString (settings[kCFNetworkProxiesHTTPProxy]);
801                         }
802                 }
803                 
804                 public bool ProxyAutoConfigEnable {
805                         get {
806                                 if (kCFNetworkProxiesProxyAutoConfigEnable == IntPtr.Zero)
807                                         return false;
808                                 
809                                 return CFNumber.AsBool (settings[kCFNetworkProxiesProxyAutoConfigEnable]);
810                         }
811                 }
812                 
813                 public string ProxyAutoConfigJavaScript {
814                         get {
815                                 if (kCFNetworkProxiesProxyAutoConfigJavaScript == IntPtr.Zero)
816                                         return null;
817                                 
818                                 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigJavaScript]);
819                         }
820                 }
821                 
822                 public string ProxyAutoConfigURLString {
823                         get {
824                                 if (kCFNetworkProxiesProxyAutoConfigURLString == IntPtr.Zero)
825                                         return null;
826                                 
827                                 return CFString.AsString (settings[kCFNetworkProxiesProxyAutoConfigURLString]);
828                         }
829                 }
830         }
831         
832         internal static class CFNetwork {
833 #if !MONOTOUCH
834                 public const string CFNetworkLibrary = "/System/Library/Frameworks/CoreServices.framework/Frameworks/CFNetwork.framework/CFNetwork";
835 #else
836                 public const string CFNetworkLibrary = "/System/Library/Frameworks/CFNetwork.framework/CFNetwork";
837 #endif
838                 
839                 [DllImport (CFNetworkLibrary, EntryPoint = "CFNetworkCopyProxiesForAutoConfigurationScript")]
840                 // CFArrayRef CFNetworkCopyProxiesForAutoConfigurationScript (CFStringRef proxyAutoConfigurationScript, CFURLRef targetURL, CFErrorRef* error);
841                 extern static IntPtr CFNetworkCopyProxiesForAutoConfigurationScriptSequential (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error);
842
843                 [DllImport (CFNetworkLibrary)]
844                 extern static IntPtr CFNetworkExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, IntPtr targetURL, CFProxyAutoConfigurationResultCallback cb, ref CFStreamClientContext clientContext);
845
846
847                 class GetProxyData : IDisposable {
848                         public IntPtr script;
849                         public IntPtr targetUri;
850                         public IntPtr error;
851                         public IntPtr result;
852                         public ManualResetEvent evt = new ManualResetEvent (false);
853
854                         public void Dispose ()
855                         {
856                                 evt.Close ();
857                         }
858                 }
859
860                 static object lock_obj = new object ();
861                 static Queue<GetProxyData> get_proxy_queue;
862                 static AutoResetEvent proxy_event;
863
864                 static void CFNetworkCopyProxiesForAutoConfigurationScriptThread ()
865                 {
866                         GetProxyData data;
867                         var data_left = true;
868
869                         while (true) {
870                                 proxy_event.WaitOne ();
871
872                                 do {
873                                         lock (lock_obj) {
874                                                 if (get_proxy_queue.Count == 0)
875                                                         break;
876                                                 data = get_proxy_queue.Dequeue ();
877                                                 data_left = get_proxy_queue.Count > 0;
878                                         }
879
880                                         data.result = CFNetworkCopyProxiesForAutoConfigurationScriptSequential (data.script, data.targetUri, out data.error);
881                                         data.evt.Set ();
882                                 } while (data_left);
883                         }
884                 }
885
886                 static IntPtr CFNetworkCopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, IntPtr targetURL, out IntPtr error)
887                 {
888                         // This method must only be called on only one thread during an application's life time.
889                         // Note that it's not enough to use a lock to make calls sequential across different threads,
890                         // it has to be one thread. Also note that that thread can't be the main thread, because the
891                         // main thread might be blocking waiting for this network request to finish.
892                         // Another possibility would be to use JavaScriptCore to execute this piece of
893                         // javascript ourselves, but unfortunately it's not available before iOS7.
894                         // See bug #7923 comment #21+.
895
896                         using (var data = new GetProxyData ()) {
897                                 data.script = proxyAutoConfigurationScript;
898                                 data.targetUri = targetURL;
899
900                                 lock (lock_obj) {
901                                         if (get_proxy_queue == null) {
902                                                 get_proxy_queue = new Queue<GetProxyData> ();
903                                                 proxy_event = new AutoResetEvent (false);
904                                                 new Thread (CFNetworkCopyProxiesForAutoConfigurationScriptThread) {
905                                                         IsBackground = true,
906                                                 }.Start ();
907                                         }
908                                         get_proxy_queue.Enqueue (data);
909                                         proxy_event.Set ();
910                                 }
911
912                                 data.evt.WaitOne ();
913
914                                 error = data.error;
915
916                                 return data.result;
917                         }
918                 }
919
920                 static CFArray CopyProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
921                 {
922                         IntPtr err = IntPtr.Zero;
923                         IntPtr native = CFNetworkCopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL.Handle, out err);
924                         
925                         if (native == IntPtr.Zero)
926                                 return null;
927                         
928                         return new CFArray (native, true);
929                 }
930                 
931                 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, CFUrl targetURL)
932                 {
933                         if (proxyAutoConfigurationScript == IntPtr.Zero)
934                                 throw new ArgumentNullException ("proxyAutoConfigurationScript");
935                         
936                         if (targetURL == null)
937                                 throw new ArgumentNullException ("targetURL");
938                         
939                         CFArray array = CopyProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
940                         
941                         if (array == null)
942                                 return null;
943                         
944                         CFProxy[] proxies = new CFProxy [array.Count];
945                         for (int i = 0; i < proxies.Length; i++) {
946                                 CFDictionary dict = new CFDictionary (array[i], false);
947                                 proxies[i] = new CFProxy (dict);
948                         }
949
950                         array.Dispose ();
951                         
952                         return proxies;
953                 }
954                 
955                 public static CFProxy[] GetProxiesForAutoConfigurationScript (IntPtr proxyAutoConfigurationScript, Uri targetUri)
956                 {
957                         if (proxyAutoConfigurationScript == IntPtr.Zero)
958                                 throw new ArgumentNullException ("proxyAutoConfigurationScript");
959                         
960                         if (targetUri == null)
961                                 throw new ArgumentNullException ("targetUri");
962                         
963                         CFUrl targetURL = CFUrl.Create (targetUri.AbsoluteUri);
964                         CFProxy[] proxies = GetProxiesForAutoConfigurationScript (proxyAutoConfigurationScript, targetURL);
965                         targetURL.Dispose ();
966                         
967                         return proxies;
968                 }
969
970                 delegate void CFProxyAutoConfigurationResultCallback (IntPtr client, IntPtr proxyList, IntPtr error);
971
972                 public static CFProxy[] ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetURL)
973                 {
974                         CFUrl url = CFUrl.Create (targetURL.AbsoluteUri);
975                         if (url == null)
976                                 return null;
977
978                         CFProxy[] proxies = null;
979
980                         var runLoop = CFRunLoop.CurrentRunLoop;
981
982                         // Callback that will be called after executing the configuration script
983                         CFProxyAutoConfigurationResultCallback cb = delegate (IntPtr client, IntPtr proxyList, IntPtr error) {
984                                 if (proxyList != IntPtr.Zero) {
985                                         var array = new CFArray (proxyList, false);
986                                         proxies = new CFProxy [array.Count];
987                                         for (int i = 0; i < proxies.Length; i++) {
988                                                 CFDictionary dict = new CFDictionary (array[i], false);
989                                                 proxies[i] = new CFProxy (dict);
990                                         }
991                                         array.Dispose ();
992                                 }
993                                 runLoop.Stop ();
994                         };
995
996                         var clientContext = new CFStreamClientContext ();
997                         var loopSource = CFNetworkExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, url.Handle, cb, ref clientContext);
998
999                         // Create a private mode
1000                         var mode = CFString.Create ("Mono.MacProxy");
1001
1002                         runLoop.AddSource (loopSource, mode);
1003                         runLoop.RunInMode (mode, double.MaxValue, false);
1004                         runLoop.RemoveSource (loopSource, mode);
1005
1006                         return proxies;
1007                 }
1008                 
1009                 [DllImport (CFNetworkLibrary)]
1010                 // CFArrayRef CFNetworkCopyProxiesForURL (CFURLRef url, CFDictionaryRef proxySettings);
1011                 extern static IntPtr CFNetworkCopyProxiesForURL (IntPtr url, IntPtr proxySettings);
1012                 
1013                 static CFArray CopyProxiesForURL (CFUrl url, CFDictionary proxySettings)
1014                 {
1015                         IntPtr native = CFNetworkCopyProxiesForURL (url.Handle, proxySettings != null ? proxySettings.Handle : IntPtr.Zero);
1016                         
1017                         if (native == IntPtr.Zero)
1018                                 return null;
1019                         
1020                         return new CFArray (native, true);
1021                 }
1022                 
1023                 public static CFProxy[] GetProxiesForURL (CFUrl url, CFProxySettings proxySettings)
1024                 {
1025                         if (url == null || url.Handle == IntPtr.Zero)
1026                                 throw new ArgumentNullException ("url");
1027                         
1028                         if (proxySettings == null)
1029                                 proxySettings = GetSystemProxySettings ();
1030                         
1031                         CFArray array = CopyProxiesForURL (url, proxySettings.Dictionary);
1032                         
1033                         if (array == null)
1034                                 return null;
1035
1036                         CFProxy[] proxies = new CFProxy [array.Count];
1037                         for (int i = 0; i < proxies.Length; i++) {
1038                                 CFDictionary dict = new CFDictionary (array[i], false);
1039                                 proxies[i] = new CFProxy (dict);
1040                         }
1041
1042                         array.Dispose ();
1043                         
1044                         return proxies;
1045                 }
1046                 
1047                 public static CFProxy[] GetProxiesForUri (Uri uri, CFProxySettings proxySettings)
1048                 {
1049                         if (uri == null)
1050                                 throw new ArgumentNullException ("uri");
1051                         
1052                         CFUrl url = CFUrl.Create (uri.AbsoluteUri);
1053                         if (url == null)
1054                                 return null;
1055                         
1056                         CFProxy[] proxies = GetProxiesForURL (url, proxySettings);
1057                         url.Dispose ();
1058                         
1059                         return proxies;
1060                 }
1061                 
1062                 [DllImport (CFNetworkLibrary)]
1063                 // CFDictionaryRef CFNetworkCopySystemProxySettings (void);
1064                 extern static IntPtr CFNetworkCopySystemProxySettings ();
1065                 
1066                 public static CFProxySettings GetSystemProxySettings ()
1067                 {
1068                         IntPtr native = CFNetworkCopySystemProxySettings ();
1069                         
1070                         if (native == IntPtr.Zero)
1071                                 return null;
1072                         
1073                         var dict = new CFDictionary (native, true);
1074
1075                         return new CFProxySettings (dict);
1076                 }
1077                 
1078                 class CFWebProxy : IWebProxy {
1079                         ICredentials credentials;
1080                         bool userSpecified;
1081                         
1082                         public CFWebProxy ()
1083                         {
1084                         }
1085                         
1086                         public ICredentials Credentials {
1087                                 get { return credentials; }
1088                                 set {
1089                                         userSpecified = true;
1090                                         credentials = value;
1091                                 }
1092                         }
1093                         
1094                         static Uri GetProxyUri (CFProxy proxy, out NetworkCredential credentials)
1095                         {
1096                                 string protocol;
1097                                 
1098                                 switch (proxy.ProxyType) {
1099                                 case CFProxyType.FTP:
1100                                         protocol = "ftp://";
1101                                         break;
1102                                 case CFProxyType.HTTP:
1103                                 case CFProxyType.HTTPS:
1104                                         protocol = "http://";
1105                                         break;
1106                                 default:
1107                                         credentials = null;
1108                                         return null;
1109                                 }
1110                                 
1111                                 string username = proxy.Username;
1112                                 string password = proxy.Password;
1113                                 string hostname = proxy.HostName;
1114                                 int port = proxy.Port;
1115                                 string uri;
1116                                 
1117                                 if (username != null)
1118                                         credentials = new NetworkCredential (username, password);
1119                                 else
1120                                         credentials = null;
1121                                 
1122                                 uri = protocol + hostname + (port != 0 ? ':' + port.ToString () : string.Empty);
1123                                 
1124                                 return new Uri (uri, UriKind.Absolute);
1125                         }
1126                         
1127                         static Uri GetProxyUriFromScript (IntPtr script, Uri targetUri, out NetworkCredential credentials)
1128                         {
1129                                 CFProxy[] proxies = CFNetwork.GetProxiesForAutoConfigurationScript (script, targetUri);
1130                                 return SelectProxy (proxies, targetUri, out credentials);
1131                         }
1132
1133                         static Uri ExecuteProxyAutoConfigurationURL (IntPtr proxyAutoConfigURL, Uri targetUri, out NetworkCredential credentials)
1134                         {
1135                                 CFProxy[] proxies = CFNetwork.ExecuteProxyAutoConfigurationURL (proxyAutoConfigURL, targetUri);
1136                                 return SelectProxy (proxies, targetUri, out credentials);
1137                         }
1138
1139
1140                         static Uri SelectProxy (CFProxy[] proxies, Uri targetUri, out NetworkCredential credentials)
1141                         {
1142                                 if (proxies == null) {
1143                                         credentials = null;
1144                                         return targetUri;
1145                                 }
1146                                 
1147                                 for (int i = 0; i < proxies.Length; i++) {
1148                                         switch (proxies[i].ProxyType) {
1149                                         case CFProxyType.HTTPS:
1150                                         case CFProxyType.HTTP:
1151                                         case CFProxyType.FTP:
1152                                                 // create a Uri based on the hostname/port/etc info
1153                                                 return GetProxyUri (proxies[i], out credentials);
1154                                         case CFProxyType.SOCKS:
1155                                         default:
1156                                                 // unsupported proxy type, try the next one
1157                                                 break;
1158                                         case CFProxyType.None:
1159                                                 // no proxy should be used
1160                                                 credentials = null;
1161                                                 return targetUri;
1162                                         }
1163                                 }
1164                                 
1165                                 credentials = null;
1166                                 
1167                                 return null;
1168                         }
1169                         
1170                         public Uri GetProxy (Uri targetUri)
1171                         {
1172                                 NetworkCredential credentials = null;
1173                                 Uri proxy = null;
1174                                 
1175                                 if (targetUri == null)
1176                                         throw new ArgumentNullException ("targetUri");
1177                                 
1178                                 try {
1179                                         CFProxySettings settings = CFNetwork.GetSystemProxySettings ();
1180                                         CFProxy[] proxies = CFNetwork.GetProxiesForUri (targetUri, settings);
1181                                         
1182                                         if (proxies != null) {
1183                                                 for (int i = 0; i < proxies.Length && proxy == null; i++) {
1184                                                         switch (proxies[i].ProxyType) {
1185                                                         case CFProxyType.AutoConfigurationJavaScript:
1186                                                                 proxy = GetProxyUriFromScript (proxies[i].AutoConfigurationJavaScript, targetUri, out credentials);
1187                                                                 break;
1188                                                         case CFProxyType.AutoConfigurationUrl:
1189                                                                 proxy = ExecuteProxyAutoConfigurationURL (proxies[i].AutoConfigurationUrl, targetUri, out credentials);
1190                                                                 break;
1191                                                         case CFProxyType.HTTPS:
1192                                                         case CFProxyType.HTTP:
1193                                                         case CFProxyType.FTP:
1194                                                                 // create a Uri based on the hostname/port/etc info
1195                                                                 proxy = GetProxyUri (proxies[i], out credentials);
1196                                                                 break;
1197                                                         case CFProxyType.SOCKS:
1198                                                                 // unsupported proxy type, try the next one
1199                                                                 break;
1200                                                         case CFProxyType.None:
1201                                                                 // no proxy should be used
1202                                                                 proxy = targetUri;
1203                                                                 break;
1204                                                         }
1205                                                 }
1206                                                 
1207                                                 if (proxy == null) {
1208                                                         // no supported proxies for this Uri, fall back to trying to connect to targetUri directly
1209                                                         proxy = targetUri;
1210                                                 }
1211                                         } else {
1212                                                 proxy = targetUri;
1213                                         }
1214                                 } catch {
1215                                         // ignore errors while retrieving proxy data
1216                                         proxy = targetUri;
1217                                 }
1218                                 
1219                                 if (!userSpecified)
1220                                         this.credentials = credentials;
1221                                 
1222                                 return proxy;
1223                         }
1224                         
1225                         public bool IsBypassed (Uri targetUri)
1226                         {
1227                                 if (targetUri == null)
1228                                         throw new ArgumentNullException ("targetUri");
1229                                 
1230                                 return GetProxy (targetUri) == targetUri;
1231                         }
1232                 }
1233                 
1234                 public static IWebProxy GetDefaultProxy ()
1235                 {
1236                         return new CFWebProxy ();
1237                 }
1238         }
1239
1240         class CFBoolean : INativeObject, IDisposable {
1241                 IntPtr handle;
1242
1243                 public static readonly CFBoolean True;
1244                 public static readonly CFBoolean False;
1245
1246                 static CFBoolean ()
1247                 {
1248                         var handle = CFObject.dlopen (CFObject.CoreFoundationLibrary, 0);
1249                         if (handle == IntPtr.Zero)
1250                                 return;
1251                         try {
1252                                 True  = new CFBoolean (CFObject.GetCFObjectHandle (handle, "kCFBooleanTrue"), false);
1253                                 False = new CFBoolean (CFObject.GetCFObjectHandle (handle, "kCFBooleanFalse"), false);
1254                         }
1255                         finally {
1256                                 CFObject.dlclose (handle);
1257                         }
1258                 }
1259
1260                 internal CFBoolean (IntPtr handle, bool owns)
1261                 {
1262                         this.handle = handle;
1263                         if (!owns)
1264                                 CFObject.CFRetain (handle);
1265                 }
1266
1267                 ~CFBoolean ()
1268                 {
1269                         Dispose (false);
1270                 }
1271
1272                 public IntPtr Handle {
1273                         get {
1274                                 return handle;
1275                         }
1276                 }
1277
1278                 public void Dispose ()
1279                 {
1280                         Dispose (true);
1281                         GC.SuppressFinalize (this);
1282                 }
1283
1284                 protected virtual void Dispose (bool disposing)
1285                 {
1286                         if (handle != IntPtr.Zero){
1287                                 CFObject.CFRelease (handle);
1288                                 handle = IntPtr.Zero;
1289                         }
1290                 }
1291
1292                 public static implicit operator bool (CFBoolean value)
1293                 {
1294                         return value.Value;
1295                 }
1296
1297                 public static explicit operator CFBoolean (bool value)
1298                 {
1299                         return FromBoolean (value);
1300                 }
1301
1302                 public static CFBoolean FromBoolean (bool value)
1303                 {
1304                         return value ? True : False;
1305                 }
1306
1307                 [DllImport (CFObject.CoreFoundationLibrary)]
1308                 [return: MarshalAs (UnmanagedType.I1)]
1309                 extern static /* Boolean */ bool CFBooleanGetValue (/* CFBooleanRef */ IntPtr boolean);
1310
1311                 public bool Value {
1312                         get {return CFBooleanGetValue (handle);}
1313                 }
1314
1315                 public static bool GetValue (IntPtr boolean)
1316                 {
1317                         return CFBooleanGetValue (boolean);
1318                 }
1319         }
1320
1321 }