1 // Licensed to the .NET Foundation under one or more agreements. 2 // The .NET Foundation licenses this file to you under the MIT license. 3 // See the LICENSE file in the project root for more information. 4 5 using System.Collections.Generic; 6 using System.Text.Internal; 7 using System.Text.Unicode; 8 9 namespace System.Text.Encodings.Web 10 { 11 /// <summary> 12 /// Represents a filter which allows only certain Unicode code points through. 13 /// </summary> 14 public class TextEncoderSettings 15 { 16 private AllowedCharactersBitmap _allowedCharactersBitmap; 17 18 /// <summary> 19 /// Instantiates an empty filter (allows no code points through by default). 20 /// </summary> TextEncoderSettings()21 public TextEncoderSettings() 22 { 23 _allowedCharactersBitmap = AllowedCharactersBitmap.CreateNew(); 24 } 25 26 /// <summary> 27 /// Instantiates the filter by cloning the allow list of another <see cref="TextEncoderSettings"/>. 28 /// </summary> TextEncoderSettings(TextEncoderSettings other)29 public TextEncoderSettings(TextEncoderSettings other) 30 { 31 if (other == null) 32 { 33 throw new ArgumentNullException(nameof(other)); 34 } 35 36 _allowedCharactersBitmap = AllowedCharactersBitmap.CreateNew(); 37 AllowCodePoints(other.GetAllowedCodePoints()); 38 } 39 40 /// <summary> 41 /// Instantiates the filter where only the character ranges specified by <paramref name="allowedRanges"/> 42 /// are allowed by the filter. 43 /// </summary> TextEncoderSettings(params UnicodeRange[] allowedRanges)44 public TextEncoderSettings(params UnicodeRange[] allowedRanges) 45 { 46 if(allowedRanges == null) 47 { 48 throw new ArgumentNullException(nameof(allowedRanges)); 49 } 50 _allowedCharactersBitmap = AllowedCharactersBitmap.CreateNew(); 51 AllowRanges(allowedRanges); 52 } 53 54 /// <summary> 55 /// Allows the character specified by <paramref name="character"/> through the filter. 56 /// </summary> AllowCharacter(char character)57 public virtual void AllowCharacter(char character) 58 { 59 _allowedCharactersBitmap.AllowCharacter(character); 60 } 61 62 /// <summary> 63 /// Allows all characters specified by <paramref name="characters"/> through the filter. 64 /// </summary> AllowCharacters(params char[] characters)65 public virtual void AllowCharacters(params char[] characters) 66 { 67 if (characters == null) 68 { 69 throw new ArgumentNullException(nameof(characters)); 70 } 71 72 for (int i = 0; i < characters.Length; i++) 73 { 74 _allowedCharactersBitmap.AllowCharacter(characters[i]); 75 } 76 } 77 78 /// <summary> 79 /// Allows all code points specified by <paramref name="codePoints"/>. 80 /// </summary> AllowCodePoints(IEnumerable<int> codePoints)81 public virtual void AllowCodePoints(IEnumerable<int> codePoints) 82 { 83 if (codePoints == null) 84 { 85 throw new ArgumentNullException(nameof(codePoints)); 86 } 87 88 foreach (var allowedCodePoint in codePoints) 89 { 90 // If the code point can't be represented as a BMP character, skip it. 91 char codePointAsChar = (char)allowedCodePoint; 92 if (allowedCodePoint == codePointAsChar) 93 { 94 _allowedCharactersBitmap.AllowCharacter(codePointAsChar); 95 } 96 } 97 } 98 99 /// <summary> 100 /// Allows all characters specified by <paramref name="range"/> through the filter. 101 /// </summary> AllowRange(UnicodeRange range)102 public virtual void AllowRange(UnicodeRange range) 103 { 104 if (range == null) 105 { 106 throw new ArgumentNullException(nameof(range)); 107 } 108 109 int firstCodePoint = range.FirstCodePoint; 110 int rangeSize = range.Length; 111 for (int i = 0; i < rangeSize; i++) 112 { 113 _allowedCharactersBitmap.AllowCharacter((char)(firstCodePoint + i)); 114 } 115 } 116 117 /// <summary> 118 /// Allows all characters specified by <paramref name="ranges"/> through the filter. 119 /// </summary> AllowRanges(params UnicodeRange[] ranges)120 public virtual void AllowRanges(params UnicodeRange[] ranges) 121 { 122 if (ranges == null) 123 { 124 throw new ArgumentNullException(nameof(ranges)); 125 } 126 127 for (int i = 0; i < ranges.Length; i++) 128 { 129 AllowRange(ranges[i]); 130 } 131 } 132 133 /// <summary> 134 /// Resets this settings object by disallowing all characters. 135 /// </summary> Clear()136 public virtual void Clear() 137 { 138 _allowedCharactersBitmap.Clear(); 139 } 140 141 /// <summary> 142 /// Disallows the character <paramref name="character"/> through the filter. 143 /// </summary> ForbidCharacter(char character)144 public virtual void ForbidCharacter(char character) 145 { 146 _allowedCharactersBitmap.ForbidCharacter(character); 147 } 148 149 /// <summary> 150 /// Disallows all characters specified by <paramref name="characters"/> through the filter. 151 /// </summary> ForbidCharacters(params char[] characters)152 public virtual void ForbidCharacters(params char[] characters) 153 { 154 if (characters == null) 155 { 156 throw new ArgumentNullException(nameof(characters)); 157 } 158 159 for (int i = 0; i < characters.Length; i++) 160 { 161 _allowedCharactersBitmap.ForbidCharacter(characters[i]); 162 } 163 } 164 165 /// <summary> 166 /// Disallows all characters specified by <paramref name="range"/> through the filter. 167 /// </summary> ForbidRange(UnicodeRange range)168 public virtual void ForbidRange(UnicodeRange range) 169 { 170 if (range == null) 171 { 172 throw new ArgumentNullException(nameof(range)); 173 } 174 175 int firstCodePoint = range.FirstCodePoint; 176 int rangeSize = range.Length; 177 for (int i = 0; i < rangeSize; i++) 178 { 179 _allowedCharactersBitmap.ForbidCharacter((char)(firstCodePoint + i)); 180 } 181 } 182 183 /// <summary> 184 /// Disallows all characters specified by <paramref name="ranges"/> through the filter. 185 /// </summary> ForbidRanges(params UnicodeRange[] ranges)186 public virtual void ForbidRanges(params UnicodeRange[] ranges) 187 { 188 if (ranges == null) 189 { 190 throw new ArgumentNullException(nameof(ranges)); 191 } 192 193 for (int i = 0; i < ranges.Length; i++) 194 { 195 ForbidRange(ranges[i]); 196 } 197 } 198 199 /// <summary> 200 /// Retrieves the bitmap of allowed characters from this settings object. 201 /// The returned bitmap is a clone of the original bitmap to avoid unintentional modification. 202 /// </summary> GetAllowedCharacters()203 internal AllowedCharactersBitmap GetAllowedCharacters() 204 { 205 return _allowedCharactersBitmap.Clone(); 206 } 207 208 /// <summary> 209 /// Gets an enumeration of all allowed code points. 210 /// </summary> GetAllowedCodePoints()211 public virtual IEnumerable<int> GetAllowedCodePoints() 212 { 213 for (int i = 0; i < 0x10000; i++) 214 { 215 if (_allowedCharactersBitmap.IsCharacterAllowed((char)i)) 216 { 217 yield return i; 218 } 219 } 220 } 221 } 222 } 223