//------------------------------------------------------------------------------ // // Copyright (c) Microsoft Corporation. All rights reserved. // //------------------------------------------------------------------------------ namespace System.Web.Security.AntiXss { using System; using System.Collections; using System.Text; using System.Threading; /// /// Provides CSS Encoding methods. /// internal static class CssEncoder { /// /// The values to output for each character. /// private static Lazy characterValuesLazy = new Lazy(InitialiseSafeList); /// /// Encodes according to the CSS encoding rules. /// /// The string to encode. /// The encoded string. internal static string Encode(string input) { if (string.IsNullOrEmpty(input)) { return input; } char[][] characterValues = characterValuesLazy.Value; // Setup a new StringBuilder for output. // Worse case scenario - CSS encoding wants \XXXXXX for encoded characters. StringBuilder builder = EncoderUtil.GetOutputStringBuilder(input.Length, 7 /* worstCaseOutputCharsPerInputChar */); Utf16StringReader stringReader = new Utf16StringReader(input); while (true) { int currentCodePoint = stringReader.ReadNextScalarValue(); if (currentCodePoint < 0) { break; // EOF } if (currentCodePoint >= characterValues.Length) { // We don't have a pre-generated mapping of characters beyond the U+00FF, so we need // to generate these encodings on-the-fly. We should encode the code point rather // than the surrogate code units that make up this code point. // See: http://www.w3.org/International/questions/qa-escapes#cssescapes char[] encodedCharacter = SafeList.SlashThenSixDigitHexValueGenerator(currentCodePoint); builder.Append(encodedCharacter); } else if (characterValues[currentCodePoint] != null) { // character needs to be encoded char[] encodedCharacter = characterValues[currentCodePoint]; builder.Append(encodedCharacter); } else { // character does not need encoding builder.Append((char)currentCodePoint); } } return builder.ToString(); } /// /// Initializes the HTML safe list. /// private static char[][] InitialiseSafeList() { char[][] result = SafeList.Generate(0xFF, SafeList.SlashThenSixDigitHexValueGenerator); SafeList.PunchSafeList(ref result, CssSafeList()); return result; } /// /// Provides the safe characters for CS encoding. /// /// The safe characters for CSS encoding. /// See http://www.owasp.org/index.php/XSS_(Cross_Site_Scripting)_Prevention_Cheat_Sheet private static IEnumerable CssSafeList() { for (int i = '0'; i <= '9'; i++) { yield return i; } for (int i = 'A'; i <= 'Z'; i++) { yield return i; } for (int i = 'a'; i <= 'z'; i++) { yield return i; } } } }