// ----------------- MimeHeaderLineBuilder.ToEncodedString ------------------------- // encode the loaded unicode string as one or more mime message lines. public string ToEncodedString( ) { string ucText = UnencodedText.ToString( ); StringBuilder sb = new StringBuilder(5000); EncodedLines lines = new EncodedLines(this); // for each chunk of text in the string. The chunks are either contiguous spaces, // text that can be placed literally ( unencoded ) on the mime header line, or // text that has to be encoded in Quoted-Printable form. Chunk chunk = new Chunk( ); lines.AddNewLine( ); while (true) { chunk = AdvanceNextChunk(ucText, chunk); if (chunk == null) { break; } // a spaces chunk. before adding the spaces to the encoded output, look ahead // to the next chunk. Will it fit on the current line? If not, use folding to // start the space chunk on the next line. if (chunk.ChunkType == ChunkType.Spaces) { chunk = ToEncodedString_SpaceChunk(chunk, lines, ucText); } else { lines.CurrentLine.AddChunk(chunk); } } // final piece. The mime header line term char sequence. // lines.CurrentLine.AddChunk( new Chunk( ChunkType.EndOfLine )) ; return(lines.ToMimeMessageString( )); }
// Encode a spaces chunk for placement in the mime output stream. // Before adding the spaces to the encoded output, look ahead // to the next chunk. Will it fit on the current line? If not, use folding to // start the space chunk on the next line. private Chunk ToEncodedString_SpaceChunk( Chunk InChunk, EncodedLines InLines, string InUcText) { Chunk chunk = InChunk; Chunk nxChunk = AdvanceNextChunk(InUcText, chunk); // how much space will this space chunk, AND the chunk that comes next, occupy in // the encoded output stream. ( cant end a line with spaces. they are trimmed by // the mail agents ) int LxNeeded = chunk.Encode(Traits).Length; if (nxChunk != null) { LxNeeded += nxChunk.Encode(Traits).Length; } // length needed exceeds the desired max size of the line ( about 80 characters ) // Place the space chunk in the encoded output stream in such a way that as many // spaces will be placed on the current line, but at least one will remain and be // folded onto the next line. if (InLines.CurrentLine.CalcDesiredMaxRemLx(Traits) < LxNeeded) { chunk = SpaceChunk_ToEndOfEncodedLine(chunk, InLines); } // This space chunk and the chunk that follows fit on the line. place the // space chunk. Next cycle will pickup and place the next chunk. else { InLines.CurrentLine.AddChunk(chunk); } return(chunk); }
// ------------------------- SpaceChunk_ToEndOfEncodedLine -------------------- // spaces being placed at the last chunk on the line. That means the last char // of the spaces must be QP encoded as =20 in order to prevent the spaces from // being trimmed by mail transfer agents. private Chunk SpaceChunk_ToEndOfEncodedLine( Chunk InChunk, EncodedLines InLines) { ChunkPair pair = null; // isolate the chunk we are working with. Chunk chunk = InChunk; // space remaining on the line. int RemLx = InLines.CurrentLine.CalcDesiredMaxRemLx(Traits); // how much room is used by single space in encoded-word form. int SingleEncodedSpaceUsedLx = new Chunk(ChunkType.Spaces, " ") .SetEncodeAlways(true) .Encode(Traits) .Length; int maxSeg1SpaceCx = RemLx - SingleEncodedSpaceUsedLx - 1; // not enough room to encode a single space. fold right here. if (SingleEncodedSpaceUsedLx > RemLx) { pair = InLines.FoldNewLine(chunk); chunk = pair.a; } // only one space in the chunk. that space is needed for the fold. fold // right away. else if (chunk.Value.Length == 1) { pair = InLines.FoldNewLine(chunk); chunk = pair.a; } // place spaces on the line, then a space in encoded-word form, then fold the // line. else { // place as many spaces before the encoded-word space. int seg1SpaceCx = chunk.Value.Length - 2; if (seg1SpaceCx > maxSeg1SpaceCx) { seg1SpaceCx = maxSeg1SpaceCx; } if (seg1SpaceCx > 0) { pair = chunk.Split(Traits, seg1SpaceCx); InLines.CurrentLine.AddChunk(pair.a); chunk = pair.b; } // there should be at least 2 spaces remaining. if (chunk.Value.Length < 2) { throw(new ApplicationException("Space chunk is too small")); } // split a space from the chunk and add it to the line in forced encoded form. // this is the last chunk on the line. pair = chunk.Split(Traits, 1); pair.a.SetEncodeAlways(true); InLines.CurrentLine.AddChunk(pair.a); chunk = pair.b; // fold the line, using another space as the fold char on the new line. pair = InLines.FoldNewLine(chunk); chunk = pair.a; } // return with the last chunk placed on the line. return(chunk); }
// -------------------------- constructor ------------------------- public LineChunkList(EncodedLines InLines) { mParentLines = InLines; }