Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
InternetContent.cs
1using System;
3using System.Reflection;
4using System.Security.Cryptography.X509Certificates;
5using System.Text;
6using System.Threading.Tasks;
8using Waher.Events;
12
13namespace Waher.Content
14{
18 public static class InternetContent
19 {
23 public static readonly Encoding ISO_8859_1 = Encoding.GetEncoding("ISO-8859-1");
24
25 private static string[] canEncodeContentTypes = null;
26 private static string[] canEncodeFileExtensions = null;
27 private static string[] canDecodeContentTypes = null;
28 private static string[] canDecodeFileExtensions = null;
29 private static string[] canGetUriSchemes = null;
30 private static string[] canPostToUriSchemes = null;
31 private static string[] canPutToUriSchemes = null;
32 private static string[] canDeleteToUriSchemes = null;
33 private static string[] canHeadUriSchemes = null;
34 private static string[] canQueryUriSchemes = null;
35 private static IContentEncoder[] encoders = null;
36 private static IContentDecoder[] decoders = null;
37 private static IContentConverter[] converters = null;
38 private static IContentGetter[] getters = null;
39 private static IContentPoster[] posters = null;
40 private static IContentPutter[] putters = null;
41 private static IContentDeleter[] deleters = null;
42 private static IContentHeader[] headers = null;
43 private static IContentQuery[] queries = null;
44 private readonly static Dictionary<string, KeyValuePair<Grade, IContentDecoder>> decoderByContentType =
45 new Dictionary<string, KeyValuePair<Grade, IContentDecoder>>(StringComparer.CurrentCultureIgnoreCase);
46 private readonly static Dictionary<string, KeyValuePair<Grade, IContentEncoder>> encodersByType =
47 new Dictionary<string, KeyValuePair<Grade, IContentEncoder>>();
48 private readonly static Dictionary<string, string> contentTypeByFileExtensions = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
49 private readonly static Dictionary<string, string> fileExtensionsByContentType = new Dictionary<string, string>(StringComparer.CurrentCultureIgnoreCase);
50 private readonly static Dictionary<string, IContentConverter> convertersByStep = new Dictionary<string, IContentConverter>(StringComparer.CurrentCultureIgnoreCase);
51 private readonly static Dictionary<string, ChunkedList<IContentConverter>> convertersByFrom = new Dictionary<string, ChunkedList<IContentConverter>>();
52 private readonly static Dictionary<string, IContentGetter[]> gettersByScheme = new Dictionary<string, IContentGetter[]>(StringComparer.CurrentCultureIgnoreCase);
53 private readonly static Dictionary<string, IContentPoster[]> postersByScheme = new Dictionary<string, IContentPoster[]>(StringComparer.CurrentCultureIgnoreCase);
54 private readonly static Dictionary<string, IContentPutter[]> puttersByScheme = new Dictionary<string, IContentPutter[]>(StringComparer.CurrentCultureIgnoreCase);
55 private readonly static Dictionary<string, IContentDeleter[]> deletersByScheme = new Dictionary<string, IContentDeleter[]>(StringComparer.CurrentCultureIgnoreCase);
56 private readonly static Dictionary<string, IContentHeader[]> headersByScheme = new Dictionary<string, IContentHeader[]>(StringComparer.CurrentCultureIgnoreCase);
57 private readonly static Dictionary<string, IContentQuery[]> queriesByScheme = new Dictionary<string, IContentQuery[]>(StringComparer.CurrentCultureIgnoreCase);
58 private static int defaultTimeout = 60000;
59 private static bool defaultTimeoutLocked = false;
60
61 static InternetContent()
62 {
63 Types.OnInvalidated += Types_OnInvalidated;
64 }
65
66 private static void Types_OnInvalidated(object Sender, EventArgs e)
67 {
68 canEncodeContentTypes = null;
69 canEncodeFileExtensions = null;
70 canDecodeContentTypes = null;
71 canDecodeFileExtensions = null;
72 canGetUriSchemes = null;
73 encoders = null;
74 decoders = null;
75 converters = null;
76 getters = null;
77 headers = null;
78 posters = null;
79 putters = null;
80 deleters = null;
81
82 lock (decoderByContentType)
83 {
84 decoderByContentType.Clear();
85 }
86
87 lock (encodersByType)
88 {
89 encodersByType.Clear();
90 }
91
92 lock (contentTypeByFileExtensions)
93 {
94 contentTypeByFileExtensions.Clear();
95 }
96
97 lock (fileExtensionsByContentType)
98 {
99 fileExtensionsByContentType.Clear();
100 }
101
102 lock (convertersByStep)
103 {
104 convertersByStep.Clear();
105 convertersByFrom.Clear();
106 }
107
108 lock (gettersByScheme)
109 {
110 gettersByScheme.Clear();
111 }
112
113 lock (headersByScheme)
114 {
115 headersByScheme.Clear();
116 }
117
118 lock (postersByScheme)
119 {
120 postersByScheme.Clear();
121 }
122
123 lock (puttersByScheme)
124 {
125 puttersByScheme.Clear();
126 }
127
128 lock (deletersByScheme)
129 {
130 deletersByScheme.Clear();
131 }
132 }
133
134 #region Default Timeout
135
139 public static int DefaultTimeout => defaultTimeout;
140
148 public static void SetDefaultTimeout(int Timeout, bool Lock)
149 {
150 if (Timeout <= 0)
151 throw new ArgumentException("Timeout must be a positive number of milliseconds.", nameof(Timeout));
152
153 if (defaultTimeoutLocked && defaultTimeout != Timeout)
154 throw new InvalidOperationException("Default timeout is locked and cannot be changed.");
155
156 defaultTimeout = Timeout;
157 defaultTimeoutLocked |= Lock;
158 }
159
160 #endregion
161
162 #region Encoding
163
167 public static string[] CanEncodeContentTypes
168 {
169 get
170 {
171 if (canEncodeContentTypes is null)
172 {
173 SortedDictionary<string, bool> ContentTypes = new SortedDictionary<string, bool>();
174
175 foreach (IContentEncoder Encoder in Encoders)
176 {
177 foreach (string ContentType in Encoder.ContentTypes)
178 ContentTypes[ContentType] = true;
179 }
180
181 string[] Types = new string[ContentTypes.Count];
182 ContentTypes.Keys.CopyTo(Types, 0);
183
184 canEncodeContentTypes = Types;
185 }
186
187 return canEncodeContentTypes;
188 }
189 }
190
194 public static string[] CanEncodeFileExtensions
195 {
196 get
197 {
198 if (canEncodeFileExtensions is null)
199 {
200 SortedDictionary<string, bool> FileExtensions = new SortedDictionary<string, bool>();
201
202 foreach (IContentEncoder Encoder in Encoders)
203 {
204 foreach (string FileExtension in Encoder.FileExtensions)
205 FileExtensions[FileExtension] = true;
206 }
207
208 string[] Types = new string[FileExtensions.Count];
209 FileExtensions.Keys.CopyTo(Types, 0);
210
211 canEncodeFileExtensions = Types;
212 }
213
214 return canEncodeFileExtensions;
215 }
216 }
217
221 public static IContentEncoder[] Encoders
222 {
223 get
224 {
225 if (encoders is null)
226 {
228 IContentEncoder Encoder;
229 Type[] EncoderTypes = Types.GetTypesImplementingInterface(typeof(IContentEncoder));
230
231 foreach (Type T in EncoderTypes)
232 {
233 ConstructorInfo CI = Types.GetDefaultConstructor(T);
234 if (CI is null)
235 continue;
236
237 try
238 {
239 Encoder = (IContentEncoder)CI.Invoke(Types.NoParameters);
240 }
241 catch (Exception)
242 {
243 continue;
244 }
245
246 Encoders.Add(Encoder);
247 }
248
249 encoders = Encoders.ToArray();
250 }
251
252 return encoders;
253 }
254 }
255
264 public static bool Encodes(object Object, out Grade Grade, out IContentEncoder Encoder, params string[] AcceptedContentTypes)
265 {
266 string Key;
267
268 if (!(AcceptedContentTypes is null) &&
269 AcceptedContentTypes.Length == 1 &&
270 AcceptedContentTypes[0] == "*")
271 {
272 AcceptedContentTypes = Array.Empty<string>();
273 Key = Object.GetType().FullName;
274 }
275 else if (AcceptedContentTypes is null || AcceptedContentTypes.Length == 0)
276 Key = Object.GetType().FullName;
277 else
278 {
279 StringBuilder sb = new StringBuilder();
280
281 sb.Append(Object.GetType().FullName);
282
283 foreach (string Accepted in AcceptedContentTypes)
284 {
285 sb.Append('|');
286 sb.Append(Accepted);
287 }
288
289 Key = sb.ToString();
290 }
291
292 lock (encodersByType)
293 {
294 if (encodersByType.TryGetValue(Key, out KeyValuePair<Grade, IContentEncoder> P))
295 {
296 Grade = P.Key;
297 Encoder = P.Value;
298
299 if (!(Encoder is null))
300 return true;
301
302 if (Object is CustomEncoding)
303 {
304 Encoder = new CustomEncoder();
305 return true;
306 }
307
308 return false;
309 }
310 }
311
312 Grade = Grade.NotAtAll;
313 Encoder = null;
314
315 foreach (IContentEncoder Encoder2 in Encoders)
316 {
317 if (Encoder2.Encodes(Object, out Grade Grade2, AcceptedContentTypes) && Grade2 > Grade)
318 {
319 Grade = Grade2;
320 Encoder = Encoder2;
321 }
322 }
323
324 lock (encodersByType)
325 {
326 encodersByType[Key] = new KeyValuePair<Grade, IContentEncoder>(Grade, Encoder);
327 }
328
329 if (!(Encoder is null))
330 return true;
331
332 if (Object is CustomEncoding)
333 {
334 Encoder = new CustomEncoder();
335 return true;
336 }
337
338 return false;
339 }
340
348 [Obsolete("Use the EncodeAsync method for more efficient processing of content including asynchronous processing elements in parallel environments.")]
349 public static ContentResponse Encode(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
350 {
351 return EncodeAsync(Object, Encoding, AcceptedContentTypes).Result;
352 }
353
361 public static Task<ContentResponse> EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
362 {
363 return EncodeAsync(Object, Encoding, null, AcceptedContentTypes);
364 }
365
374 public static Task<ContentResponse> EncodeAsync(object Object, Encoding Encoding,
375 ICodecProgress Progress, params string[] AcceptedContentTypes)
376 {
377 if (!Encodes(Object, out Grade _, out IContentEncoder Encoder, AcceptedContentTypes))
378 return Task.FromResult(new ContentResponse(new ArgumentException("No encoder found to encode objects of type " + (Object?.GetType()?.FullName) + ".", nameof(Object))));
379
380 return Encoder.EncodeAsync(Object, Encoding, Progress);
381 }
382
388 public static bool IsAccepted(string ContentType, params string[] AcceptedContentTypes)
389 {
390 if (AcceptedContentTypes.Length == 0)
391 return true;
392 else
393 return Array.IndexOf(AcceptedContentTypes, ContentType) >= 0;
394 }
395
401 public static bool IsAccepted(string[] ContentTypes, params string[] AcceptedContentTypes)
402 {
403 return IsAccepted(ContentTypes, out string _, AcceptedContentTypes);
404 }
405
412 public static bool IsAccepted(string[] ContentTypes, out string ContentType, params string[] AcceptedContentTypes)
413 {
414 if (ContentTypes.Length == 0)
415 {
416 ContentType = null;
417 return false;
418 }
419
420 if ((AcceptedContentTypes?.Length ?? 0) == 0)
421 {
422 ContentType = ContentTypes[0];
423 return true;
424 }
425
426 foreach (string ContentType2 in ContentTypes)
427 {
428 if (IsAccepted(ContentType2, AcceptedContentTypes))
429 {
430 ContentType = ContentType2;
431 return true;
432 }
433 }
434
435 ContentType = null;
436 return false;
437 }
438
439 #endregion
440
441 #region Decoding
442
446 public static string[] CanDecodeContentTypes
447 {
448 get
449 {
450 if (canDecodeContentTypes is null)
451 {
452 SortedDictionary<string, bool> ContentTypes = new SortedDictionary<string, bool>();
453
454 foreach (IContentDecoder Decoder in Decoders)
455 {
456 foreach (string ContentType in Decoder.ContentTypes)
457 ContentTypes[ContentType] = true;
458 }
459
460 string[] Types = new string[ContentTypes.Count];
461 ContentTypes.Keys.CopyTo(Types, 0);
462
463 canDecodeContentTypes = Types;
464 }
465
466 return canDecodeContentTypes;
467 }
468 }
469
473 public static string[] CanDecodeFileExtensions
474 {
475 get
476 {
477 if (canDecodeFileExtensions is null)
478 {
479 SortedDictionary<string, bool> FileExtensions = new SortedDictionary<string, bool>();
480
481 foreach (IContentDecoder Decoder in Decoders)
482 {
483 foreach (string FileExtension in Decoder.FileExtensions)
484 FileExtensions[FileExtension] = true;
485 }
486
487 string[] Types = new string[FileExtensions.Count];
488 FileExtensions.Keys.CopyTo(Types, 0);
489
490 canDecodeFileExtensions = Types;
491 }
492
493 return canDecodeFileExtensions;
494 }
495 }
496
500 public static IContentDecoder[] Decoders
501 {
502 get
503 {
504 if (decoders is null)
505 {
507 IContentDecoder Decoder;
508 Type[] DecoderTypes = Types.GetTypesImplementingInterface(typeof(IContentDecoder));
509
510 foreach (Type T in DecoderTypes)
511 {
512 ConstructorInfo CI = Types.GetDefaultConstructor(T);
513 if (CI is null)
514 continue;
515
516 try
517 {
518 Decoder = (IContentDecoder)CI.Invoke(Types.NoParameters);
519 }
520 catch (Exception)
521 {
522 continue;
523 }
524
525 Decoders.Add(Decoder);
526 }
527
528 decoders = Decoders.ToArray();
529 }
530
531 return decoders;
532 }
533 }
534
542 public static bool Decodes(string ContentType, out Grade Grade, out IContentDecoder Decoder)
543 {
544 lock (decoderByContentType)
545 {
546 if (decoderByContentType.TryGetValue(ContentType, out KeyValuePair<Grade, IContentDecoder> P))
547 {
548 Grade = P.Key;
549 Decoder = P.Value;
550
551 return !(Decoder is null);
552 }
553 }
554
555 Grade = Grade.NotAtAll;
556 Decoder = null;
557
558 foreach (IContentDecoder Decoder2 in Decoders)
559 {
560 if (Decoder2.Decodes(ContentType, out Grade Grade2) && Grade2 > Grade)
561 {
562 Grade = Grade2;
563 Decoder = Decoder2;
564 }
565 }
566
567 lock (decoderByContentType)
568 {
569 decoderByContentType[ContentType] = new KeyValuePair<Grade, IContentDecoder>(Grade, Decoder);
570 }
571
572 return !(Decoder is null);
573 }
574
584 [Obsolete("Use the DecoceAsync method for more efficient processing of content including asynchronous processing elements in parallel environments.")]
585 public static ContentResponse Decode(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair<string, string>[] Fields, Uri BaseUri)
586 {
587 return DecodeAsync(ContentType, Data, Encoding, Fields, BaseUri).Result;
588 }
589
599 public static Task<ContentResponse> DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair<string, string>[] Fields, Uri BaseUri)
600 {
601 return DecodeAsync(ContentType, Data, Encoding, Fields, BaseUri, null);
602 }
603
614 public static Task<ContentResponse> DecodeAsync(string ContentType, byte[] Data, Encoding Encoding,
615 KeyValuePair<string, string>[] Fields, Uri BaseUri, ICodecProgress Progress)
616 {
617 if (string.IsNullOrEmpty(ContentType))
618 {
619 if ((Data?.Length ?? 0) == 0)
620 return Task.FromResult(new ContentResponse(string.Empty, null, Data));
621 else
622 {
623 return Task.FromResult(new ContentResponse(BinaryCodec.DefaultContentType,
625 }
626 }
627 else if (Decodes(ContentType, out Grade _, out IContentDecoder Decoder))
628 return Decoder.DecodeAsync(ContentType, Data, Encoding, Fields, BaseUri, Progress);
629 else
630 {
631 return Task.FromResult(new ContentResponse(ContentType,
632 new CustomEncoding(ContentType, Data), Data));
633 }
634 }
635
643 [Obsolete("Use the DecoceAsync method for more efficient processing of content including asynchronous processing elements in parallel environments.")]
644 public static ContentResponse Decode(string ContentType, byte[] Data, Uri BaseUri)
645 {
646 return DecodeAsync(ContentType, Data, BaseUri).Result;
647 }
648
656 public static Task<ContentResponse> DecodeAsync(string ContentType, byte[] Data, Uri BaseUri)
657 {
658 return DecodeAsync(ContentType, Data, BaseUri, null);
659 }
660
669 public static Task<ContentResponse> DecodeAsync(string ContentType, byte[] Data, Uri BaseUri,
670 ICodecProgress Progress)
671 {
672 ParseContentType(ref ContentType, out Encoding Encoding,
673 out KeyValuePair<string, string>[] Fields);
674
675 return DecodeAsync(ContentType, Data, Encoding, Fields, BaseUri, Progress);
676 }
677
689 public static bool ParseContentType(ref string ContentType, out Encoding Encoding,
690 out KeyValuePair<string, string>[] Fields)
691 {
692 int i;
693
694 Encoding = null;
695
696 i = ContentType.IndexOf(';');
697 if (i > 0)
698 {
699 Fields = CommonTypes.ParseFieldValues(ContentType.Substring(i + 1).TrimStart());
700 ContentType = ContentType.Substring(0, i).TrimEnd();
701
702 foreach (KeyValuePair<string, string> Field in Fields)
703 {
704 if (string.Compare(Field.Key, "CHARSET", true) == 0)
705 Encoding = GetEncoding(Field.Value);
706 }
707
708 return true;
709 }
710 else
711 {
712 Fields = Array.Empty<KeyValuePair<string, string>>();
713 return false;
714 }
715 }
716
722 public static Encoding GetEncoding(string CharacterSet)
723 {
724 if (string.IsNullOrEmpty(CharacterSet))
725 return null;
726
727 // Reference: http://www.iana.org/assignments/character-sets/character-sets.xhtml
728 switch (CharacterSet.ToUpper())
729 {
730 case "ASCII":
731 case "US-ASCII":
732 return Encoding.ASCII;
733
734 case "UTF-16LE":
735 case "UTF-16":
736 return Encoding.Unicode;
737
738 case "UTF-16BE":
739 return Encoding.BigEndianUnicode;
740
741 case "UTF-32":
742 case "UTF-32LE":
743 return Encoding.UTF32;
744
745 case "UNICODE-1-1-UTF-7":
746 case "UTF-7":
747 return Encoding.UTF7;
748
749 case "UTF-8":
750 return Encoding.UTF8;
751
752 default:
753 return Encoding.GetEncoding(CharacterSet);
754 }
755 }
756
757 #endregion
758
759 #region File extensions
760
768 public static string GetContentType(string FileExtension)
769 {
770 if (TryGetContentType(FileExtension, out string ContentType))
771 return ContentType;
772 else
774 }
775
782 public static bool TryGetContentType(string FileExtension, out string ContentType)
783 {
784 FileExtension = FileExtension.ToLower();
785 if (FileExtension.StartsWith("."))
786 FileExtension = FileExtension.Substring(1);
787
788 lock (contentTypeByFileExtensions)
789 {
790 if (contentTypeByFileExtensions.TryGetValue(FileExtension, out ContentType))
791 return true;
792 }
793
794 foreach (IContentDecoder Decoder in Decoders)
795 {
796 if (Decoder.TryGetContentType(FileExtension, out ContentType))
797 {
798 lock (contentTypeByFileExtensions)
799 {
800 contentTypeByFileExtensions[FileExtension] = ContentType;
801 }
802
803 return true;
804 }
805 }
806
807 foreach (IContentEncoder Encoder in Encoders)
808 {
809 if (Encoder.TryGetContentType(FileExtension, out ContentType))
810 {
811 lock (contentTypeByFileExtensions)
812 {
813 contentTypeByFileExtensions[FileExtension] = ContentType;
814 }
815
816 return true;
817 }
818 }
819
820 return false;
821 }
822
830 public static string GetFileExtension(string ContentType)
831 {
832 if (TryGetFileExtension(ContentType, out string FileExtension))
833 return FileExtension;
834 else
835 return "bin";
836 }
837
844 public static bool TryGetFileExtension(string ContentType, out string FileExtension)
845 {
846 ContentType = ContentType.ToLower();
847
848 lock (fileExtensionsByContentType)
849 {
850 if (fileExtensionsByContentType.TryGetValue(ContentType, out FileExtension))
851 return true;
852 }
853
854 foreach (IContentDecoder Decoder in Decoders)
855 {
856 if (Decoder.TryGetFileExtension(ContentType, out FileExtension))
857 {
858 lock (fileExtensionsByContentType)
859 {
860 fileExtensionsByContentType[ContentType] = FileExtension;
861 }
862
863 return true;
864 }
865 }
866
867 foreach (IContentEncoder Encoder in Encoders)
868 {
869 if (Encoder.TryGetFileExtension(ContentType, out FileExtension))
870 {
871 lock (fileExtensionsByContentType)
872 {
873 fileExtensionsByContentType[ContentType] = FileExtension;
874 }
875
876 return true;
877 }
878 }
879
880 return false;
881 }
882
883 #endregion
884
885 #region Content Conversion
886
887
892 {
893 get
894 {
895 if (converters is null)
896 FindConverters();
897
898 return converters;
899 }
900 }
901
913 public static bool CanConvert(string FromContentType, string ToContentType, out IContentConverter Converter)
914 {
915 lock (convertersByStep)
916 {
917 if (converters is null)
918 FindConverters();
919
920 string PathKey = FromContentType + " -> " + ToContentType;
921 if (convertersByStep.TryGetValue(PathKey, out Converter))
922 return !(Converter is null);
923
924 if (!convertersByFrom.TryGetValue(FromContentType, out ChunkedList<IContentConverter> Converters))
925 return false;
926
928 ConversionStep Step;
929
930 foreach (IContentConverter C in Converters)
931 {
932 Step = new ConversionStep()
933 {
934 From = FromContentType,
935 Converter = C,
936 TotalGrade = C.ConversionGrade,
937 Prev = null,
938 Distance = 1
939 };
940
941 Queue.Add(Step);
942 }
943
944 Dictionary<string, ConversionStep> Possibilities = new Dictionary<string, ConversionStep>();
945 ConversionStep Best = null;
946 Grade BestGrade = Grade.NotAtAll;
947 int BestDistance = int.MaxValue;
948 Grade StepGrade;
949 int StepDistance;
950 bool First;
951
952 while (Queue.HasFirstItem)
953 {
954 Step = Queue.RemoveFirst();
955
956 StepDistance = Step.Distance + 1;
957 StepGrade = Step.Converter.ConversionGrade;
958 if (Step.TotalGrade < StepGrade)
959 StepGrade = Step.TotalGrade;
960
961 foreach (string To in Step.Converter.ToContentTypes)
962 {
963 if (string.Compare(To, ToContentType, true) == 0 || To == "*")
964 {
965 if (StepGrade > BestGrade || StepGrade == BestGrade && StepDistance < BestDistance)
966 {
967 Best = Step;
968 BestGrade = StepGrade;
969 BestDistance = StepDistance;
970 }
971 }
972 else
973 {
974 if (Possibilities.TryGetValue(To, out ConversionStep NextStep) && NextStep.TotalGrade >= StepGrade && NextStep.Distance <= StepDistance)
975 continue;
976
977 if (!convertersByFrom.TryGetValue(To, out Converters))
978 continue;
979
980 First = true;
981 foreach (IContentConverter C in Converters)
982 {
983 NextStep = new ConversionStep()
984 {
985 From = To,
986 Converter = C,
987 TotalGrade = StepGrade,
988 Prev = Step,
989 Distance = StepDistance
990 };
991
992 if (First)
993 {
994 Possibilities[To] = NextStep;
995 First = false;
996 }
997
998 Queue.Add(NextStep);
999 }
1000 }
1001 }
1002 }
1003
1004 if (!(Best is null))
1005 {
1007
1008 while (!(Best is null))
1009 {
1010 List.Insert(0, new KeyValuePair<string, IContentConverter>(Best.From, Best.Converter));
1011 Best = Best.Prev;
1012 }
1013
1014 Converter = new ConversionSequence(FromContentType, ToContentType, BestGrade, List.ToArray());
1015 convertersByStep[PathKey] = Converter;
1016 return true;
1017 }
1018 else
1019 {
1020 convertersByStep[PathKey] = null;
1021 Converter = null;
1022 return false;
1023 }
1024 }
1025 }
1026
1027 private class ConversionStep
1028 {
1029 public IContentConverter Converter;
1030 public Grade TotalGrade;
1031 public ConversionStep Prev;
1032 public string From;
1033 public int Distance;
1034 }
1035
1036 private static void FindConverters()
1037 {
1039 IContentConverter Converter;
1040 Type[] ConverterTypes = Types.GetTypesImplementingInterface(typeof(IContentConverter));
1041
1042 convertersByStep.Clear();
1043 convertersByFrom.Clear();
1044
1045 lock (convertersByStep)
1046 {
1047 foreach (Type T in ConverterTypes)
1048 {
1049 ConstructorInfo CI = Types.GetDefaultConstructor(T);
1050 if (CI is null)
1051 continue;
1052
1053 try
1054 {
1055 Converter = (IContentConverter)CI.Invoke(Types.NoParameters);
1056 }
1057 catch (Exception)
1058 {
1059 continue;
1060 }
1061
1062 Converters.Add(Converter);
1063
1064 foreach (string From in Converter.FromContentTypes)
1065 {
1066 if (!convertersByFrom.TryGetValue(From, out ChunkedList<IContentConverter> List))
1067 {
1068 List = new ChunkedList<IContentConverter>();
1069 convertersByFrom[From] = List;
1070 }
1071
1072 List.Add(Converter);
1073
1074 foreach (string To in Converter.ToContentTypes)
1075 {
1076 if (To != "*")
1077 convertersByStep[From + " -> " + To] = Converter;
1078 }
1079 }
1080 }
1081 }
1082
1083 converters = Converters.ToArray();
1084 }
1085
1091 public static IContentConverter[] GetConverters(string FromContentType)
1092 {
1093 lock (convertersByStep)
1094 {
1095 if (converters is null)
1096 FindConverters();
1097
1098 if (!convertersByFrom.TryGetValue(FromContentType, out ChunkedList<IContentConverter> Converters))
1099 return null;
1100
1101 return Converters.ToArray();
1102 }
1103 }
1104
1105 #endregion
1106
1107 #region Getting resources
1108
1112 public static string[] CanGetUriSchemes
1113 {
1114 get
1115 {
1116 if (canGetUriSchemes is null)
1117 {
1118 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
1119
1120 foreach (IContentGetter Getter in Getters)
1121 {
1122 foreach (string Scheme in Getter.UriSchemes)
1123 UriSchemes[Scheme] = true;
1124 }
1125
1126 string[] Schemes = new string[UriSchemes.Count];
1127 UriSchemes.Keys.CopyTo(Schemes, 0);
1128
1129 canGetUriSchemes = Schemes;
1130 }
1131
1132 return canGetUriSchemes;
1133 }
1134 }
1135
1139 public static IContentGetter[] Getters
1140 {
1141 get
1142 {
1143 if (getters is null)
1144 BuildGetters();
1145
1146 return getters;
1147 }
1148 }
1149
1150 private static void BuildGetters()
1151 {
1153 Type[] GetterTypes = Types.GetTypesImplementingInterface(typeof(IContentGetter));
1154 Dictionary<string, ChunkedList<IContentGetter>> ByScheme = new Dictionary<string, ChunkedList<IContentGetter>>();
1155 IContentGetter Getter;
1156
1157 foreach (Type T in GetterTypes)
1158 {
1159 ConstructorInfo CI = Types.GetDefaultConstructor(T);
1160 if (CI is null)
1161 continue;
1162
1163 try
1164 {
1165 Getter = (IContentGetter)CI.Invoke(Types.NoParameters);
1166 }
1167 catch (Exception)
1168 {
1169 continue;
1170 }
1171
1172 Getters.Add(Getter);
1173
1174 foreach (string Schema in Getter.UriSchemes)
1175 {
1176 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentGetter> List))
1177 {
1178 List = new ChunkedList<IContentGetter>();
1179 ByScheme[Schema] = List;
1180 }
1181
1182 List.Add(Getter);
1183 }
1184 }
1185
1186 lock (gettersByScheme)
1187 {
1188 foreach (KeyValuePair<string, ChunkedList<IContentGetter>> P in ByScheme)
1189 gettersByScheme[P.Key] = P.Value.ToArray();
1190 }
1191
1192 getters = Getters.ToArray();
1193 }
1194
1202 public static bool CanGet(Uri Uri, out Grade Grade, out IContentGetter Getter)
1203 {
1204 if (Uri is null)
1205 {
1206 Grade = Grade.NotAtAll;
1207 Getter = null;
1208 return false;
1209 }
1210
1211 if (getters is null)
1212 BuildGetters();
1213
1215
1216 lock (gettersByScheme)
1217 {
1218 if (Uri is null || !gettersByScheme.TryGetValue(Uri.Scheme, out Getters))
1219 {
1220 Getter = null;
1221 Grade = Grade.NotAtAll;
1222 return false;
1223 }
1224 }
1225
1226 Grade = Grade.NotAtAll;
1227 Getter = null;
1228
1229 foreach (IContentGetter Getter2 in Getters)
1230 {
1231 if (Getter2.CanGet(Uri, out Grade Grade2) && Grade2 > Grade)
1232 {
1233 Grade = Grade2;
1234 Getter = Getter2;
1235 }
1236 }
1237
1238 return !(Getter is null);
1239 }
1240
1247 public static Task<ContentResponse> GetAsync(Uri Uri, params KeyValuePair<string, string>[] Headers)
1248 {
1249 return GetAsync(Uri, null, null, Headers);
1250 }
1251
1259 public static Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
1260 {
1261 return GetAsync(Uri, Certificate, null, Headers);
1262 }
1263
1272 public static Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
1273 params KeyValuePair<string, string>[] Headers)
1274 {
1275 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1276 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1277
1278 return Getter.GetAsync(Uri, Certificate, RemoteCertificateValidator, Headers);
1279 }
1280
1288 public static Task<ContentResponse> GetAsync(Uri Uri, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1289 {
1290 return GetAsync(Uri, null, null, TimeoutMs, Headers);
1291 }
1292
1301 public static Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1302 {
1303 return GetAsync(Uri, Certificate, null, TimeoutMs, Headers);
1304 }
1305
1315 public static Task<ContentResponse> GetAsync(Uri Uri, X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
1316 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1317 {
1318 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1319 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1320
1321 return Getter.GetAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
1322 }
1323
1330 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, params KeyValuePair<string, string>[] Headers)
1331 {
1332 return GetTempStreamAsync(Uri, null, null, null, Headers);
1333 }
1334
1342 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
1343 {
1344 return GetTempStreamAsync(Uri, null, null, Destination, Headers);
1345 }
1346
1354 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
1355 {
1356 return GetTempStreamAsync(Uri, Certificate, null, null, Headers);
1357 }
1358
1367 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate, TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
1368 {
1369 return GetTempStreamAsync(Uri, Certificate, null, Destination, Headers);
1370 }
1371
1380 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
1381 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
1382 {
1383 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1384 return Task.FromResult(new ContentStreamResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1385
1386 return Getter.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, Headers);
1387 }
1388
1398 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
1399 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
1400 {
1401 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1402 return Task.FromResult(new ContentStreamResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1403
1404 return Getter.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, Destination, Headers);
1405 }
1406
1414 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1415 {
1416 return GetTempStreamAsync(Uri, null, null, TimeoutMs, Headers);
1417 }
1418
1427 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, int TimeoutMs, TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
1428 {
1429 return GetTempStreamAsync(Uri, null, null, TimeoutMs, Destination, Headers);
1430 }
1431
1440 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1441 {
1442 return GetTempStreamAsync(Uri, Certificate, null, TimeoutMs, Headers);
1443 }
1444
1454 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs,
1455 TemporaryStream Destination, params KeyValuePair<string, string>[] Headers)
1456 {
1457 return GetTempStreamAsync(Uri, Certificate, null, TimeoutMs, Destination, Headers);
1458 }
1459
1469 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
1470 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1471 {
1472 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1473 return Task.FromResult(new ContentStreamResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1474
1475 return Getter.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
1476 }
1477
1488 public static Task<ContentStreamResponse> GetTempStreamAsync(Uri Uri, X509Certificate Certificate,
1489 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, TemporaryStream Destination,
1490 params KeyValuePair<string, string>[] Headers)
1491 {
1492 if (!CanGet(Uri, out Grade _, out IContentGetter Getter))
1493 return Task.FromResult(new ContentStreamResponse(new ArgumentException("URI Scheme not recognized (GET): " + Uri.Scheme, nameof(Uri))));
1494
1495 return Getter.GetTempStreamAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Destination, Headers);
1496 }
1497
1498 #endregion
1499
1500 #region Posting to resources
1501
1505 public static string[] CanPostToUriSchemes
1506 {
1507 get
1508 {
1509 if (canPostToUriSchemes is null)
1510 {
1511 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
1512
1513 foreach (IContentPoster Poster in Posters)
1514 {
1515 foreach (string Scheme in Poster.UriSchemes)
1516 UriSchemes[Scheme] = true;
1517 }
1518
1519 string[] Schemes = new string[UriSchemes.Count];
1520 UriSchemes.Keys.CopyTo(Schemes, 0);
1521
1522 canPostToUriSchemes = Schemes;
1523 }
1524
1525 return canPostToUriSchemes;
1526 }
1527 }
1528
1532 public static IContentPoster[] Posters
1533 {
1534 get
1535 {
1536 if (posters is null)
1537 BuildPosters();
1538
1539 return posters;
1540 }
1541 }
1542
1543 private static void BuildPosters()
1544 {
1546 Type[] PosterTypes = Types.GetTypesImplementingInterface(typeof(IContentPoster));
1547 Dictionary<string, ChunkedList<IContentPoster>> ByScheme = new Dictionary<string, ChunkedList<IContentPoster>>();
1548 IContentPoster Poster;
1549
1550 foreach (Type T in PosterTypes)
1551 {
1552 ConstructorInfo CI = Types.GetDefaultConstructor(T);
1553 if (CI is null)
1554 continue;
1555
1556 try
1557 {
1558 Poster = (IContentPoster)CI.Invoke(Types.NoParameters);
1559 }
1560 catch (Exception)
1561 {
1562 continue;
1563 }
1564
1565 Posters.Add(Poster);
1566
1567 foreach (string Schema in Poster.UriSchemes)
1568 {
1569 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentPoster> List))
1570 {
1571 List = new ChunkedList<IContentPoster>();
1572 ByScheme[Schema] = List;
1573 }
1574
1575 List.Add(Poster);
1576 }
1577 }
1578
1579 lock (postersByScheme)
1580 {
1581 foreach (KeyValuePair<string, ChunkedList<IContentPoster>> P in ByScheme)
1582 postersByScheme[P.Key] = P.Value.ToArray();
1583 }
1584
1585 posters = Posters.ToArray();
1586 }
1587
1595 public static bool CanPost(Uri Uri, out Grade Grade, out IContentPoster Poster)
1596 {
1597 if (Uri is null)
1598 {
1599 Grade = Grade.NotAtAll;
1600 Poster = null;
1601 return false;
1602 }
1603
1604 if (posters is null)
1605 BuildPosters();
1606
1608
1609 lock (postersByScheme)
1610 {
1611 if (Uri is null || !postersByScheme.TryGetValue(Uri.Scheme, out Posters))
1612 {
1613 Poster = null;
1614 Grade = Grade.NotAtAll;
1615 return false;
1616 }
1617 }
1618
1619 Grade = Grade.NotAtAll;
1620 Poster = null;
1621
1622 foreach (IContentPoster Poster2 in Posters)
1623 {
1624 if (Poster2.CanPost(Uri, out Grade Grade2) && Grade2 > Grade)
1625 {
1626 Grade = Grade2;
1627 Poster = Poster2;
1628 }
1629 }
1630
1631 return !(Poster is null);
1632 }
1633
1641 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, params KeyValuePair<string, string>[] Headers)
1642 {
1643 return PostAsync(Uri, Data, null, null, Headers);
1644 }
1645
1654 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
1655 {
1656 return PostAsync(Uri, Data, Certificate, null, Headers);
1657 }
1658
1668 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, X509Certificate Certificate,
1669 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
1670 {
1671 if (!CanPost(Uri, out Grade _, out IContentPoster Poster))
1672 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (POST): " + Uri.Scheme, nameof(Uri))));
1673
1674 return Poster.PostAsync(Uri, Data, Certificate, RemoteCertificateValidator, Headers);
1675 }
1676
1685 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1686 {
1687 return PostAsync(Uri, Data, null, null, TimeoutMs, Headers);
1688 }
1689
1699 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1700 {
1701 return PostAsync(Uri, Data, Certificate, null, TimeoutMs, Headers);
1702 }
1703
1714 public static Task<ContentResponse> PostAsync(Uri Uri, object Data, X509Certificate Certificate,
1715 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1716 {
1717 if (!CanPost(Uri, out Grade _, out IContentPoster Poster))
1718 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (POST): " + Uri.Scheme, nameof(Uri))));
1719
1720 return Poster.PostAsync(Uri, Data, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
1721 }
1722
1731 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair<string, string>[] Headers)
1732 {
1733 return PostAsync(Uri, EncodedData, ContentType, null, null, Headers);
1734 }
1735
1745 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType,
1746 X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
1747 {
1748 return PostAsync(Uri, EncodedData, ContentType, Certificate, null, Headers);
1749 }
1750
1761 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType,
1762 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
1763 {
1764 if (!CanPost(Uri, out Grade _, out IContentPoster Poster))
1765 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (POST): " + Uri.Scheme, nameof(Uri))));
1766
1767 return Poster.PostAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, Headers);
1768 }
1769
1779 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1780 {
1781 return PostAsync(Uri, EncodedData, ContentType, null, null, TimeoutMs, Headers);
1782 }
1783
1794 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType,
1795 X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
1796 {
1797 return PostAsync(Uri, EncodedData, ContentType, Certificate, null, TimeoutMs, Headers);
1798 }
1799
1811 public static Task<ContentBinaryResponse> PostAsync(Uri Uri, byte[] EncodedData, string ContentType,
1812 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs,
1813 params KeyValuePair<string, string>[] Headers)
1814 {
1815 if (!CanPost(Uri, out Grade _, out IContentPoster Poster))
1816 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (POST): " + Uri.Scheme, nameof(Uri))));
1817
1818 return Poster.PostAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
1819 }
1820
1821 #endregion
1822
1823 #region Putting to resources
1824
1828 public static string[] CanPutToUriSchemes
1829 {
1830 get
1831 {
1832 if (canPutToUriSchemes is null)
1833 {
1834 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
1835
1836 foreach (IContentPutter Putter in Putters)
1837 {
1838 foreach (string Scheme in Putter.UriSchemes)
1839 UriSchemes[Scheme] = true;
1840 }
1841
1842 string[] Schemes = new string[UriSchemes.Count];
1843 UriSchemes.Keys.CopyTo(Schemes, 0);
1844
1845 canPutToUriSchemes = Schemes;
1846 }
1847
1848 return canPutToUriSchemes;
1849 }
1850 }
1851
1855 public static IContentPutter[] Putters
1856 {
1857 get
1858 {
1859 if (putters is null)
1860 BuildPutters();
1861
1862 return putters;
1863 }
1864 }
1865
1866 private static void BuildPutters()
1867 {
1869 Type[] PutterTypes = Types.GetTypesImplementingInterface(typeof(IContentPutter));
1870 Dictionary<string, ChunkedList<IContentPutter>> ByScheme = new Dictionary<string, ChunkedList<IContentPutter>>();
1871 IContentPutter Putter;
1872
1873 foreach (Type T in PutterTypes)
1874 {
1875 ConstructorInfo CI = Types.GetDefaultConstructor(T);
1876 if (CI is null)
1877 continue;
1878
1879 try
1880 {
1881 Putter = (IContentPutter)CI.Invoke(Types.NoParameters);
1882 }
1883 catch (Exception)
1884 {
1885 continue;
1886 }
1887
1888 Putters.Add(Putter);
1889
1890 foreach (string Schema in Putter.UriSchemes)
1891 {
1892 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentPutter> List))
1893 {
1894 List = new ChunkedList<IContentPutter>();
1895 ByScheme[Schema] = List;
1896 }
1897
1898 List.Add(Putter);
1899 }
1900 }
1901
1902 lock (puttersByScheme)
1903 {
1904 foreach (KeyValuePair<string, ChunkedList<IContentPutter>> P in ByScheme)
1905 puttersByScheme[P.Key] = P.Value.ToArray();
1906 }
1907
1908 putters = Putters.ToArray();
1909 }
1910
1918 public static bool CanPut(Uri Uri, out Grade Grade, out IContentPutter Putter)
1919 {
1920 if (Uri is null)
1921 {
1922 Grade = Grade.NotAtAll;
1923 Putter = null;
1924 return false;
1925 }
1926
1927 if (putters is null)
1928 BuildPutters();
1929
1931
1932 lock (puttersByScheme)
1933 {
1934 if (Uri is null || !puttersByScheme.TryGetValue(Uri.Scheme, out Putters))
1935 {
1936 Putter = null;
1937 Grade = Grade.NotAtAll;
1938 return false;
1939 }
1940 }
1941
1942 Grade = Grade.NotAtAll;
1943 Putter = null;
1944
1945 foreach (IContentPutter Putter2 in Putters)
1946 {
1947 if (Putter2.CanPut(Uri, out Grade Grade2) && Grade2 > Grade)
1948 {
1949 Grade = Grade2;
1950 Putter = Putter2;
1951 }
1952 }
1953
1954 return !(Putter is null);
1955 }
1956
1964 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, params KeyValuePair<string, string>[] Headers)
1965 {
1966 return PutAsync(Uri, Data, null, null, Headers);
1967 }
1968
1977 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
1978 {
1979 return PutAsync(Uri, Data, Certificate, null, Headers);
1980 }
1981
1991 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, X509Certificate Certificate,
1992 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
1993 {
1994 if (!CanPut(Uri, out Grade _, out IContentPutter Putter))
1995 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
1996
1997 return Putter.PutAsync(Uri, Data, Certificate, RemoteCertificateValidator, Headers);
1998 }
1999
2008 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2009 {
2010 return PutAsync(Uri, Data, null, null, TimeoutMs, Headers);
2011 }
2012
2022 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2023 {
2024 return PutAsync(Uri, Data, Certificate, null, TimeoutMs, Headers);
2025 }
2026
2037 public static Task<ContentResponse> PutAsync(Uri Uri, object Data, X509Certificate Certificate,
2038 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2039 {
2040 if (!CanPut(Uri, out Grade _, out IContentPutter Putter))
2041 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2042
2043 return Putter.PutAsync(Uri, Data, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2044 }
2045
2054 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair<string, string>[] Headers)
2055 {
2056 return PutAsync(Uri, EncodedData, ContentType, null, null, Headers);
2057 }
2058
2068 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
2069 {
2070 return PutAsync(Uri, EncodedData, ContentType, Certificate, null, Headers);
2071 }
2072
2083 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType,
2084 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
2085 {
2086 if (!CanPut(Uri, out Grade _, out IContentPutter Putter))
2087 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2088
2089 return Putter.PutAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, Headers);
2090 }
2091
2101 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2102 {
2103 return PutAsync(Uri, EncodedData, ContentType, null, null, TimeoutMs, Headers);
2104 }
2105
2116 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2117 {
2118 return PutAsync(Uri, EncodedData, ContentType, Certificate, null, TimeoutMs, Headers);
2119 }
2120
2132 public static Task<ContentBinaryResponse> PutAsync(Uri Uri, byte[] EncodedData, string ContentType,
2133 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2134 {
2135 if (!CanPut(Uri, out Grade _, out IContentPutter Putter))
2136 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2137
2138 return Putter.PutAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2139 }
2140
2141 #endregion
2142
2143 #region Deleting to resources
2144
2148 public static string[] CanDeleteToUriSchemes
2149 {
2150 get
2151 {
2152 if (canDeleteToUriSchemes is null)
2153 {
2154 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
2155
2156 foreach (IContentDeleter Deleter in Deleters)
2157 {
2158 foreach (string Scheme in Deleter.UriSchemes)
2159 UriSchemes[Scheme] = true;
2160 }
2161
2162 string[] Schemes = new string[UriSchemes.Count];
2163 UriSchemes.Keys.CopyTo(Schemes, 0);
2164
2165 canDeleteToUriSchemes = Schemes;
2166 }
2167
2168 return canDeleteToUriSchemes;
2169 }
2170 }
2171
2176 {
2177 get
2178 {
2179 if (deleters is null)
2180 BuildDeleters();
2181
2182 return deleters;
2183 }
2184 }
2185
2186 private static void BuildDeleters()
2187 {
2189 Type[] DeleterTypes = Types.GetTypesImplementingInterface(typeof(IContentDeleter));
2190 Dictionary<string, ChunkedList<IContentDeleter>> ByScheme = new Dictionary<string, ChunkedList<IContentDeleter>>();
2191 IContentDeleter Deleter;
2192
2193 foreach (Type T in DeleterTypes)
2194 {
2195 ConstructorInfo CI = Types.GetDefaultConstructor(T);
2196 if (CI is null)
2197 continue;
2198
2199 try
2200 {
2201 Deleter = (IContentDeleter)CI.Invoke(Types.NoParameters);
2202 }
2203 catch (Exception)
2204 {
2205 continue;
2206 }
2207
2208 Deleters.Add(Deleter);
2209
2210 foreach (string Schema in Deleter.UriSchemes)
2211 {
2212 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentDeleter> List))
2213 {
2214 List = new ChunkedList<IContentDeleter>();
2215 ByScheme[Schema] = List;
2216 }
2217
2218 List.Add(Deleter);
2219 }
2220 }
2221
2222 lock (deletersByScheme)
2223 {
2224 foreach (KeyValuePair<string, ChunkedList<IContentDeleter>> P in ByScheme)
2225 deletersByScheme[P.Key] = P.Value.ToArray();
2226 }
2227
2228 deleters = Deleters.ToArray();
2229 }
2230
2238 public static bool CanDelete(Uri Uri, out Grade Grade, out IContentDeleter Deleter)
2239 {
2240 if (Uri is null)
2241 {
2242 Grade = Grade.NotAtAll;
2243 Deleter = null;
2244 return false;
2245 }
2246
2247 if (deleters is null)
2248 BuildDeleters();
2249
2251
2252 lock (deletersByScheme)
2253 {
2254 if (Uri is null || !deletersByScheme.TryGetValue(Uri.Scheme, out Deleters))
2255 {
2256 Deleter = null;
2257 Grade = Grade.NotAtAll;
2258 return false;
2259 }
2260 }
2261
2262 Grade = Grade.NotAtAll;
2263 Deleter = null;
2264
2265 foreach (IContentDeleter Deleter2 in Deleters)
2266 {
2267 if (Deleter2.CanDelete(Uri, out Grade Grade2) && Grade2 > Grade)
2268 {
2269 Grade = Grade2;
2270 Deleter = Deleter2;
2271 }
2272 }
2273
2274 return !(Deleter is null);
2275 }
2276
2283 public static Task<ContentResponse> DeleteAsync(Uri Uri, params KeyValuePair<string, string>[] Headers)
2284 {
2285 return DeleteAsync(Uri, null, null, Headers);
2286 }
2287
2295 public static Task<ContentResponse> DeleteAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
2296 {
2297 return DeleteAsync(Uri, Certificate, null, Headers);
2298 }
2299
2308 public static Task<ContentResponse> DeleteAsync(Uri Uri, X509Certificate Certificate,
2309 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
2310 {
2311 if (!CanDelete(Uri, out Grade _, out IContentDeleter Deleter))
2312 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (DELETE): " + Uri.Scheme, nameof(Uri))));
2313
2314 return Deleter.DeleteAsync(Uri, Certificate, RemoteCertificateValidator, Headers);
2315 }
2316
2324 public static Task<ContentResponse> DeleteAsync(Uri Uri, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2325 {
2326 return DeleteAsync(Uri, null, null, TimeoutMs, Headers);
2327 }
2328
2337 public static Task<ContentResponse> DeleteAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2338 {
2339 return DeleteAsync(Uri, Certificate, null, TimeoutMs, Headers);
2340 }
2341
2351 public static Task<ContentResponse> DeleteAsync(Uri Uri, X509Certificate Certificate,
2352 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs,
2353 params KeyValuePair<string, string>[] Headers)
2354 {
2355 if (!CanDelete(Uri, out Grade _, out IContentDeleter Deleter))
2356 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (DELETE): " + Uri.Scheme, nameof(Uri))));
2357
2358 return Deleter.DeleteAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2359 }
2360
2361 #endregion
2362
2363 #region Getting headers of resources
2364
2368 public static string[] CanHeadUriSchemes
2369 {
2370 get
2371 {
2372 if (canHeadUriSchemes is null)
2373 {
2374 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
2375
2376 foreach (IContentHeader Header in Headers)
2377 {
2378 foreach (string Scheme in Header.UriSchemes)
2379 UriSchemes[Scheme] = true;
2380 }
2381
2382 string[] Schemes = new string[UriSchemes.Count];
2383 UriSchemes.Keys.CopyTo(Schemes, 0);
2384
2385 canHeadUriSchemes = Schemes;
2386 }
2387
2388 return canHeadUriSchemes;
2389 }
2390 }
2391
2395 public static IContentHeader[] Headers
2396 {
2397 get
2398 {
2399 if (headers is null)
2400 BuildHeaders();
2401
2402 return headers;
2403 }
2404 }
2405
2406 private static void BuildHeaders()
2407 {
2409 Type[] HeaderTypes = Types.GetTypesImplementingInterface(typeof(IContentHeader));
2410 Dictionary<string, ChunkedList<IContentHeader>> ByScheme = new Dictionary<string, ChunkedList<IContentHeader>>();
2411 IContentHeader Header;
2412
2413 foreach (Type T in HeaderTypes)
2414 {
2415 ConstructorInfo CI = Types.GetDefaultConstructor(T);
2416 if (CI is null)
2417 continue;
2418
2419 try
2420 {
2421 Header = (IContentHeader)CI.Invoke(Types.NoParameters);
2422 }
2423 catch (Exception)
2424 {
2425 continue;
2426 }
2427
2428 Headers.Add(Header);
2429
2430 foreach (string Schema in Header.UriSchemes)
2431 {
2432 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentHeader> List))
2433 {
2434 List = new ChunkedList<IContentHeader>();
2435 ByScheme[Schema] = List;
2436 }
2437
2438 List.Add(Header);
2439 }
2440 }
2441
2442 lock (headersByScheme)
2443 {
2444 foreach (KeyValuePair<string, ChunkedList<IContentHeader>> P in ByScheme)
2445 headersByScheme[P.Key] = P.Value.ToArray();
2446 }
2447
2448 headers = Headers.ToArray();
2449 }
2450
2458 public static bool CanHead(Uri Uri, out Grade Grade, out IContentHeader Header)
2459 {
2460 if (Uri is null)
2461 {
2462 Grade = Grade.NotAtAll;
2463 Header = null;
2464 return false;
2465 }
2466
2467 if (headers is null)
2468 BuildHeaders();
2469
2471
2472 lock (headersByScheme)
2473 {
2474 if (Uri is null || !headersByScheme.TryGetValue(Uri.Scheme, out Headers))
2475 {
2476 Header = null;
2477 Grade = Grade.NotAtAll;
2478 return false;
2479 }
2480 }
2481
2482 Grade = Grade.NotAtAll;
2483 Header = null;
2484
2485 foreach (IContentHeader Header2 in Headers)
2486 {
2487 if (Header2.CanHead(Uri, out Grade Grade2) && Grade2 > Grade)
2488 {
2489 Grade = Grade2;
2490 Header = Header2;
2491 }
2492 }
2493
2494 return !(Header is null);
2495 }
2496
2503 public static Task<ContentResponse> HeadAsync(Uri Uri, params KeyValuePair<string, string>[] Headers)
2504 {
2505 return HeadAsync(Uri, null, null, Headers);
2506 }
2507
2515 public static Task<ContentResponse> HeadAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
2516 {
2517 return HeadAsync(Uri, Certificate, null, Headers);
2518 }
2519
2528 public static Task<ContentResponse> HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
2529 params KeyValuePair<string, string>[] Headers)
2530 {
2531 if (!CanHead(Uri, out Grade _, out IContentHeader Header))
2532 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (HEAD): " + Uri.Scheme, nameof(Uri))));
2533
2534 return Header.HeadAsync(Uri, Certificate, RemoteCertificateValidator, Headers);
2535 }
2536
2544 public static Task<ContentResponse> HeadAsync(Uri Uri, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2545 {
2546 return HeadAsync(Uri, null, null, TimeoutMs, Headers);
2547 }
2548
2557 public static Task<ContentResponse> HeadAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2558 {
2559 return HeadAsync(Uri, Certificate, null, TimeoutMs, Headers);
2560 }
2561
2571 public static Task<ContentResponse> HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator,
2572 int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2573 {
2574 if (!CanHead(Uri, out Grade _, out IContentHeader Header))
2575 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (HEAD): " + Uri.Scheme, nameof(Uri))));
2576
2577 return Header.HeadAsync(Uri, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2578 }
2579
2580 #endregion
2581
2582 #region Querying resources
2583
2587 public static string[] CanQueryToUriSchemes
2588 {
2589 get
2590 {
2591 if (canQueryUriSchemes is null)
2592 {
2593 SortedDictionary<string, bool> UriSchemes = new SortedDictionary<string, bool>();
2594
2595 foreach (IContentQuery Query in Queries)
2596 {
2597 foreach (string Scheme in Query.UriSchemes)
2598 UriSchemes[Scheme] = true;
2599 }
2600
2601 string[] Schemes = new string[UriSchemes.Count];
2602 UriSchemes.Keys.CopyTo(Schemes, 0);
2603
2604 canQueryUriSchemes = Schemes;
2605 }
2606
2607 return canQueryUriSchemes;
2608 }
2609 }
2610
2614 public static IContentQuery[] Queries
2615 {
2616 get
2617 {
2618 if (queries is null)
2619 BuildQueries();
2620
2621 return queries;
2622 }
2623 }
2624
2625 private static void BuildQueries()
2626 {
2628 Type[] QueryTypes = Types.GetTypesImplementingInterface(typeof(IContentQuery));
2629 Dictionary<string, ChunkedList<IContentQuery>> ByScheme = new Dictionary<string, ChunkedList<IContentQuery>>();
2630 IContentQuery Query;
2631
2632 foreach (Type T in QueryTypes)
2633 {
2634 ConstructorInfo CI = Types.GetDefaultConstructor(T);
2635 if (CI is null)
2636 continue;
2637
2638 try
2639 {
2640 Query = (IContentQuery)CI.Invoke(Types.NoParameters);
2641 }
2642 catch (Exception)
2643 {
2644 continue;
2645 }
2646
2647 Queries.Add(Query);
2648
2649 foreach (string Schema in Query.UriSchemes)
2650 {
2651 if (!ByScheme.TryGetValue(Schema, out ChunkedList<IContentQuery> List))
2652 {
2653 List = new ChunkedList<IContentQuery>();
2654 ByScheme[Schema] = List;
2655 }
2656
2657 List.Add(Query);
2658 }
2659 }
2660
2661 lock (queriesByScheme)
2662 {
2663 foreach (KeyValuePair<string, ChunkedList<IContentQuery>> P in ByScheme)
2664 queriesByScheme[P.Key] = P.Value.ToArray();
2665 }
2666
2667 queries = Queries.ToArray();
2668 }
2669
2677 public static bool CanQuery(Uri Uri, out Grade Grade, out IContentQuery Query)
2678 {
2679 if (Uri is null)
2680 {
2681 Grade = Grade.NotAtAll;
2682 Query = null;
2683 return false;
2684 }
2685
2686 if (queries is null)
2687 BuildQueries();
2688
2690
2691 lock (queriesByScheme)
2692 {
2693 if (Uri is null || !queriesByScheme.TryGetValue(Uri.Scheme, out Queries))
2694 {
2695 Query = null;
2696 Grade = Grade.NotAtAll;
2697 return false;
2698 }
2699 }
2700
2701 Grade = Grade.NotAtAll;
2702 Query = null;
2703
2704 foreach (IContentQuery Query2 in Queries)
2705 {
2706 if (Query2.CanQuery(Uri, out Grade Grade2) && Grade2 > Grade)
2707 {
2708 Grade = Grade2;
2709 Query = Query2;
2710 }
2711 }
2712
2713 return !(Query is null);
2714 }
2715
2723 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, params KeyValuePair<string, string>[] Headers)
2724 {
2725 return QueryAsync(Uri, Data, null, null, Headers);
2726 }
2727
2736 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
2737 {
2738 return QueryAsync(Uri, Data, Certificate, null, Headers);
2739 }
2740
2750 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, X509Certificate Certificate,
2751 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
2752 {
2753 if (!CanQuery(Uri, out Grade _, out IContentQuery Query))
2754 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2755
2756 return Query.QueryAsync(Uri, Data, Certificate, RemoteCertificateValidator, Headers);
2757 }
2758
2767 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2768 {
2769 return QueryAsync(Uri, Data, null, null, TimeoutMs, Headers);
2770 }
2771
2781 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2782 {
2783 return QueryAsync(Uri, Data, Certificate, null, TimeoutMs, Headers);
2784 }
2785
2796 public static Task<ContentResponse> QueryAsync(Uri Uri, object Data, X509Certificate Certificate,
2797 EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2798 {
2799 if (!CanQuery(Uri, out Grade _, out IContentQuery Query))
2800 return Task.FromResult(new ContentResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2801
2802 return Query.QueryAsync(Uri, Data, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2803 }
2804
2813 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair<string, string>[] Headers)
2814 {
2815 return QueryAsync(Uri, EncodedData, ContentType, null, null, Headers);
2816 }
2817
2827 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, params KeyValuePair<string, string>[] Headers)
2828 {
2829 return QueryAsync(Uri, EncodedData, ContentType, Certificate, null, Headers);
2830 }
2831
2842 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType,
2843 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, params KeyValuePair<string, string>[] Headers)
2844 {
2845 if (!CanQuery(Uri, out Grade _, out IContentQuery Query))
2846 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2847
2848 return Query.QueryAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, Headers);
2849 }
2850
2860 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2861 {
2862 return QueryAsync(Uri, EncodedData, ContentType, null, null, TimeoutMs, Headers);
2863 }
2864
2875 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2876 {
2877 return QueryAsync(Uri, EncodedData, ContentType, Certificate, null, TimeoutMs, Headers);
2878 }
2879
2891 public static Task<ContentBinaryResponse> QueryAsync(Uri Uri, byte[] EncodedData, string ContentType,
2892 X509Certificate Certificate, EventHandler<RemoteCertificateEventArgs> RemoteCertificateValidator, int TimeoutMs, params KeyValuePair<string, string>[] Headers)
2893 {
2894 if (!CanQuery(Uri, out Grade _, out IContentQuery Query))
2895 return Task.FromResult(new ContentBinaryResponse(new ArgumentException("URI Scheme not recognized (PUT): " + Uri.Scheme, nameof(Uri))));
2896
2897 return Query.QueryAsync(Uri, EncodedData, ContentType, Certificate, RemoteCertificateValidator, TimeoutMs, Headers);
2898 }
2899
2900 #endregion
2901
2902 #region Local domains
2903
2910 public static bool IsLocalDomain(string DomainOrHost, bool IncludeAlternativeDomains)
2911 {
2912 if (DomainOrHost == "localhost")
2913 return true;
2914
2915 LocalDomainEventArgs e = new LocalDomainEventArgs(DomainOrHost, IncludeAlternativeDomains);
2916 LocalDomainCheck.Raise(typeof(InternetContent), e);
2917
2918 return e.IsLocal ?? false;
2919 }
2920
2924 public static event EventHandler<LocalDomainEventArgs> LocalDomainCheck = null;
2925
2926 #endregion
2927 }
2928}
const string DefaultContentType
text/plain
Definition: BinaryCodec.cs:24
Encodes custom-encoded objects
A custom encoded object.
Helps with parsing of commong data types.
Definition: CommonTypes.cs:15
static KeyValuePair< string, string >[] ParseFieldValues(string Value)
Parses a set of comma or semicolon-separated field values, optionaly delimited by ' or " characters.
Definition: CommonTypes.cs:474
Contains information about a binary response to a content request.
Contains information about a response to a content request.
Contains information about a stream response to a content request.
Static class managing encoding and decoding of internet content.
static string[] CanDecodeContentTypes
Internet content types that can be decoded.
static bool IsAccepted(string ContentType, params string[] AcceptedContentTypes)
Checks if a given content type is acceptable.
static ContentResponse Encode(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
static Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static Task< ContentResponse > PutAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static IContentConverter[] GetConverters(string FromContentType)
Gets available converters that can convert content from a given type.
static EventHandler< LocalDomainEventArgs > LocalDomainCheck
Event raised when a local domain is to be checked.
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static IContentHeader[] Headers
Available Internet Content Header-retrievers.
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static ContentResponse Decode(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
static bool CanPost(Uri Uri, out Grade Grade, out IContentPoster Poster)
If a resource can be posted to, given its URI.
static Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static string GetFileExtension(string ContentType)
Gets the file extension of an item, given its content type. It uses the TryGetFileExtension to see if...
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > HeadAsync(Uri Uri, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static bool CanGet(Uri Uri, out Grade Grade, out IContentGetter Getter)
If a resource can be gotten, given its URI.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Uri BaseUri)
Decodes an object.
static IContentQuery[] Queries
Available Internet Content Queries.
static Task< ContentResponse > GetAsync(Uri Uri, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static int DefaultTimeout
Default timeout of internet access methods, in milliseconds.
static IContentDecoder[] Decoders
Available Internet Content Decoders.
static bool Encodes(object Object, out Grade Grade, out IContentEncoder Encoder, params string[] AcceptedContentTypes)
If a given object can be encoded.
static void SetDefaultTimeout(int Timeout, bool Lock)
Sets the default timeout of internet access methods, in milliseconds.
static string[] CanPutToUriSchemes
Internet URI Schemes that can be put to.
static Task< ContentResponse > EncodeAsync(object Object, Encoding Encoding, ICodecProgress Progress, params string[] AcceptedContentTypes)
Encodes an object.
static string[] CanDeleteToUriSchemes
Internet URI Schemes that can be deleted to.
static Task< ContentResponse > DeleteAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > PutAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static string GetContentType(string FileExtension)
Gets the content type of an item, given its file extension. It uses the TryGetContentType to see if a...
static IContentEncoder[] Encoders
Available Internet Content Encoders.
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > EncodeAsync(object Object, Encoding Encoding, params string[] AcceptedContentTypes)
Encodes an object.
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static bool CanConvert(string FromContentType, string ToContentType, out IContentConverter Converter)
Checks if it is possible to convert content from one type to another.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri, ICodecProgress Progress)
Decodes an object.
static bool CanQuery(Uri Uri, out Grade Grade, out IContentQuery Query)
If a resource can be queried, given its URI.
static Task< ContentResponse > DeleteAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static IContentPutter[] Putters
Available Internet Content Putters.
static Task< ContentResponse > PostAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > PostAsync(Uri Uri, object Data, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static string[] CanHeadUriSchemes
Internet URI Schemes where it is possible to get headers.
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static IContentGetter[] Getters
Available Internet Content Getters.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentResponse > PostAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static IContentDeleter[] Deleters
Available Internet Content Deleters.
static string[] CanEncodeContentTypes
Internet content types that can be encoded.
static readonly Encoding ISO_8859_1
ISO-8859-1 character encoding.
static bool Decodes(string ContentType, out Grade Grade, out IContentDecoder Decoder)
If an object with a given content type can be decoded.
static Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static IContentPoster[] Posters
Available Internet Content Posters.
static ContentResponse Decode(string ContentType, byte[] Data, Uri BaseUri)
Decodes an object.
static Task< ContentResponse > PutAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > GetAsync(Uri Uri, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Uri BaseUri, ICodecProgress Progress)
Decodes an object.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static bool IsAccepted(string[] ContentTypes, out string ContentType, params string[] AcceptedContentTypes)
Checks if at least one content type in a set of content types is acceptable.
static Task< ContentResponse > HeadAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static string[] CanDecodeFileExtensions
File extensions that can be decoded.
static Task< ContentResponse > HeadAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Heads a resource, given its URI.
static bool CanPut(Uri Uri, out Grade Grade, out IContentPutter Putter)
If a resource can be put to, given its URI.
static string[] CanPostToUriSchemes
Internet URI Schemes that can be posted to.
static Task< ContentResponse > DeleteAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > PostAsync(Uri Uri, object Data, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > DeleteAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static bool CanHead(Uri Uri, out Grade Grade, out IContentHeader Header)
If the headers of a resource can be gotten, given its URI.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, int TimeoutMs, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentResponse > PostAsync(Uri Uri, object Data, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > PutAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static bool IsLocalDomain(string DomainOrHost, bool IncludeAlternativeDomains)
Checks if a domain or nost name is local.
static string[] CanGetUriSchemes
Internet URI Schemes that can be gotten.
static Task< ContentResponse > DeleteAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static IContentConverter[] Converters
Available Internet Content Converters.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentBinaryResponse > PostAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentBinaryResponse > PutAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Task< ContentResponse > PostAsync(Uri Uri, object Data, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Posts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static bool ParseContentType(ref string ContentType, out Encoding Encoding, out KeyValuePair< string, string >[] Fields)
Parses a Content-Type, providing the base Content-Type, character encoding, if any,...
static Task< ContentResponse > QueryAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > DecodeAsync(string ContentType, byte[] Data, Encoding Encoding, KeyValuePair< string, string >[] Fields, Uri BaseUri)
Decodes an object.
static bool IsAccepted(string[] ContentTypes, params string[] AcceptedContentTypes)
Checks if at least one content type in a set of content types is acceptable.
static bool CanDelete(Uri Uri, out Grade Grade, out IContentDeleter Deleter)
If a resource can be deleted to, given its URI.
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static string[] CanQueryToUriSchemes
Internet URI Schemes that can be queried.
static Task< ContentResponse > PutAsync(Uri Uri, object Data, X509Certificate Certificate, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static string[] CanEncodeFileExtensions
File extensions that can be encoded.
static Task< ContentResponse > DeleteAsync(Uri Uri, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Deletes a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > PutAsync(Uri Uri, object Data, params KeyValuePair< string, string >[] Headers)
Puts to a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentBinaryResponse > QueryAsync(Uri Uri, byte[] EncodedData, string ContentType, X509Certificate Certificate, EventHandler< RemoteCertificateEventArgs > RemoteCertificateValidator, int TimeoutMs, params KeyValuePair< string, string >[] Headers)
Queries a resource, using a Uniform Resource Identifier (or Locator).
static Task< ContentResponse > GetAsync(Uri Uri, params KeyValuePair< string, string >[] Headers)
Gets a resource, given its URI.
static bool TryGetContentType(string FileExtension, out string ContentType)
Tries to get the content type of an item, given its file extension.
static Task< ContentStreamResponse > GetTempStreamAsync(Uri Uri, X509Certificate Certificate, TemporaryStream Destination, params KeyValuePair< string, string >[] Headers)
Gets a (possibly big) resource, given its URI.
static Encoding GetEncoding(string CharacterSet)
Gets a character encoding from its name.
static bool TryGetFileExtension(string ContentType, out string FileExtension)
Tries to get the file extension of an item, given its content type.
Local domain check event arguments.
A chunked list is a linked list of chunks of objects of type T .
Definition: ChunkedList.cs:54
void Insert(int Index, T Item)
Inserts an item to the list at the specified index.
T[] ToArray()
Returns an array containing all elements of the collection.
Static class that dynamically manages types and interfaces available in the runtime environment.
Definition: Types.cs:15
static object[] NoParameters
Contains an empty array of parameter values.
Definition: Types.cs:572
static Type[] GetTypesImplementingInterface(string InterfaceFullName)
Gets all types implementing a given interface.
Definition: Types.cs:85
static ConstructorInfo GetDefaultConstructor(Type Type)
Gets the default constructor of a type, if one exists.
Definition: Types.cs:1742
Manages a temporary stream. Contents is kept in-memory, if below a memory threshold,...
Interface for reporting progress about an encoding or decoding.
Basic interface for Internet Content encoders. A class implementing this interface and having a defau...
Grade ConversionGrade
How well the content is converted.
string[] FromContentTypes
Converts content from these content types.
string[] ToContentTypes
Converts content to these content types. Return an array of "*" to signify content can be converted t...
Basic interface for Internet Content decoders. A class implementing this interface and having a defau...
bool Decodes(string ContentType, out Grade Grade)
If the decoder decodes an object with a given content type.
Basic interface for Internet Content deleters. A class implementing this interface and having a defau...
string[] UriSchemes
Supported URI schemes.
bool CanDelete(Uri Uri, out Grade Grade)
If the deleter is able to delete to a resource, given its URI.
Basic interface for Internet Content encoders. A class implementing this interface and having a defau...
bool Encodes(object Object, out Grade Grade, params string[] AcceptedContentTypes)
If the encoder encodes a given object.
Basic interface for Internet Content getters. A class implementing this interface and having a defaul...
bool CanGet(Uri Uri, out Grade Grade)
If the getter is able to get a resource, given its URI.
Basic interface for Internet Content headers. A class implementing this interface and having a defaul...
bool CanHead(Uri Uri, out Grade Grade)
If the getter is able to get headers of a resource, given its URI.
Basic interface for Internet Content posters. A class implementing this interface and having a defaul...
string[] UriSchemes
Supported URI schemes.
bool CanPost(Uri Uri, out Grade Grade)
If the poster is able to post to a resource, given its URI.
Basic interface for Internet Content putters. A class implementing this interface and having a defaul...
string[] UriSchemes
Supported URI schemes.
bool CanPut(Uri Uri, out Grade Grade)
If the putter is able to put to a resource, given its URI.
Basic interface for Internet Content query handlers. A class implementing this interface and having a...
string[] UriSchemes
Supported URI schemes.
bool CanQuery(Uri Uri, out Grade Grade)
If the query handler is able to query a resource, given its URI.
bool TryGetContentType(string FileExtension, out string ContentType)
Tries to get the content type of an item, given its file extension.
string[] ContentTypes
Supported content types.
bool TryGetFileExtension(string ContentType, out string FileExtension)
Tries to get the file extension of an item, given its Content-Type.
string[] FileExtensions
Supported file extensions.
Definition: ImplTypes.g.cs:58
Grade
Grade enumeration
Definition: Grade.cs:7