Beispiel #1
0
        private static bool ShouldEncodeChar(UrlEncodingSettings settings, char[] chars, int index)
        {
            char ch = chars[index];

            // the char should be encoded if the user-supplied function indicates it should
            if (settings.ShouldEncodeChar(ch))
            {
                return(true);
            }

            // the char should be encoded if it's the char used to encode spaces
            if (settings.EncodedSpaceChar.HasValue && ch == settings.EncodedSpaceChar.Value)
            {
                return(true);
            }

            // the char should be encoded if it's a space (and spaces have custom encodings)
            if (settings.EncodedSpaceChar.HasValue && ch == ' ')
            {
                return(true);
            }

            // the char should be encoded if it's the char used to encode other characters
            return(ch == settings.EncodedBytePrefixChar &&
                   !(settings.PreventDoubleEncoding && index + 2 < chars.Length && IsCharHex(chars[index + 1]) && IsCharHex(chars[index + 2])));
        }
Beispiel #2
0
        /// <summary>
        /// Decodes a string with the specified settings.
        /// </summary>
        /// <param name="value">The string to be decoded.</param>
        /// <param name="settings">The settings to use when decoding.</param>
        /// <returns>The decoded string.</returns>
        public static string Decode(string value, UrlEncodingSettings settings)
        {
            // check arguments
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            // null decodes to null
            if (value == null)
            {
                return(null);
            }

            // empty string decodes to empty string
            if (value.Length == 0)
            {
                return(value);
            }

            // replace encoded spaces if necessary
            if (settings.EncodedSpaceChar.HasValue)
            {
                value = value.Replace(settings.EncodedSpaceChar.Value, ' ');
            }

            // decode hex-encoded characters
            return(value.IndexOf(settings.EncodedBytePrefixChar) == -1 ? value : DecodeHex(value, settings));
        }
 private UrlEncodingSettings(UrlEncodingSettings settings)
 {
     ShouldEncodeChar      = settings.ShouldEncodeChar;
     EncodedSpaceChar      = settings.EncodedSpaceChar;
     EncodedBytePrefixChar = settings.EncodedBytePrefixChar;
     PreventDoubleEncoding = settings.PreventDoubleEncoding;
     UppercaseHexDigits    = settings.UppercaseHexDigits;
     TextEncoding          = settings.TextEncoding;
 }
Beispiel #4
0
        private static string DecodeHex(string str, UrlEncodingSettings settings)
        {
            var output          = new char[str.Length];
            var outputIndex     = 0;
            var singleByteArray = new byte[1];
            var decoder         = settings.TextEncoding.GetDecoder();
            var isUtf8          = object.ReferenceEquals(settings.TextEncoding, Encoding.UTF8);

            // walk the string, looking for the prefix character
            for (int index = 0; index < str.Length; index++)
            {
                char ch = str[index];
                if (index < str.Length - 2 && ch == settings.EncodedBytePrefixChar && IsCharHex(str[index + 1]) && IsCharHex(str[index + 2]))
                {
                    // found two hex characters; add their byte value to the buffer
                    var value = unchecked ((byte)((CharHex(str[index + 1]) << 4) + CharHex(str[index + 2])));
                    index += 2;

                    if (isUtf8 && value <= 0x7F)
                    {
                        // this byte converts straight to the equivalent char
                        output[outputIndex++] = (char)value;
                    }
                    else
                    {
                        // use the decoder to decode this byte
                        singleByteArray[0] = value;
                        outputIndex       += decoder.GetChars(singleByteArray, 0, 1, output, outputIndex);
                    }
                }
                else
                {
                    // decode the buffer first if it contains data
                    if (singleByteArray[0] != 0)
                    {
                        outputIndex       += decoder.GetChars(singleByteArray, 0, 0, output, outputIndex, flush: true);
                        singleByteArray[0] = 0;
                    }

                    // copy this character as-is
                    output[outputIndex++] = ch;
                }
            }

            // decode any remaining bytes in the buffer
            if (singleByteArray[0] != 0)
            {
                outputIndex += decoder.GetChars(singleByteArray, 0, 0, output, outputIndex, flush: true);
            }

            return(new string(output, 0, outputIndex));
        }
Beispiel #5
0
 private static char HexChar(int n, UrlEncodingSettings settings)
 {
     // convert integer to hex nybble
     return((char)(n < 10 ? n + '0' : n - 10 + (settings.UppercaseHexDigits ? 'A' : 'a')));
 }
Beispiel #6
0
        /// <summary>
        /// Encodes a string with the specified settings.
        /// </summary>
        /// <param name="value">The string to encode.</param>
        /// <param name="settings">The settings to use when encoding.</param>
        /// <returns>The encoded string.</returns>
        public static string Encode(string value, UrlEncodingSettings settings)
        {
            // check arguments
            if (settings == null)
            {
                throw new ArgumentNullException(nameof(settings));
            }

            // null encodes to null
            if (value == null)
            {
                return(null);
            }

            // empty string encodes to empty string
            if (value.Length == 0)
            {
                return(value);
            }

            // convert string to array of characters
            char[] chars  = value.ToCharArray();
            int    length = chars.Length;

            // count characters that should be encoded and spaces
            int charsToEncode = 0;

            for (int index = 0; index < length; index++)
            {
                if (ShouldEncodeChar(settings, chars, index))
                {
                    charsToEncode++;
                }
            }

            // we're done if there are no characters to encode
            if (charsToEncode == 0)
            {
                return(value);
            }

            // each byte becomes 3 characters
            Encoding encoding = settings.TextEncoding;

            char[] output     = new char[length + 3 * settings.TextEncoding.GetMaxByteCount(charsToEncode)];
            int    outputChar = 0;

            // walk characters
            char?encodedSpaceChar      = settings.EncodedSpaceChar;
            char encodedBytePrefixChar = settings.EncodedBytePrefixChar;
            int  encodeStart           = 0;
            int  encodeLength          = 0;

            for (int index = 0; index < length; index++)
            {
                // determine if character needs to be encoded
                bool shouldEncode      = ShouldEncodeChar(settings, chars, index);
                bool encodingSpaceChar = shouldEncode && chars[index] == ' ' && encodedSpaceChar.HasValue;

                // determine if the next character doesn't need text encoding
                if (!shouldEncode || encodingSpaceChar)
                {
                    // encode any characters that needed text encoding
                    if (encodeLength != 0)
                    {
                        foreach (byte by in encoding.GetBytes(chars, encodeStart, encodeLength))
                        {
                            output[outputChar++] = encodedBytePrefixChar;
                            output[outputChar++] = HexChar((by >> 4) & 0xf, settings);
                            output[outputChar++] = HexChar(by & 0xf, settings);
                        }

                        encodeLength = 0;
                    }
                }

                if (encodingSpaceChar)
                {
                    // encode space character directly
                    output[outputChar++] = encodedSpaceChar.Value;
                }
                else if (shouldEncode)
                {
                    // start run of characters that need to be encoded
                    if (encodeLength == 0)
                    {
                        encodeStart = index;
                    }
                    encodeLength++;
                }
                else
                {
                    // copy character to destination
                    output[outputChar++] = chars[index];
                }
            }

            // encode any characters that needed text encoding
            if (encodeLength != 0)
            {
                foreach (byte by in encoding.GetBytes(chars, encodeStart, encodeLength))
                {
                    output[outputChar++] = encodedBytePrefixChar;
                    output[outputChar++] = HexChar((by >> 4) & 0xf, settings);
                    output[outputChar++] = HexChar(by & 0xf, settings);
                }
            }

            // create new string from array of characters
            return(new string(output, 0, outputChar));
        }