| File: System\Net\Mime\QEncoder.cs | Web Access |
| Project: src\runtime\src\libraries\System.Net.Mail\src\System.Net.Mail.csproj (System.Net.Mail) |
// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. namespace System.Net.Mime { internal sealed class QEncoder : ByteEncoder { private const int SizeOfQEncodedChar = 3; // e.g. "=3A" private readonly WriteStateInfoBase _writeState; internal override WriteStateInfoBase WriteState => _writeState; protected override bool HasSpecialEncodingForCRLF => true; internal QEncoder(WriteStateInfoBase wsi) { _writeState = wsi; } protected override void AppendEncodedCRLF() { //the encoding for CRLF is =0D=0A WriteState.Append("=0D=0A"u8); } protected override bool LineBreakNeeded(byte b) { // Fold if we're before a whitespace and encoding another character would be too long int lengthAfterAddingCharAndFooter = WriteState.CurrentLineLength + SizeOfQEncodedChar + WriteState.FooterLength; bool isWhitespace = b == ' ' || b == '\t' || b == '\r' || b == '\n'; if (lengthAfterAddingCharAndFooter >= WriteState.MaxLineLength && isWhitespace) { return true; } // Or just adding the footer would be too long. int lengthAfterAddingFooter = WriteState.CurrentLineLength + WriteState.FooterLength; if (lengthAfterAddingFooter >= WriteState.MaxLineLength) { return true; } return false; } protected override bool LineBreakNeeded(ReadOnlySpan<byte> bytes) { if (bytes.Length == 1 || IsCRLF(bytes)) // preserve same behavior as in EncodeBytes { return LineBreakNeeded(bytes[0]); } int numberOfCharsToAppend = bytes.Length * SizeOfQEncodedChar; return WriteState.CurrentLineLength + numberOfCharsToAppend + _writeState.FooterLength > WriteState.MaxLineLength; } protected override int GetCodepointSize(string value, int i) { // specific encoding for CRLF if (value[i] == '\r' && i + 1 < value.Length && value[i + 1] == '\n') { return 2; } if (IsSurrogatePair(value, i)) { return 2; } return 1; } // no padding in q-encoding public override void AppendPadding() { } protected override void AppendEncodedByte(byte b) { if (b == ' ') { //spaces should be escaped as either '_' or '=20' and //we have chosen '_' for parity with other email client //behavior WriteState.Append((byte)'_'); } // RFC 2047 Section 5 part 3 also allows for !*+-/ but these arn't required in headers. // Conservatively encode anything but letters or digits. else if (char.IsAsciiLetterOrDigit((char)b)) { // Just a regular printable ascii char. WriteState.Append(b); } else { //append an = to indicate an encoded character WriteState.Append((byte)'='); //shift 4 to get the first four bytes only and look up the hex digit WriteState.Append((byte)HexConverter.ToCharUpper(b >> 4)); //clear the first four bytes to get the last four and look up the hex digit WriteState.Append((byte)HexConverter.ToCharUpper(b)); } } } }